我正在构建一个应用程序,它需要有多种语言和地区。
我的问题不是纯粹的技术问题,而是关于架构,以及人们在生产中实际使用的模式来解决这个问题。我在任何地方都找不到这方面的“食谱”,所以我转向我最喜欢的问答网站:)
以下是我的要求(它们实际上是“标准”):
以下是我可以想到的可能解决方案:
每个组件都单独处理翻译
这意味着每个组件都有一组en。json、fr.json等文件以及翻译后的字符串。以及一个帮助函数,用于帮助根据所选语言从中读取值。
每个组件通过道具接收翻译
所以他们不知道当前的语言,他们只是将一系列字符串作为道具,这些字符串恰好与当前的语言相匹配
你稍微绕过了道具,可能会使用上下文来传递当前的语言
如果你有任何其他想法,请说!
你是怎么做到的?
Antoine的解决方案很好,但有一些注意事项:
这就是为什么我们在redux和AirBNB的polyglot之上构建redux polyglot
(我是作者之一)
tc(键)
:大写翻译 import setLanguage from 'redux-polyglot/setLanguage';
store.dispatch(setLanguage('en', {
common: { hello_world: 'Hello world' } } }
}));
import React, { PropTypes } from 'react';
import translate from 'redux-polyglot/translate';
const MyComponent = props => (
<div className='someId'>
{props.p.t('common.hello_world')}
</div>
);
MyComponent.propTypes = {
p: PropTypes.shape({t: PropTypes.func.isRequired}).isRequired,
}
export default translate(MyComponent);
如果你有任何问题/建议,请告诉我!
根据我的经验,最好的方法是创建一个国际化的redux状态并使用它,原因有很多:
1-这将允许您从数据库、本地文件甚至从EJS或jade等模板引擎传递初始值
2-当用户更改语言时,您可以更改整个应用程序语言,甚至无需刷新UI。
3-当用户更改语言时,这也将允许您从API、本地文件甚至常量中检索新语言
4-您还可以使用字符串保存其他重要内容,例如时区、货币、方向(RTL/LTR)和可用语言列表
5-您可以将更改语言定义为正常的还原操作
6-您可以将后端和前端字符串放在一个地方,例如,在我的例子中,我使用i18n节点进行本地化,当用户更改UI语言时,我只需执行一个普通的API调用,在后端,我只返回i18n。getCatalog(req)这将仅返回当前语言的所有用户字符串
我对i18n初始状态的建议是:
{
"language":"ar",
"availableLanguages":[
{"code":"en","name": "English"},
{"code":"ar","name":"عربي"}
],
"catalog":[
"Hello":"مرحباً",
"Thank You":"شكراً",
"You have {count} new messages":"لديك {count} رسائل جديدة"
],
"timezone":"",
"currency":"",
"direction":"rtl",
}
国际化的额外有用模块:
1-字符串模板这将允许您在目录字符串之间插入值,例如:
import template from "string-template";
const count = 7;
//....
template(i18n.catalog["You have {count} new messages"],{count}) // لديك ٧ رسائل جديدة
2-人类格式此模块允许您将数字转换为人类可读字符串,例如:
import humanFormat from "human-format";
//...
humanFormat(1337); // => '1.34 k'
// you can pass your own translated scale, e.g: humanFormat(1337,MyScale)
3-momentjs最著名的日期和时间npm库,您可以翻译moment,但它已经有一个内置翻译,您只需要传递当前状态语言即可,例如:
import moment from "moment";
const umoment = moment().locale(i18n.language);
umoment.format('MMMM Do YYYY, h:mm:ss a'); // أيار مايو ٢ ٢٠١٧، ٥:١٩:٥٥ م
目前,有许多框架使用react-context-API实现相同的概念(没有redux),我个人推荐I18next
在尝试了很多解决方案后,我想我找到了一个运行良好的解决方案,并且应该是React 0.14的惯用解决方案(即它不使用混音,而是使用高阶组件)(编辑:当然,React 15也非常好!)。
因此,这里的解决方案从底部开始(各个组件):
组件唯一需要的(按照惯例)是一个字符串。它应该是一个包含组件所需的各种字符串的对象,但实际上它的形状取决于您。
它确实包含默认的翻译,因此您可以在其他地方使用该组件,而无需提供任何翻译(在本例中,它将使用默认语言英语即时可用)
import { default as React, PropTypes } from 'react';
import translate from './translate';
class MyComponent extends React.Component {
render() {
return (
<div>
{ this.props.strings.someTranslatedText }
</div>
);
}
}
MyComponent.propTypes = {
strings: PropTypes.object
};
MyComponent.defaultProps = {
strings: {
someTranslatedText: 'Hello World'
}
};
export default translate('MyComponent')(MyComponent);
高阶分量
在前面的代码片段中,您可能在最后一行注意到了这一点:translate('MyComponent')(MyComponent)
在本例中,translate是一个更高阶的组件,它封装了您的组件,并提供了一些额外的功能(这种结构取代了以前版本的React的混搭)。
第一个参数是一个键,将用于在翻译文件中查找翻译(我在这里使用了组件的名称,但它可以是任何东西)。第二个(请注意函数是卷曲的,以允许ES7装饰器)是要包装的组件本身。
以下是translate组件的代码:
import { default as React } from 'react';
import en from '../i18n/en';
import fr from '../i18n/fr';
const languages = {
en,
fr
};
export default function translate(key) {
return Component => {
class TranslationComponent extends React.Component {
render() {
console.log('current language: ', this.context.currentLanguage);
var strings = languages[this.context.currentLanguage][key];
return <Component {...this.props} {...this.state} strings={strings} />;
}
}
TranslationComponent.contextTypes = {
currentLanguage: React.PropTypes.string
};
return TranslationComponent;
};
}
这并不神奇:它只需从上下文中读取当前语言(而该上下文不会溢出整个代码库,只是在这个包装器中使用),然后从加载的文件中获取相关的strings对象。在这个例子中,这条逻辑相当幼稚,可以按照你真正想要的方式来完成。
重要的一点是,它从上下文中获取当前语言,并根据提供的键将其转换为字符串。
在等级制度的最顶端
在根组件上,只需从当前状态设置当前语言。下面的示例使用Redux作为类似Flux的实现,但可以使用任何其他框架/模式/库轻松地进行转换。
import { default as React, PropTypes } from 'react';
import Menu from '../components/Menu';
import { connect } from 'react-redux';
import { changeLanguage } from '../state/lang';
class App extends React.Component {
render() {
return (
<div>
<Menu onLanguageChange={this.props.changeLanguage}/>
<div className="">
{this.props.children}
</div>
</div>
);
}
getChildContext() {
return {
currentLanguage: this.props.currentLanguage
};
}
}
App.propTypes = {
children: PropTypes.object.isRequired,
};
App.childContextTypes = {
currentLanguage: PropTypes.string.isRequired
};
function select(state){
return {user: state.auth.user, currentLanguage: state.lang.current};
}
function mapDispatchToProps(dispatch){
return {
changeLanguage: (lang) => dispatch(changeLanguage(lang))
};
}
export default connect(select, mapDispatchToProps)(App);
最后,翻译文件:
翻译文件
// en.js
export default {
MyComponent: {
someTranslatedText: 'Hello World'
},
SomeOtherComponent: {
foo: 'bar'
}
};
// fr.js
export default {
MyComponent: {
someTranslatedText: 'Salut le monde'
},
SomeOtherComponent: {
foo: 'bar mais en français'
}
};
你们觉得怎么样?
我认为它解决了我在问题中试图避免的所有问题:翻译逻辑不会在源代码中流血,它是相当孤立的,并且允许在没有它的情况下重用组件。
例如,MyComponent不需要通过Transp()进行包装,并且可以是单独的,允许任何希望按自己的意思提供字符串
的其他人重用它。
[编辑:31/03/2016]:我最近在使用React构建的回顾展板(用于敏捷回顾展)上工作
您可以在此处找到代码:https://github.com/antoinejaussoin/retro-board/tree/master
问题内容: 我正在构建一个应用程序,它将需要提供多种语言和区域设置。 我的问题不是纯粹的技术问题,而是关于架构以及人们在生产中实际用来解决此问题的模式。我在那里找不到任何“食谱”,所以我转向了我最喜欢的问答网站:) 这是我的要求(它们实际上是“标准”): 用户可以选择语言(平凡) 更改语言后,界面应自动翻译成新选择的语言 我现在不太担心格式化数字,日期等的问题,我想要一个简单的解决方案来只翻译字符
在这个例子中,我们将每个传递参数显示语言环境。 文件:I18NTester.java - 执行上面示例代码,得到以下输出结果 -
问题内容: 在我当前的项目中,我们正在考虑逐步淘汰旧的表示层,并用更现代,更知名的东西代替它。由于各种原因,选择了JSP作为技术。可能与Apache Tiles结合使用。我也许应该提到,如果这很重要的话,我们将在后面使用Spring。 国际化是一项要求,特别是在以用户语言显示文本消息方面。令我感到惊讶的是,关于这方面的信息并不像我预期的那么多。 我发现的是JSTL 名称空间。特别是与一起使用。但是
目录 4.1 编写适应国际化的应用程序 4.2 使用 POSIX.1 本地语言支持 (NLS) 的本地化消息 4.1 编写适应国际化的应用程序 为了使你的程序对于使用其他语言的用户更加有用, 我们希望你的程序应该国际化。 GNU的gcc编译器和GUI库比如QT或者GTK等通过对字符串的特殊处理来支持国际化。 生成一个支持国际化的程序非常容易。 它使得发布者很快的把你的程序移植成其他语言。 请参看详
问题内容: 我从Google得知,国际化是使我的Web应用程序使用所有语言的过程。我想了解Unicode的国际化过程,所以我从这里到那里了解了Unicode 。 我能够了解Unicode,即如何将一个字符集设置为编码为字节,然后再将字节解码为字符集。但是我不知道如何进一步前进。我想学习如何比较字符串,还需要知道如何在Web应用程序中实现国际化。有什么建议吗?请指导我。 我的目标: 我的主要目标是开
我目前正在开发一个PHP Web应用程序,需要有法语和英语版本。我环顾四周,发现Gettext()功能提供了最好的性能。 我生成了我的。使用命令创建pot文件 并成功地生成了一个。锅铲。我使用PoEdit生成消息。采购订单文件和创建的邮件。瞬间 以下是我的服务器文件: 我在php文件中设置了这样的语言环境: 但我只看到标签,没有看到翻译。。。我试着用'fr_fr'代替'fr_fr.UTF-8'和各