这是 Mozilla 身份团队的“节点.JS 假期季系列”的第 11 集,共 12 集。这是关于本地化的最后一部分,希望让你对处理本地化工作感到信心满满!
使用我们的字符串
所以,我们首先将 i18n-abide 模块添加到我们的代码中,然后我们的 本地化 (L10n) 团队进行了一些字符串整理,现在我们有了多个语言环境,包含翻译后的字符串……
让我们准备好这些字符串,用于节点.js 并看看这个小家伙的运行情况!
下一步是,我们需要你的 PO 文件,通常在这样的文件系统中
locale
en
LC_MESSAGES
messages.po
de
LC_MESSAGES
messages.po
es
LC_MESSAGES
messages.po
我们需要一种方法,在运行时将字符串从我们的 PO 文件获取到我们的应用程序中。您可以通过多种方法来实现
- 拥有 **服务器端字符串**,并且 i18n-abide 提供的
gettext
函数将发挥其魔力。 - 拥有 **客户端字符串**,你将在代码中包含一个 gettext.js 脚本。它与 i18n-abide 一起发布。
**这两种方法都需要** 将字符串以 **JSON** 文件格式存储。
服务器端翻译在应用程序启动时加载它们,而客户端翻译通过 HTTP 加载它们(或者您可以将它们放入构建并缩小的 JavaScript 中)。
由于此系统与 GNU Gettext 兼容,因此服务器端字符串的第三种选择是使用 node-gettext。它在进行服务器端翻译方面非常有效。
在本博文中,我们将使用第一个选项,因为它是最常见的 i18n-abide 使用方法。
compile-json
那么,我们如何将字符串从 PO 文件获取到 JSON 文件中呢?
我们的构建脚本称为 compile-json
。
假设我们的文件位于项目顶层目录 locale
中,并且我们希望 .json
文件放到 static/i18n
中,我们会这样做
示例
$ mkdir -p static/i18n
$ ./node_modules/.bin/compile-json locale static/i18n
我们获得的文件结构如下
static
i18n
en
messages.json
messages.js
de
messages.json
messages.js
es
messages.json
messages.js
compile-json
遍历每个 .po
文件并对其调用 po2json.js
,生成 .json
和 .js
文件。po2json.js
是 i18n-abide 提供的另一个程序。
如果我们从这些博文中获得迄今为止的西班牙语 messages.po,我们会看到
# Spanish translations for PACKAGE package.
# Copyright (C) 2013 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Austin King <ozten@localhost>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSIONn"
"Report-Msgid-Bugs-To: n"
"POT-Creation-Date: 2012-06-24 09:50+0200n"
"PO-Revision-Date: 2013-04-24 16:42-0700n"
"Last-Translator: Austin King <ozten@nutria.localdomain>n"
"Language-Team: Spanishn"
"Language: esn"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=UTF-8n"
"Content-Transfer-Encoding: 8bitn"
"Plural-Forms: nplurals=2; plural=(n != 1);n"
#: /home/ozten/abide-demo/views/homepage.ejs:3
msgid "Mozilla Persona"
msgstr "Mozilla Personidada"
它将被转换为
messages": {
"": {
"Project-Id-Version": " PACKAGE VERSIONnReport-Msgid-Bugs-To: nPOT-Creation-Date: 2012-06-24 09:50+0200nPO-Revision-Date: 2013-04-24 16:42-0700nLast-Translator: Austin King <ozten@nutria.localdomain>nLanguage-Team: GermannLanguage: denMIME-Version: 1.0nContent-Type: text/plain; charset=UTF-8nContent-Transfer-Encoding: 8bitnPlural-Forms: nplurals=2; plural=(n != 1);n"
},
"Mozilla Persona": [
null,
"Mozilla Personidada"
]
}
}
因此,我们可以从 Node 代码中的服务器端使用这些 .json 文件,或者通过 AJAX 请求它们,在客户端使用它们。
static
目录公开给网页流量,因此对 /i18n/es/messages.json
的请求将获得西班牙语 JSON 文件。
此 static
目录是 express 约定,你可以将这些文件存储在你希望的任何位置。你可以通过节点.js 或诸如 nginx
之类的网页服务器来提供静态文件。
注意: 你 **不需要** 将 .PO 文件 **部署到生产环境**,但将其一起发布并没有什么坏处。
配置
i18n-abide
需要一些配置,以确定支持哪些语言以及在哪里找到我们的 JSON 文件。
正如我们在 第一期中看到的那样,以下是我们的应用程序所需的配置
app.use(i18n.abide({
supported_languages: ['en-US', 'de', 'es', 'zh-TW'],
default_lang: 'en-US',
translation_directory: 'static/i18n'
}));
supported_languages
告诉应用程序它支持英语、德语、西班牙语、中文(繁体)。translation_directory
配置表示翻译后的 JSON 文件位于 static/i18n 下。- 请注意,
translation_directory
仅适用于 **服务器端** gettext。
我们在第一篇文章中解释过,i18n-abide 将尽力提供合适的本地化字符串。
它将查看配置中的 supported_languages
,以找到最佳语言匹配。
你只应将你准备好的语言环境 JSON 文件的语言添加到 supported_languages
中。
启动引擎
好了,现在配置到位,并且至少有一个语言环境已翻译,让我们启动它!
npm start
在你的网页浏览器中,将你的首选语言更改为你已本地化的语言。
现在加载应用程序的页面。你应该看到它现在已被翻译了。
对于真实世界的示例,以下是 **希腊语** 的 Mozilla Persona。太酷了!
乱码
如果你想 **测试** 你的 L10n 设置,**在你完成真正的翻译** 之前,我们已经构建了一个很棒的测试语言环境。它受 大卫·鲍伊的迷宫 启发。
要使用它,只需将 it-CH
或你目前未使用的其他语言环境添加到你的配置中的 **supported_languages
** 和 **debug_lang** 设置下。
示例*部分*配置
app.use(i18n.abide({
supported_languages: ['en-US', 'de', 'es', 'zh-TW', 'it-CH'],
debug_lang: 'it-CH',
...
现在,如果你将浏览器的首选语言设置为意大利语/瑞士语 (it-CH),i18n-abide 将使用乱码来本地化内容。
这是一种方便的方法,可以确保你的视觉设计和散文适用于希伯来语等双向语言。你的网页设计师可以在你拥有资源创建实际的希伯来语字符串之前,测试他们的 RTL CSS。
深入探讨
我们只是触及了 i18n 和 l10n 的表面。如果你以多种语言环境发布基于节点.js 的服务,你将会遇到许多问题和有趣的细微差别。
以下是一些其他主题的提示。
字符串插值
i18n-abide 提供了一个 format
函数,它可以在客户端或服务器端的 JavaScript 代码中使用。
Format 接收一个格式化字符串,并在运行时将参数替换为实际值。此函数可以在两种参数替换风格中使用。
格式
- %s –
format
被调用时带有一个格式化字符串,然后是一个字符串数组。每个字符串将按顺序被替换。 - %(named)s –
format
被调用时带有一个格式化字符串,然后是一个对象,其中键与命名参数匹配。
你可以使用 format
将字符串中的 HTML 最小化。
考虑以下三个示例
<%= gettext('Buy Blue Tickets Now!
') %>
<%= format(gettext('Buy Blue Tickets Now!'), ['/buy?prod=blue&tyep=ticket']) %>
<%= format(gettext('Buy Blue Tickets Now!'), {url: '/buy?prod=blue&tyep=ticket'}) %>
在 PO 文件中,它们生成以下字符串
Buy Blue Tickets Now!
"
msgid "Buy Blue Tickets Now!"
msgid "Buy Blue Tickets Now!"
第一个示例有一个段落标签,它出现在 PO 文件中。太糟糕了。如果你更改了标记……你可能需要在每个语言环境中更新它!
此外,看看那个难看的 URL。
使用 format
的原因
- 避免让不熟悉 HTML 的本地化人员感到困惑,他们可能会意外地破坏你的代码
- 避免维护问题
命名参数很不错,因为它们是自文档的。本地化人员知道该变量是一个 URL。字符串插值在软件本地化中很常见。
另一个示例是注入到字符串中的运行时数据。
<%= format(gettext('Welcome back, %(user_name)s'), {user_name: user.name}) %>
避免不灵活的设计
我们需要尽早戴上 L10n 帽子。从我们审核网站的初始图形设计时就开始。
-
避免将文本放入图像中。使用 CSS 将单词作为纯文本定位在图像上。
-
确保 CSS 是防弹的。德语中的一个英语单词可能会大很多倍,并破坏一个
计划不周的设计。 -
试试这个书签:Fauxgermanhausen das Pagen!
基于数据库的网站已经教会我们以系统的方式思考设计,但设计师可能不习惯允许可变长度的标签或按钮。
字符串冻结
还记得我们为本地化人员准备翻译文件而进行的构建步骤吗?在本博文中,我们了解了 po2json.js
,用于在我们的应用程序中使用这些字符串…… 好吧,这意味着我们需要协调我们的软件发布与 L10n 社区。
连续部署在 L10n 中还没有解决。要么你必须在部署之前等待 100%
的字符串翻译完成,要么你必须接受在某些语言环境中使用部分翻译的应用程序。
L10n 团队可能需要 1、2 甚至 3 周时间来本地化你的应用程序,具体取决于字符串的数量。安排在 QA 周期内进行。
提供一个实时预览网站,以便本地化人员可以检查他们的工作。
总结
在这三篇博文中,我们了解了如何使用 i18n-abide
开发本地化应用程序,如何将 L10n 阶段添加到我们的发布构建中,最后是如何测试我们的工作。
本地化你的网站或应用程序将使你的网站对全球更多受众更有价值。
节点.js 黑客们,去让你们的服务为全世界所用!
系列中的前几篇文章
这是 关于节点.js 的共 12 篇帖子的系列的第十一部分。前面的文章是
- 追踪节点.js 中的内存泄漏
- 全负荷节点
- 使用安全的客户端会话构建简单且可扩展的节点.JS 应用程序
- 出色的前端性能,第一部分 - 连接、压缩和缓存
- 构建不会熔化的节点.JS 服务器
- 出色的前端性能,第二部分:使用 etagify 缓存动态内容
- 使用 node-convict 驯服配置
- 出色的前端性能,第三部分 - 通过优化字体获得巨大的性能提升
- 本地化你的节点.js 服务,3/1
- 本地化社区、工具和流程,3/2
关于 Austin King
西雅图非教条主义艺术家/程序员类型人类。应用程序工程团队的无赖网页开发者。拼写检查是针对一周的。
关于 Robert Nyman [编辑名誉退休]
Mozilla Hacks 的技术布道者和编辑。他做演讲和写博客,主题是 HTML5、JavaScript 和开放网络。Robert 是 HTML5 和开放网络的坚定支持者,从 1999 年起就在瑞典和纽约市从事网络前端开发。他还定期在 http://robertnyman.com 上写博客,喜欢旅行和结识新朋友。
5 条评论