web-dev-qa-db-ja.com

PHPで言語ファイルを作成する最も効率的な方法は?

新しい質問を作成する代わりに更新された質問...

私が構築しているソーシャルネットワークサイトで英語以外のいくつかの代替言語を提供したいのですが、これはあらゆる種類の言語翻訳を行うのが初めてなので、ご容赦ください。
私は研究しているので、私は常に耳を傾け、アイデアを受け入れています。そして、私はすでにここに多くの質問があります。

1)
i18nの意味、SOで言語翻訳を研究しているときによく見られますか?

2)
ほとんどの人が使用すると言います gettext PHPには拡張機能またはサポートがありますが、
まあ、私はそれを研究していて、私がそれをこのルートに進むには多くの追加の作業であると言える限り、それについての基本的な理解があります、
つまり、自分のサイトをその機能を使用するようにコーディングすることです。 _( 'hello world i's in English for now')またはelsegettext( 'hello world i'今のところmは英語です ')私が行くルートはそれを必要とするので問題ありません。
しかし、あなたはあなたのサーバーにgettextをインストールしてそれを動作させる必要があります、
次に、特別なエディタを使用して特別なファイルを作成し、それらをコンパイルすると思いますか?

痛みのように聞こえますが、これが最善のルートだと思いますが、みんなそうだと言っているようです。
では、なぜこれが進むべき道なのかを誰かに教えてもらえますか?

3)
私はこのアプローチのシンプルさが本当に好きです。言語配列を構築し、以下の例のような関数で必要なフレーズを呼び出すだけで、適切な言語配列を持つファイルを含めるだけです。

私が本当に知りたいのは、これはgettextを使用する場合と比較して、トラフィックが多く、かなり大きなサイトでのパフォーマンスが劣る方法でしょうか。

<?PHP
//Have seperate language files for each language I add, this would be english file
function lang($phrase){
    static $lang = array(
        'NO_PHOTO' => 'No photo\'s available',
        'NEW_MEMBER' => 'This user is new'
    );
    return $lang[$phrase];
}
//Then in application where there is text from the site and not from users I would do something like this
echo lang('NO_PHOTO');  // No photo's available would show here
?>

*以下のbrianreavisの回答から使用されているコード

26
JasonDavis

車輪を再発明しないでください。たとえば gettext または Zend_Translate を使用します。

4
raspi

言語マッピングを処理する関数を定義するのがおそらく最善でしょう。そうすれば、doが後でどのように機能するかを変更したい場合、$lang[...]を使用して置き換えた場合に何百ものスクリプトを精査する必要はありませんそれらを別のもので。

このようなものはうまくいき、ナイスで速いでしょう:

function lang($phrase){
    static $lang = array(
        'NO_PHOTO' => 'No photo\'s available',
        'NEW_MEMBER' => 'This user is new'
    );
    return $lang[$phrase];
}

Make sure関数内で配列がstaticと宣言されているため、関数が呼び出されるたびに再割り当てされません。これは、$langが本当に大きい場合に特に重要です。

それを使用するには:

echo lang('NO_PHOTO');

複数の言語を処理するには、この関数を複数のファイル(en.phpfr.phpなど)で定義し、require()をユーザーに適したものにします。

21
brianreavis

これはうまくいくかもしれません:

function _L($phrase){
static $_L = array(
    'NO_PHOTO' => 'No photo\'s available',
    'NEW_MEMBER' => 'This user is new'
);

     return (!array_key_exists($phrase,$_L)) ? $phrase : $_L[$phrase];
}

それは私が今使用するものです。言語が見つからない場合、エラーではなくフレーズが返されます。

配列に含めることができるアイテムは最大で65500であることに注意してください。十分ですが、まあ、言うだけです。

これは、ユーザーの言語を確認するために使用するコードです。

<?php
function setSessionLanguageToDefault() {
    $ip=$_SERVER['REMOTE_ADDR'];
    $url='http://api.hostip.info/get_html.php?ip='.$ip;
    $data=file_get_contents($url);
    $s=explode (':',$data);
    $s2=explode('(',$s[1]);

    $country=str_replace(')','',substr($s2[1], 0, 3));

    if ($country=='us') {
        $country='en';
    }

    $country=strtolower(ereg_replace("[^A-Za-z0-9]", "", $country ));
    $_SESSION["_LANGUAGE"]=$country;
}

