Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gettext will always use system default locale

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 development box. I've used trial and error together with Process Monitor to overcome the poor and inaccurate documentation and I've managed to make _() display strings from the *.po catalogue that corresponds to the computer's default locale (Modern Spanish in my case). All my attempts to set a different locale are silently ignored.

I've written a test script with lots of redundant stuff:

<dl><?php

define('DIR_LOCALE', __DIR__ . DIRECTORY_SEPARATOR . 'locale');
bindtextdomain('general', DIR_LOCALE);
bind_textdomain_codeset('general', 'UTF-8');
textdomain('general');

if(!defined('LC_MESSAGES')){
    define('LC_MESSAGES', 5);
}

$pruebas = array(
    'enu',
    'es_ES',
    'en_GB',
    'english-uk',
    'Spanish_Spain.1252',
    'esn',
    'spanish',
    'spanish-modern',
);
foreach($pruebas as $locale){
    putenv("LC_ALL=$locale");
    setlocale(LC_ALL, $locale);

    putenv("LC_MESSAGES=$locale");
    setlocale(LC_MESSAGES, $locale);

    putenv("LANGUAGE=$locale");
    putenv("LANG=$locale");
?>
    <dt><?=htmlspecialchars($locale)?></dt>
    <dd><?=_('codigo_idioma')?></dd>
<?php } ?>
</dl>

In my case, <?=_('codigo_idioma')?> always prints es_ES@modern.

I have PHP/5.4.5 but I'm expecting to get it working in any reasonably up-to-date server our customers own.

I've read lots of vague references about the need to install locales even on Windows but no exact details. What can the problem be?

(I'm aware that the common advice is to dump gettext and use any other library.)


Further testing:

My code run flawlessly as-is in another two computers: 32-bit Windows Vista and 32-bit Windows 7 32-bit. It fails in my computer (64-bit Windows 7) and another one (32-bit Windows Server 2003)

  • Apache version seems irrelevant (it also happens with the command-line interpreter).
  • PHP version seems irrelevant (also tried latest 32-bit PHP/5.5.5 in my PC).
  • My [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls] registry tree is identical to the other Seven box.

Edit: While testing on the command-line, I've discovered that setting the LANG environment variable before running the PHP script finally changes the language:

C:\>set LANG=en_GB
C:\>php C:\test\gettext.php

This definitively proves that my computer has the correct assets but also makes me wonder why PHP claims that putenv() works and then ignores it:

var_dump( getenv('LANG'), putenv('LANG=en_GB'), getenv('LANG') );
bool(false)
bool(true)
string(5) "en_GB"

Even this doesn't have any effect:

$_ENV['LANG'] = 'en_GB';
$_SERVER['LANG'] = 'en_GB';
like image 464
Álvaro González Avatar asked Oct 24 '13 14:10

Álvaro González


2 Answers

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);
like image 197
Camille Avatar answered Oct 31 '22 11:10

Camille


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

like image 42
Buzogany Laszlo Avatar answered Oct 31 '22 12:10

Buzogany Laszlo