preface

Recently set up a project, from 0 to do, need to do multi-language internationalization, did today, basically achieved the desired effect, the first time to find gold do not spray, here simply share:

background

Internationalization scheme

  • Overview of internationalization Solutions
  • Front-end internationalization detailed explanation, examples
  • Internationalize resource file management
  • Collaboration between projects and between developers and translators
  • Appendix of internationalization Specification
  • Further reading

Overview of internationalization Solutions

Internationalization is a seemingly simple but actually very complex field. When you actually do internationalization work, you will find that it often involves many contents:

  • Front-end internationalization
  • Server-side internationalization
  • Internationalize resource file management
  • How do projects and developers and translators collaborate

Moreover, internationalization scenarios are often tied to specific technology stacks.

This internationalization solution is only for React technology stack and does not involve server-side internationalization content.

Front-end internationalization detailed explanation, examples

The core steps of internationalization are two:

  1. Create a resource file and store it in key-value mode
  2. Load the resource file and replace the contents of the key on the page with the associated value

Some exploring

I didn’t really explore it, but I googled it and found a mature library on GitHub: React-i18Next

react-intl

react-intl-universa

How to use it

react-i18next

The installation

npm install i18next react-i18next --saveCopy the code

The introduction of the App. Js

import i18n from 'i18next';
import { useTranslation, initReactI18next } from 'react-i18next';
Copy the code

Initialize the

const lng = 'en';
i18n
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    resources: {
      en: {
        translation: {
          Welcome: 'Welcome to React',
        },
      },
      zh: {
        translation: {
          Welcome: 'Welcome to React',
        },
      },
    },
    lng: lng,
    fallbackLng: lng,

    interpolation: {
      escapeValue: false,}});Copy the code

Actual results

function App() {
  const { t } = useTranslation();
  return (
    <div className="App">
      <p>{t('Welcome')}</p>
    </div>
  );
}

export default App;
Copy the code

Packaging results:

// ...
import i18n from '@src/i18n';
// xxx component
console.log('I18N one shot :', i18n.t('INVALID_ORDER'));
render() {/ /... <button> {i18n.t('INVALID_ORDER')} </button>
}Copy the code

react-intl

Background:

Use to internationalize React components. Provide React components and apis to format dates, numbers, strings (including plural and translation).

The React-Intl library is one of the most popular libraries in the industry. React-intl decorates your React.Com component as a package component that dynamically injects internationalization messages so that locale data can be loaded dynamically without needing to reload the page

Installation:

 npm install react-intl --saveCopy the code

Load locale data.

React Intl relies on this data to support singular, complex and relative time formatting.

// Main.js
import { addLocaleData } from 'react-intl'; /* react-intl imports */
import en from 'react-intl/locale-data/en';
import zh from 'react-intl/locale-data/zh'; addLocaleData([...en, ...zh]); // Introduce data from a multilingual environmentCopy the code

Although I only used the text translation function and thought I wouldn’t need to load this data, it turned out to be a necessary step. Error:

[React Intl] Missing locale data for locale: "zh". Using default locale: "en" as fallback.Copy the code

use

The component package requires the root component to be internationalized, and the component tree will then be in the i18N context of the configuration.

Since react-hot-Loader is used in the project, the root Main component is wrapped in

and imported from a separate file.

//app.js
import { AppContainer } from 'react-hot-loader'
import Main from './components/Main'/ /... . const render = Component => { ReactDOM.render( <AppContainer> <Component /> </AppContainer>, document.getElementById('app')
    )
}
render(Main);Copy the code

Use the

component directly in main.js. Just add it to the outermost layer of render() to return the node.

