Internationalization has never before become so easy. That is, if you also make use of the default app.js
which deals with the proper routing on the clientside. You set up internationalization in just a few steps:
Generate translated pages
Step 1: Define the languages that your web-application is using
Inside manifest.json
, the languages should be defined. Always make sure a default-language is specified:
manifest.json
{
"port": 3001,
"languages": {
"en": "default",
"nl": true,
"de": false,
"fr": false
}
}
In this example, only 2 languages are activated: en and nl. English is the default language. Whenever a client is visiting the web-app, the language is selected by the following rules:
- If set by the client’s uri: use this language (overruled by a url starting with /lang/xxxx)
- If not set by the client’s uri, try use the client’s preferred language
- If the client’s preferred language is not activated, then use the web-app’s default language
Step 2: Create your language-files
All your language-files should retain in the folder /src/languages/filename.json
, where filename
equals the language. F.e. en.json
and fr.json
. These files should define object with unique keys
to refer to and their properties being the translations.
Example languagefile /languages/en.json
{
"Hello world": "Hello world"
}
Example languagefile /languages/fr.json
{
"Hello world": "Bonjour le monde"
}
Step 3: Create your view with models that recieve the language that is used and can return the translated data
Itsa-react-server has a pre-defined module itsa-react-server/lib/language-files
that will read the right translated file.
Example model-file /models/index.js
const languageFiles = require('itsa-react-server/lib/language-files');
const model = async (request, reply, modelConfig, language /* , manifest */) => {
const languageFile = await languageFiles.readFile(language); // asynchronously
return {
msg: languageFile['Hello world']
};
};
module.exports = model;
Step 4 use the model’s data in the view
Example of /views/index.jsx):
const React = require('react');
class Index extends React.Component {
render() {
return <div>{this.props.msg}</div>;
}
}
module.exports = Index;
Translated browser page-titles
The title that appear in the browser are internationalized as well. To manage this, you should maintain the files inside the pagetitles folder. Every language should have its own json-file, where every view gets a translated title. This languagefile is affinity-aware as well: you can define different titles per device.
Example /pagetitles/en.json
{
"index": "Our beautiful website",
"help": "Help whenever you need it",
"help@phone": "Help"
}
Pagetitles will have their language automaticly set by the server. When switching language on the client, this will also be the case if you are using itsa-react-router
.
Menu for switching languages
You can create a MenuComponent that will switch to the languages like this (the styles below use purecss):
Example /views/index.jsx
const React = require('react'),
PropTypes = require('prop-types'),
classList = 'pure-menu-list',
classMenuItem = 'pure-menu-item',
classMenuItemSelected = 'pure-menu-selected',
classMenuItemLink = 'pure-menu-link';
class LanguageMenu extends React.Component {
render() {
// because this.props.__appProps.languages is an object, we need to transform it into an array first:
var languages = [];
var keys = Object.keys(this.props.__appProps.languages);
keys.forEach(lang => {
if (this.props.__appProps.languages[lang]!==false) {
languages.push(lang);
}
});
return (
<ul className={classList}>
{languages.map(lang => {
var classname = classMenuItem + ((this.props.__appProps.lang===lang) ? ' '+classMenuItemSelected : ''),
link = '/'+lang+this.props.__appProps.uri,
label = lang.toUpperCase(); // <-- you can specify another label here, perhaps countryflags
return (
<li className={classname} key={lang}>
<a className={classMenuItemLink} data-setlang={lang} href={link}>
{label}
</a>
</li>
);
})}
</ul>
);
}
}
LanguageMenu.propTypes = {
__appProps: PropTypes.object.isRequired
};
module.exports = LanguageMenu;