【问题标题】:PHP gettext() without relying setlocalePHP gettext() 不依赖 setlocale
【发布时间】:2014-06-13 08:01:20
【问题描述】:

目前我需要在我的 translate 函数上设置和恢复语言环境,因为如果全局使用 setlocale 会影响我们系统的其他部分(即遗留代码)

所以我们需要使用..

function translate($text, $locale) {

    $original = getenv('LC_ALL');

    putenv('LC_ALL=' . $locale);
    setlocale(LC_ALL, $locale);

    $translated = _("text);

    putenv('LC_ALL=' . $original);
    setlocale(LC_ALL, $original);

    return $translated;
}

有没有更好的办法?

【问题讨论】:

标签: php localization internationalization gettext


【解决方案1】:

不要使用LC_ALL,只需使用LC_MESSAGES。虽然设置LC_ALL 当然会起作用,因为它会全局设置语言,只设置LC_MESSAGES 就足够了——只有这个变量用于翻译:

setlocale(LC_ALL, "en_US");
setlocale(LC_MESSAGES, "cs_CZ");
_("something") # you will get czech translation now, even if globally you use EN

因此,如果您的旧代码可以正确处理 LC_MESSAGES 设置,那就没问题了。

有关每个LC_* 变量的详细信息,请参阅http://us2.php.net//manual/en/function.setlocale.php

【讨论】:

    【解决方案2】:

    您应该从 LANG 环境变量中提取语言环境,因为可能未设置 LC_ALL。这可能与 Windows 不兼容,如果您需要它,请告诉我,我会更新它。


    //default locale to use when all else fails
    define('DEFAULT_LANG',    'en_US.UTF-8');
    
    /**
     * returns the current locale based on the LANG environment variable. 
     * Only calls getenv() once, after that uses a cached value.  remove the static 
     * keyword to disable this functionality.
     * 
     * @return string returns the current locale, or DEFAULT_LANG on error.
     */
    function get_lang() {
      static $lang; //static variable, so the resulting call to getenv() only fire once
      if (!isset($lang) || $lang=="") { 
        $lang = getenv('LANG');
        if (trim($lang)=='')
          $lang = DEFAULT_LANG;    
      }
      return $lang;
    }
    
    /**
     * @param string $text string to translate
     * @param string $locale locale to translate to, i.e. de_DE
     * @param boolean $provideFallback - provide the original local as a fallback if locale is not     recognized
     * @return boolean|string returns $text translated to $locale, or FALSE on error. 
     */
    function translate($text, $locale, $provideFallback = FALSE, $resetLocale = TRUE) {
      if ((empty($locale) || trim($locale)=='') && !$provideFallback) 
        return FALSE;
      if (empty($text))
        return $text;
    
      $original = get_lang();
    
      //provide a fallback locale in case $locale is not recognized.
      if ($provideFallback) {
        $l = strval($locale);
        if (empty($locale) || trim($locale)=='')
          $l = $original; //set locale to the original locale, since none was provided.
        $locale = array($l, $original, DEFAULT_LANG);
      }
    
      setlocale(LC_ALL, $locale);
      $translated = _($text);
      if ($resetLocale) {
        setlocale(LC_ALL, $original);
      }
      return $translated;
    }
    
    
    echo get_lang().PHP_EOL;
    echo translate("test1", "de_DE.UTF-8") . PHP_EOL;
    echo translate("test2", "de_DE.UTF-8") . PHP_EOL;
    

    【讨论】:

      【解决方案3】:

      也许php-gettext 是一个选项?它是 gettext 功能的纯 PHP 实现。它的gettext_reader 类可以读取 gettext .mo 文件,而无需依赖语言环境功能或任何其他全局状态。 (php-gettext 还可以提供标准 PHP gettext API 的替代品,但这看起来相当丑陋/危险。)

      免责声明:从未在生产中实际使用过。

      【讨论】:

        【解决方案4】:

        我认为这是正确的做法。 几年前我也遇到过同样的问题。

        这是我的代码,和你的类似:

        // Translate
        $_SESSION['locale'] = $locale;
        \Application::GetInstance()->getLocaleManager()->refresh();
        $output["data"][] = array(
            "text" => utf8_encode($menuItem->getLibelle()),
            "lang" => utf8_encode(ucfirst($localeName)),
            "translation" => utf8_encode(_($menuItem->getLibelle()))
        );
        // Restore lang
        $_SESSION['locale'] = "fr";
        \Application::GetInstance()->getLocaleManager()->refresh();
        

        refresh() 正在做:

        • \Locale::setDefault($locale)
        • setlocale(...)
        • putenv("LANG=".$locale); // windows 环境下需要
        • putenv("LANGUAGE=".$locale); // windows 环境下需要

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-28
          • 1970-01-01
          • 1970-01-01
          • 2014-11-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多