DxGetText-DelphiおよびC ++ Builder用のGNU Gettext

幸運なことに、STOの指導の下で仕事をすることができました。STOは、1つの興味深いプロジェクト-DelphiとC ++ Builder用のGNU Gettextの共著者です。 Delphiでのみチェックアウトしましたが、これは作業の原理を理解し、その機能を理解するのに十分です。

要するに、これは一般的に受け入れられている方法で製品に高品質のローカライズを実装できるライブラリであり、次のように機能します。

  1. ほとんどいつものようにコードを書く。
  2. 翻訳するテキストのソースをスキャンするアプリケーションを起動します。
  3. ROファイルを生成します。
  4. 便利なエディタで翻訳してください。
  5. ROファイルをMOファイルにコンパイルします。
  6. 翻訳をEXEに直接実装するか、MOファイルを近くに置くかを選択できます。
  7. 結果をお楽しみください-アプリケーションの言語は再起動しなくても変更できます。


この方法がクールな理由:



それでは、インストールに進みましょう。

サイトとソースコードは長い間更新されていません。 ここでコンパイルされたツールを入手するか、 ここでソースを入手して自分でビルドすることができます。 これらは、POファイルとアクションを生成するためのツールです。 また、Delphiプロジェクトの場合、使用するファイルを1つ追加するだけです-gnugettext.pas



使用してみてください。

アプリケーションの起動時、その言語はわかりません。つまり、 彼は「 未翻訳 」になります。 言語は、 初期化 、フォームコンストラクター、ユーザーが言語を選択した後など、どこでも指定できます。 フォームを翻訳するには、コンストラクターでtranslatecomponentメソッドを呼び出す必要があります。

フォームコンストラクターで次のテキストを使用してVCLフォームアプリケーションを作成してみましょう。

procedure TForm1.FormCreate(Sender: TObject); begin UseLanguage ('EN'); translatecomponent(self); end;
      
      





サポートされている言語コードのリストは、 ここにあります

次に、 Caption:= 'Translate me'でボタンをクリックして、メッセージを表示し、アプリケーションの言語を切り替えます。

 procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(_('Changing language')); UseLanguage ('RU'); Retranslatecomponent(self); end;
      
      





関数「 _ 」(または「 gettext 」)は、指定されたテキストの翻訳を見つけて、見つかった場合はそれを返すか、入力からテキストを返します。

現在、アプリケーションにはローカライズがありません。ROおよびMOファイルはありません。 すべてが正常に機能し、エラーは発生せず、翻訳が必要です。 修正してみましょう。

アプリケーションフォルダーで、「 locale 」という名前のフォルダーを作成し、その中に言語(この場合は「 ru 」および「 en 」)のフォルダーを作成し、言語の各フォルダーにフォルダー「 LC_MESSAGES 」を作成し、空のテキストファイル「 default.po 」を作成します。 その後、アプリケーションのルートフォルダーに次の内容のupdatepofiles.cmdファイルを作成します。

 echo Extracting texts from source code dxgettext -q --delphi --useignorepo -b . echo Updating Russian translations pushd locale\ru\LC_MESSAGES copy default.po default-backup.po ren default.po default-old.po echo Merging msgmergedx default-old.po ..\..\..\default.po -o default.po del default-old.po popd echo Updating English translations pushd locale\en\LC_MESSAGES copy default.po default-backup.po ren default.po default-old.po echo Merging msgmergedx default-old.po ..\..\..\default.po -o default.po del default-old.po popd
      
      





ソースツールdxgettext.exeからアプリケーションのルートフォルダーにあるdefault.poファイルにPOファイルを生成します。 翻訳のないファイルは生成中に作成されるため、翻訳がそこに追加されると、次にdxgettextが呼び出されたときに消えることを考慮する必要があります。 これを行うために、スクリプトは、翻訳のない新しいファイルと翻訳のある古いファイルをさらにマージ( msgmergedx )します。 その結果、古いレコードと翻訳をすべて保存し、新しいレコードは翻訳なしで追加されます。 オリジナルのすべての同じテキストが1つのレコードにグループ化され、同じ方法で翻訳されることに注意してください。 つまり、3つのフォームに「 保存 」メニュー項目がある場合、POファイルにはエントリが1つしかなく、翻訳は3つのフォームすべてで同じになります。 dxgettextの便利な機能は、レコードのコメントに、それが発生するコード内のすべての場所がリストされることです。

今、何かを翻訳してみてください。 インターネットから任意のエディターを使用できます。テキストエディターだけを使用できますが、私は同じ著者である私の元ボスであるGormからエディターを取得しました。 また、オープンソースであり、他に類を見ない機能が満載です。 したがって、 ロケール\ en \ LC_MESSAGES \フォルダーに移動し、 default.poで Gormを開きます

翻訳が正しく機能するためには、このファイルの言語を指定する必要があります。必要に応じて、他の情報-翻訳の作成者、バージョンなどを指定する必要があります。 これを行うには、 ファイル/ヘッダー編集し、 言語フィールドで英語を選択します。 フォント名の付いた不要なアイテムも翻訳に含まれていることに気付くかもしれません。 翻訳しないようにするには、右側の[ 無視 ]ボタンをクリックします。 残りについては、以下の翻訳フィールドに翻訳を入力します。



保存します。 ロシア語についても同じことを行い、ヘッダーで指定します。 ここで、アプリケーションに翻訳を表示するには、ROファイルをコンパイルする必要があります。 dxgettextがインストールされている場合、ROファイルをダブルクリックすることで実行できます。Gorm'e- Tools / Compile to MO fileで直接実行できます 。 アプリケーションで翻訳ファイルを表示するには、プロジェクトでOutputディレクトリをプロジェクトのルートフォルダー(空のパスまたは「。」)に変更する必要があります。 今すぐ実行します。





