mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
merge localization
This commit is contained in:
commit
0ef0558e3f
@ -15,7 +15,6 @@ class PieceListActions {
|
||||
PieceListFetcher
|
||||
.fetch(page, pageSize, search, orderBy, orderAsc)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
this.actions.updatePieceList({
|
||||
page,
|
||||
pageSize,
|
||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
|
||||
import AccordionListItemTable from './accordion_list_item_table';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let AccordionListItem = React.createClass({
|
||||
propTypes: {
|
||||
@ -19,7 +20,7 @@ let AccordionListItem = React.createClass({
|
||||
</div>
|
||||
<div className="info-wrapper">
|
||||
<h1>{this.props.content.title}</h1>
|
||||
<h3>by {this.props.content.artist_name}</h3>
|
||||
<h3>{getLangText('by %s', this.props.content.artist_name)}</h3>
|
||||
</div>
|
||||
<span style={{'clear': 'both'}}></span>
|
||||
</div>
|
||||
|
@ -5,6 +5,8 @@ import TableItem from '../ascribe_table/table_item';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let AccordionListItemTable = React.createClass({
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
|
@ -15,6 +15,8 @@ import TableItemText from '../ascribe_table/table_item_text';
|
||||
import TableItemCheckbox from '../ascribe_table/table_item_checkbox';
|
||||
import TableItemAclFiltered from '../ascribe_table/table_item_acl_filtered';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let AccordionListItemTableEditions = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
@ -52,9 +54,9 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
render() {
|
||||
let columnList = [
|
||||
new TableColumnContentModel((item) => { return { 'editionId': item.id, 'pieceId': this.props.parentId, 'selectItem': this.selectItem, 'selected': item.selected }}, '', '', TableItemCheckbox, 1, false),
|
||||
new TableColumnContentModel((item) => { return { 'content': item.edition_number }}, 'num_editions', 'Nr', TableItemText, 1, false),
|
||||
new TableColumnContentModel((item) => { return { 'content': item.bitcoin_id }}, 'bitcoin_id', 'Bitcoin Address', TableItemText, 5, false),
|
||||
new TableColumnContentModel((item) => { return { 'content': item.acl }}, 'acl', 'Actions', TableItemAclFiltered, 4, false)
|
||||
new TableColumnContentModel((item) => { return { 'content': item.edition_number }}, 'num_editions', '#', TableItemText, 1, false),
|
||||
new TableColumnContentModel((item) => { return { 'content': item.bitcoin_id }}, 'bitcoin_id', getLangText('Bitcoin Address'), TableItemText, 5, false),
|
||||
new TableColumnContentModel((item) => { return { 'content': item.acl }}, 'acl', getLangText('Actions'), TableItemAclFiltered, 4, false)
|
||||
];
|
||||
|
||||
return (
|
||||
|
@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let Link = Router.Link;
|
||||
|
||||
let PaginationButton = React.createClass({
|
||||
@ -25,14 +27,14 @@ let PaginationButton = React.createClass({
|
||||
page -= 1;
|
||||
directionDisplay = (
|
||||
<span>
|
||||
<span aria-hidden="true">←</span> Previous
|
||||
<span aria-hidden="true">←</span> {getLangText('Previous')}
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
page += 1;
|
||||
directionDisplay = (
|
||||
<span>
|
||||
Next <span aria-hidden="true">→</span>
|
||||
{getLangText('Next')} <span aria-hidden="true">→</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import TableColumnMixin from '../../mixins/table_column_mixin';
|
||||
import GeneralUtils from '../../utils/general_utils';
|
||||
import TableHeaderItem from './table_header_item';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
|
@ -5,6 +5,14 @@ import AltContainer from 'alt/AltContainer';
|
||||
import UserActions from '../actions/user_actions';
|
||||
import UserStore from '../stores/user_store';
|
||||
|
||||
import Nav from 'react-bootstrap/lib/Nav';
|
||||
import Navbar from 'react-bootstrap/lib/Navbar';
|
||||
import NavItem from 'react-bootstrap/lib/NavItem';
|
||||
import DropdownButton from 'react-bootstrap/lib/DropdownButton';
|
||||
import MenuItem from 'react-bootstrap/lib/MenuItem';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
let Link = Router.Link;
|
||||
|
||||
let Header = React.createClass({
|
||||
@ -24,40 +32,24 @@ let Header = React.createClass({
|
||||
|
||||
render() {
|
||||
return (
|
||||
<nav className="navbar navbar-default">
|
||||
<div className="container">
|
||||
<div className="navbar-header">
|
||||
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span className="sr-only">Toggle navigation</span>
|
||||
<span className="icon-bar"></span>
|
||||
<span className="icon-bar"></span>
|
||||
<span className="icon-bar"></span>
|
||||
</button>
|
||||
<Navbar>
|
||||
<Nav>
|
||||
<a className="navbar-brand" href="#">
|
||||
<span>ascribe </span>
|
||||
<span className="glyph-ascribe-spool-chunked ascribe-color"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navbar" className="navbar-collapse collapse">
|
||||
<ul className="nav navbar-nav navbar-left">
|
||||
</ul>
|
||||
<ul className="nav navbar-nav navbar-right">
|
||||
<li className="dropdown">
|
||||
<a href="#" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{this.state.currentUser.username} <span className="caret"></span></a>
|
||||
<ul className="dropdown-menu" role="menu">
|
||||
<li><a href="/art/faq/">Account Settings</a></li>
|
||||
</Nav>
|
||||
<Nav right>
|
||||
<DropdownButton eventKey={3} title={this.state.currentUser.username}>
|
||||
<MenuItem eventKey="1" href="/art/account_settings/">{getLangText('Account Settings')}</MenuItem>
|
||||
<li className="divider"></li>
|
||||
<li><a href="/art/faq/">FAQ</a></li>
|
||||
<li><a href="/art/terms/">Terms of Service</a></li>
|
||||
<li className="divider"></li>
|
||||
<li><a href="/api/users/logout/">Log out</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<MenuItem eventKey="2" href="/art/faq/">{getLangText('FAQ')}</MenuItem>
|
||||
<MenuItem eventKey="3" href="/art/terms/">{getLangText('Terms of Service')}</MenuItem>
|
||||
<MenuItem divider />
|
||||
<MenuItem eventKey="4" href="/api/users/logout/">{getLangText('Log out')}</MenuItem>
|
||||
</DropdownButton>
|
||||
</Nav>
|
||||
</Navbar>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
32
js/constants/languages.js
Normal file
32
js/constants/languages.js
Normal file
@ -0,0 +1,32 @@
|
||||
const languages = {
|
||||
'en-US': {
|
||||
'Bitcoin Address': 'Bitcoin Address',
|
||||
'Actions': 'Actions',
|
||||
'Hide': 'Hide',
|
||||
'Show the edition': 'Show the edition',
|
||||
'Show all %d Editions': 'Show all %d Editions',
|
||||
'by %s': 'by %s',
|
||||
'Account Settings': 'Account Settings',
|
||||
'FAQ': 'FAQ',
|
||||
'Terms of Service': 'Terms of Service',
|
||||
'Log out': 'Log out',
|
||||
'Previous': 'Previous',
|
||||
'Next': 'Next'
|
||||
},
|
||||
'de': {
|
||||
'Bitcoin Address': 'Bitcoin Adresse',
|
||||
'Actions': 'Aktionen',
|
||||
'Hide': 'Verstecke',
|
||||
'Show the edition': 'Zeige die Edition',
|
||||
'Show all %d Editions': 'Zeige alle %d Editionen an',
|
||||
'by %s': 'von %s',
|
||||
'Account Settings': 'Kontoeinstellungen',
|
||||
'FAQ': 'Fragen & Antworten',
|
||||
'Terms of Service': 'AGB',
|
||||
'Log out': 'Log out',
|
||||
'Previous': 'Zurück',
|
||||
'Next': 'Weiter'
|
||||
}
|
||||
};
|
||||
|
||||
export default languages;
|
@ -1,7 +1,6 @@
|
||||
import fetch from '../utils/fetch';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
import FetchApiUtils from '../utils/fetch_api_utils';
|
||||
|
||||
|
||||
let EditionFetcher = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import AppConstants from '../constants/application_constants';
|
||||
import FetchApiUtils from '../utils/fetch_api_utils';
|
||||
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
|
||||
import fetch from '../utils/fetch';
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ let PieceListFetcher = {
|
||||
* Can be called with all supplied queryparams the API.
|
||||
*/
|
||||
fetch(page, pageSize, search, orderBy, orderAsc) {
|
||||
let ordering = FetchApiUtils.generateOrderingQueryParams(orderBy, orderAsc);
|
||||
let ordering = generateOrderingQueryParams(orderBy, orderAsc);
|
||||
return fetch.get('pieces_list', { page, pageSize, search, ordering });
|
||||
}
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
import fetch from '../utils/fetch';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
import FetchApiUtils from '../utils/fetch_api_utils';
|
||||
|
||||
|
||||
let UserFetcher = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import GeneralUtils from '../utils/general_utils';
|
||||
import { sumNumList } from '../utils/general_utils';
|
||||
|
||||
let TableColumnMixin = {
|
||||
/**
|
||||
@ -11,7 +11,7 @@ let TableColumnMixin = {
|
||||
let bootstrapClasses = ['col-xs-', 'col-sm-', 'col-md-', 'col-lg-'];
|
||||
|
||||
let listOfRowValues = list.map((column) => column.rowWidth );
|
||||
let numOfUsedColumns = GeneralUtils.sumNumList(listOfRowValues);
|
||||
let numOfUsedColumns = sumNumList(listOfRowValues);
|
||||
|
||||
if(numOfUsedColumns > numOfColumns) {
|
||||
throw new Error('This table has only ' + numOfColumns + ' columns to assign. You defined ' + numOfUsedColumns + '. Change this in the columnMap you\'re passing to the table.')
|
||||
|
@ -1,11 +1,11 @@
|
||||
import alt from '../alt';
|
||||
import EditionAction from '../actions/edition_actions';
|
||||
import EditionActions from '../actions/edition_actions';
|
||||
|
||||
|
||||
class EditionStore {
|
||||
constructor() {
|
||||
this.edition = {};
|
||||
this.bindActions(EditionAction);
|
||||
this.bindActions(EditionActions);
|
||||
}
|
||||
|
||||
onUpdateEdition(edition) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { default as _fetch } from 'isomorphic-fetch';
|
||||
import FetchApiUtils from '../utils/fetch_api_utils';
|
||||
import { argsToQueryParams } from '../utils/fetch_api_utils';
|
||||
|
||||
|
||||
class UrlMapError extends Error {};
|
||||
@ -66,7 +66,7 @@ class Fetch {
|
||||
});
|
||||
|
||||
if (attachParamsToQuery && params && Object.keys(params).length > 0) {
|
||||
newUrl += FetchApiUtils.argsToQueryParams(params);
|
||||
newUrl += argsToQueryParams(params);
|
||||
}
|
||||
|
||||
return newUrl;
|
||||
|
@ -1,8 +1,6 @@
|
||||
import GeneralUtils from './general_utils';
|
||||
|
||||
import { sanitize } from './general_utils';
|
||||
|
||||
// TODO: Create Unittests that test all functions
|
||||
let FetchApiUtils = {
|
||||
|
||||
/**
|
||||
* Takes a key-value object of this form:
|
||||
@ -20,9 +18,9 @@ let FetchApiUtils = {
|
||||
* CamelCase gets converted to snake_case!
|
||||
*
|
||||
*/
|
||||
argsToQueryParams(obj) {
|
||||
export function argsToQueryParams(obj) {
|
||||
|
||||
obj = GeneralUtils.sanitize(obj);
|
||||
obj = sanitize(obj);
|
||||
|
||||
return Object
|
||||
.keys(obj)
|
||||
@ -40,13 +38,13 @@ let FetchApiUtils = {
|
||||
return s + snakeCaseKey + '=' + encodeURIComponent(obj[key]);
|
||||
})
|
||||
.join('');
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Takes a string and a boolean and generates a string query parameter for
|
||||
* an API call.
|
||||
*/
|
||||
generateOrderingQueryParams(orderBy, orderAsc) {
|
||||
export function generateOrderingQueryParams(orderBy, orderAsc) {
|
||||
let interpolation = '';
|
||||
|
||||
if(!orderAsc) {
|
||||
@ -54,14 +52,11 @@ let FetchApiUtils = {
|
||||
}
|
||||
|
||||
return interpolation + orderBy;
|
||||
},
|
||||
};
|
||||
|
||||
status(response) {
|
||||
export function status(response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response
|
||||
}
|
||||
throw new Error(response.json())
|
||||
}
|
||||
};
|
||||
|
||||
export default FetchApiUtils;
|
||||
|
@ -1,10 +1,6 @@
|
||||
// TODO: Create Unittests that test all functions
|
||||
|
||||
let GeneralUtils = {
|
||||
/**
|
||||
* Removes undefined and null values from an key-value object.
|
||||
*/
|
||||
sanitize(obj) {
|
||||
export function sanitize(obj) {
|
||||
Object
|
||||
.keys(obj)
|
||||
.map((key) => {
|
||||
@ -16,26 +12,52 @@ let GeneralUtils = {
|
||||
});
|
||||
|
||||
return obj;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the values of an object.
|
||||
*/
|
||||
valuesOfObject(obj) {
|
||||
export function valuesOfObject(obj) {
|
||||
return Object
|
||||
.keys(obj)
|
||||
.map(key => obj[key]);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sums up a list of numbers. Like a Epsilon-math-kinda-sum...
|
||||
*/
|
||||
sumNumList(l) {
|
||||
export function sumNumList(l) {
|
||||
let sum = 0;
|
||||
l.forEach((num) => sum += parseFloat(num) || 0);
|
||||
return sum;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default GeneralUtils;
|
||||
/*
|
||||
Taken from http://stackoverflow.com/a/4795914/1263876
|
||||
Behaves like C's format string function
|
||||
*/
|
||||
export function formatText() {
|
||||
var args = arguments,
|
||||
string = args[0],
|
||||
i = 1;
|
||||
return string.replace(/%((%)|s|d)/g, function (m) {
|
||||
// m is the matched format, e.g. %s, %d
|
||||
var val = null;
|
||||
if (m[2]) {
|
||||
val = m[2];
|
||||
} else {
|
||||
val = args[i];
|
||||
// A switch statement so that the formatter can be extended. Default is %s
|
||||
switch (m) {
|
||||
case '%d':
|
||||
val = parseFloat(val);
|
||||
if (isNaN(val)) {
|
||||
val = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return val;
|
||||
});
|
||||
};
|
||||
|
30
js/utils/lang_utils.js
Normal file
30
js/utils/lang_utils.js
Normal file
@ -0,0 +1,30 @@
|
||||
import languages from '../constants/languages';
|
||||
|
||||
import { formatText } from './general_utils';
|
||||
|
||||
/**
|
||||
* Is used to translate strings to another language. Basically can be used with C's string format method.
|
||||
* @param {string} s The string you want to translate
|
||||
* @param {array} args An array of arguments (essentially JavaScript's this.arguments) that can be used to substitute digits and other strings
|
||||
* @return {string} The formated string
|
||||
*/
|
||||
export function getLangText(s, ...args) {
|
||||
let lang = navigator.language || navigator.userLanguage;
|
||||
// this is just for testing, as changing the navigator.language wasn't possible
|
||||
lang = 'de';
|
||||
try {
|
||||
if(lang in languages) {
|
||||
return formatText(languages[lang][s], args);
|
||||
} else {
|
||||
// just use the english language
|
||||
return formatText(languages['en-US'][s], args);
|
||||
}
|
||||
} catch(err) {
|
||||
if(!(s in languages[lang])) {
|
||||
console.error(new Error('Language-string is not in constants file. Add: "' + s + '" to the "' + lang + '" language file.'));
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user