跳转到主要内容
rli 提交于 5 July 2012

原文链接: http://drupal.org/node/304002

当您在开发一个模块时,您需要考虑到使您模块显示的部分能够被翻译成其他语言。这个过程的概论在多语言支持页面可以找到。

本页将会注重讨论翻译过程的第一步:是用户输入的内容能够被翻译。注意,如果用户所输入的信息都保存在node里,那么drupal的locale模块和Content Translation模块将会帮您翻译这些信息。但是如果您的模块使用户在非node的地方输入信息,而且这些信息将会被显示,那么您将需要继续阅读本章来找到翻译这些内容的方法。

核心模块中的Locale模块将支持其他语言的安装和默认语言的设计,导入和导出所用到语言文件(.pot, .po)是需要被外部软件应用和编辑的。请参看locale的手册页面http://drupal.org/handbook/modules/locale

Drupal7

我们先讨论drupal7。储存在数据库中的用户所输入的字符串可能被能够修改数据库命令的第三方模块所翻译。要想为这些可被翻译的字符串在您的模块中准备储存空间,您需要按照一下的步骤:

  • 重写数据库命令可以帮助翻译内容。所以,要翻译的内容必须储存在专门的数据库表格里,而且不能是以压缩格式的数组形式储存。
  • 在您的hook_schema中,设置元素: 'translatable' => TRUE,block.install中的例子: function block_schema() { $schema['block'] = array( // ... 'title' => array( 'type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => '', 'description' => 'Custom title for the block. (Empty string will use block default title, will remove the title, text will cause block to use specified title.)', 'translatable' => TRUE, ),
  • 在获得数据是,使用db_select()方法,而不是db_query()方法。然后添加‘translatable‘命令标识: ->addTag('translatable')这将会启动命令修改。下面是从block.module中来的例子: $query = db_select('block', 'b'); ->fields('b') ->condition('b.theme', $theme_key) ->condition('b.status', 1) ->orderBy('b.region') ->orderBy('b.weight') ->orderBy('b.module') ->addTag('block_load') ->addTag('translatable') ->execute(); 默认情况下drupal核心模块将不会翻译这些内容。所有的翻译,储存,编辑都将留给第三方模块。

Drupal6

在Drupal6中,locale模块可以翻译同种类的数据。Drupal核心模块包含了对核心模块代码中定义的字符串的支持。而其他第三方模块可以通过hook_implement来注册它们自己的数据类型。

第三方的多语言包提供扩展功能,使hook_locale()能够翻译更多的数据类型,比如taxonomies,variables, forums, 用户资料等等。i18n还包括一个通用的多语言的字符串模块。它能够提供一个工具包,这样模块的作者们就可以通过locale系统来输出该模块的数据了。

locale系统更适用于那些不需要经常要改动的数据,而不适用于那些经常要被更新的数据。

locale系统的特点在于,对于所给条目只有一个版本。字符串的替换发生在运行的时候,比如,在显示内容之前。这是locale系统和内容翻译系统的最大区别。内容翻译系统对每一条内容都有多个版本,基于每种语言。

模块开发者可以通过下面机充选择来通过locale系统把他们的数据变成可被翻译的:

  • 直接与locale系统来工作
  • 基于Internationalization的开发--字符串翻译模块和其API的使用。
  • 对指定条目引进多版本控制,每个语言一个版本。

上面每一条都会在下面的章节里详细解释。

一些窍门

下面是一些在与locale和语言工作过程中比较使用的方法:

直接与locale系统工作

如果想要注册一个或多个新的(字符串的类型)从而使locale系统来识别它们,您需要执行hook_locale()。但是,除了这个hook,locale模块并没有提供其他的帮助。

locale系统还在着重于默认的情况(代码中通过t()方法传入的字符串)。locale()方法被编写来适用这个情况。对locale()方法的研究也许会有帮助,虽然它并不能直接帮助您开发自己的locale group类型。当字符串被注册,locale系统将提供一个UI来翻译这个字符串, 但是,当它完成对字符串的注册,并确保字符串会被应用时,您基本上就不会从locale系统得到任何帮助了。因此,在模块中注意按照i18n标准建立字符串将帮助您反正这个任务。

要想直接与locale系统工作,您需要:

  • 把源代码中的字符串存放到locale_source表格中。
  • 当已有的翻译已经更改,及时更新它。
  • 为当前语言从locale_target表格中选取可使用的字符串。

与Internationalization工作-字符串翻译模块

应用Internationalization模块的API来进行字符串翻译的步骤入下:

  • 执行hook_locale来为您的模块定义一个翻译组。比如您也许需要用"terms_of_use"在作为Terms of Use模块的翻译组。下面会有完整的例子。
  • 确保字符串翻译模块已经被安装了,再激活该模块。用下面的代码来判断: if (module_exists('i18nstrings')) { }
  • 找到您模块中, 要显示用户数入的信息的地方,确保设置输入与本站点默认的语言。或者告诉UI如何来用字符串翻译模块来翻译字符串。
  • 付给每个字符串一个机器名,并与你模块的翻译组名保持一致性。在您模块内的部分赋予下属翻译小组的机器名, 然后是字符串名,并用冒号隔开。(比如"terms_of_use:tou:checkbox_label"可以用在Terms of Use模块的tou页面里面的checkbox)
  • 无论何时,只要用户更新了字符串,调用tt()方法来获取当前的翻译。比如: // First store the text in variable_set() or a database table. Then: if (module_exists('i18nstrings')) { $language = language_default('language'); tt('terms_of_use:tou:checkbox_label', $text_user_entered, $language, TRUE); }
  • 无论合适,当您要显示一个用户输入的内容,调用tt()方法来获取当前的翻译。比如: // First retrieve the text from variable_get or a database table. Then: if (module_exists('i18nstrings')) { $text_to_display = tt('terms_of_use:tou:checkbox_label', $text_to_display); }
  • 在您执行的hook_locale()里添加一个刷新动作,这样能获取数据库中未翻译的内容,然后调用tt()方法。比如: function terms_of_use_locale($op = 'groups', $group = NULL) { switch ($op) { case 'groups': return array('terms_of_use' => t('Terms of Use')); case 'refresh': if(module_exists('i18nstrings')) { // Get the checkbox label from the database or from variable_get first. Then: tt('terms_of_use:tou:checkbox_label', $label_text, NULL, TRUE); } } }

提供第三方多语言支持

当遇到复杂的冗长的或者频繁更新的字符串,第三方的支持是被需要的

  • 在您的数据库表格中添加一个language字段
  • 在编辑表单中,显示一个语言显示元素,参看locale_form_alter()
  • 插入和更新数据库表格时,存储language表单的数据
  • 当显示数据时,用适当的语言显示您的数据。(用全局的language变量)
  • 在显示数据时,提供一个类似于"翻译"的链接,然后输出一个待翻译数据的表单转被翻译。