15

我一直在寻找国际化开源项目的选项:

  • 似乎每个人都推荐的 Gettext 显然需要“安装在您的系统上”才能使用语言环境。请参阅 PHP 手册上的此注释,它准确地反映了我的情况。这个SO question也询问了同样的问题。这不适合开源项目,因为我不能相信最终用户在他们的系统上安装了适当的语言环境。此外,您必须安装语言环境才能使用已翻译的字符串(IMO),这非常奇怪。

  • Zend_Translate 有时也推荐使用 gettext,但我没有使用 Zend 框架,所以我认为这不是我的选择。有人说你可以将它从 Zend 框架中分离出来,但我不知道如何。如果有人能告诉我需要哪些文件(我已经下载了 Zend 框架的压缩包)来挑选,我愿意使用 Zend_Translate。

  • 数组。这就是我现在正在做的事情,但这并不理想,因为:

    • 当当前页面不会使用大多数翻译时,它将占用大量内存来定义每个翻译。
    • 我在发现自己复制数组中的键时遇到了问题,这已经变成了 1000 行代码长而且我几乎没有添加任何东西......
    • 这意味着非程序员无法真正翻译,而 POedit 是每个人都希望使用的标准。

我可以.mo在没有 Gettext 或 Zend_Translate 的情况下以某种方式读取文件,还是必须使用 Gettext?如果是这样,我怎样才能使所有语言环境都工作,就像我上面链接的问题一样?

编辑:我现在愿意使用 Zend_Translate。我只需要弄清楚我需要什么文件(如果可以将它们合并到一个文件中那就太好了)——我不想在我的项目中使用整个 Zend 框架。


更新:我很想看看大型开源项目如何处理 i18n:

因此,据我所知,这三个随机项目都没有使用 Zend_Translate,也没有直接使用 gettext。

也许使用语言环境是个好主意,将C语言名称存储在文本域名中,然后从那里开始。


因此,就我所知:

$lang = 'de'; //debug
setlocale( LC_ALL, 'C' );
bindtextdomain( 'default', PATH . "/locale/$lang" );
bind_textdomain_codeset( 'default', 'UTF-8' );
textdomain( 'default' );

var_dump( file_exists( PATH . "/locale/$lang/C/LC_MESSAGES/default.mo" ) ); //bool(true)

但我仍然只是得到英文字符串,即使我使用 poedit、msgfmt 等来制作适当的文件。我也尝试过重新启动 Apache。

4

3 回答 3

4

尝试gettext-php。它是用 PHP 编写的 gettext 的替代品。我认为它最初是为 WordPress 完成的,因为 WP 需要在共享主机上运行,​​而共享主机并不总是为每个语言环境配置。在我看来,这也是你的问题。

它对性能有一点影响,但对我来说根本不是问题。

于 2013-03-22T22:44:37.440 回答
4

这是解决方案:

$lang = 'de'; //debug
setlocale( LC_ALL, 'C.UTF-8' );
bindtextdomain( 'default', PATH . "/locale/$lang" );
bind_textdomain_codeset( 'default', 'UTF-8' );
textdomain( 'default' );

这与我在答案底部发布的示例之间的唯一区别是它不仅C.UTF-8使用C.

我将对此进行更多测试,如果它可以跨平台工作,如果我发现其他任何内容,我会更新这个答案。

于 2013-03-22T22:38:23.217 回答
0

对于任何对此仍有疑问的人,您可以尝试下面的代码,我从这里获得:http: //php.net/manual/en/function.gettext.php#58310

它解决了我在 freebsd 服务器上的问题,没有额外的语言环境安装(fr_FR 和 my_MY) 当您遇到 gettext 缓存问题时,此代码也很有用。

<?php
function initialize_i18n($locale) {
  $locales_root="/app/php/locale"; // change This to where you locale folder at
  putenv('LANG='.$locale);
  setlocale(LC_ALL,"");
  setlocale(LC_MESSAGES,$locale);
  setlocale(LC_CTYPE,$locale);
  $domains = glob($locales_root.'/'.$locale.'/LC_MESSAGES/*.mo');
  $current = basename($domains[0],'.mo');
  $timestamp = preg_replace('{messages-}i','',$current);
  bindtextdomain($current,$locales_root);
  textdomain($current);
}
?>
于 2018-08-01T08:04:56.457 回答