12

Windows 専用の PHP Web アプリケーションをローカライズする必要があり、gettext 拡張機能を評価していますが、Windows 7 開発ボックスで動作させるのに最も苦労しています。私はProcess Monitorと一緒に試行錯誤を繰り返して貧弱で不正確なドキュメントを克服_()し、コンピューターのデフォルト ロケール (私の場合は現代スペイン語) に対応する *.po カタログから表示文字列を作成することができました。別のロケールを設定しようとする試みはすべて、黙って無視されます。

多くの冗長なものを含むテスト スクリプトを作成しました。

<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>

私の場合、<?=_('codigo_idioma')?>常に印刷されes_ES@modernます。

私は PHP/5.4.5 を持っていますが、顧客が所有する適度に最新のサーバーで動作することを期待しています。

Windows でもロケールをインストールする必要があるというあいまいなリファレンスをたくさん読みましたが、正確な詳細はありません。問題は何ですか?

(一般的なアドバイスは、gettext をダンプして他のライブラリを使用することであることは承知しています。)


さらなるテスト:

私のコードは、別の 2 台のコンピューター (32 ビット Windows Vista と 32 ビット Windows 7 32 ビット) で問題なく動作します。私のコンピューター (64 ビット Windows 7) と別のコンピューター (32 ビット Windows Server 2003) で失敗します。

  • Apache のバージョンは関係ないようです (コマンドライン インタープリターでも発生します)。
  • PHP のバージョンは関係ないようです (最新の 32 ビット PHP/5.5.5 も PC で試しました)。
  • 私の[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls]レジストリ ツリーは、他のセブン ボックスと同じです。

編集:コマンドラインでテストしているときにLANG、PHP スクリプトを実行する前に環境変数を設定すると、最終的に言語が変更されることがわかりました。

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

これは、私のコンピューターが正しい資産を持っていることを明確に証明していますが、PHP が機能すると主張しputenv()、それを無視する理由も不思議に思います。

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

これでも何の効果もありません:

$_ENV['LANG'] = 'en_GB';
$_SERVER['LANG'] = 'en_GB';
4

7 に答える 7

6

これは、PHP チームによって認識され、部分的に修正された問題です。

これはかなり技術的なことで、基盤となるプラットフォームが (gettext が大きく依存する) 環境変数を処理する方法に明らかに関連しています。また、VC9 から VC11 への Visual C ランタイム ライブラリで何かが変更され、これらすべてに影響します。

総括する:

  • 非スレッドセーフ ビルドは、2014 年 11 月 21 日にソース ツリーで修正されまし
  • スレッド セーフ ビルド (Apache モジュールなど) はそうではなく、明確な解決策も見えていません。
于 2015-03-06T11:48:38.270 に答える
0

最初の問題: setlocale()

これを機能させるには、有効なロケールを設定する必要があります。Windows では、setlocale() が期待どおりに機能しません。次のように、環境変数を設定する必要があります。

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

2 番目の問題: ロケール名。

Windows のロケール名は Linux とは異なります。「ita」、「eng」、「deu」、「ger」、「esp」で試してください。ここで完全なリストを取得できます: http://www.microsoft.com/resources/msdn/goglobal/default.mspx

例:

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

3 つ目の大きな問題: Windows の gettext 拡張機能はスレッド セーフではありません。言語を変更するたびに、その変更はプロセス全体に及びます。php を fast-cgi として実行すれば問題ありません。たとえば、php を apache モジュールとして実行すると、php インスタンスごとに言語が変わるため、完全に混乱します。問題は、 gettext() がロケール設定に依存していることです。この設定は、Windows PHP のプロセス全体に適用されます。PHP スレッドのロケールは変更できませんが、PHP プロセスのロケールのみを変更できます。

これは言った、ここにいくつかの作業コードがあります:

// $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');

ロケール ディレクトリ構造は次のようにする必要があります。

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
于 2014-02-13T11:23:25.640 に答える
-2

Windows 用の PHP 5.6.6 にアップグレードする必要があります。

于 2015-03-05T01:33:05.323 に答える