What is Internationalization?

Internationalization: Internationalization is the design and development of a product, application or document content that enables easy localization for target audiences that vary in culture, region, or language.
Localization: Localization refers to the adaptation of a product, application or document content to meet the language, cultural and other requirements of a specific target market (a locale).
ref: W3C Localization vs. Internationalization

Why Internationalize your website or webapp?

If your target market(s) speak more than one language you need to consider how to internationalize (and localize) your meteor app.
The official meteor guide briefly explains some internationalization methods.

Why  Internationalize Meteor with Universe:i18n ?

I looked at a few of the different internationalization solutions and for one reason or another found them overly complex to implement. I wanted the simplest possible solution that made the code also easy to read. At this point in time Universe:i18n seems to do that. While the official meteor guide mentions Universe:i18n I felt it lacked some detail needed to get started, hence this short tutorial.

To demonstrate internationalization in the context of a working app I’m going to walk you through you a basic internationalization of the excellent Meteor Chef boilerplate Base project. The Base project is great because it follows the meteor structure guidelines, as well as implements React as the UI with React Router. We’ll refer to this as MC Base through the rest of this tutorial.

Here’s what MC Base looks like out of the box:

mcbase1

MC Base Internationalized, with English selected:

mcbase2

MC Base Internationalized, with Japanese selected:

mcbase3

MC Base Internationalized, with German selected:

mcbase4

The Process

So, how do we do it?

Step 1

The source code for this tutorial is based on MC Base 4.7.0 and is available on github here. I’m using SourceTree and GitFlow, so there are two branches in this repo:

  • master – containing the original MC Base 4.7.0 codebase
  • develop – containing the working internationalized codebase

Familiarize yourself with the MC Base file structure, which is explained here. The rest of the tutorial assumes you’re adding it to the original MC Base in master branch, but you can also just read through it to understand where to look in the develop branch.

Step 2

Add Universe:i18n to your meteor project with “meteor add universe:i18n“.

Step 3

Read about the universe:i18n translation file formats and options here.

Decide which languages you want to implement, then create the JSON files for them and add them to the meteor project in a directory where they can be accessed by the client and the server.

For the purposes of this tutorial we have created three JSON language files that have a namespace of “common” and they have been added  to directory “both/i18n”:

  • en.i18n.json
  • de.i18n.json
  • jp.i18n.json

Here’s the English file named “en.i18n.json”:

{
"_locale": "en-US",
"_namespace": "common",
"navbar": {
  "userName": "User name",
  "Language": "Language",
  "enUS": "English - U.S.",
  "jaJP": "Japanese",
  "deDE": "German",
  "Index": "Index",
  "Documents": "Documents",
  "Signup": "Sign Up",
  "Login": "Log In",
  "Logout": "Logout"
},
"signupform": {
  "Signup": "Sign Up",
  "Firstname": "First Name",
  "Lastname": "Last Name",
  "Email": "Email Address",
  "Password": "Password"
},
"loginform": {
  "Login": "Log In",
  "Email": "Email Address",
  "Password": "Password",
  "ForgotPassword": "Forgot Password?"
}
}

Here’s the Japanese jp.i18n.json :

{
"_locale": "ja-JP",
"_namespace": "common",
"navbar": {
  "userName": "ユーザー名",
  "Language": "言語",
  "enUS": "英語 - 米",
  "jaJP": "日本語",
  "deDE": "ドイツ人",
  "Index": "インデックス",
  "Documents": "ドキュメント",
  "Signup": "サインアップ",
  "Login": "ログイン",
  "Logout": "ログアウト"
},
"signupform": {
  "Signup": "サインアップ",
  "Firstname": "ファーストネーム",
  "Lastname": "苗字",
  "Email": "電子メールアドレス",
  "Password": "パスワード"
},
"loginform": {
  "Login": "ログイン",
  "Email": "電子メールアドレス",
  "Password": "パスワード",
  "ForgotPassword": "パスワードをお忘れですか"
}
}

The strings are simply accessed as keys by references such as namespace.JSONelement1.JSONelement2 etc. For example, common.navbar.Signup or common.loginform.Email , where common is the namespace 2nd line of the JSON files. You don’t have to have a namespace, but for more complex localization efforts it may be needed so this demonstrates how to use it.

Step 4

Identify the files you need to change to add the internationalization dropdown. MC Base demonstrates public routing and authenticated routing. If you wish to have the localization menu available on the navbar of both routes you will need to implement it on both.

  • imports/ui/components/public-navigation.js
  • imports/ui/components/authenticated-navigation.js

Identify any other files that need to be localized. Since we are also localizing the login and signup pages you will need to modify them as well.

  • imports/ui/pages/login.js
  • imports/ui/pages/signup.js

Step 5

Open the file imports/ui/components/public-navigation.js and modify it as follows:

You need to import universe:i18n, so add the following after the main imports in the file:

import i18n from 'meteor/universe:i18n';

You need to add a dropdown menu with menu items, and as these are not in the original import you need to add them:

import { MenuItem, Nav, NavDropdown, NavItem } from 'react-bootstrap';

There’s a couple of ways to translate strings with Universe:i18n, but since we’re using React it comes with a very neat inline react component which you can read about here. All you need to do is create an instance of the react translation component and feed it the keys from our translation files.

//instance of translate component with top-level context
const T = i18n.createComponent();

The following code from public-navigation.js shows how that is implemented on the main navigation bar.
Note the language switching is done simply by changing the locale eg: “i18n.setLocale(‘ja-JP’);” and everything else is automatically handled by the string references in the NavItems to the JSON language files.

export const PublicNavigation = React.createClass({

handleSelect(eventKey) {
event.preventDefault();
switch (eventKey) {
  case 5.1:
    i18n.setLocale('en-US');
    break;
  case 5.2:
    i18n.setLocale('ja-JP');
    break;
  case 5.3:
    i18n.setLocale('de-DE');
    break;
  default:
    i18n.setLocale('en-US');
    break;
}
},
render() {
return (




);
}
});

Step 6

Modify the imports/ui/components/authenticated-navigation.js file to reflect the same structure as Step 5. Note it has two extra menu items (index, documents) for the authenticated route.

export const AuthenticatedNavigation = React.createClass({

handleSelect(eventKey) {
event.preventDefault();
  switch (eventKey) {
  case 5.1:
    i18n.setLocale('en-US');
    break;
  case 5.2: 
    i18n.setLocale('ja-JP');
    break;
  case 5.3:
    i18n.setLocale('de-DE');
    break;
  default:
    i18n.setLocale('en-US');
    break;
}
},
render() {
return (





);
}
});

Step 7

Modify the signup & login forms as per step 4 and 5.

Step 8

That’s it.

Further Improvements

It would be nice to add flag icons instead of text for languages but I’ll leave that as an exercise for you.
Add it to the github and send me a PR;-)

Thanks for reading, if you got this far!

Pin It on Pinterest

Share This