React.JS Localization v0.2
Remember my last post about React.js localization? Not 2 years passed yet and I’m happy to share with you the “proper” way to do localization in React.js.
Globalize.js
Yes, I still use globalize. As I said in my previous post, the Common Locale Data Repository is maintained by Unicode Consortium and have support for every possible locale. Please don’t re-invent the wheel. Languages are hard (believe me, I know Russian) and I’ve seen a lot of people trying to do their own localization and plurals. Kudos to them, its a valuable experience to get, but when you are doing a professional web site, you want to use proper plurals.
But while CLDR is only data (usually JSON, but if you are old and nostalgic you can get it in XML format), globalize is the tool. You feed globalize with data and it gives you way to produce shiny localized numbers or dates. Globalize API is very extensive and modular, the core library is only 1KB minified + gzipped and you can add other modules depending on your needs.
Getting CLDR
The way you get CLDR did not change from my previous post. I still think it should be part of your build step. The only difference is that I no longer use cldr-data-downloader since it is limited in the way it downloads the CLDR. Instead I use the combination of gulp-download and gulp-decompress as well as a custom mapping JSON file to map the different packages and versions of CLDR.
What I do recommend you pay attention to, is that CLDR package is split into two “modules”: Locale files and Supplemental files. It is important that you do not ship everything as one json file. Supplemental data is shared across all locales, so if a user switches between different locales, he will use the same supplemental file, but different locale file. This will allow the browser to cache the supplemental.json file if it was already requested once. So while you package your cldr, split it into at least 2 files: {locale}.json and supplemental.json, where {locale} is being the locale you are shipping.
Here are the 2 gulp tasks that I use to create supplemental.json and {locale}.json for the locales I support:
|
|
Localization
Now that you have your CLDR ready, you can start with the actual localization.
The main and the most important file is the GlobalizeProvider:
|
|
locale — is the actual locale name (e.g. “en”, “ru” etc), supplemental — is the content of supplemental.json and data is the content of {locale}.json.
You can theoretically load ALL locale data you will ever support, but its a huge huge huge waste. Locale is not something that users change every 5 minutes, so if I prefer an en_US version of you website, most likely Ill never switch to ru or en_GB, and even if I will switch, I’m ok with you reloading the website and loading the locale data again.
So we have the GlobalizeProvider. It uses context to pass the globalize instance (you can read about context in one of my posts). We will need one more Container component that handles the locale loading based on any strategy you want (guess it from the browser, headers, make the user select; whatever, I prefer to start with en_US and let the user select). Here is a snippet of my RootContainer component that handles the locale loading (I’m using redux here):
|
|
And now we have GlobalizeProviderContainer that wraps our whole application, and since it uses context we can pass initialized globalize instance to every leaf component.
Localized Leaf Components
The only thing left is to implement Localized leaf components.
Here is an example for DateTime component to display date & time in given format:
|
|
Notice the static contextTypes declaration. This is what gives us access to the globalize instance provided from GlobalizeProviderContainer (for more info read my context post).
Inside the Localized component, you use pure globalize API to access the different formatting methods.
You can even query the CLDR itself for data. Take a look at Currency component below:
|
|
This component, when rendered like this:
|
|
Will produce:
|
|
But when rendered like this
|
|
Will produce
|
|
For en_US locale, and for the ru locale it will produce
|
|
You can now go on and implement as much Localized Leaf components as you wish, depending on your needs. I have Country and Currency Selects that are entirely localized, Date Picker that is based entirely on CLDR and Globalize (as opposed to a lot of date pickers that use internal localization files) and etc.
Hope this helped you to become a better React.js developer. Best of luck :)