Translation组件

安装 

你可以通过下述两种方式安装:

然后,包容vendor/autoload.php文件,以开启Composer提供的自动加载机制。否则,你的程序将无法找到这个Symfony组件的类。

构建Translator 

Translation组件的主要入口点是 Translator。在使用它之前,你需要配置它并加载待译信息 (被称作 message catalogs)。

译注:message catalog

其实就是用于翻译的源文件,但是按字面意思,译为“信息目录”。Symfony Translation相关文档中的所谓信息(message),是指待译的词汇条目,它们是xml规格的数据,一条一条地罗列而成,真的很像目录。官方推荐使用国际通用 xliff 文件(ng2前端翻译组件也转而使用这种格式)。因此文中的“信息目录”,就理解为那个xliff文件中的内容即可。

配置 

Translator 类的构造器需要一个参数: locale。

1
2
3
4
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\MessageSelector;
 
$translator = new Translator('fr_FR', new MessageSelector());

这里的locale设置,用的是默认locale。在翻译字符串时,你可以覆写这个locale。

locale 一词简单来说就是指用户的语言和国家。它可以是任意字符串,被你的程序用来管理翻译和其他的格式差异(比如货币格式)的。推荐的格式是,ISO 639-1 language 码,一个下划线 (_),然后是 ISO 3166-1 alpha-2 country 码(比如,对于French/France,locale就是 fr_FR)。

加载Message Catalogs 

(用于翻译的)信息(message)被存放于 Translator 类中的信息目录中。一个信息目录,对于一种特定语言来说,就好像一本翻译字典。

Translation组件使用了loader类来加载目录。你可以加载同一locale的多个资源,它们会在后面被合并成一个目录。

组件内置了一些默认的加载器,你也可以创建自己的加载器。默认的loader是:

所有的文件加载器都需要 Config组件

你也可以 创建你自己的Loader,如果文件格式不被默认加载器所支持的话。

首先,你应该添加一个或多个加载器到 Translator:

1
2
// ...
$translator->addLoader('array', new ArrayLoader());

第一个参数,是你要引用的translator中的加载器名字,第二个参数是loader自身的实例。之后,你就可以利用正确的加载器来添加你的资源了。

用ArrayLoader加载Messages 

调用 addResource() 可以完成信息的加载。第一个参数是loader名称(也就是 addLoader() 方法的第一个参数),第二个参数是resource(翻译源),第三个参数是locale:

1
2
3
4
// ...
$translator->addResource('array', array(
    'Hello World!' => 'Bonjour',
), 'fr_FR');

用FileLoader加载Messages 

如果你使用了某一种文件加载器,你应该使用 addResource 方法。唯一的区别是,你要把源文件的文件名作为第二个参数传入,而不是传一个数组:

1
2
3
// ...
$translator->addLoader('yaml', new YamlFileLoader());
$translator->addResource('yaml', 'path/to/messages.fr.yml', 'fr_FR');

翻译的过程 

真正去翻译信息(message)时,Translator使用的是一个简单流程:

  • locale (如 fr_FR) 所定义的翻译源中加载一个信息目录。如果它们不存在,Fallback Locales 的信息会被加载到这个目录中。最终结果,是一个巨大的翻译"字典";
  • 如果能从目录中找到信息,则翻译(结果)会被返回。否则,translator返回的是原始信息。

通过调用 trans()transChoice(),你可以启动翻译进程。接下来,Translator在合适的信息目录中寻找正确的字符串并返回它(如果存在的话)。

Locales回滚 

如果信息在特定locale的目录中没有被找到,translator将去一或多个回滚的locale的目录中继续查找。例如,假设你尝试(把信息)翻译成 fr_FR locale:

  1. 首先,translator 在 fr_FR locale 中寻找翻译(的信息目录);
  2. 如果没找到,translator 会在 fr locale 中寻找翻译信息;
  3. 如果仍然找不到,translator 会使用一或多个“显式地设定在translator中”的 fallback locales。

对于第(3)点,fallback locales 可以通过调用 setFallbackLocales() 来设置:

1
2
// ...
$translator->setFallbackLocales(array('en'));

使用Message Domains 

如你所见,信息文件被组织在“它们要翻译(成)”的不同的locale中。同时,信息文件还可以被进一步地组织到“domain”中。(译注:翻译域)。

域(domain),是 addResource() 方法的第四个参数。默认的域就是 messages。例如,假设为了便于组织,翻译信息被分割到三个不同的域中: messages, adminnavigation。法语的翻译会像下面这样加载:

1
2
3
4
5
6
7
8
9
10
11
// ...
$translator->addLoader('xlf', new XliffFileLoader());
 
$translator->addResource('xlf', 'messages.fr.xlf', 'fr_FR');
$translator->addResource('xlf', 'admin.fr.xlf', 'fr_FR', 'admin');
$translator->addResource(
    'xlf',
    'navigation.fr.xlf',
    'fr_FR',
    'navigation'
);

当翻译(信息)的字符串无法在默认的域 (messages) 中找到时,你必须指定一个域作为 trans() 的第三个参数:

1
$translator->trans('Symfony is great', array(), 'admin');

Symfony 现在会去指定locale的 admin 域来寻找翻译信息。

用法 

阅读 使用Translator 以了解如何使用Translation组件。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)