In our work, all the projects of our group are multi-lingual. Of course, they are not separated from each other. They are realized by copying each time. Given this opportunity to write the React component library, incorporate this component into the component library.

Effect of 1.



2. General components

Let’s implement a normal form. Writes the page text content inside the component.


import React, { useState } from 'react';
import { Form, Input, Button, ConfigProvider, CheckBox } from 'biz-web-library';

const hobbys = [
  { value: 1.label: 'swimming' },
  { value: 2.label: 'running' },
  { value: 3.label: 'rope skipping'},
  { value: 4.label: 'boxing'},];export default() = > {return (
    <Form 
      labelCol= {{span: 5}}
      filedCol = {{span: 10}}
      >
        <Form.Item label={'UserName'} name={'name'} >
          <Input />
        </Form.Item >
          <Form.Item label={'Password'} name={'password'} >
        <Input />
      </Form.Item>
      <Form.Item  label={'Hobby'} desc={'You can choose multiple'} name={'hobby'} >
        <CheckBox.Group dataSource={hobbys} />
      </Form.Item>
      <Form.Item filedCol={{span: 8.offset: 4}} >
        <Button htmlType='submit' type={'primary'} >Commit</Button>
      </Form.Item>
      <Form.Item filedCol={{span: 8.offset: 4}} >
        <Button htmlType='submit' type={'primary'} >Cancel</Button>
      </Form.Item>
    </Form>)};Copy the code

2. Implement multi-language components

Now if the project needs to support multilingual, we need to write multilingual files. Judge the current page is belonging to that language through JS, and then get the corresponding file.

2.1 Extraction of multi-language files

English, Chinese and Korean are selected here.

// en_us
export default {
  username: 'UserName'.password: 'Password'.hobby: 'Hobby'.hobby_des: 'You can choose multiple'.commit: 'Commit'.cancel: 'Cancel'
}

// zh_cn
export default {
  username: 'Username'.password: 'password'.hobby: 'interest'.hobby_des: 'You can choose more than one hobby'.commit: 'submit'.cancel: 'cancel'
}

// ko_kr
export default {
  username: 'Luteya 용자 taitae 름'.password: '비밀번호'.hobby: '관 심'.hobby_des: '여러 취미를 선택 lands 수 있습니.'.commit: '제 출'.cancel: '취 소'
}

class I18N {
	static getMultiMessages(local? : string) {
		let cookieLocal = getCookie('urlmap_lan');
		let localmsg = (local || cookieLocal).toLocaleLowerCase();
		if(! ['en_us'.'ja_jp'.'ko_kr'.'zh_cn'.'zh_tw'].includes(localmsg)) {
			localmsg = 'ko_kr';
		}
		let messages = require(`. /${localmsg}.ts`);
		returnmessages.default; }}Copy the code

2.2 Use of multi-language components

How to manage multilingual files and where to load them into the project. Here our component is named ConfigProvider. It is best to configure multilingualism in the project entry where the project route is configured, because multilingualism is global after all. The locale parameter of the ConfigProvider component is the multilingual file passed into the project.

<Provider store={store}>
 <ConnectedRouter history={reducerUtils.getHistory()}>
  <ConfigProvider locale={I18N.getMultiMessages()} size={'middle'} >
    <Switch>
	{
	routers.map(({path, Component}, index) => {
	return (<Route key={index} exact={true} path={path} component={Component} />);})
	}
   </Switch>
</ConfigProvider>
</ConnectedRouter>
</Provider>
, document.getElementById('app'));Copy the code

2.3 Implementation of multi-language components

The React Context is accessible throughout the project. Therefore, it is best to use React.Context to store data here. The locale property here is our multilingual. We store the data through configContext.provider and then consume it using ConfigContext.consumer.

import ko_kr from '.. /locale/ko_kr';
import React from 'react';
import renderEmpty from './renderEmpty';
import { ConfigProviderProps } from './type';

export const ConfigContext = React.createContext<ConfigProviderProps>({
  prefixCls: 'biz',
  renderEmpty,
  size: undefined.locale: ko_kr,
});

