覆盖 gettext .mo 文件
对于应用程序中的翻译,我们使用 Zend Translate 和 gettext 适配器。每个模块中都有一个文件夹 translations
,其中包含所有语言的 .mo 文件;
- da.mo
- nl.mo
- en.mo
通过 addTranslation()
方法扫描并添加:
if ( is_dir( $translations_dir ) ) {
foreach ( new DirectoryIterator( $translations_dir ) as $file ) {
if ( substr( $file, -3 ) == '.mo' ) {
$ZendTranslate->addTranslation( $file->getPathname(), $file->getBasename('.mo') );
}
}
}
我的应用程序中的字符串使用 _()
方法进行翻译,传递当前语言作为参数(它存储在我的框架的语言类中):
$ZendTranslate->_( $string, $this->language );
现在我需要为特定客户自定义荷兰语 (nl) 语言字符串。我不想修改 nl.mo
文件,因为这会影响其他客户。因此,我创建了一个名为 nl_kpn.mo
的文件(kpn 是客户名称),并将 $this->language
切换为“nl_kpn”。我希望 Zend Transate 将 nl.mo
作为基本文件,覆盖 nl_kpn.mo
中找到的自定义字符串。但不幸的是,正如手册所述,我经历了:
fr_CH 将降级为 fr
因此,即使 $this->language
设置为“nl_kpn”,所有字符串仍来自 nl.mo
文件。那么如何创建一种更具体的语言版本,覆盖通用语言中的字符串呢?一定有可能吧?因为还有 en_UK 和 en_US,它们是同一语言的不同“方言”。
For translations in our application, we're using Zend Translate with the gettext adapter. In each module is a folder translations
, containing .mo files for all the languages;
- da.mo
- nl.mo
- en.mo
Which are scanned and added through the addTranslation()
method:
if ( is_dir( $translations_dir ) ) {
foreach ( new DirectoryIterator( $translations_dir ) as $file ) {
if ( substr( $file, -3 ) == '.mo' ) {
$ZendTranslate->addTranslation( $file->getPathname(), $file->getBasename('.mo') );
}
}
}
The strings in my application are translated using the _()
method, passing the current language as a parameter (it's stored in my framework's Language class):
$ZendTranslate->_( $string, $this->language );
Now I need to customize the Dutch (nl) language strings for a specific customer. I don't want to modify the nl.mo
file, as that would affect other customers. So I created a file called nl_kpn.mo
(kpn is the customer name), and switched the $this->language
to 'nl_kpn'. I was hoping Zend Transate would take nl.mo
as the base file, overriding the customized strings found in nl_kpn.mo
. But unfortunately I experienced, as the manual states:
fr_CH will be downgraded to fr
So all the strings were still from the nl.mo
file, even though $this->language
was set to 'nl_kpn'. So how can I create a more specific version of a language, overriding strings from the general one? It must be possible, right? Because there's also en_UK and en_US, which are different 'dialects' of the same language.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我想答案就是这是不可能的。语言环境必须是现有的语言/方言,并使用 Zend_Locale 中的列表进行验证:
我想我只需要设计一种不同的方法来覆盖文件。也许只是从 PHP 加载不同的
.po
文件。I think the answer is just this is not possible. The locale has to be an existing language/dialect, and is validated with the list in
Zend_Locale
:I guess I'll just have to devise a different way to override the files. Maybe just loading in a different
.po
file from PHP.正如 Rijk 所说,Zend_Translate 将尝试调用 Zend_Locale,但它根本不存在。不幸的是,列表已设置为私有,因此我们可能无法使用继承来简单地派生我们自己的实现。
但是,您有两个选择。根据您的设置,您可以通过在配置中提供不同的目录来为此特定客户设置您自己的
nl.mo
文件。这样,您就可以链接所有其他语言文件,并为 kpn 客户端创建一个单独的语言文件。第二个选择是摆脱 Zend_Translate 并使用默认的 php gettext 。由于您已经在使用 gettext-files 并且似乎使用了
translate()
函数,因此除了将 $ZendTranslate 重构为 gettext-class 之外,您不需要做更多的工作。如果您确实在其他类中自动使用 Zend_Translate(例如在 Zend_Navigation 中),则可以保持它们不变。虽然第二个选项确实有效,但它有点混乱 - 然而,第三个干净的替代方案是继承 Zend_Locale 并重写所有访问私有语言列表的方法。这样,您就可以添加自己的。或者您甚至可以重写 Zend_Locale 的部分内容以支持动态添加语言并发送补丁文件 - 这样,我们也可以从您的工作中受益。 ;)
As Rijk said, Zend_Translate will try to invoke a Zend_Locale, which simply does not exist. Unfortunatly, the listing has been set to private, so we may not use inheritance to simply derive our own implementation.
However, you have two options. Depending on your setup, you may just set your own
nl.mo
-file for this specific customer by providing a different directory in the configuration. That way, you may link all other language-files and have a separate one for the kpn-client.The second option you have is to get rid of Zend_Translate and use the default php gettext. As you are already using gettext-files and seem to use the
translate()
-function, you would not have any more work than to refactor $ZendTranslate to your gettext-class. If you do use Zend_Translate automatically in other classes (e.g. in Zend_Navigation), you can just leave those intact.While the 2nd option does work, it is a bit messy - however, the third and clean alternative is to inherit Zend_Locale and rewriting all methods accessing the private language list. That way, you can add your own. Or you even go the lenghts of rewriting the parts of Zend_Locale to support dynamical adding of languages and send a patch file in - that way, we may benefit from your work, too. ;)
您可以尝试从 Zend_Translate_Adapter 重写 _() 方法并检查文件名:
you can try to override _() method from Zend_Translate_Adapter and check file name :
我认为最好的方法是使用 isTranslated 方法。您可以
isTranslated ($messageId, $original = false, $locale = null)
将您要检查的文本作为其第一个参数,以及作为可选的第三个参数,您要检查的区域设置。可选的第二个参数声明翻译是固定为声明的语言还是可以使用较低的翻译集。如果您有一个可以为“en”返回但不能为“en_US”返回的文本,您通常会得到返回的翻译,但通过将 $original 设置为 true,isTranslated() 将返回 false。
这对你有用吗?
I think that the best way to do this is using the isTranslated method. You can do
isTranslated ($messageId, $original = false, $locale = null)
takes the text you want to check as its first parameter, and as optional third parameter the locale for which you want to do the check. The optional second parameter declares whether translation is fixed to the declared language or a lower set of translations can be used. If you have a text which can be returned for 'en' but not for 'en_US' you will normally get the translation returned, but by setting $original to true, isTranslated() will return false.
Does this works for you?