I18N是Internationalization的缩写 I(中间18个字符)n
原理
- 语言包作为静态资源单独保存: xml, json
- 每种语言对应一个文件
- 切换语言设置时,语言文件也会随之切换
I18n工具
- i18next : 目前最主流的框架
- react-i18next : i18next 的 React 插件
安装
yarn add react-i18next i18next
(自带了 ts 声明, 不需要安装额外 ts 声明文件)
配置
在src目录新建 i18n 目录
将 json 格式的语言包都放在这个目录
语言包的格式就是 key: value 的hash表, 不同的语言,key相同,value不同
{"header": {"slogan": "Make travel happier","add_new_language": "add new language","title": "React Travel","register":"Register","signin":"Sign In","home_page": "Home","weekend": "Weekend","group": "Group","backpack": "Backpack","private": "Private","cruise": "Cruise","hotel": "Hotel & Attractions","local": "Local","theme": "Theme","custom": "Custom","study": "Study","visa":"Visa","enterprise":"Enterprise","high_end":"High-end","outdoor":"Outdoor","insurance":"Insurance"},"footer": {"detail" : "All rights reserved @ ReactTravel.com"},}
新建 configs.ts
import i18n from 'i18next'import { initReactI18next } from 'react-i18next'// 导入语言包import translation_en from './en.json'import translation_zh from './zh.json'const resources = {en: {translation: translation_en,},zh: {translation: translation_zh,},}i18n.use(initReactI18next) // passes i18n down to react-i18next.init({resources,lng: 'zh', // 默认语言// keySeparator: false, // we do not use keys in form messages.welcome// header.sloganinterpolation: {escapeValue: false, // react already safes from xss},})export default i18n
在入口文件 index.tsx 中导入 configs.ts
import './i18n/configs'
此时就配置完成了,可以使用 i18n 了
插入语言包内容
在类组件中使用
// ...// 引入高阶组件withTranslation和接口WithTranslationimport { withTranslation, WithTranslation } from 'react-i18next'class HomePageComponent extends React.Component<WithTranslation> {render() {const { t } = this.props // 通过 t 访问json语言包中的keyreturn (<><Header /><div className={styles['page-content']}>// ...<ProductCollectiontitle={<Typography.Title level={3} type="warning">{t('home_page.hot_recommended')} // 获取语言包中对应的项</Typography.Title>}sideImage={sideImage}products={productList1}/>// ...</div></>)}}// 导出高阶组件, 注意withTranslation有2个括号export const HomePage = withTranslation()(HomePageComponent)
在函数式组件中使用
import { Layout, Typography } from 'antd'import { useTranslation } from 'react-i18next'export const Footer: React.FC = () => {const { t } = useTranslation() // 使用钩子return (<Layout.Footer><Typography.Title level={3} style={{ textAlign: 'center' }}>{t('footer.detail')} {/* 获取语言包中对应的项*/}</Typography.Title></Layout.Footer>)}
切换语言
使用 i18next.changeLanguage 实现语言切换
i18next.changeLanguage(lng, callback) // 返回的是一个promise
import i18n from "i18next";i18n.changeLanguage('en');
在redux的reducer中实现语言切换
reducer应该是纯函数,不该有副作用
import i18n from "i18next";export default (state = defaultState, action) => {switch (action.type) {case "change_language":i18n.changeLanguage(action.payload); // 这样处理是不标准的,有副作用return { ...state, language: action.payload };// ...default:return state;}};