const ConfigProvider: React.FC<ConfigProviderProps> = ({ children, ... config }) = > {
  return (
    <ConfigContext.Consumer>{originConfig => {// Reset the value of config, if config is not passed in, Use the default value Object. Keys (originConfig) forEach (v = > {config [v] = config [v] | | originConfig [v]; }); return (<ConfigContext.Provider value={config}>
            {children}
          </ConfigContext.Provider>
        );
      }}
    </ConfigContext.Consumer>
  );
};

export default ConfigProvider;
Copy the code

2.4 globalConfig components

How to use a component is to get data from configContext.consumer in each component. But if every component is used, the same logic needs to be written, so here is a higher-level component that extracts the logic that gets the data into a globalConfig component.

import React from 'react';
import { ConfigContext } from './index';
import { ConfigProviderProps } from './type';

/** * Get the component name: used to get the component's corresponding multilingual **@param Component Component object */
export const getComponentName = (Component: React.ComponentType) = > {
  return Component.displayName || Component.name || 'Component';
};

/** * Globally configure the consumer method **@param Component applies to components */
const globalConfig = <T extends{} >(Component: any) => {
  let displayName = getComponentName(Component as React.ComponentType);
  const ConfigComponent = (props: T & ConfigProviderProps) => {
    return (
      <ConfigContext.Consumer>
        {(config: ConfigProviderProps) => {

          return <Component {. config} {. props} / >;
        }}
      </ConfigContext.Consumer>
    );
  };

  ConfigComponent.displayName = `Config${displayName}`;
  return ConfigComponent;
};

export default globalConfig;
Copy the code

2.5 Component Application

For the above components, we do it in multiple languages.

import React, { useState } from 'react';
import { Form, Input, Button, ConfigProvider, globalConfig, CheckBox } from 'biz-web-library';

// en_us
const language = {
  en_us: {
  username: 'UserName'.password: 'Password'.hobby: 'Hobby'.hobby_des: 'You can choose multiple'.commit: 'Commit'.hobbylist: [{value: 1.label: 'swimming' },
    { value: 2.label: 'running' },
    { value: 3.label: 'rope skipping'}},],zh_cn: {
  username: 'Username'.password: 'password'.hobby: 'interest'.hobby_des: 'You can choose more than one hobby'.commit: 'submit'.hobbylist: [{value: 1.label: 'swimming' },
    { value: 2.label: 'running' },
    { value: 3.label: 'rope'}},],ko_kr: {
  username: 'Luteya 용자 taitae 름'.password: '비밀번호'.hobby: '관 심'.hobby_des: '여러 취미를 선택 lands 수 있습니.'.commit: '제 출'.hobbylist: [{value: 1.label: '수 영' },
    { value: 2.label: '운 영' },
    { value: 3.label: '줄넘기'}}},]const FormField = ({locale}) = > {
  return (
      <Form 
      labelCol= {{span: 5}}
      filedCol = {{span: 10}}
      >
        <Form.Item label={locale.username} name={'name'} >
          <Input />
        </Form.Item >
          <Form.Item label={locale.password} name={'password'} >
        <Input />
      </Form.Item>
      <Form.Item  label={locale.hobby} desc={locale.hobby_des} name={'hobby'} >
        <CheckBox.Group dataSource={locale.hobbylist} />
      </Form.Item>
      <Form.Item filedCol={{span: 8.offset: 4}} >
        <Button htmlType='submit' type={'primary'} >{locale.commit}</Button>
      </Form.Item>
    </Form>)}; const App = globalConfig(FormField); export default () => { const [ languageIndex, setLanguageIndex ] = useState(0); let langs = ['ko_kr', 'zh_cn', 'en_us']; const changeLanguage = () => { let index = languageIndex + 1; index = index === 3 ? 0 : index; setLanguageIndex(index); } return (<>
      <Button onClick={changeLanguage}>Change Language</Button> 
      <span style={{marginLeft: '40px', color: 'red'}} >{langs[languageIndex]}</span>

      <ConfigProvider locale={language[langs[languageIndex]]}>
        <App/>
      </ConfigProvider>
   </>)};Copy the code

3. Global configuration

Of course, this approach does not only apply to multiple languages, such as global size/theme can be customized through this component. At present, I support size, style prefix and multi-mandarin. If there is anything else to be configured, you can make it up later.