翻译与JavaScript

将翻译添加到JavaScript会引起一些问题:

  • JavaScript代码无法访问一个 gettext 的实现。

  • JavaScript 代码并不访问 .po或 .mo 文件;它们需要由服务器分发。

  • 针对JavaScript的翻译目录应尽量小。

Django已经提供了一个集成解决方案: 它会将翻译传递给JavaScript,因此就可以在JavaScript中调用 gettext 之类的代码。

javascript_catalog视图

这些问题的主要解决方案就是 javascript_catalog 视图。该视图生成一个JavaScript代码库,包括模仿 gettext 接口的函数,和翻译字符串的数组。 这些翻译字符串来自于你在info_dict或URl中指定的应用,工程或Django内核。

像这样使用:

  1. js_info_dict = {
  2. 'packages': ('your.app.package',),
  3. }
  4. urlpatterns = patterns('',
  5. (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
  6. )

packages 里的每个字符串应该是Python中的点分割的包的表达式形式(和在 INSTALLED_APPS 中的字符串相同的格式),而且应指向包含 locale 目录的包。 如果指定了多个包,所有的目录会合并成一个目录。 如果有用到来自不同应用程序的字符串的JavaScript,这种机制会很有帮助。

你可以动态使用视图,将包放在urlpatterns里:

  1. urlpatterns = patterns('',
  2. (r'^jsi18n/(?P<packages>\S+)/$', 'django.views.i18n.javascript_catalog'),
  3. )

这样的话,就可以在URL中指定由加号( + )分隔包名的包了。 如果页面使用来自不同应用程序的代码,且经常改变,还不想将其放在一个大的目录文件中,对于这些情况,显然这是很有用的。 出于安全考虑,这些值只能是 django.confINSTALLED_APPS 设置中的包。

使用JavaScript翻译目录

要使用这个目录,只要这样引入动态生成的脚本:

  1. <script type="text/javascript" src="/path/to/jsi18n/"></script>

这就是管理页面如何从服务器获取翻译目录。 当目录加载后,JavaScript代码就能通过标准的 gettext 接口进行访问:

  1. document.write(gettext('this is to be translated'));

也有一个ngettext接口:

  1. var object_cnt = 1 // or 0, or 2, or 3, ...
  2. s = ngettext('literal for the singular case',
  3. 'literal for the plural case', object_cnt);

甚至有一个字符串插入函数:

  1. function interpolate(fmt, obj, named);

插入句法是从Python借用的,所以interpolate 函数对位置和命名插入均提供支持:

位置插入 obj包括一个JavaScript数组对象,元素值在它们对应于fmt的占位符中以它们出现的相同次序顺序插值 。 例如:
  1. fmts = ngettext('There is %s object. Remaining: %s',
  2. 'There are %s objects. Remaining: %s', 11);
  3. s = interpolate(fmts, [11, 20]);
  4. // s is 'There are 11 objects. Remaining: 20'
命名插入 通过传送为真(TRUE)的布尔参数name来选择这个模式。 obj包括一个 JavaScript 对象或相关数组。 例如:
  1. d = {
  2. count: 10
  3. total: 50
  4. };
  5. fmts = ngettext('Total: %(total)s, there is %(count)s object',
  6. 'there are %(count)s of a total of %(total)s objects', d.count);
  7. s = interpolate(fmts, d, true);

但是,你不应重复编写字符串插值: 这还是JavaScript,所以这段代码不得不重复做正则表达式置换。 它不会和Python中的字符串插补一样快,因此只有真正需要的时候再使用它(例如,利用 ngettext 生成合适的复数形式)。

创建JavaScript翻译目录

你可以创建和更改翻译目录,就像其他

Django翻译目录一样,使用django-admin.py makemessages 工具。 唯一的差别是需要提供一个 -d djangojs 的参数,就像这样:

  1. django-admin.py makemessages -d djangojs -l de

这样来创建或更新JavaScript的德语翻译目录。 和普通的Django翻译目录一样,更新了翻译目录后,运行 compile-messages.py 即可。