レシピ囜際化。 ベヌシス-バベル、コヌヒヌずjson、お奜みに合わせおhbsずグラント

以前の投皿で、ハンドルバヌテンプレヌトからgettext文字列を抜出するpybabel-hbsを䜜成する必芁がある理由ず理由に぀いお曞きたした。



少し埌に、jsonから同じものを抜出する必芁がありたした。

これが、pybabel-jsonが生たれた方法です。

githubに pybabel-jsonをpipむンストヌルする



babelに組み蟌たれたjavascript lexerを䜿甚したしたが、埮劙な違いもありたしたが、投皿はそれに぀いおではなく、hbsプラグむンよりも面癜く曞かれおおらず、ほずんど泚意する必芁はありたせん。



この投皿は、ロヌカラむズのセット党䜓が、デヌタベヌスたたは他のたったく静的でない堎所からのデヌタをどのように凊理するのか、䞀般的にどのように芋えるかに぀いおです。

含たれるもの

私は蚀う必芁がありたす-アむテムは必須ではありたせん、これはすべお郚分的にのみ必芁に応じおアプリケヌションに接続するのは非垞に簡単です



-バベル。 アプリケヌションをロヌカラむズするためのナヌティリティのセット。

-うめき。 タスクマネヌゞャヌ、

-コヌヒヌスクリプト。 プレれンテヌションは必芁ありたせん。クラむアントコヌドはすべおコヌヒヌで曞かれおおり、そこから文字列を抜出する必芁もありたす。

-ハンドルバヌ-テンプレヌト

-json-文字列ストレヌゞ

-ゞェド。 js甚のgettextクラむアント

-po2json。 Jedがサポヌトする.poファむルを.json圢匏に倉換するナヌティリティ







gettextず神話に぀いお



gettextは圓初、アプリケヌションをロヌカラむズするためのナヌティリティのセットでしたが、今日はgettextを䞀般に受け入れられおいる圢匏ずも呌びたす。 唯䞀のものず混同しないでください

最小限の゚ッセンスは次のように説明できたす特定のgettext関数を通過しお目的の蚀語の行に倉わる英語の行がありたすが、耇数圢の異なる曲甚に関する蚀語の芏則+コンテキストずドメむンを指定する機胜を保持したす。

行であり、キヌであり、どこかでテキストになる定数USER_WELCOME_MESSAGEではないこずに泚意するこずが重芁です。



誰もがコンテキストを必芁ずしおいるわけではなく、䞍必芁にプルリク゚ストを歓迎しおいるため、Babelプラグむンにはただ実装しおいたせん

埌でドメむンに関するいく぀かの単語がありたす。

ただし、 ngettextは、 すべおではないにしおも、倚くの人にずっお必需品です。

そしお神話に぀いお。



りんごはれロ。 リンゎなし
リンゎ䞀個。 リンゎ1個
 2぀のリンゎ。 りんご2個
 5぀のリンゎ。  5぀のリンゎ




この簡単な䟋は、「USER_WELCOME_MESSAGE」に䌌た蚀語定数を愛するすべおの人を瀺しおいたす。



babelで事前定矩および説明されおいるルヌルにより、遞択する行が決たりたす。

たずえば、これは英語甚です。

"Plural-Forms: nplurals=2; plural=(n != 1)\n"
      
      







これはロシア語甚です

 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
      
      





グレヌトずマむティ:)

恐れる必芁はありたせん。たずえば日本語の堎合、これを手動で曞く必芁はありたせん。



だから、神話に぀いお。

䜕床か、メむンサむトをロシア語で䜜成し、ロシア語の行をgettext呌び出しでラップしおから英語を远加できるずいう意芋を聞きたした。

同じ蚀語定数を䜿甚しおいる束葉杖を持っおいる堎合、数字を含む傟斜文はなく、「You have apples1」のようなugい圢匏を䜿甚しおいるので、もちろん基本的なロシア語を実行できたす。

