background

  • Project: large-scale data management system, involving hardware equipment data monitoring, daily business information management, etc
  • Technology: The front and rear ends are separated, and the front end is mainly based on React-Redux
  • Requirement: Switch languages seamlessly with one click on the front end

Use the react – intl

When you think about internationalization of React projects, the first thing that comes to mind is the famous React-IntL library, which provides various internationalization methods for components, dates, numbers, strings, and more. It’s easy to use:

  1. Put the translation files of different languages in their own JS files, and use the same key for multiple language translations of the same text

    // en_US.js
    const en_US = {
        "intl_hello": "Hello!",}export default en_US;
    
    // zh_CN.js
    const zh_CN = {
        "intl_hello": "Hello!,}export default zh_CN;
    Copy the code
  2. Configure the react-intl library in the entry file

    // index.js import { addLocaleData, IntlProvider } from 'react-intl'; Import en from 'react-intl/locale-data/en'; import zh from 'react-intl/locale-data/zh'; addLocaleData([...en, ...zh]); Import en_US from '... /intl/en_US.js'; import zh_CN from '... /intl/zh_CN.js'; const messagesMap = { en: en_US, zh: zh_CN } const locale = 'zh'; // The locale render((// wrap the project component with <IntlProvicer>, <IntlProvider locale={local} messages={messages[local]}> //··· </IntlProvider>), document.getElementById("root"));Copy the code
  3. Use the built-in components or methods in React-IntL to replace strings and times that require multiple languages. For details, refer to the API documentation.


The react – intl and story

Since the project uses Redux to manage the state, put the language environment and translated text into reducer, and use relevant actions to trigger the language switch:

// actions.js export const switchLocal = local => ({ type: 'SWITCH_INTL_LOCAL', payload: { local }, }); // reducers.js import en_US from '... /intl/en_US.js'; import zh_CN from '... /intl/zh_CN.js'; Const messagesMap = {en: en_US, zh: zh_CN} const defaultLocal = {// Default locale, local: 'zh', messages: messagesMap.zh }; export const intlLocal = (state=defaultLocal, action) => { switch(action.type) { case 'SWITCH_INTL_LOCAL': return { local: action.payload.local, messages: messagesMap[action.payload.local], } default: return state; Const {local, messages} = store.getState().intllocal; const {local, messages} = store.getState(). Render ((// react-redux Provider needs to be outside of IntlProvider, <Provider store={store}> <IntlProvider locale={local} messages={messages}> //··· </IntlProvider> </Provider> ), document.getElementById("root"));Copy the code

After completion, it was found that store could be accessed during initialization and the specified default language environment was used, but the language change was invalid. After check, it was found that reducer did change after action was triggered, but no component update was triggered. Use the key property inside React to force the update:

// index.js
render((
    <Provider store={store}>// Add the key attribute to force the update<IntlProvider key={local} locale={local} messages={messages}>/ /...</IntlProvider>
	</Provider>
), document.getElementById("root"));
Copy the code

Discussion on existing problems and schemes

Use key in the previous step to force an update, which is fine for a simple web site or front-end system.

However, because the system is too complex to take over, when using key to forcibly trigger component update, it will cause all the components under the

package to be updated, resulting in the effect similar to the page as a whole being refreshed, resulting in websocket reconnection, data loss and a series of problems, because it is not convenient to use other modules, There are two options left:

  1. Give corresponding prompts when switching languages, and then jump to the welcome interface, so that when re-entering each subsystem, re-initiate various connections. Since language switching does not happen very often, and language switching generally happens when you just enter the system, this scheme is the most practical and the most labor-saving. But, because the project background is more complex, the above leadership means that like those large websites “seamless” switch between Chinese and English, a jump on the “seam”. Regardless of the difference between a website and a large B/S system, the most appropriate solution is an emergency backup in the unlikely event of a demand downgrade.
  2. To modify the react-intl library, wrap each method used in the library, changing the data source from Context to Redux’s Store. The react-intl library doesn’t rely on strings, so I wrote a script similar to intl’s<FormattedMessage>Component, when using and found that can only be used for the limitations of components, and reference Alireact-intl-universal, writes a method to generate translated text directly from key. This scheme is still being perfected and tested.