多語言解決方案

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']
        }
    }
}
複製代碼

相關文章
相關標籤/搜索