Gettext will always use system default locale

后端 未结 7 639
孤城傲影
孤城傲影 2020-12-30 09:30

I need to localise a Windows-only PHP web application and I\'m evaluating the gettext extension but I\'m having the hardest time trying to make it work in my Windows 7 devel

相关标签:
7条回答
  • 2020-12-30 09:48

    You must upgrade to PHP 5.6.6 for Windows, it works!

    0 讨论(0)
  • 2020-12-30 09:51

    Add a system variable 'LANG' with the desired locale for the value (for example 'en_US' or 'nl_NL'), restart apache and translations corresponding to that locale are shown.

    Environment variables

    This works for XAMPP with php 7.1 (thread safe) on windows 10 and locale directories structured as follows:

        // Directory structure
        <locale_dir>\en_US\LC_MESSAGES\bundle.po
        <locale_dir>\nl_NL\LC_MESSAGES\bundle.po
        ...
    
    0 讨论(0)
  • 2020-12-30 09:54

    I had same problem with PHP 5.6.30 VC11 Theard Safe on Windows 10. Workaround found and fix this issue here by sirio3mil.

    Apparently PHP with TS can access only Locale language folder. So when setlocale and putenv function is call with another language than system's one, folder with .mo and .po cannot be read.

    Workaround is to have only one language folder with system language and multiple pairs of .mo/.po files for each translated languages. Domain will be set with wanted language.

    Example with Swiss French, German and Italian:

    Folder structure

    \Locale\fr_CH\LC_MESSAGES

    • fr_CH.mo + fr_CH.po // system language
    • de_CH.mo + de_CH.po
    • it_CH.mo + it_CH.po

    Code

    $lang = 'fr_CH' or 'de_CH' or 'it_CH'
    
    bindtextdomain($lang, '.\Locale');
    textdomain($lang);
    bind_textdomain_codeset($lang, 'UTF-8');
    setlocale (LC_ALL, $lang);
    putenv('LC_ALL=' . $lang);
    
    0 讨论(0)
  • 2020-12-30 09:55

    First problem: setlocale()

    To make this work, you need to set a valid locale. On windows, setlocale() won't work as expected. You need to set an environment variable, like this:

    // putenv("LANG=$lang");  <- WRONG!
    putenv('LC_ALL='.$locale);
    

    Second problem: locale names.

    Windows locale names are different from Linux. Try with 'ita', 'eng', 'deu', 'ger', 'esp'. You can get a complete list here: http://www.microsoft.com/resources/msdn/goglobal/default.mspx

    Example:

    //putenv("LANG=esp");  <- WRONG!
    putenv('LC_ALL=esp');
    

    Third problem, the big one: gettext extension on windows is not thread safe. Each time you change language, the change is process wide. If you run php as fast-cgi you're ok. If you run php as apache module (for example) it's a total mess because language changes for every php instance. The problem is that gettext() relies on locale setting. This setting is process wide on windows PHP. You cannot change locale for a PHP thread but only for PHP process.

    Said this, here is some working code:

    // $MAINPATH is your document root
    
    $locales=array(
      'it'=>'ita',
      'en'=>'eng',
      'de'=>'deu',
      'fr'=>'fra',
      'es'=>'esp',
      'ru'=>'rus'
    );
    
    $locale = $locales[$lang];
    $res=putenv('LC_ALL='.$locale);
    $rres=bindtextdomain('default', $MAINPATH.'locale');
    $dres=textdomain('default');
    

    locale directory structure must be the following:

    deu
      LC_MESSAGES
        default.mo
    esp
      LC_MESSAGES
        default.mo
    fra
      LC_MESSAGES
        default.mo
    ita
      LC_MESSAGES
        default.mo
    rus
      LC_MESSAGES
        default.mo
    
    0 讨论(0)
  • 2020-12-30 10:02

    It's an issue that's been acknowledged and partially fixed by the PHP team.

    It's a fairly technical thing, apparently related to the way environment variables (on which gettext heavily depends) are handled by the underlying platform. Also, something has changed in the Visual C Runtime libraries from VC9 to VC11 that affects all this.

    To sum up:

    • Non thread-safe builds have been fixed in the source tree on 21st Nov. 2014.
    • Thread-safe builds (e.g. Apache module) haven't and there isn't a clear solution in sight.
    0 讨论(0)
  • 2020-12-30 10:07

    The key is to use a Non Thread Safe (=NTS) version of PHP.

    Unfortunatelly Windows and PHP does not handle well the environments for threaded processes, so the putenv('LC_ALL='.$locale); command does not work.

    Finally I end up with Apache 2.4 + FCGID + PHP 7.1 NTS, which works well now on Windows 7, and it is a non thread safe installation.

    A step by step instruction on how to install a such system is here: https://www.youtube.com/watch?v=UXrJPrGaPB0

    I have used the VC14 and x64 version for all components (VC is abbreviation for "Microsoft Visual C++ Redistributable"). For this I first installed VC14, downloaded from here: https://www.microsoft.com/en-us/download/details.aspx?id=48145

    0 讨论(0)
提交回复
热议问题