本文概述
- 1.安装i18n模块
- 2.使用模块
- 3.从文件加载区域设置数据
- 动态更新标签
在本文中, 你将学习如何本地化React应用程序。
1.安装i18n模块 为了处理你的应用程序中的国际化, 我们将使用i18n-react模块。此模块可轻松处理文本国际化和外部化。在命令行中使用以下命令安装模块:
npm install i18n-react --save
该模块运行良好, 非常易于理解和使用。有关更多信息和文档, 请在此处访问官方的Github存储库。
2.使用模块 使该模块正常工作的逻辑很简单:
- 在应用程序顶部(主要组件)需要或导入模块。
- 在应用程序顶部(主要组件)添加应用程序文本。不必从主要组件执行此操作, 也不必从子组件执行该操作。
- 使用该模块并翻译其他组件中的标签。
提供文字
首先, 你需要提供一些文本, 这些文本将通过setTexts方法进行翻译。显然, 需要根据你使用的EcmaScript版本导入或需要该模块:
/* ES6 &
TS */import T from 'i18n-react';
/* commonJS */var T = require('i18n-react').default;
/* when using UMD version w/o modules */var T = window['i18n-react'].default;
// Set some textsT.setTexts({welcome: "Bienvenido {username}!", buttons: {exit: "Salir", start: "Iniciar"}});
请注意, i18n支持插值以动态地修改翻译中的某些值(因为并非每种语言都遵循相同的结构)。实现国际化模块的基本特征之一是, 它不应仅支持简单的字符串到字符串的转换, 而应支持复数。 i18n-react支持其他本地化, 多元化, 对正式和非正式的支持, 请在此处阅读有关这些功能的更多信息。
该方法可能会初始化一次, 并可能在你的应用程序入口点执行。
正在翻译
一旦有一些可用的文本, 就可以使用它们来翻译具有相同模块的应用中的标签。你可以使用单一转换方法通过键检索标签, 也可以直接呈现不同类型的元素, 例如a, p或span元素:
import React from 'react';
import {render} from 'react-dom';
// Our custom react component with some elements insideimport Main from './Main';
// Import the translation moduleimport T from 'i18n-react';
// link<
T.a text="buttons.exit" href="http://www.srcmini.com/a's href"/>
// Text<
T.text tag='h1' text="buttons.start" context: "context-if-any"/>
// Paragraph<
T.p text={{ key: "path.to.string", var1: "string", var2: 2}} anyValidHtmlAttribute="p.will.have.it"/>
// Span<
T.span text={{ key: "path.to.string", context: "context-if-any", var1: "string", var2: 2, var3: <
span className="c">
X<
/span>
}}/>
/* Or translate without using an Element with the T.translate method */<
h1>
{T.translate("welcome", { username: "Bruce Wayne" })}<
/h1>
默认情况下, 如果不存在指定键的翻译, 则返回键本身, 以帮助你查找丢失的翻译。通过在选项或MDText对象中提供notFound属性, 可以增强此行为。
例子
我们有以下app.js初始化一个React应用程序。在这里, 我们将使用i18n模块, 我们将提供一个对象, 其中包含一些西班牙语按钮的文本。它们将在你的应用程序初始化时声明:
import React from 'react';
import {render} from 'react-dom';
// Our custom react component with some elements insideimport Main from './Main';
// Import the translation moduleimport T from 'i18n-react';
// Add the texts for your APPT.setTexts({labels: {accept: "Aceptar", decline: "Declinar"}});
// Render the Main app react component into the app div.// For more details see: https://facebook.github.io/react/docs/top-level-api.html#react.renderrender(<
Main />
, document.getElementById('app'));
现在, 有了一些标签, 我们可以从组件中使用它了。在我们的主要组件中, 我们将仅添加2个按钮, 这些按钮将根据单击的项目触发警报, 这些按钮的标签将通过i18n模块获得:
import React from 'react';
// Some button component exampleimport FlatButton from 'material-ui/FlatButton';
// Import Internationalizationimport T from 'i18n-react';
export default class Main extends React.Component {constructor(props) {super(props);
this.state = {};
}actionAccepted = () =>
{alert("You declined this");
}actionDeclined = () =>
{alert("You declined this");
}render() {return (<
div>
<
FlatButtonlabel={<
T.span text="labels.accept" />
}onTouchTap={this.actionAccepted}/>
<
FlatButtonlabel={T.translate("labels.decline")}onTouchTap={this.actionDeclined}/>
<
/div>
);
}}
【React国际化(i18n)入门】注意, text参数或translate函数的第一个参数期望对象的名称为” Javascript样式” (对象的结构)。上一个示例毫不奇怪地呈现:
文章图片
如你所见, 你唯一需要担心的就是如何提供标签。请注意, 我们仅针对西班牙语执行此操作, 因此, 如果你有另一个对象使用不同的语言, 则需要以新语言的标签作为第一个参数来执行setTexts方法。
建议将翻译存储在JSON或YAML等外部文件中(而不是直接在你的代码中混合使用), 然后再以对象格式在你的代码中要求它们。
3.从文件加载区域设置数据 如前所述, 最好将语言环境存储在JSON之类的特殊文件中, 这样可以轻松管理应用中不同语言的标签。这一步完全取决于你, 是从浏览器中检索语言环境的方式, 还是将语言环境存储在文件中的方式, 等等。但是, 我们将向你展示一种可行的方法, 并且易于实现。
首先, 我们需要知道如何将语言环境存储在外部文件中, 我们将使用JSON文件。例如, 西班牙语标签将存储在具有以下内容的JSON文件(es.json)中:
{"labels": {"accept": "Aceptar", "decline": "Declinar"}}
然后, 一旦为任何一种语言添加了一些标签, 就需要在浏览器中确定用户当前正在使用哪种语言。这随你的项目而变化很大, 你可以将这种语言存储在数据库中或其他内容中, 但是为了说明这一点, 我们将使用浏览器的语言。将使用以下代码进行检索:
var language = (navigator.languages &
&
navigator.languages[0]) || navigator.language || navigator.userLanguage;
// language would be something like es-ES or es_ES// However we store our files with format es.json or en.json// therefore retrieve only the first 2 digitsif (language.length >
2) {language = language.split("-")[0];
language = language.split("_")[0];
}// language would be now only "es"
由于我们项目的翻译文件非常简单, 因此它们将具有名称结构(仅2位数字):es, de, en, ru, jp, zh等。我们将使用它来请求正确的翻译文件。
根据你的工作方式以及应用程序语言环境的大小(和数量), 你可以从静态JSON文件中加载语言环境。
A.请求语言环境文件
如你所知, 你可以自由使用任何第三方库在React中请求文件。你可以使用本机浏览器实现的fetch(建议也包括针对过时的浏览器的whatwg-fetch之类的polyfill), 也可以使用axios之类的特殊库(或jQuery ajax, 这里没有人判断没有人)。
使它工作的逻辑非常简单, 因为你知道setTexts方法需要一个对象, 因此, 这是你唯一需要担心的事情, 为对象提供国际化所需的结构, 你就可以开始使用。以下示例(我们将使用每个开发人员都可能知道的jQuery ajax的getJSON方法)下载一个JSON文件并将其转换为Javascript对象, 该对象作为第一个参数自动传递给我们所使用的国际化库的setTexts方法刚刚安装:
$.getJSON("path-to/locales/"+ language +".json", function( data ) {T.setTexts(data);
});
请注意, 你将需要在语言环境更新后更新组件。可以从任何更改应用程序语言的表单元素(例如, Dropdown, Select等)触发此功能。你可以在本地存储已使用的语言环境(使用localStorage或webStorage), 以防止对服务器的不必要请求执行。
B.使用webpack加载器
如果你的应用程序使用webpack并且你的语言环境文件不是那么大(只有3种语言, 并且它们不会显着增加app.min.js的文件大小), 或者它可以脱机工作(不用担心app.min.js文件大小)(例如在Electron或Cordova下运行的React应用程序), 你可以使用json文件的特殊加载程序(json-loader)将json格式的语言环境文件添加到你的应用程序中。
注意 从webpack V2开始, JSON文件将默认运行。如果使用自定义文件扩展名, 则可能仍要使用此功能。
使用以下命令安装json-loader模块:
npm install --save-dev json-loader
安装模块后, 你需要修改webpack- < env> .config.js(生产和开发)文件并添加自定义加载程序:
{test: /\.json$/, loader: "json", include: "path/to/locales/json-files"}
完成此操作后, 你将可以要求区域设置并将其包含在你的构建文件中。
注意 即使你的应用使用多种语言, 也建议至少在默认语言环境(例如英语)中使用此方法。这样, 你的第一页将已经具有所需的基本消息, 从而避免了使用默认标签的GET请求, 直到用户显式更改语言环境为止:
T.setTexts(require(`!json!./path-to-locales/${language}.json`));
请注意, 必须使用webpack来添加!json!字符串以使其正常工作。你可以创建一个包装所有前面步骤的自定义方法
动态更新标签 如果你已经在项目中使用本教程实现了本地化, 则可能已经注意到, 如果使用T.setTexts更新文本, 则显然没有任何反应(尽管确实发生了, 但项目中的标签并未更新, 它们仍然与你第一次执行setTexts的内容相同)。让我告诉你, 这种行为不是错误。当前, 没有模块可以自动在每个组件上动态更新元素。因此, 你将需要弄清楚(根据你使用React的方式, 通常当某人更改应用程序的语言时, 在React的情况下应重新启动或重新渲染它)如何动态地更新它们, 例如设置语言环境在组件状态下。
如果你不想花时间在上面, 那么还有其他简单的解决方案可能会根据你的项目的体系结构工作, 例如, 仅重新渲染组件就可以解决某些项目的问题:
// The app starts normally with english locale ...// Then set it to spanishT.setTexts(require('!json!./locales/es.json'));
// Render component again ... voila in Spanishthis.forceUpdate();
// Wait 5 seconds ...// Now change it to GermanT.setTexts(require('!json!./locales/de.json'));
// Render component again ... voila in germanthis.forceUpdate();
如果你选择简单的方法, 请阅读有关如何重新渲染React组件的更多信息, 因为这里有关于如何重新渲染组件的讨论。显然应该避免使用forceUpdate, 因为它偏离了React的思维方式, 因此你可以使用另一种方式, 例如从组件重置状态:
// The app starts normally with english locale ...// Then set it to spanishT.setTexts(require('!json!./locales/es.json'));
// Render component again ... voila in Spanishthis.setState(this.state);
// Wait 5 seconds ...// Now change it to GermanT.setTexts(require('!json!./locales/de.json'));
// Render component again ... voila in germanthis.setState(this.state);
请注意, 更新将影响单个组件(仅在将应用程序与React Router或类似的东西一起使用时有用)。
编码愉快!
推荐阅读
- 修复Laravel 5.4中的”指定密钥太长错误”异常
- 如何在React JSX中发表评论
- 处理XP下无法访问Windows7文件
- 处理Windows xp无法安装字体
- 教你进入WindowsXP系统后假死机的处理办法
- 分享运用Windows XP组策略局限访问电脑磁盘的最好办法
- 电脑在Windows XP系统下完成共享上网办法
- 取消Windows XP开始菜单文档运用记录
- 你不知道的9个windows XP隐秘