さらに、MOファイルを削除することができ、アプリケーションはそれらがなくても翻訳を処理します。 これを行うには、アプリケーションのルートフォルダーに別のスクリプトを作成し、 translate.cmdを呼び出します。 彼はROファイルをコンパイルし(はい、これを行う別の方法)、EXEファイルに翻訳を実装します。



 set sourceroot=%CD%\ echo Compiling language files and embedding those echo English... cd %sourceroot%locale\en\LC_MESSAGES msgfmt.exe -o default.mo default.po echo Russian... cd ..\..\ru\LC_MESSAGES msgfmt.exe -o default.mo default.po cd ..\..\.. echo Embedding translations... copy Project1.exe Project1_Translated.exe assemble.exe --dxgettext Project1_Translated.exe echo Compiling language files and embedding those completed cd %sourceroot% pause
      
      





これで、 Project1_Translated.exeファイルが作成されました。このファイルは、別のフォルダー、別のマシンに移動でき、既に翻訳が組み込まれています。



次に、アプリケーションにローカライズを実装するときにプログラマが遭遇する典型的なタスクを検討します。



フォーマット文字列


場合によっては、変数の値をテキストに追加する必要があります。 そのような行を翻訳する場合、意味を失い、翻訳者がこの作品の内容を理解するのが困難になるため、それを断片に分割する必要はありません。 翻訳は次の方法で実行できます。

 var s:string; d:integer; begin s:=_('Apple'); d:=7; showmessage(format(_('%s count: %d'),[s,d])); end;
      
      





翻訳関数は形式内にある必要があります。たとえば、ロシア語への翻訳は「 Quantity%s:%d 」になります。 この場合、翻訳内のフォーマットパラメータの数が異なる場合、Gormは警告を表示します。



複数


異なる言語では、カウントされたアイテムの数に応じて、複数形を異なる方法で翻訳できます。 DxGetTextは、 ngettext関数を使用してこれを実行できます。 彼女は単語を単数形、複数形、そして翻訳が必要な量を伝える必要があります。 例:

 var i:integer; s:string; begin s:=emptystr; for i:=1 to 11 do s:=s+format(('%d %s'),[i, ngettext('apple', 'apples', i)])+slinebreak; i:=21; s:=s+format(('%d %s'),[i, ngettext('apple', 'apples', i)]); showmessage(s); end;
      
      







ここにGormの最初のマイナスが表示されます-彼はそのような翻訳を編集できません。 したがって、プロジェクトに対してupdatepofiles.cmdを呼び出し、テキストエディターで翻訳を書き込もうとします。 これを行うには、 ロケール\ ru \ LC_MESSAGES \ default.poを開き、リンゴを見つけます。 翻訳は次のようになります。

msgstr "リンゴ"

msgid_plural "apples"

msgstr [0] apple

msgstr [1]りんご

msgstr [2]りんご



ROファイルをコンパイルし、アプリケーションを実行します。 リンゴのマッサージは次のようになります。

英語 ロシア語
リンゴ1個 リンゴ1個
リンゴ2個 リンゴ2個
リンゴ3個 リンゴ3個
リンゴ4個 リンゴ4個
リンゴ5個 リンゴ5個
りんご6個 りんご6個
リンゴ7個 リンゴ7個
リンゴ8個 リンゴ8個
リンゴ9個 リンゴ9個
リンゴ10個 リンゴ10個
リンゴ11個 リンゴ11個
りんご21個 りんご21個


異なる意味を持つ同一の単語


アプリケーションに、言語の異なる意味で、デフォルトで同じ方法で書かれた単語(同名)がある場合、POファイルに翻訳を引き出すdxgettext.exeは、この1つと同じ単語を考慮し、翻訳はすべての場所で同じになりますこの単語が見つかりました。 たとえば、アプリケーション内の「弓」という言葉を奇跡的に弓(射る)として、また楽器の弓として翻訳する必要がある場合、不確実性が生じます。 例:

 var s:string; begin s:=_('bow'); Showmessage( format(_('Use %s to shoot enemies.'),[s]) + slinebreak + format(_('Use %s to play violin.'),[s])); end;
      
      





ここでは、弓で撃つか、弓で遊ぶことができます。 値で単語を分割することにより、この問題を回避できます。

 var s1,s2:string; begin s1:=_('bow_music'); s2:=_('bow_weapon'); Showmessage( format(_('Use %s to shoot enemies.'),[s2]) + slinebreak + format(_('Use %s to play violin.'),[s1])); end;
      
      







結果:

弓を使って敵を撃ちます。

弓を使ってバイオリンを弾きます。



ドメイン


アプリケーションはモジュールに分割される場合があり、これらのモジュールは個別に翻訳する必要があります。 このため、ドメインはdxgettextで使用されます。 デフォルトでは、すべての翻訳は「デフォルト」ドメインに分類されるため、ROファイルはそのように呼び出されます。 ただし、パラメータでドメインが指定されているdgettextまたはdngettext関数を使用すると、翻訳は指定されたドメインのPOファイルに分類されるため、翻訳はドメイン名のファイルで検索されます。 さらに、 textdomainプロシージャによってドメインを永続的に設定できます。



結論



dxgettextの機能は、プロフェッショナルで大規模なソフトウェア製品でもローカライズするのに十分です。 実行可能ファイルに翻訳を導入すると、ボリュームに数メガバイトが追加されます。Delphiの場合、小さなアプリケーションがすでに数十メガバイトの重さがある場合は許容できます;)



PS:考慮された例のソースは、 ここまたはGitHubからダウンロードできます。



All Articles