「リンゎが1個ありたす」、「リンゎが7個ありたす」など、もう少し矎しいメッセヌゞをナヌザヌに衚瀺する堎合は、メむン蚀語を英語にする必芁がありたす。



なんで りんごがすべおです。

耇数圢は垞に単数圢であるずは限らず、単数圢は垞に単䜍であるずは限りたせん。

この点で英語は簡単ですが、ロシア語ではありたせん。



キヌは正確に英語を想定しおいるため、デフォルトではngettext。 さらに、ngettextは、入力ずしお2぀のパラメヌタヌ単数圢ず耇数圢のみを取りたす。 そしお、耇数の配列ではありたせん。



したがっお、デフォルトでロシア語を匕き続き䜿甚する堎合は、少なくずもロシア語ずロシア語の翻蚳ファむルをサポヌトする必芁がありたす。このファむルでは、「You haves apples」ずいう行が正しい曲甚に倉わりたす。 はい、できたす-しかし、曲がっおいたす。

倉曎するずきは、ロシア語の文字列ではなく、キヌのみが倉曎されるこずを芚えおおく必芁がありたす。たた、ロシア語の蚀語ファむルを䞊行しお線集する必芁がありたす。 䞀般に、これを行う必芁はありたせん。 ngettextは、元の英語ず可胜な限り互換性がありたす。



ずころで、同時に.poファむルが英語ずロシア語を怜玢する方法の䟋を瀺したす

 msgid "You have %(apples_count)d apple" msgid_plural "You have %(apples_count)d apples" msgstr[0] "  %(apples_count)d " msgstr[1] "  %(apples_count)d " msgstr[2] "  %(apples_count)d "
      
      







 msgid "You have %(apples_count)d apple" msgid_plural "You have %(apples_count)d apples" msgstr[0] "" msgstr[1] ""
      
      







぀たり、結果の行数は蚀語構成に䟝存したす。 たぶん、ダヌスの耇数圢がある蚀語がありたす...



OK、それではどこから始めたすか



ただ3個のリンゎを持っおいるすべおの人は、始めるためにやる気がなければなりたせん



pip install babel


難しい郚分は埌ろにありたす。



残りたす

-コヌド内のすべおのテキストをgettext呌び出しに倉曎したす

-コヌドにbabelを蚭定する

-受信した.potファむルに基づいお、目的の各蚀語に察応する.poファむルを䜜成したす。



そしお実際に䜕を翻蚳したすか





質問は䞀芋簡単そうではありたせん



シンプルな郚分はテンプレヌトずコヌドです。

Djangoずフラスコ-テンプレヌトからの抜出がありたす

Pythonずjavascriptはbabelによっおネむティブにサポヌトされおいたす

handlebarsずjson-投皿の最初にリンクを䜜成する必芁がありたした。

coffeescriptの堎合-レシピの詳现

その他すべお-Googleによる救助



繰り返したすが、この郚分は単玔です。このため、すべおの行は、各抜出プログラムが必芁ずする圢匏に埓っおgettext / ngettextの呌び出しでラップする必芁がありたす。 原則ずしお、䜿甚する機胜をオヌバヌラむドする機胜も提䟛したす。

たずえば、私はこれを持っおいたす

 pybabel extract -F babel.cfg -o messages.pot -k "trans" -k "ntrans:1,2" -k "__" .
      
      





transずntransはjavascriptに察しお指定され、__はpythonに察しお指定されたす。この関数は文字列を透過的に送信するために䜿甚されたす詳现は埌ほど



以䞊です

print "apple"はprintngettext "apple"に倉換する必芁がありたす

そしおすべお

print "i haves apples"to printngettext "I haves apples"、 "I haves apples"、num_of_applesnum_of_apples



ここで、私は誰も䜿甚しないこずを望み、名前のないパラメヌタヌの䜿甚を掚奚しないこずに泚意する必芁がありたす。

私の堎合-名前付きのもののみ、぀たり、次のようになりたす。



Python

 print(gettext("I have an apple!")) print(ngettext( "I have %(apples_count)d apple", "I have %(apples_count)d apples", num_of_apples ).format(apples_count=num_of_apples))
      
      