if (!isset($_SESSION["_LANGUAGE"])) {
    setSessionLanguageToDefault();
}

if (file_exists(APP_DIR.'/language/'.$_SESSION["_LANGUAGE"].'.php')) {
    include(APP_DIR.'/language/'.$_SESSION["_LANGUAGE"].'.php');
} else {
    include(APP_DIR.'/language/'.DEFAULT_LANG.'.php');
}

?>

まだ完了していませんが、これは非常に役立つと思います。

10
Rob Quist

独自の言語フレームワークを記述しないでください。 gettext を使用します。 PHPには、インストール可能な標準 バインディング があります。

5
Fragsworth

残念ながらgettextはうまく動作せず、さまざまなOS(WindowsまたはLinux)などのさまざまな状況で問題が発生し、動作させるのは非常に困難です。

さらに、多くの環境変数とドメインを設定する必要があり、これには意味がありません。

開発者が単にテキストの翻訳を取得したい場合、.moファイルパスを設定し、translate( "hello"、 "en_EN");のような1つの関数で翻訳を取得する必要があります。 gettextでは、これは不可能です。

1

他の答えは実際にはすべての質問に答えるものではないので、私は答えに加えて賢明な代替案を提供します。

1)I18nは国際化の略で、I-18-nといくつかの類似点があります。

2)正直なところ、gettextは時間の無駄です。

3)あなたのアプローチは良さそうです。探す必要があるのは言語変数です。 WoltLab Community Framework 2. は、双方向言語システムを実装しています。一度、データベースとテンプレート内に保存されている言語変数があります。1つは変数の名前のみを使用し、現在の言語の変数のコンテンツに置き換えられます(可能な場合)。システムの2番目の部分は、ユーザーが生成したコンテンツを複数の言語で保存する方法を提供します(複数の言語での入力が必要です)。

基本的に、開発者が定義したインターフェーステキストとユーザーが定義したコンテンツがあります。コンテンツの多言語テキストは言語変数に保存され、言語変数の名前は特定のコンテンツテーブルのテキストフィールドの値として使用されます(単一言語コンテンツも可能です)。

悲しいことに、WCFの構造は、フレームワークの外でコードを再利用することが非常に困難ですが、インスピレーションとして使用できます。システムの範囲は、サイトで何を達成したいかにのみ依存します。それが大きくなる場合は、WCFシステムを必ず確認してください。それが小さい場合は、いくつかの専用言語ファイル(de.php、en.phpなど)から、現在の言語に適したものが含まれています。

1
Jim Martens

なぜあなたはそれを多次元配列として作成しないのですか...このような

<?php

$lang = array(
    'EN'=> array(
        'NO_PHOTO'=>'No photo\'s avaiable',
        'NEW_MEMBER'=>'This user is new',
    ),
    'MY'=> array(
        'NO_PHOTO'=>'Tiada gambar',
        'NEW_MEMBER'=>'Ini adalah pengguna baru',
    )
);

?>
0
user149513

あなたはこれを行うことができます:

class T {
const language = "English";
const home = "Home";
const blog = "Blog";
const forum = "Forum";
const contact = "Support";
}

言語ごとにこのようなファイルを作成します。テキストを使用するには:

There is no place like <?=T::home?>.

欠点は、新しい定数を追加する場合、すべての言語ファイルに対してそれを行う必要があることです。 1つ忘れると、その言語でページが壊れます。これは少し厄介ですが、大きな連想配列を作成する必要がなく、値がインライン化される可能性もあるため、効率的です。

たぶんアクセスが改善されるかもしれません、例えば:

class T {
    const home = "home";

    public static function _ ($name) {
        $value = @constant("self::$name");
        return $value ? $value : $name;
    }

    // Or maybe through an instance:
    public function __get ($name) {
        $value = @constant("self::$name");
        return $value ? $value : $name;
    }
}
echo "There is no " . T::_("place") . " like " . T::_("home");
$T = new T();
echo "There is no " . $T->place . " like " . $T->home;

私たちはまだ配列を避け、定数を直接使用するよりも負荷が高いと思います constant に依存してルックアップを行います。利点は、キーが見つからない場合にルックアップがフォールバックを使用できることです。

0
NateS