國際化(譯者註:即Internationalization,因為這個單字I 和n 之間有18個字母,因此常縮寫為I18N) 是指設計一種應用軟體的過程,這種軟體無需做大的工程改變就能適應不同的語言和地區的需要。 對 Web 應用來說,國際化尤其重要,因為潛在的使用者可能來自世界的各個角落。
Yii 在若干方面提供了對 I18N 的支援
它為每種可能的語言和變數提供了本地化資料。
它提了供資訊和文件的翻譯服務。
它提供了基於本地化的日期和時間格式。
它提供了基於本地話的數字格式。
在下面的小節中,我們將對以上幾個方面進行詳細說明。
區域是一系列參數,它定義了使用者的語言、使用者所在國家以及使用者所有想要在他們的介面中看到的特殊參數。 它通常由一個包含了語言 ID 和區域 ID 的 ID 來識別。例如, ID en_US
表示英語區域和美國。 為維持一致性,Yii 中所有的區域 ID 被規範為小寫的 語言 ID
或 語言 ID_地區 ID
(例如 en
, en_us
)。
區域資料由一個 CLocale 實例表示。它提供了基於區域的信息,包括貨幣符號,數字符號, 日期和時間格式以及日期相關的名稱。由於語言資訊已經由區域 ID 實現,因此 CLocale 不再提供。 同理,我們通常會變換地使用字詞「區域」和「語言」。
透過一個區域 ID,就可以透過 CLocale::getInstance($localeID)
或CApplication::getLocale($localeID)
取得對應的 CLocale 實例。
資訊: Yii 幾乎包含所有語言和區域的區域化資料。 這些數據來自於 Common Locale Data Repository(CLDR)。在每個區域中, 只提供了 CLDR 中的部分數據,因為原始的 CLDR 數據中包含了大量不太常用的資訊。從版本 1.1.0 起, 使用者也可以使用他們自訂的區域資料。只需要配置CApplication::localeDataPath 屬性為包含了自訂區域資料的目錄即可。 請參考位於
framework/i18n/data
目錄中的檔案建立自訂的區域資料檔案。
在一個 Yii 應用程式中,我們區分了它的 目標語言(target language) 和 來源語言(source language)。目標語言是應用程式的目標使用者的語言(區域), 而原始語言是指寫在應用程式原始碼中的語言(區域)。國際化只會在這兩種語言不同的情況下發生。
你可以設定 應用設定 中的 目標語言 ,或是在發生國際化之前動態設定此參數。
提示: 有時候,我們想要設定目標語言為使用者所使用的語言(就是在使用者的瀏覽器選項中指定的語言)。 只需使用 CHttpRequest::preferredLanguage 就可以取得到使用者設定的語言。
在 I18N 中用到的最多的可能就是翻譯了,包括 資訊翻譯 和 視圖翻譯。 前者將一則文字訊息翻譯為期望的語言,後者將整合文件翻譯為期望的語言。
一個翻譯請求包含要被翻譯的對象,對象所使用的源語言,和對象所需要翻譯到的目標語言。 在 Yii 中,原始語言預設為 應用程式原始語言 而目標語言預設為 應用程式語言。 如果兩者語言相同,翻譯將不會發生。
訊息翻譯是透過呼叫 Yii::t() 來實現的。此方法會將訊息從 源語言 翻譯為 目標語言。
當翻譯一條訊息時,必須指定它的分類(category),因為一條訊息在不同的分類或上下文中可能會有 不同的翻譯。分類 yii
保留為僅限 Yii 框架核心使用。
資訊可以包含參數佔位符,它們將會在呼叫 Yii::t() 時被實際的參數值取代。 例如,以下的資訊翻譯請求將會取代原始資訊中的 {alias}
佔位符為實際的別名(alias) 值。
Yii::t('app', 'Path alias "{alias}" is redefined.', array('{alias}'=>$alias))
注意: 要翻譯的資訊必須是常數字串。它們不能包含可能會改變訊息內容的變數 (例如
"Invalid {$message} content."
)。如果一則訊息需要透過一些參數改變,請使用 參數佔位符。
翻译过的信息会存储在一个叫做 信息源(message source) 的库中。 信息源是一个 CMessageSource 或其子类的实例。当 Yii::t() 被调用时, 它将从信息源中查找相应的信息,如果找到了,就会返回翻译后的版本。
Yii 含有如下几种信息源。你也可以扩展 CMessageSource 创建自己的信息源类型。
CPhpMessageSource: 信息的翻译存储在一个 PHP 的 键值对 数组中。 原始信息为键,翻译后的信息为值。每个数组表示一个特定信息分类的翻译,分别存储在不同的 PHP 脚本文件中,文件名即分类名。 针对同一种语言的 PHP 翻译文件存储在同一个以区域 ID 命名的目录中。而所有的这些目录位于 basePath 指定的目录中。
CGettextMessageSource: 信息的翻译存储在 GNU Gettext 文件中。
CDbMessageSource: 信息的翻译存储在数据库的表中。
信息源是作为一个 应用程序组件 载入的。 Yii 预定义了一个名为 messages 的应用程序组件以存储用户程序中用到的信息。 默认情况下,此信息源的类型是 CPhpMessageSource ,而存储这些 PHP 翻译文件的目录是protected/messages
。
总体来说,要实现信息翻译,需要执行如下几步:
在合适的位置调用 Yii::t() ;
以 protected/messages/LocaleID/CategoryName.php
的格式创建 PHP 翻译文件。 每个文件简单的返回一个信息翻译数组。 注意,这是假设你使用默认的 CPhpMessageSource 存储翻译信息。
配置 CApplication::sourceLanguage 和 CApplication::language。
提示: 使用 CPhpMessageSource 作为信息源时,Yii 中的
yiic
工具可用于管理信息翻译。 它的message
命令可以自动从所选的源文件中提取要翻译的信息,并在需要时将其合并为现存的翻译。 关于使用message
命令的更多信息,请执行yiic help message
。
从版本 1.0.10 起,当使用 CPhpMessageSource 管理信息源时, 扩展类(例如一个 widget 小物件,一个模块)中的信息可以以一种特殊的方式管理并使用。 具体来说,如果一条信息属于一个类名为 Xyz
的扩展,那么分类的名字可以以 Xyz.categoryName
的格式指定。 相应的信息文件就是BasePath/messages/LanguageID/categoryName.php
,其中 BasePath
是指包含此扩展类文件的那个目录。 当使用 Yii::t()
翻译一条扩展信息时,需要使用如下格式:
Yii::t('Xyz.categoryName', '要翻译的信息');
从 1.0.2 起,Yi 添加了对 choice format 的支持。Choice format 是指选择按照一个给定数字的值选择一条翻译。例如,在英语中,视不同的数量,单词 'book' 可以有一个单数形式或者一个复数形式。而在其他语言中, 这个词可能就没有不同的形式(例如汉语)或者有更复杂的复数规则(例如俄语)。 Choice format 以一种简单而又高效的方式解决了这个问题。
要使用 choice format,翻译的信息必须包含一个由 |
分割的 “表达式-信息” 对序列。如下所示:
'expr1#message1|expr2#message2|expr3#message3'
其中 exprN
表示一个有效的 PHP 表达式,它会计算出一个布尔型的值,以确定相应的信息是否应该被返回。 只有第一个返回值为 true 的表达式对应的信息会被返回。 一个表达式可以包含一个特殊的变量 n
(注意,它不是$n
),它带有通过第一个信息参数传递的数字的值。 例如,假设有如下一条翻译信息:
'n==1#one book|n>1#many books'
而我们在调用 Yii::t() 时在参数数组中传递了数字值 2 , 我们就会得到 many books
作为最终的翻译信息。
作为一种简便写法,如果一个表达式是一个数字,它将被视为等同于 n==Number
。因此,上面的翻译信息也可以写为如下格式:
'1#one book|n>1#many books'
檔案翻譯是透過呼叫 CApplication::findLocalizedFile() 完成的。 給定一個要翻譯的檔案的路徑,此方法就會在區域 ID
子目錄中尋找相同檔案名稱的檔案。 如果找到了,就會返回此文件的路徑;否則,將返回原始文件的路徑。
檔案翻譯主要用於渲染一個視圖。 當在控制器或小對像中呼叫任一渲染方法時,視圖檔案將會自動翻譯。例如,若 目標語言 是 zh_cn
而 來源語言 是 en_us
,而渲染一個名為 edit
的視圖時,程式將會尋找protected/views/Controller 如果此檔案找到,就會透過此翻譯版本渲染。否則,就會使用檔案
protected/views/ControllerID/edit.php 渲染。
$dateFormatter->format('yyyy-MM-dd',$timestamp))。
short 格式,時間的
long 格式)。
$numberFormatter->format(' #,##0.00',$number))。