Localizing Meteor Applications Powered by React

Meteor is a popular full-stack JavaScript platform to develop powerful web and mobile applications. In this article, you will learn how to localize Meteor applications powered by React templates.

Meteor is a quite popular full-stack JavaScript platform to create powerful web and mobile applications. It allows you to develop both client-side and server-side in JavaScript, and also can be used in conjunction with Angular or React. Many developers are fond of Meteor because with it you can create applications blazingly fast, which is especailly important in prototyping, for example.

In this article we are going to talk about adding internationalization to Meteor applications with the help of meteor-universe-i18n. You are going to learn how to setup this library, prepare translations, perform localization, switch between locales, infer locale based on the user’s preferences, and work with currencies. Our demo application will be powered by Meteor combined with React so we’ll also see how to perform translations using React components.

Sounds good? So let’s get started!

The source code for this article can be found on GitHub.

Hello, Meteor I18n!

Preparing the App

To start, create a new Meteor application called ShopFu:

This is going to be an online shop with some random goods. Of course, we are not aiming at something like Shopify at the moment, but who knows what the future might bring…

At the time of writing this article, meteor-universe-i18n had some compatibility issues with Meteor 1.7, so you might need to downgrade to version 1.6:

The next thing to do is introduce React support into our application. UniverseI18n is mainly focused on localizing Meteor+React applications, but there is an accompanying library that provides some helpers for the Blaze templates.

So, we are installing all React goodies and are getting rid of the Blaze templates. All templating will now be done by React itself.

Also install the UniverseI18n:

Nice! Before proceeding to the next section, let’s render a very simple welcoming message at the main page of the site. To do that, replace all contents inside the client/main.html file with the following:

Replace everything inside the client/main.js with:

Effectively, we are waiting for Meteor to start up and then render the Header component.

This component will live in the imports/ui/Header.js file:

That’s it! You may now boot your app by running

Navigate to http://localhost:3000 and make sure that the header is displayed. The next step is to translate this header, so let’s proceed to the next section.

Setting Up UniverseI18n

Getting started with UniverseI18n is quite simple really. All you need to do is import it, provide basic configuration, add load translations. Let’s do that inside the client/main.js file:

I’ve pinpointed the main parts of this code, so let’s talk about them a bit:

  1. Here we are importing the UniverseI18n — nothing special.
  2. This is how you can load translations for the English locale. Out of the box UniverseI18n supports dozens of languages (including information about currency, locale’s native name etc), and in this demo we’ll also add support for the Russian locale. Also, note that it is possible to store translations in a separate JSON or YAML file as explained here.
  3. This Common key is called a “namespace”. You may have as many namespaces as you like, which is especially important for large applications with hundreds of translations. In this demo, we’ll have only one namespace.
  4. This is the actual translation. welcome here is key, whereas the 'Welcome to the Shop Fu!' string is the value to be displayed.
  5. In the same way we are loading translations for the Russian language.
  6. Here you may set options for the UniverseI18n. It has sane defaults, so all I’d like to do here is provide the default language to use.

That’s it! We may now translate our first message!

Performing Translations

You have two options to perform translations in UniverseI18n:

  • By using i18n.getTranslation() or i18n.__() methods
  • By creating a React component

In this demo, we’ll mostly deal with React components as they’re much more convenient to work with but let me briefly show you how to perform translations explicitly.  Add the following line of code to client/main.js:

After reloading the page, you should see ‘Welcome to the Shop Fu!’ in the browser console. Basically, the i18n.__() accepts a namespace, a translation key, and parameters (which are optional). It is also possible to create a special “translator” object, provide options there and perform translations in the following way:

Translating with React Components

Now let’s see how to translate using React components. Modify the Header.js file by importing UniverseI18n and creating a special T constant:

Now modify the render() method:

<T> is a special tag that is going to perform the actual translation. Common, as you remember, is our namespace, whereas welcome is the key. As you see, nothing complex about this approach.

However, after you reload the page, you’ll note that the welcoming message is now displayed in a <span> tag, rather than <h1>. To fix that, override the tag name inside the render() method:

Switching Between Locales

Our translation works, however, there is no way to switch to a different language. Let’s introduce this feature now by creating a new Locales.js file under the imports/ui:

