React-每个组件的翻译

时间:2018-11-15 06:28:08

标签: reactjs internationalization translation create-react-app i18next

我正在为我的React应用程序使用create-react-app,而我目前正在尝试找出翻译。

现在,我每个语言环境都有一个大的JSON文件,每个语言环境文件都包含所有组件的翻译-这并不理想,我希望每个组件都有单独的翻译文件。

因此语言环境的结构如下所示: 组分A -语言环境   -en.json   -sk.json

ComponentB -语言环境   -en.json   -sk.json

实现此目标的最佳方法是什么?我应该使用哪些模块来实现这一目标?

我不想将这些语言环境文件包含到构建中,因为我们将支持10种语言,因此捆绑包的大小将太大。

2 个答案:

答案 0 :(得分:2)

我要回答我自己的问题。经过研究,我发现用例很少,因此我决定进行一些语言环境预处理以实现所需的功能。

我正在与create-react-app一起运行react-i18next的默认配置,我的文件结构如下所示:

src
  - Component A
    - locales
      - en.json
      - sk.json
  - Component B
    - locales
      - en.json

以下是react-i18next模块的设置:

i18n
  .use(Backend)
  .use('en')
  .use(reactI18nextModule)
  .init({
    fallbackLng: 'en',
    debug: false,
    backend: {
      loadPath: function() {
        return `${config.BASE_URL}locales/{{lng}}.json`;
      }
    },
    react: {
      wait: true
    }
  });

由于我使用的是create-react-app的默认配置,因此可以从应用程序的public文件夹提供语言环境并自行构建。

现在变得棘手。由于语言环境文件位于组件树中(而不是公共文件夹中),因此我们需要对语言环境进行一些预处理-基本上,我们需要合并所有JSON文件并将其移至公共文件夹中。

使用以下节点任务(prepare-locales.js)动态创建公用文件夹文件:

const jsonConcat = require('json-concat');
const minifyJson = require('minify-json');
const glob = require('glob');
const availableLocales = ['en', 'sk'];
const path = require('path');

module.exports.development = function() {
  availableLocales.forEach(locale => {
    glob(`./src/**/locales/${locale}.json`, {}, (err, globFiles) => {
      if (globFiles.length) {
        const file = `./public/locales/${locale}.json`;

        jsonConcat(
          {
            src: globFiles,
            dest: file
          },
          json => {
            minifyJson(file);
          }
        );
      }
    });
  });
};

module.exports.production = function() {
  glob('./build/static/js/main.*.js', {}, (err, globFiles) => {
    const files = require('source-map-explorer')(globFiles[0]).files;

    let localeFolders = [];
    Object.keys(files).forEach(fileName => {
      localeFolders.push(path.dirname(fileName).replace('./', ''));
    });
    localeFolders = [...new Set(localeFolders)];

    availableLocales.forEach(locale => {
      const localeFiles = localeFolders.map(
        lf => `./src/${lf}/locales/${locale}.json`
      );

      if (localeFiles.length) {
        const file = `./build/locales/${locale}.json`;

        jsonConcat(
          {
            src: localeFiles,
            dest: file
          },
          json => {
            minifyJson(file);
          }
        );
      }
    });
  });
};

对于开发版本,我将隐藏在树中找到的所有JSON文件。

对于生产版本,我使用的是source-map-explorer,而我只隐含了构建中使用的那些语言环境。

这是我的简化package.json,其中包含完成此工作所需的任务:

{
  "devDependencies": {    
    "json-concat": "0.0.1",
    "minify-json": "^1.0.0",
    "npm-watch": "^0.4.0",
    "path": "^0.12.7",
    "react-scripts": "2.1.1",
    "source-map-explorer": "^1.6.0"
  },
  "scripts": {    
    "start": "react-scripts start & npm run prepare-locales:development:watch",
    "build:production": "react-scripts build && npm run prepare-locales:production",    
    "prepare-locales:development:watch": "npm-watch prepare-locales:development",
    "prepare-locales:development": "node -e 'require(\"./prepare-locales.js\").development()'",
    "prepare-locales:production": "node -e 'require(\"./prepare-locales.js\").production()'"
  },
  "watch": {
    "prepare-locales:development": {
      "patterns": "src/**/locales/",
      "extensions": "json"
    }
  }  
}

也许这不是最好的解决方案,但它适用于我的用例,希望它将对遇到类似问题的人有所帮助。

答案 1 :(得分:0)

这是一个如何将i18next + React + Typescript与类定义和用于翻译的单独文件一起使用的示例https://gitlab.com/damjan89/i18next-typescript-example