多语言解决方案

next-i18next

next-i18next 用于next.js 项目的插件html

  1. 容许快速启动和运行翻译
  2. 彻底支持SSR、多个名称空间和代码分割

next-i18next 底层使用的是 i18next 和 react-i18next,须要react和 next 的支持react

翻译的文件内容须要遵循必定的规范

默认状况下,next-i18next 中对应的JSON 文件的路径方式以下: 只须要将翻译内容整理到JSON文件中json

└── static └── locales ├── en | └── common.json └── de └── common.json数组

在组件中使用:

  1. 引入高阶组件 import { withNamespaces } from 'i18n';安全

  2. 使用: (withNamespaces('moduleDemo')(TradeForm)) 调用的时候须要将json文件和组件进行包裹,这样会返回高阶组件处理以后的组件bash

  3. moduleDemo 为提取的变量,后面的参数是组件app

  4. moduleDemo 为 json 文件名称,里面的是页面中的各个变量less

  5. withNamespaces 这个高阶组件负责将 函数 t 传给组件,它支持i18next提供的全部翻译功能。 在调用withNamespaces 这个高阶组件的时候,其实就至关于给组件注入了一个函数 t,在返回的组件中就可使用这个函数 t。async

  6. 而后在组件中就可使用函数 t 对对应的变量进行翻译,json文件中的变量和组件中的变量一一对应函数

  7. 在json文件中提取的变量最好不要有:,.这样的特殊内容,不然解析会出错。

在非渲染组件中使用

在action中使用:由于在action中有对应的一些提示性的内容,这样就须要提取: action为单独js文件

  1. 引入: import { i18n } from 'i18n';

  2. 调用库里面的方法,返回对应的函数 t: const t = i18n.getFixedT(i18n.language, 'common');

  3. 目前action中的变量提取到 common.json 文件中 以后就能够调用 t 方法来进行翻译

翻译的内容中带参数是如何处理的

  1. 变量中的参数定义: t('Amount can not be less than the minimum {{min}} {{currency}}', { min, currency, });

在这里有两个变量: {{min}} {{currency}}

  1. 一样在json变量文件中也须要一样的变量 "Amount can not be less than the minimum {{min}} {{currency}}": "Amount can not be less than the minimum {{min}} {{currency}}",

  2. 在react中使用就须要用 dangerouslySetInnerHTML 这样的方式来使用:

由于这样会将数据动态的插入到页面中,这样的话,就会涉及到安全性的问题。 这个在React中是不容许的。

<span
  className={classNames(classes.contentRoot)}
  dangerouslySetInnerHTML={{
    __html: t('termsContent'),
  }}
/>
复制代码

项目中的配置及读取的方式:

  1. 定义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',
});

复制代码

  1. 获取i18n对象后,构造一个配置内容,好比默认的语言 localePath 这个配置指定本地语言包的路径: app/static/locales/en app/static/locales/zh 之后若是要新增新的语言包就是这样的路径

  2. 项目中server.js中引入了这个配置,并经过中间件的形式调用这个配置

const nextI18NextMiddleware = require('next-i18next/middleware');
const nextI18next = require('./app/i18n');
server.use(nextI18NextMiddleware(nextI18next));
复制代码

问题:

  1. 为何要使用高阶组件的形式来给组件传递函数?为何这样使用了,函数t就已经在组件的props中了呢?withNamespaces 作了哪些事情?

高阶组件是一个函数,接收一个组件并返回一个新的组件,这也就意味着,高阶组件能够实现

属性代理

经过包裹原来的组件来操做props,好比咱们接收一个组件,同时原封不动的返回这个组件原来的样式,只是对接收组件的props属性进行操做,这样返回的新的组件中就有了新的props 固然操做props只是一个方面,另外能够将被包裹的组件的状态提取到包裹组件中,从而完成组件状态的抽象,好比能够实现将非受控组件转变成受控组件。

  1. 函数t的主要功能是什么?是怎么找到对应的文件中对应的变量的?如何根据语言去选择哪一种变量呢?

  2. 在 next-i18next 文档中能够看出,next-i18next 组件底层依赖 react-i18next: import { Trans } from 'react-i18next'

  3. 而 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']
        }
    }
}
复制代码

相关文章
相关标签/搜索