フラスコずゞャンゎには独自のラッパヌがあるため、暙準のgettextが䜿甚されたす



Javascript

 console.log(i18n.trans("I have an apple!")) console.log(i18n.ntrans("I have %(apples_count)d apple","I have %(apples_count)d apples",num_of_apples,{apples_count:num_of_apples}));
      
      





ここおよびコヌヒヌプロキシは、ここからJedメ゜ッドに䜿甚されたす。

github.com/tigrawap/pybabel-hbs/blob/master/client_side_usage/i18n.coffee

組み蟌みのJed sprintfにより、パラメヌタヌが文字列に枡されたす





Coffeescript

 console.log i18n.trans "I have an apple!" console.log i18n.ntrans "I have %(apples_count)d apple", "I have %(apples_count)d apples", num_of_apples, apples_count:num_of_apples
      
      







ハヌドルバヌ

 {{#trans}} I have an apple! {{/trans}} {{# ntrans num_of_apples apples_count=num_of_apples}} I have %(apples_count)d apple {{else}} I have %(apples_count)d apples {{/ntrans}}
      
      







JSON文字列ストア

 { "anykey":"I have an apple!", "another_any_key":{ "type":"gettext_string", "funcname":"ngettext", "content":"I have %(apples_count)d apples", "alt_content":"I have %(apples_count)d apples" } }
      
      





オフトピックpybabel-jsonドキュメントでのこの圢匏の説明



num_of_applesが呌び出しごずに2回繰り返されるこずに気付くのは難しくないず思いたす。

理由は、ngettextの匕数ずしお枡されるず、どの文字列を䜿甚するかを決定し、2回目は、この文字列に代入される他の可胜なパラメヌタずずもに、文字列のパラメヌタずしお䜿甚するためです。



-私が蚀ったように-これは単玔な郚分で、既存のテキストをラップしたす。

次に必芁



1テキストのあるボタンに刻たれおいるすべおのボタンを倉曎したす。 テキスト付きのボタンが悪いこずは誰もが知っおいたす。 しかし、倚くの堎合、これはより高速であり、蚭蚈者はそのように望んでいるため、受け入れられなければなりたせん:)

-この段萜ではすべおが明確になりたす-退屈ですが、必芁です



2

もっず興味深い点は、䞀芋䞀定に芋える行をどう凊理するかですが、どれが完党に䞀定ではないのでしょうか

䟋ずしお、私たちのケヌス-歌のゞャンル-を挙げたす。 それはダむナミクスのようであり、それらはデヌタベヌスに保存されたすが、実際には-たれにしか倉化しないスタティックであり、切り取っお翻蚳に送信するのが良いでしょう。



これがたさにpybabel-jsonの原因です。

この゜リュヌションは、サヌドパヌティのサヌバヌ゚ラヌメッセヌゞぞの応答など、他の翻蚳の問題に察する゜リュヌションでもありたす。 これは静的であるず蚀えたすが、これは制埡できない静的であり、翻蚳のために矎しくラップする必芁がありたす。

必芁なのは、.jsonファむルを䜜成するこずだけです

errors.json

コンテンツ付き

 { "from_F_service": [ "Connection error", "Access denied" ], "from_T_service":[ "Oops, it is too long" ] }
      
      







キヌなし、文字列のクリヌン配列。

サヌビスがメッセヌゞを倉曎した堎合に発生する最悪の事態は、ナヌザヌが未翻蚳バヌゞョンを受け取るこずです。 原則ずしお、これらはささいなこずです



デヌタベヌス内のデヌタに぀いおは、build-push-deployシステムでの状況は䜕でも䌌おいたす結局のずころ、䜕かありたすか。 すべおを組み立おるためのコマンドがあり、すべおのbabelがデヌタベヌスから必芁なすべおのデヌタを抜出し、同様のjsonを収集するこれらのコマンドの前にスクリプトを远加する必芁がある同じレベルで、トラックによっお起動されたbabelはすでにデヌタを収集したす。

もちろん、゜ヌス管理が萜ちないように、そのようなファむルは䞀般的に.gitignoreたたは䜕かの類䌌物に远加する必芁がありたす



この方法で取埗されたすべおの文字列は、gettext関数の呌び出しを通過する必芁がありたす

぀たり、Pythonの堎合、gettext、js Jedたたは前述のプロキシメ゜ッドの堎合



たた、逆の順序で実行する堎合もあるこずに泚意しおください。 たたは、逆の順序で行う必芁がありたす。

぀たり、コヌド内で行を翻蚳する必芁があるが、翻蚳自䜓は別の堎所で開始されるこずを決定したす。

Pythonで䟋を瀺したす。



 class SomeView(MainView): title=gettext("This view title")
      
      







このようなコヌドを䜜成するず、サヌバヌの起動時にクラスが䜜成された堎合は英語でクラスの䜜成枈みコピヌを取埗するリスクが発生したす。䜜成が動的であるが最初の呌び出しでキャッシュされた堎合は䞭囜語版など



そのような堎合、翻蚳に泚意したいが、正しい堎所で翻蚳したい

適切な堎所は、クラスではなくオブゞェクトを䜜成するこずです

぀たり

 def __(string,*k,**kwargs): return string class MainView(SomeParent): def __init__(self): #.... self.title=gettext(self._title) #.... class SomeView(MainView): _title=__("This view title")
      
      







぀たり、文字列コレクタは__を翻蚳甚の文字列ずしお定矩し、関数自䜓は䜕も実行せず、適切なタむミングで翻蚳が開始されたす。

したがっお、すべおが1぀の堎所にあり、矎しく芋えたす。



これは、node.jsで蚘述する堎合、coffeescriptやjavascriptを含む倚くの蚀語に適甚されたす。

ブラりザにずっおは、クラスの䜜成時でも、どの蚀語を䜜成するかがすでにわかっおいるはずなので、これはあたり意味がありたせん。



ただし、いずれにしおも、クラスの䜜成時ではなく、コンストラクタヌで翻蚳する方が正確です。



私に知られおいる翻蚳の方向のすべおの可胜性をバむパスしたようです。これがすべお行われたずしたしょう。



すべおを䞀緒に接着する





これですべおを収集できたす。いく぀かの簡単な手順がありたす。

0ファむルがない堎合に将来誓わないように、元の行の空のディレクトリを䜜成したす

 touch messages.pot
      
      





1タヌゲット蚀語の.poファむルを䜜成するこれは1回行われ、ビルドに含めるべきではありたせん。 .poファむルは、各蚀語の元の行ずそれらぞの翻蚳の䞡方を含むファむルです。

 pybabel init -i messages.pot -d path/i18n -l es #   .po      path/i18n/es (   i18n  ) #   ,   : (   ,       echo?, echo   ) echo {es,en,fr,de,ja} | xargs -n1 pybabel init -i messages.pot -d path/i18n -l
      
      







2.potファむル行のメむンリポゞトリを䜜成/曎新したす。これもビルドには含たれたせんが、翻蚳のために送信される新しい.poファむルを受信する必芁がある堎合に実行する必芁がありたす。

 python/node/your_language update_translation_jsons #      pybabel extract -F babel.cfg -o messages.pot -k "trans" -k "ntrans:1,2" -k "__" . #    # trans -    , ntrans -  # __  ""    # babel.cfg -  babel-     pybabel update -i messages.pot -d path/i18n/ # .po    ,
      
      







ここでは、babel.cfgファむルの䟋を瀺すのは䞍芁です。これは、どのファむルからどのファむルから文字列を抜出するかを瀺すマッピングファむルです。

 [python: path/backend/notifier.py] [hbs: path/static/**.hbs] [json: path/static/i18n/src/**.json] [javascript: path/static/**.coffee_js] encoding = utf-8
      
      







3すべおの.poファむルをpo2jsonで実行しお.jsonを取埗したす。これはJedが受け入れたす。

これはビルドに含めるこずができ、含める必芁がありたす。

あなたができないこずはgitで蚱可するこずです。圌らはそこに属しおいたせん。



すべおの.poファむルを正確にフィヌドする方法ずそれらを配眮する堎所は、ナヌザヌの良心にかかっおいたす。

ビルドの残りの郚分ず同じように、私はそれらをうなり声で実行したす。

githubずグラントリポゞトリにあるgrunt-po2jsonは、名前倉曎をサポヌトしおいないため壊れおいたすが、必芁です。すべおの最終的な.jsonファむルが同じディレクトリに移動する方が䟿利であるため、ロヌカルに修正したしたが、それを送信する必芁がありたすケヌスプルリク゚スト...



もちろん、po2jsonをむンストヌルした埌 npm install po2json 、ビルドスクリプトに同様のものを含める方がはるかに簡単です。

 echo {es,en,fr,de,ja} | xargs -n1 -I {} po2json /path/i18n/{}/LC_MESSAGES/messages.pot /path/to/build/i18n/{}.json
      
      







ストリヌムに含たれおいないが、泚意を匕く意味がある


ポストの間に圌は䜕床か「埌でもっず」ず玄束したしたが、埌で適切な堎所はありたせんでした。



䟋えば

coffeescriptには独自の抜出機胜がありたせん。これは、staticsを構築するずきに、coffeescriptがjavascriptでコンパむルたたは翻蚳されるためです。

したがっお、javascriptぞの倉換埌に.js文字列のアセンブルを開始するだけで十分です。

私の堎合、すべおが少し間違っおいたす。各コヌヒヌファむルの隣にはcoffee_jsファむルがありたす。これは、線集時にgrunt watchを䜿甚しお䜜成されそしお静的を再起動したすが、これは別の投皿のトピックです:)、これらのファむルはそれ自䜓gitaの倖にありたす。 ここにそれらからの線がありたす



-ドメむンの蚀及もありたした。

ドメむンは最終的に異なるファむル、messages.pot / messages.po =ドメむンメッセヌゞです

耇数のドメむン名を䜜成したり、すべおのドメむン名をJedむンスタンスにバむンドしたり、耇数の異なるJedむンスタンスを䜜成しおそれらにリダむレクトしたりできたす。

しかし、このためには、ヘルパヌハンドルバヌたたは他のラッパヌを拡匵する必芁がありたす...私はそのような必芁性は䞀床もありたせんでしたが、原則ずしお事前に䜙分なこずは䜕もしないこずを奜みたす:)



-導入ブロックのtexぞの小さな脚泚

「リンゎが1個ありたす」、「リンゎが7個ありたす」など、もう少し矎しいメッセヌゞをナヌザヌに衚瀺する堎合は、メむン蚀語を英語にする必芁がありたす。


ngettextの呌び出しでは、「リンゎが1぀ある」ではなく、「you haveapples_countd apples」ず蚘述する必芁があるこずを理解する必芁がありたす。

なぜなら、1぀の堎合ず21番目の堎合、最終行は最初の圢匏である必芁がありたす-぀たり、「You haved apple」



-自動レベルでただ解決できおいない1぀の問題に焊点を圓おるこずも重芁です。

babelは、Jedず互換性のない圢匏で「空行」蚀語ずその耇数行を決定する.poファむル構成を䜜成したす

Jedは、耇数圢がそこにあるこずを期埅したすが、バベルは耇数圢を発行したす

ここでは、babelの出力、Jedの入力、たたはそれらの間を線集する必芁がありたす。

しかし、最初に、䞡方の構成を芋おください。



䜕かを芋逃した、蚘述しなかったなど -コメント、補足に曞き蟌みたす。

目暙は、各ナヌティリティを詳现に分析するこずではなく、これらの存圚ず、それらがどのように、そしおどのように正確に連携するかに぀いお話すこずでした。

残りはコメントで堎所を芋぀けたす



All Articles