// Main.js
import { addLocaleData, IntlProvider } from 'react-intl'; /* react-intl imports */
render() {return(<IntlProvider> //··· </IntlProvider>)}Copy the code

Add text for multiple languages.

For example, to support Both Chinese and English, in order to facilitate later maintenance, you can create two new files:

// en_us.js const en_US = {hello:"Hello!", / /... . }export default en_US;

// zh_CN.js
const zh_CN = {
    hello: "Hello!, / /... . }export default zh_CN;Copy the code

Then introduce these two variables in main.js.

// Main.js
import zh_CN from ".. /locale/zh_CN"     // import defined messages in Chinese
import en_US from ".. /locale/en_US"     // import defined messages in EnglishCopy the code

Global configures the current language, and the corresponding text.

That is, configure the two properties of the

component, locale and messages.

// Main.js
render() {let messages = {}
    messages['en'] = en_US;
    messages['zh'] = zh_CN;
    return(<IntlProvider locale={this.state.lang} Messages ={messages[this.state.lang]}> //··· </IntlProvider>)}Copy the code

With the basic configuration complete, you can change the page language by changing the value of this.state.lang.

// Main.js
/**
 * Change language
 * @param {String} lang new language
 */
changeLanguage(lang) {
    this.setState({
        lang: lang
    })
}Copy the code

Next, add the translated text to the page

There is basically only one component to use:
. By default, this component generates a
with translated text, which is the value of the corresponding field in messages.

Introduce the FormattedMessage component in the component to which you want to add internationalized text.

import { FormattedMessage  } from 'react-intl'; /* react-intl imports */ //... . <FormattedMessage id="hello" />Copy the code

When the current language is EN, the result is generated:

<span>Hello! </span>Copy the code

At this point, the react-Intl basic internationalization is implemented.

Note: You can use useIntl to get locale, messages, formatMessage. You can use useIntl to get locale, messages, formatMessage. You can use useIntl to get locale, messages, formatMessage. The demo address

The end of the

Write specifications

  1. DefaultMessage must be filled in and used as a Chinese translation
  2. Id must not be repeated
  3. When using intl.formatMessage(), you must use defineMessages, predefined messages

Further reading

  • react-intl
  • react-intl-corner-cases

react-intl-universal

Background:

React international library launched by Alibaba

The best thing about this library is that it is easy to use and less intrusive

The installation

Install using NPM

npm install react-intl-universal --saveCopy the code

Initialize the

On the initial page, initialize the library and configure the language package. The JSON file is determined according to the required languages. In the following picture, only Chinese and English are supported

Configure internationalization in the project entry file

import intl from 'react-intl-universal';

// locale data
const locales = {
  "en-US": require('./locales/en-US.json'),
  "zh-CN": require('./locales/zh-CN.json'),}; class App extends Component { state = {initDone:false}

  componentDidMount() {
    this.loadLocales();
  }

  loadLocales() {// react-inl-universal is a singleton and should only be instantiated once intl.init({currentLocale:'en-US', // TODO: determine locale here
      locales,
    })
    .then(() => {
    this.setState({initDone: true});
    });
  }

  render() {
    return (
      this.state.initDone &&
      <div>
        {intl.get('SIMPLE')} </div> ); }}Copy the code

The language configuration file can be either JSON or JS. The JSON format is as follows:

English configuration file./locales/ en-us.json

{
    "SIMPLE": "Simple Sentence"."LANG_TYPE": "paas-us"."INPUT_MOBILE": "Mobile Number"."HELLO": "Hello, {name}. Welcome to {where}!"
}Copy the code

Chinese configuration file./locales/ zh-cn.json

{
    "SIMPLE": "Simple sentences."."LANG_TYPE": "paas-cn"."INPUT_MOBILE": "Cell phone number"."HELLO": "Hello, {name}. Welcome to {where}!"
}Copy the code

call

In the initialization code, the render function is already called. Elsewhere in the project, it can be called directly because it has already been initialized. The following is an example of a call:

import intl from 'react-intl-universal';

class Test extends Component {
  render() {
    return (
      <div>
        {intl.get('INPUT_MOBILE')} </div> ); }}Copy the code

switch

Now let’s look at the initialization function

intl.init({
    currentLocale: 'en-US', // TODO: determine locale here
    locales,
})Copy the code

In addition to specifying the language directly, the initialization can also be specified by the function determineLocale based on the following configuration:

  1. Query parameter in the Url
  2. Parameters in cookies
  3. The browser’s current language (when query and cookie parameters are not configured)

These configurations work as shown in the following code:

let currentLocale = intl.determineLocale({
  urlLocaleKey: "lang",
  cookieLocaleKey: "lang"
});

intl.init({
    currentLocale, // determine locale here
    locales,
})Copy the code

Then, we can use the following way to switch: when the appropriate language is selected, trigger the callback function, in the function, change the URL or cookie, and then refresh the page, re-initialize, can switch the language.

Here’s an example of switching by cookie:

handleClick = (lang) => {
    Cookies.set('lang', lang, { expires: '1Y' });
    window.location.reload(true);
}Copy the code

The advanced

The React-Intil-Universal library has many other features for language processing, such as:

  • HTML text with HTML tags
  • variable
  • Singular and plural form
  • currency
  • The date of

HTML references text in resource packs

A. Plain text, use intl.get()

<div> {intl.get('SIMPLE')} </div>Copy the code

B. Text with an HTML template, use the intl.gethtml () method

For example, this is defined in resource bundles

{ 
   "SIMPLE": "This is <span style='color:red'>HTML</span>" 
}Copy the code

The reference uses the getHTML() method to get the text

<div>{intl.getHTML('SIMPLE')}</div>
Copy the code

Numeric and thousandth separators

In the following example, the variable num can only be a number if you label it plural. When num is 0, “no photos.” is displayed; When the value is 1, “One photo.” is displayed. When the value is another number such as 25000, “25,000 photos.” is displayed, where the ‘#’ indicates adding a thousandth separator to the value of num

{ 
   "PHOTO": "You have {num, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}" 
}Copy the code

The results are as follows:

intl.get('PHOTO', {num:0}); // "You have no photos."
intl.get('PHOTO', {num:1}); // "You have one photo."
intl.get('PHOTO', {num:1000000}); // "You have 1000000 photos."Copy the code

Display currency format

The syntax is {variable name, type, format}. In this example, the variable name is “price”, and its type is number. “USD” means that the value is preceded by the dollar sign ($).

{ 
   "SALE_PRICE": "The price is {price, number, USD}" 
}Copy the code

Reference and display results are as follows:

intl.get('SALE_PRICE'{price: 123456.78}); // The price isThe $123, 456.78Copy the code

Display the date

The syntax is the same as above: {variable name, type, format}. When the type is “date”, the formatting options are short,medium,long,full, or no formatting

{
  "SALE_START": "Sale begins {start, date}"."SALE_END": "Sale ends {end, date, long}"
}Copy the code

Reference and display:

intl.get('SALE_START', {start:new Date()}); // Sale begins 4/19/2017
intl.get('SALE_END', {end:new Date()}); // Sale ends April 19, 2017Copy the code

Configuring the default message

You can configure a default message when, for example, a misspelling fails to match a text in a resource bundle. In this case, the default message will be displayed when the resource bundle does not match

//"defaultMessage()"Can be abbreviated to"d()"
intl.get('not-exist-key').defaultMessage('Can't find that sentence');Copy the code

You can also configure the default message with an HTML template

intl.getHTML('not-exist-key'<h2> </h2>Copy the code

Message with variables

The configuration in the resource bundle is as follows

{
    "HELLO": "Hello, {name}. Welcome to {where}!" 
}Copy the code

When referencing in HTML

<div> intl.get('HELLO', {name:'banana'.where:'China'}) </div>Copy the code

The command output is Hello, banana.welcome to China!

The end of the

React-intil-universal is a universal universal universal universal universal universal universal universal universal universal universal universal universal universal

Git address: github.com/alibaba/rea…

Antd/ANTD-Mobile internationalization solution

LocaleProvider internationalization

The component LocaleProvider is used to configure international copywriting globally

Ant. The design/components /…

Provide uniform internationalization support for component built-in copywriting

Using the React Context feature with LocaleProvider, it only needs to be wrapped around the application once to take effect globally.

import { LocaleProvider } from 'antd';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';

moment.locale('zh-cn'); .return <LocaleProvider locale={zh_CN}><App /></LocaleProvider>;Copy the code

English, Chinese, Russian, French, German and other languages are supported, and all language packs can be found here.

Note: If you need to use the UMD version of dist file, you should introduce antd/dist/antd-with-locales.js, along with the moment locale, and then use it as follows:

const { LocaleProvider, locales } = window.antd; .return <LocaleProvider locale={locales.en_US}><App /></LocaleProvider>;Copy the code

To this end today’s international sharing daqo, my personal feeling or React-Intil-Universal is better, if it helps you remember a little attention oh,

The case has been uploaded to Github, there are relevant needs can go to see, the first time to write do not spray, if there is a problem please correct!