next-i18next
next-i18next 用于next.js 项目的插件
- 允许快速启动和运行翻译
- 完全支持SSR、多个名称空间和代码分割
next-i18next 底层使用的是 i18next 和 react-i18next,需要react和 next 的支持
翻译的文件内容需要遵循一定的规范
默认情况下,next-i18next 中对应的JSON 文件的路径方式如下: 只需要将翻译内容整理到JSON文件中
└── static └── locales ├── en | └── common.json └── de └── common.json
在组件中使用:
-
引入高阶组件 import { withNamespaces } from 'i18n';
-
使用: (withNamespaces('moduleDemo')(TradeForm)) 调用的时候需要将json文件和组件进行包裹,这样会返回高阶组件处理之后的组件
-
moduleDemo 为提取的变量,后面的参数是组件
-
moduleDemo 为 json 文件名称,里面的是页面中的各个变量
-
withNamespaces 这个高阶组件负责将 函数 t 传给组件,它支持i18next提供的所有翻译功能。 在调用withNamespaces 这个高阶组件的时候,其实就相当于给组件注入了一个函数 t,在返回的组件中就可以使用这个函数 t。
-
然后在组件中就可以使用函数 t 对对应的变量进行翻译,json文件中的变量和组件中的变量一一对应
-
在json文件中提取的变量最好不要有:,.这样的特殊内容,否则解析会出错。
在非渲染组件中使用
在action中使用:因为在action中有对应的一些提示性的内容,这样就需要提取: action为单独js文件
-
引入: import { i18n } from 'i18n';
-
调用库里面的方法,返回对应的函数 t: const t = i18n.getFixedT(i18n.language, 'common');
-
目前action中的变量提取到 common.json 文件中 之后就可以调用 t 方法来进行翻译
翻译的内容中带参数是如何处理的
- 变量中的参数定义: t('Amount can not be less than the minimum {{min}} {{currency}}', { min, currency, });
在这里有两个变量: {{min}} {{currency}}
-
同样在json变量文件中也需要同样的变量 "Amount can not be less than the minimum {{min}} {{currency}}": "Amount can not be less than the minimum {{min}} {{currency}}",
-
在react中使用就需要用 dangerouslySetInnerHTML 这样的方式来使用:
因为这样会将数据动态的插入到页面中,这样的话,就会涉及到安全性的问题。 这个在React中是不允许的。
'termsContent'),
}}
/>
复制代码
项目中的配置及读取的方式:
- 定义i18n的配置,在项目中的i18n.js:
const NextI18Next = require('next-i18next/dist/commonjs').default;
module.exports = new NextI18Next({
defaultLanguage: 'en',
debug: false,
otherLanguages: ['zh'],
// localeSubpaths: 'foreign',
localeSubpaths: 'all',
// localePath: `${isBrowser() ? '' : 'app/'}static/locales`,
localePath: 'app/static/locales',
});
复制代码
-
获取i18n对象后,构造一个配置内容,比如默认的语言 localePath 这个配置指定本地语言包的路径: app/static/locales/en app/static/locales/zh 以后如果要新增新的语言包就是这样的路径
-
项目中server.js中引入了这个配置,并通过中间件的形式调用这个配置
const nextI18NextMiddleware = require('next-i18next/middleware');
const nextI18next = require('./app/i18n');
server.use(nextI18NextMiddleware(nextI18next));
复制代码
问题:
- 为什么要使用高阶组件的形式来给组件传递函数?为什么这样使用了,函数t就已经在组件的props中了呢?withNamespaces 做了哪些事情?
高阶组件是一个函数,接收一个组件并返回一个新的组件,这也就意味着,高阶组件可以实现
属性代理
通过包裹原来的组件来操作props,比如我们接收一个组件,同时原封不动的返回这个组件原来的样式,只是对接收组件的props属性进行操作,这样返回的新的组件中就有了新的props 当然操作props只是一个方面,另外可以将被包裹的组件的状态提取到包裹组件中,从而完成组件状态的抽象,比如可以实现将非受控组件转变成受控组件。
-
函数t的主要功能是什么?是怎么找到对应的文件中对应的变量的?如何根据语言去选择哪种变量呢?
-
在 next-i18next 文档中可以看出,next-i18next 组件底层依赖 react-i18next: import { Trans } from 'react-i18next'
-
而 react-i18next 中对这块代码的实现为函数:useTranslation,而这里采用了React最新特性:React Hooks
语言包按需加载
每个页面加载的数据并不是很多,所以对应的语言包文件中的内容也不会特别的多,
而页面加载时需要对语言包文件进行load,如果加载所有的语言包的话,就会非常耗时,这是不可取的。
在加载组件时,作为页面的顶层组件中去获取数据的时候,在next-i18next 中,默认情况下会在初始请求时将所有名称空间发送到客户端,所以默认有个配置:
在配合next.js时,需要通过页面级组件上的getInitialProps返回namespacesRequired数组。
import React from 'react';
class Home extends React.Component {
static async getInitialProps() {
return {
namespacesRequired: ['common', 'footer']
}
}
}
复制代码