This is going to render all supported languages in an unordered list. Upon clicking on one of the languages, the locale should be switched.

Code the renderLanguages() method:

Here we are loading the supported languages and then use the Language component to display them. This component is going to be created in a moment, but before that let’s also add the getLanguages():

This method relies on UniverseI18n’s getLanguages() that loads all available locales. Then we construct an object with the language’s code and its native name (fetched with the help of getLanguageNativeName()).

Now add a Language.js file inside the ui/imports:

Inside this file, we render a list item with the language’s name. List item also has a click event handler that calls the setLocale() method and switches the language to the chosen one.

Lastly, don’t forget to import this newly created file:

This feature is done, so we may render the locale switcher inside the main.js:

Add the div#locales to the main.html:

Now reload the page and observe the result! One cool thing to note is that after you switch locale, the welcoming message is instantly translated thanks to our React component.

Inferring User’s Locale

Another common thing to do is trying to “guess” which locale the user prefers. In the simplest case it can be done by introducing a new function to the main.js:

After everything is rendered on the screen, we set locale to an inferred one. Feel free to tweak this code to make sure that the inferred locale is actually supported by our app.

Displaying Product List

As long as we are creating a pseudo-shop, there should be some products, right? Let’s render them in a separate component, just like we did with locales. Create a Product.js file inside the ui/imports folder:

We render an array of products that are returned by the getProducts method. In a real world you would probably fetch them from a Mongo database, but for the purposes of this demo it is not required.

Now code the Product.js file inside the ui/imports:

Note that here I am passing the Common namespace right to the createComponent() method, because I would like to dynamically perform translation based on the product’s name. Alternatively, you may specify namespace as an attribute:

Now we need to provide translations for each product, and render our products:

Don’t forget to tweak main.html by adding:

Good! Now the products are translated properly, however these is one minor thing: they don’t have any price. Yeah, actually it is quite a major problem because the users are supposed to pay for the products, rather than receive them for free. Therefore, let’s solve this task as well!

Updating Prices

Working with prices is a bit more complex than with products’ names. Why? Well, because ideally we should also convert the prices to the local currency and display the proper currency symbol. For English locale that’ll be dollars, but for Russian it should be roubles. Therefore we can’t simply render the price inside the <T> tag — some other approach should be used. For example, we can add a data- attribute to the tag with price, and store the initial value (in dollars) there. When the locale is switched, we recalculate the price and display the correct currency symbol.

Start by modifying the Product.js file and adding a new <span> tag inside the <T>:

And now what we can do is listen for the “locale changed” event and recalculate the prices. Here is the event listener inside the main.js:

And here is the implementation of the updatePrice() function:

ratios is the object that we are going to use to convert price in dollars to price in another currency. 1 dollar currently equals about 63 roubles, that’s why I’ve provided 63 for the ru-RU key.

Then we just fetch each .price element, get the initial value from the data-price attribute, parse it, and multiply by the ratio. After that use getCurrencySymbol() to display either $ or Р, and also parse the number with the help of parseNumber(). Pretty cool, eh?

Here I am taking advantage of jQuery, so hook it up inside the main.html file:

This is it! Try switching between locales and make sure that both the product’s name and its price are being updated properly.

PhraseApp and Translation Files

Working with translation files is hard, especially when the app is big and supports many languages. You might easily miss some translations for a specific language which will lead to user’s confusion. And so PhraseApp can make your life easier!

Grab your 14-days trial. PhraseApp supports many different languages and frameworks, including JavaScript of course. It allows to easily import and export translations data. What’s cool, you can quickly understand which translation keys are missing because it’s easy to lose track when working with many languages in big applications. On top of that, you can collaborate with translators as it’s much better to have professionally done localization for your website.

Conclusion

In this article, we have discussed how to introduce internationalization support for Meteor applications powered by React. We have seen meteor-universe-i18n library in action, added support for two languages, performed translations in various ways, added locale switcher, and also worked with events a bit. UniverseI18n has a bunch of other features available so be sure to browser its docs and read the official Meteor guide about I18n.

Hopefully, this article was interesting and useful for you! As always, thanks for staying with me and until the next time.

Localizing Meteor Applications Powered by React
Rate this post
Related Posts
Comments