我已经构建了一个基于RactiveJS的web应用程序。它使用RequireJS来处理模块和依赖关系。Racive模板是用rv加载的。
现在我想支持多种语言(最初只有德语和英语)。
所以我的问题是:
在RactiveJS中实现国际化的良好实践是什么
到目前为止,我看到了两种选择:
1.从模板中剥离所有文本,将它们放在资源文件中,并通过查找方法传递
缺点:
在<div>The Item {{name}} is used <b>{{count}}</b> times.</div>
等情况下,要么将文本分开,留下无意义的块,要么中断数据绑定
2.重复模板
缺点:
•重复的模板代码
•无法弄清楚如何使用RequireJS Optimizer 为模板构建单独的语言包
3
还有其他想法吗?
BTW:可以在语言更改时重新加载整个应用程序。我更喜欢一个解决方案,其中只有当前所选语言的资源将通过RequireJS加载。
没有规范的方法可以做到这一点。然而,您可以通过使用decorator来摆脱它。将文本包装在<span>
中,并向<span>
添加一个装饰器。decorator所做的是获取<span>
的内容,从准备好的映射中获取翻译,并替换该文本。
<div>
<span decorator="i18n">Some random text to translate</span>
</div>
要生成翻译文件,您可以使用grunt/gulp/whatthing工具任务来运行所有组件文件,解析其中的HTML部分,并使用decorator="i18n"
查找元素。然后根据它生成JSON模板,并手动填写翻译。
{
"Some random text to translate": "Alcuni testo casuale da tradurre",
...
}
然后,您可以有某种类型的全局指示符来向decorator模块发出要加载哪些翻译映射的信号。由于翻译可以随时更改,因此无法通过RequireJS静态加载。映射将需要AJAX关闭或通过动态require
调用完成。无论哪种方式,优化器都不会包括翻译。
此外,渲染过程中还有一些开销,因为使用该装饰器渲染的每个组件都会动态更改文本。
要解决1+2的问题,即在不复制所有模板的同时保持模板的意义,请考虑将主要语言(比如英语)的文本作为默认提供给翻译函数。
根据这个Racive问题中的讨论,并由kurdin在这个小提琴中演示,你的模板可能看起来是这样的:
<p>{{{ t('Hello <strong>{{name}}</strong> and have a nice day!', 'hello', {name: user.name}) }}}</p>
然后,定义一个专门处理默认值的转换函数t
。
Translations = [] // load those however you want
Translations["ru"] = {
localization: 'пример локализации',
hello: "Привет <strong>{{name}}</strong> хорошего тебе дня!",
language: 'Язык: {{lang}} ',
lang: 'Русский'
}
I18n.translations = Translations;
I18n.defaultLocale = "en";
function t(defaultText, name, context) {
return (I18n.locale === I18n.defaultLocale) ? defaultText : I18n.t(name, context);
}
缺点是:
- 不一致。默认语言在模板中是硬编码的,即默认语言与语言包的位置不同
- 开销:您可能会加载两种语言的数据,因为默认值总是加载在模板中
为了解决第一个问题,即一致性,您可能也想提供一个英语语言包,并跳过自定义t
函数。