使用react的context实现一个简单i18n
受withApollo的启示,仔细研究了一下context的API,在开发中还没用过context,但是想antd中的form这种跨组件传递数据,那i18n正适合啊
基本代码
先来三个基本组件,到时候准备替换的就是title和desc
import React, { useState } from 'react'
const Title = () => {
  return (
    <div>title</div>
  )
}
const Descrption = () => {
  return (
    <div>desc</div>
  )
}
const Container = () => {
  return (
    <div>
      <Title />
      <Descrption />
    </div>
  )
}
export default Container
语言配置
准备了en和cn的两个版本的语言配置文件:
// en.js
export default {
  locale: 'en',
  messages: {
    title: 'title',
    desc: 'this is description'
  }
}
// zh-CN.js
export default {
  locale: 'zh-CN',
  messages: {
    title: '中文',
    desc: '这是一段描述'
  }
}
加载语言配置,
// load_language.js
import en from './en'
import zhCN from './zh-CN'
const list = {
  [en.locale]: en.messages,
  [zhCN.locale]: zhCN.messages
}
写到这,我想起来webpack的ignore的plugin,加载多语言配置,肯定会将所有的语言全都load,假如你只需要cn,那么其他的语言包对你来说都是没有用的。经常见的就是moment这个,你会使用ignorePlugin忽略它,然后再手动引入
使用context注入
1、 准备conext
// context.js
import React from 'react'
const LanguageContext = React.createContext('zh-CN')
export default LanguageContext
2、向load_language增加消费:
const t = (title) => {
  return (
    <LanguageContext.Consumer>
      {language => (
        list[language][title]
      )}
    </LanguageContext.Consumer>
  )
}
3、然后我就可以直接改造我的title和desc了:
const Title = () => {
  return (
    <div>{t('title')}</div>
  )
}
const Descrption = () => {
  return (
    <div>{t('desc')}</div>
  )
}
4、Container中增加切换语言的按钮:
  const [language, setLanguage] = useState('zh-CN')
  const changeLanguage = () => {
    setLanguage(language === 'zh-CN' ? 'en' : 'zh-CN')
  }
  return (
    <LanguageContext.Provider value={language}>
      <button onClick={changeLanguage}>切换语言:当前是{language}</button>
      <Title />
      <Descrption />
      <Descrption22 />
    </LanguageContext.Provider>
  )
}
ok,可以了
使用hoc注入
另外,t还可以使用hoc的形式注入
export const withLanguage = (Component) => (props) => {
  return (
    <LanguageContext.Consumer>
      {
        language => (
          <Component {...props} t={(title) => list[language][title] } />
        )
      }
    </LanguageContext.Consumer>
  )
}
在组件中使用:
const Descrption2 = ({ t }) => {
  return (
    <div>hoc: {t('desc')}</div>
  )
}
const Descrption22 = withLanguage(Descrption2)
走到这,一个简单的i18n就完成了。
PS: 如果中文网站要做国际化的话,可能最快的方式还是开发一套英文网站,再它的基础上做国际化。中文转英文,长度是由短变长,排版上改的会让人崩溃。