Internationalization

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;
OFFLINE