国际化(称为i18n)和本地化(称为l10n)非常重要(尽管经常如此)。硬)将在世界范围内使用的任何应用程序的步骤。在其中一个前几条我们已经看到了如何在RubyonRails驱动的后端实现i18n,但是今天是时候讨论前端了。在本文中,我们将讨论如何使用以下解决方案本地化JavaScript应用程序:
- jQuery.I18n
- Airbnb
- jQuery团队的全球化
所有这些解决方案都是完全不同的,它们都有自己的特点,因此我们将看到它们都在行动中。
源代码可在GitHub.

Preparations
在进入主要部分之前,让我们快速地为我们的简单演示项目准备一个基本结构。创建一个单独的文件夹。index.html文件在里面。我们将复制这个文件来测试各种解决方案。然后创建一个嵌套文件夹,名为共同在里面放置jquery.js可以从jquery.com网站。您可以根据您希望支持的浏览器来选择jQuery(1、2或3)的任何一个版本--对于这个演示程序来说,这并不重要。
现在人口index.html带有一些标记:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="common/jquery.js"></script>
</head>
<body>
</body>
</html>
这对我们来说已经足够开始了!
jQuery.I18n
让我们从一个基于jQuery的国际化库开始,这个库是由维基媒体。维基媒体是一个全球性的运动,负责维基百科、维基新闻、维基图书等知名项目。jQuery.I18n反过来,使用基于JSON的本地化文件格式,并支持性别、语法形式、语言的动态变化、回退链等。
jQuery.I18n的翻译可以在多个文件中分隔(en.json, de.json(等)全部存储在一个文件中。下面是一个例子en.json:
{
"@metadata": {
"authors": [
"Me"
],
"last-updated": "2016-09-21",
"locale": "en",
"message-documentation": "qqq"
},
"appname-title": "Example Application",
"appname-sub-title": "An example application with jquery.i18n"
}
因此,如您所见,这些文件支持元数据,您可以在其中指定作者、最新更新日期、区域设置和其他信息。接下来,以键值格式提供实际的翻译。建议在键前加上应用程序的名称,以使其独一无二,但这不是强制性的。
对于较小的应用程序,您可以在单文件。在这种情况下,语言的名称指定为父键:
{
"@metadata": { ... }
"en": {
"appname-title": "Example Application"
},
"ru": {
"appname-title": "Тестовое приложение"
}
}
此外,您甚至可以提供翻译文件的路径:
{
"@metadata": { ... }
"en": {
"appname-title": "Example Application"
},
"ru": "ru.yml"
}
现在,当然,你想知道如何加载这些翻译进入你的应用程序。有几种方法,第一种可能是最简单的方法。与创建单独的JSON文件不同,您可以将所有翻译直接放到脚本中,方法是将它们传递给load职能:
$.i18n().load({
'en': {
'appname-title': 'Example Application'
},
'ru' : {
'appname-title': 'Тестовое приложение'
}
});
我不能说这是一个推荐的做法,但对于非常小的项目,它是好的。
另一个解决方案是从外部URL加载消息
$.i18n().load({
en: 'i18n/en.json'
})
使用此方法时,load将返回一个承诺,因此您可以在done职能:
$.i18n().load({
en: 'i18n/en.json'
}).done( function() { console.log('done!') } )
你可以的设置地区在库的初始化时,使用locale期权
$.i18n( {
locale: 'en'
} );
或者通过在lang属性的html标签:
<html lang="en" dir="ltr">
当然,通过重新定义locale备选方案:
$.i18n({
locale: 'de'
});
// or
$.i18n().locale = 'de';
翻译一封信给你会提供的钥匙$.i18n功能
$.i18n('message-key1');
或者只是雇用 a data-属性(不需要额外的JavaScript)。初始内容是要显示的后备文本,以防出现问题而无法找到翻译:
<li data-i18n="message-key">Fallback text</li>
注意,消息通过接受参数来支持内插。这些都写成$1, $2等等:
var message = "Good day, $1";
$.i18n(message, 'Joe');
复数和性别使用以下语法处理:
var message = "Found $1 {{PLURAL:$1|result|results}}";
$.i18n(message, 1);
var message = "$1 changed {{GENDER:$2|his|her}} profile picture";
$.i18n(message, 'Emma', 'female');
在实践中
要开始,复制我们的基地index.html文件作为jQuery_i18n.html。创建一个新的jQuery_i18n目录并将main-jQuery_i18n.js文件在里面。下一个克隆jQuery.I18n在您的PC和子模块:
$ git clone https://github.com/wikimedia/jquery.i18n.git
$ cd jquery.i18n
$ git submodule update --init
我们将要求从SRC目录(没有语言)以及CLDRPluralRuleParser.js从LIBS\CLDRPluralRuleParser\src。将所有这些复制到jQuery_i18n文件夹,然后按正确的顺序将它们包括在内:
jQuery_i18n.html
[...]
<script src="jquery_i18n/CLDRPluralRuleParser.js"></script>
<script src="jquery_i18n/jquery.i18n.js"></script>
<script src="jquery_i18n/jquery.i18n.messagestore.js"></script>
<script src="jquery_i18n/jquery.i18n.fallbacks.js"></script>
<script src="jquery_i18n/jquery.i18n.language.js"></script>
<script src="jquery_i18n/jquery.i18n.parser.js"></script>
<script src="jquery_i18n/jquery.i18n.emitter.js"></script>
<script src="jquery_i18n/jquery.i18n.emitter.bidi.js"></script>
<script src="jquery_i18n/main-jquery_i18n.js"></script>
[...]
让我们还通过lang属性:
jQuery_i18n.html
[...]
<html lang="en" dir="ltr">
[...]
最后,添加链接以切换语言和几个空标记,这些标记将托管我们翻译的内容。我将使用英语和俄语,但当然,你可以选择任何其他语言-这并不重要,但对于现实世界的应用程序要确保你的文本是正确翻译, 最好是人类.
jQuery_i18n.html
[...]
<body>
<a href="#" class="lang-switch" data-locale="en">English</a> |
<a href="#" class="lang-switch" data-locale="ru">Русский</a>
<h1 data-i18n="welcome"></h1>
<p id="messages"></p>
</body>
[...]
现在继续看剧本。我们需要在文档准备好后立即加载翻译。为了简单起见,让我们将所有消息存储在脚本中:
main-jQuery_i18n.js
[...]
jQuery(document).ready(function() {
$.i18n().load({
'en': {
'welcome': 'Welcome!',
}
'ru': {
'welcome': 'Добро пожаловать!',
}
});
});
[...]
注意welcome键-在data-i18n属性的h1标签。这样就会自动使用适当的转换-我们所要做的就是通过调用i18n()功能。我会把它从update_texts:
main-jQuery_i18n.js
[...]
jQuery(document).ready(function() {
var update_texts = function() {
$('body').i18n();
};
$.i18n().load({...});
update_texts();
});
[...]
现在让我们来处理语言转换。这很简单-听一下click事件的提取值。data-locale属性,然后相应地设置区域设置:
main-jQuery_i18n.js
[...]
$('.lang-switch').click(function(e) {
e.preventDefault();
$.i18n().locale = $(this).data('locale');
update_texts();
});
[...]
最后,我们将为#messages部分。这将变得更加复杂:
main-jQuery_i18n.js
[...]
$.i18n().load({
'en': {
'welcome': 'Welcome!',
'message_from': '$1 has send you $2 {{plural:$2|message|messages}}. {{gender:$3|He|She}} is waiting for your response!'
},
'ru': {
'welcome': 'Добро пожаловать!',
'message_from': '$1 {{gender:$3|отправил|отправила}} вам $2 {{plural:$2|сообщение|сообщений|сообщения}}. {{gender:$3|Он|Она}} ждёт ответа!'
}
});
[...]
在这里,多元化和性别信息被同时使用。对于俄语,我不得不增加更多的选项,因为多元化规则更为复杂。为了使其工作,可以调整update_texts()职能:
main-jQuery_i18n.js
[...]
var update_texts = function() {
$('body').i18n();
$('#messages').text($.i18n('message_from', 'Ann', 2, 'female'));
};
[...]
现在打开页面,试着在语言之间切换--一切都应该很好!
Polyglot.js
Polyglot.js是由爱彼迎(一家工程公司)在浏览器和Common.js环境中工作。它支持插值和多元化,同时具有零依赖关系。抓取生产版本这里.
开始和Polyglot合作,实例化:
var polyglot = new Polyglot();
它是基于类的,因此您可以同时使用不同的区域设置。
下一步提供一个短语清单:
polyglot.extend({
"hello": "Hello"
});
// or
var polyglot = new Polyglot({phrases: {"hello": "Hello"}});
作为一种常见的模式,文档建议在后端准备一个短语散列,然后将它们输出到script标签。请注意,Polyglot不会进行翻译--您的工作是根据用户的地区提供适当的短语。
短语可以完全替换或删除(例如,释放内存)replace或clear方法分别.
注意,嵌套也是受支持的:
polyglot.extend({
"nav": {
"sidebar": {
"welcome": "Welcome"
}
}
});
如果你来自铁路世界,内插你应该很熟悉:
polyglot.extend({
"hello_name": "Hello, %{name}."
});
若要执行实际翻译,请使用t方法:
polyglot.t("hello_name", {name: "John"});
如果您的键是嵌套的,那么使用点。.作为分隔符:
polyglot.t("nav.sidebar.welcome");
请注意,语言的名称在任何地方都没有提供--目前只有在使用多元化时才使用它。若要设置它,请使用locale功能
polyglot.locale("de")
或在实例化新对象时将其设置为传递locale选择。
消息多元化应该用四个管道分隔(||||):
polyglot.extend({
"num_cars": "%{smart_count} car |||| %{smart_count} cars",
});
正确的消息将根据smart_count参数。
在实践中
现在,让我们快速地看到这个解决方案的作用。复制index.html文件并命名它polyglot.html。然后创建一个多角化文件夹并将生产版本里面的剧本。还创建main-polyglot.js在那里归档,把所有东西连接起来:
polyglot.html
[...]
<script src="polyglot/polyglot.js"></script>
<script src="polyglot/main-polyglot.js"></script>
[...]
在这个演示中,我们将使用.js的模板引擎将用于呈现内容(尽管您可以继续使用车把或其他解决方案)。如果您以前没有使用过这样的模板,那么这个想法非常简单:您有一个带有一些参数的标记。然后,该模板将被“编译”(意味着参数接收它们的值),并像其他HTML一样呈现在页面上。
放置下划线的制作版本进入共同文件夹并要求:
polyglot.html
[...]
<script src="common/jquery.js"></script>
<script src="common/underscore.js"></script>
[...]
我将把我们的模板直接放在页面上,在最下面。注意,它必须用script标记具有特殊类型(防止浏览器试图将其作为JavaScript代码处理):
polyglot.html
<script type="text/template" id="main-content">
<p><%= hello %></p>
<small><%= unread %></small>
</script>
现在,在脚本中,让我们等待文档准备就绪,然后实例化Polyglot类,同时提供两条消息:
main-polyglot.js
jQuery(document).ready(function() {
var polyglot = new Polyglot({
phrases: {
"hello": "Hello, %{name}!",
"unread": "You have %{smart_count} unread message |||| You have %{smart_count} unread messages"
}
});
});
这里我们使用了插值和复数(注意参数的名称)smart_count-当使用另一个名称时,复数似乎停止工作)。现在让我们抓住模板
var main_content_temp = _.template($('#main-content').html());
,然后向其中的参数提供值。
$('body').prepend(main_content_temp({
hello: polyglot.t('hello', {name: 'John'}),
unread: polyglot.t('unread', {smart_count: 2})
}));
以下是生成的代码:
main-polyglot.js
jQuery(document).ready(function() {
var polyglot = new Polyglot({
phrases: {
"hello": "Hello, %{name}!",
"unread": "You have %{smart_count} unread message |||| You have %{smart_count} unread messages"
}
});
var main_content_temp = _.template($('#main-content').html());
$('body').prepend(main_content_temp({
hello: polyglot.t('hello', {name: 'John'}),
unread: polyglot.t('unread', {smart_count: 2})
}));
});
加载HTML文档并测试它!
全球化
全球化是jQuery核心团队成员开发的一个相当大的国际化库。它在浏览器中工作(支撑所有现代浏览器和IE从版本9开始使用Node.js,提供了许多有用的特性,包括数字、日期和时间解析、多元化、内插、单元支持等等。它的使用为软件提供了关键的构建块,以支持世界上的语言,拥有最大和最广泛的地区数据标准存储库。更重要的是,全球化模块化并且不包含任何i18n数据--您可以自己加载它。
有三个主要的API函数:
Globalize.load()以JSON格式加载CLDR区域设置数据(例如日期和时间格式、月份名称等)
Globalize.locale()-为现场获取和设置
[new] Globalize-实例化一个新的Globalization对象
此外,您还可以为每个模块找到各种不同的功能。这里.
在实践中
让我们马上看看全球化的行动。复制index.html给它起个名字globalize.html。还创建全球化文件夹中的globalize-main.js文件在里面。只要全球化是模块化的,相依性必须按照正确的顺序加载(甚至有一个在线工具可以帮助您找出需要哪些依赖项)。
因此,您需要下载最新版本的全球化以及CLDR。以下是要抓取的Globalization文件列表(将它们放置在全球化(项目文件夹):
Dist/globalize.js
Dist/globalization/date.js
区域/全球化/编号.js
Dist/globalization/currency.js
Dist/globalization/message.js
Dist/globalization/Multial.js
不幸的是,这还不是全部。下面是必须放在里面的所需的CLDR文件cldr文件夹(立即创建):
Dist/cldr.js
Dist/cldr/event.js
DIST/cldr/addulal.js
哎呀。最后一部分是为cdr提供一些常见的地区数据-下载。这里并放置在cldr/cldr_data.js名字。最后,将所有这些文件按正确的顺序挂起:
globalize.html
[...]
<script src="common/jquery.js"></script>
<script src="cldr/cldr.js"></script>
<script src="cldr/event.js"></script>
<script src="cldr/supplemental.js"></script>
<script src="globalize/globalize.js"></script>
<script src="globalize/message.js"></script>
<script src="globalize/number.js"></script>
<script src="globalize/plural.js"></script>
<script src="globalize/currency.js"></script>
<script src="globalize/date.js"></script>
<script src="cldr/cldr_data.js"></script>
<script src="globalize/globalize-main.js"></script>
[...]
还为我们的内容添加了两个占位符:
globalize.html
[...]
<body>
<h1 id="welcome"></h1>
<p id="earnings"></p>
</body>
[...]
现在,让我们加载一条欢迎消息:
globalize-main.js
jQuery(document).ready(function() {
Globalize.loadMessages({
"en": {
'welcome': 'Welcome, {name}!'
}
});
});
这里我们使用的是消息格式化程序模块。接下来,实例化Globalization类。
var globalize = new Globalize("en");
并填充#welcome部分:
$('#welcome').text( globalize.messageFormatter('welcome')({name: 'John'}) );
请注意messageFormatter返回一个函数,然后调用该函数并传递包含名称的对象。这可以重写为
var welcome_message = globalize.messageFormatter('welcome');
$('#welcome').text( welcome_message({name: 'John'}) );
实际上,消息的参数不需要命名--您可能会说0, 1, 2等等:
'welcome': 'Welcome, {0}!'
在本例中,向格式化程序传递一个数组:
$('#welcome').text(globalize.messageFormatter('welcome')(['John']));
接下来,提供另一条包含今天和总收入的信息:
"en": {
'welcome': 'Welcome, {0}!',
'earned': 'Today is {date} and you\'ve earned {amount}!'
}
在本例中,我们将使用日期和货币格式化者:
$('#earnings').text(
globalize.messageFormatter('earned')({
amount: globalize.formatCurrency(500.5, 'USD'),
date: globalize.formatDate( new Date(), {
datetime: "medium"
})
})
)
在格式化货币时,我们传递USD作为第二个论点。此参数用于在呈现结果时显示适当的符号。符号本身定义在clrd_data.js档案:
"currencies": {
"USD": {
"symbol": "#34;
}
}
medium是datetime格式的名称-它也是在clrd_data.js文件为
"dateTimeFormats": {
"medium": "{1}, {0}"
}
这里1是日期和0是时候了。日期和时间依次使用下列掩码进行格式化:
"dateFormats": {
"medium": "MMM d, y"
},
"timeFormats": {
"medium": "h:mm:ss a"
}
现在一切都准备好了,您可以观察结果了!
PhraseApp再次拯救这一天
管理多种语言的翻译确实很乏味。然而,有了PhraseApp,整个过程就变得简单多了。
PhraseApp支持各种各样的格式,从简单到嵌套的JSON(以及AngularJS或Reaction的特定格式)。接下来,只需根据需要添加尽可能多的区域设置,并上传现有的带有翻译的JSON文件(如果有的话)。
完成之后,您将能够快速了解哪些翻译丢失,管理您的密钥和消息,以及下载更新的翻译,只需一次点击。更酷的是,您可以很容易地请求专业翻译人员的支持(这可能更好,因为本地化不仅仅是关于翻译)。因此,我真的鼓励您尝试一下PhraseApp!
结语
因此,在本文中,我们研究了各种帮助您本地化应用程序的解决方案:jQuery.I18n、Globalization和Polyglot。Polyglot似乎是最小和最简单的库,而Globalization和jQuery.I18n是相当大和复杂的--这取决于您选择哪一个!
希望您能发现这篇文章既有用又有趣。谢谢你和我在一起,快乐的编码!
为感谢您对我们的认可,特意准备了一些IT入门和进阶的干货
包括:Java、UI设计、H5前端、Python+人工智能、软件测试和新媒体运营六大学科视频资料。以及IT就业大礼包。
线上视频、音频,随时学习观看
关注我们并私信“资料”即可获取。