/react-i18n

React i18n library with async/sync bundle loading support.

Primary LanguageJavaScriptMIT LicenseMIT

React i18n

React i18n facilitates localizing your application using multiple languages. The idea behind this library is to group localization files into smaller bundle for easier digestion. Lazy loading is supported out of the box.

Bundle text can be managed manually using JSON/es5 modules or automatically using Google Sheets. i18n-cli will aide in importing from Google Sheets and exporting existing bundles to CSV.

Another localization library!!!

  1. Ease of migrating html. Use existing tags such as paragraph and span tags, just prefix the exising tags and add the data-i18n attribute.
<p>
  Hello { name }!
</p>

becomes

i18n.loadSync({
  'en-US': {
    common: {
      helloUser: 'Hello { name }!',
    }
  }
});

<i18n.p
  data-i18n="common.helloUser"
  className=""
  fallback=""
  options={{
    name: 'John',
  }}
/>
  1. Avoid injecting text via innerHTML since this is counter intuitive to react lifecycle rendering. In other words, innerHTML doesn't play well with nested React nodes.
  <i18n.p
    data-i18n="common.helloUser"
    className=""
    fallback=""
    options={{
      name: (
        <myCustomComponent>
          John
        <myCustomComponent>
      ),
    }}
  />
  1. Unopinionated data formatting. This lib facilitates localization message rendering. Data formatting library must be provided by the user.
  i18n.loadSync({
    'en-US': {
      common: {
        callUsNow: 'Call {phoneNumber} to work with a licensed Advisor',
      }
    }
  });

  <i18n.p
    data-i18n="common.callUsNow"
    className=""
    fallback=""
    options={{
      phoneNumber: '800-123-4567',
    }}
  />

  <i18n.p
    data-i18n="common.callUsNow"
    className=""
    fallback=""
    options={{
      phoneNumber: '(800) 123-4567',
    }}
  />

Quickstart

This quickstart will cover the basic steps to use the react-i18n component. It is still necessary to load the localization bundles, so refer the Load bundles section for more details.

To add features to this project, look at the Setup Development Environment for more information.

  1. Save to package.json

    $ npm i --save @bretkikehara/react-i18n
  2. Configure the localization inside your app base:

    import i18n from 'react-i18n';
    
    i18n.setConfig({ ... });
  3. Load your localization bundles!

  4. Define your JSX component:

    import i18n from 'react-i18n';
    
    // creates the JSX node
    const paragraph = (
      <i18n.p
        className="my-custom-class"
        data-i18n="common.helloWorld"
        options={{
          name: "John"
        }}
        fallback="Hello world!" />
    );

Bundle file structure

JSON bundles

JSON bundles should be nested inside its respective localization.

├── lang
│   ├── en-US
│   │   ├── common.lang.json
│   │   ├── myPage.lang.json
│   ├── fr-FR
│   │   ├── common.lang.json
│   │   ├── myPage.lang.json

Module bundles

Module bundles should be nested in the same manner as the JSON bundles, but also include an index.js for easy import of the bundles for synchronous loading.

├── lang
│   ├── index.js
│   ├── en-US
│   │   ├── index.js
│   │   ├── common.lang.js
│   │   ├── myPage.lang.js
│   ├── fr-FR
│   │   ├── index.js
│   │   ├── common.lang.js
│   │   ├── myPage.lang.js

Loading Bundles

The preferred method is to asynchronously load your localization bundles to support multiple languages without needing to have the all bundles at page load. For the sake of speed, sync loading is also included.

Loading Bundles - sync

Use loadSync to load multiple bundles on all supported locales on application init. For example, if French and English are the only supported languages:

import i18n from 'react-i18n';
import bundles from '../i18n/index';

i18n.setConfig({ ... });

/**
* bundles = {
*  'en-US': {
*    common: {
*      helloWorld: "Hello {name}!",
*    }
*  },
*  'fr-FR': {
*    common: {
*      helloWorld: "Bonjour {name}!",
*    }
*  },
* }
*/
i18n.loadSync(bundles);

const node = <i18n.p data-i18n="common.helloWorld" options={{ name: 'John' }} />

Loading Bundles - async

To asynchronously load the bundles, set the url config property. All localization bundles should be available at this URL.

import i18n from 'react-i18n';

i18n.setConfig({
  url: 'http://example.com/lang'
});

// The ajax call will automatically execute under the hood.
const node = <i18n.p tag="common.helloWorld" options={{ name: 'John' }} />

Setup Development Environment

Run these commands to setup your local development environment. It is assumed that Java Development Kit has alredy been installed.

$ git clone https://github.com/bretkikehara/react-i18n.git
$ cd react-i18n
$ npm install
$ npm run selenium:install
$ npm run selenium
$ npm run test

Problems running Selenium?

  1. Check is JDK is available in your path.

    $ javac -version
  2. Is selenium-standalone installed globally? If so, remove the local selenium-standalone from node_modules.

    $ rm -rf node_mdules/selenium-standalone

Folders dist vs lib

The lib and dist folder exists to fulfill different scenarios where the library may come in handy. The lib holds the transpiled es5 module ready to be included Webpack or Browerify. The dist is useful to load script tag since its a prepacked umd module.

Publish release

Bump the version in the package.json according to semantic versioning. The build task must be explicitly run due to npm issue 3059.

$ npm run release && npm publish