【问题标题】:Use PHP Gettext without having to install locales无需安装语言环境即可使用 PHP Gettext
【发布时间】:2013-03-10 14:55:18
【问题描述】:

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

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

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

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

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

我可以在没有 Gettext 或 Zend_Translate 的情况下以某种方式读取 .mo 文件,还是必须使用 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。

【问题讨论】:

  • 安装语言环境?你的意思是?您只需包含特定的.mo 文件并设置适当的语言环境。它真的没有你想象的那么可怕。
  • 如果是这样的话那就太好了,但我认为不是……请参阅问题顶部的链接。 PHP 手册上的User notes 也这样说,并且您需要运行locale -a 以查看可用的语言环境(并运行sudo apt-get install language-pack-langcode-base 以安装额外的语言包)。我自己的测试也反映了这一点。这不适合开源项目,因为我不能指望用户这样做。
  • 简单的键 => 值数组对于完整的翻译系统来说是不够的。他们支持复数吗?语境?类别?域?注释?这些都是您应该使用的功能,也许您只是还不知道。如果你不喜欢 gettext,试试 Zend_Translate。你反对它的理由真的是没有理由的。
  • 是的,这就是我想从数组切换到其他东西的原因。如果需要,我想我愿意使用 Zend_Translate,但是如何使用呢? SO have said 上的人们说他们可以将它从 Zend 框架的其余部分中分离出来,但我不知道如何。
  • 只需将 Zend 框架放在某处并加载 Zend_Translate 类,完成。

标签: php arrays gettext zend-translate php-gettext


【解决方案1】:

对于任何对此仍有疑问的人,您可以尝试下面的代码,我从这里得到: 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);
}
?>

【讨论】:

    【解决方案2】:

    解决办法如下:

    $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

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

    【讨论】:

    • 恭喜,它似乎也对我有用。但这似乎真的很hacky,我不敢相信这是解决这个问题的常用方法。我不明白“C.UTF-8”是什么语言,但它似乎安装在每个环境中。由于您的帖子是 2 年前发布的,因此我想请问您在此期间是否找到了更好的解决方案。
    • 对不起@steven,从那以后我就没有真正使用过 PHP。然而,现在我不太受最佳实践的困扰,可能会直接使用基于数组的解决方案,因为我知道 gettext 的挫败感。
    • 你知道如何在 xampp for windows 上安装语言环境吗?
    【解决方案3】:

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

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

    【讨论】:

    • 感谢您的建议。现在我(终于)开始使用 Gettext,我想我现在会坚持下去,但我会记住这一点,以防我遇到更多问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多