gettext:Javascriptのアンテロープローストレシピ


CMFを開発するときに、i18n(多言語)を正しく実装する必要に直面し、さまざまなオプションを検討し始めました...

まず、過去の経験に基づいて、数字のハックで「言語定数」と苦難を作りたかった。 しかし、幸いなことに、強力で人気のある(Unixベースの)ツールであるGNU gettextを選択しました。 すぐに、検索エンジンによって索引付けされていないフレーズの翻訳でサーバーをオーバーロードすることは意味がなく、場合によってはクライアントで翻訳する方が良いことに気付きました。 ただし、単一の形式で翻訳を行うには、統一されたシステムが必要でした。
gettext javascriptをググリングして、いくつかの実装を見ました。

最初のキャッチ-code.google.com/p/gettext-js
プラスは、元のpoファイルの追加の変換を必要としないことです。マイナス-ngettextはありません。

次に、 plugins.jquery.com / project / gettextを見つけました
私はそれを使用することにしました。 ただし、プラグインでは、MOファイルから特別なJSONファイルを準備する必要があります。

変換のために、Pythonで関数が提供されます。
import simplejson as enc import gettext def gettext_json(domain, path, lang = [], indent = False): try: tr = gettext.translation(domain, path, lang) # for unknown reasons, instead of having plural entries like # key: [sg, pl1...] # tr._catalog has (key, n): pln, keys = tr._catalog.keys() keys.sort() ret = {} for k in keys: v = tr._catalog[k] if type(k) is tuple: if k[0] not in ret: ret[k[0]] = [] ret[k[0]].append(v) else: ret[k] = v return enc.dumps(ret, ensure_ascii = False, indent = indent) except IOError: return None 


コードを修正して動作させるために、gugglezhとドックの調査に20分費やさなければなりませんでした。 その結果、私は通常のUnixプログラムを誕生させました。

gettext2json
 #!/usr/bin/python import sys import simplejson as enc import gettext def gettext_json(domain, path, lang = [], indent = False): try: tr = gettext.translation(domain, path, lang) # for unknown reasons, instead of having plural entries like # key: [sg, pl1...] # tr._catalog has (key, n): pln, keys = tr._catalog.keys() keys.sort() ret = {} for k in keys: v = tr._catalog[k] if type(k) is tuple: if k[0] not in ret: ret[k[0]] = [] ret[k[0]].append(v) else: ret[k] = v return enc.dumps(ret, ensure_ascii = True, indent = indent) except IOError as (errno, strerror): print "I/O error({0}): {1}".format(errno, strerror) print gettext_json(sys.argv[1],sys.argv[2],[sys.argv[3]], True) 


また、テキストPOファイルからバイナリMOファイルを作成するプロセスを自動化することにしました。

BuildLocales:
 #!/usr/bin/php -q <?php chdir(__DIR__); $lcPath = './locale'; $jsPath = './static/locale'; foreach (glob($lcPath.'/*/LC_MESSAGES/*.po') as $poFile) { $locale = pathinfo(dirname(dirname($poFile)), PATHINFO_FILENAME); $domain = pathinfo($poFile, PATHINFO_FILENAME); $moFile = dirname($poFile).'/'.$domain.'.mo'; $jsFile = $jsPath.'/'.$locale.'/'.$domain.'.json'; shell_exec('mkdir -p '.escapeshellarg($jsPath.'/'.$locale)); shell_exec('msgfmt -o '.escapeshellarg($moFile).' '.escapeshellarg($poFile)); $cmd = 'gettext2json '.escapeshellarg($domain).' '.escapeshellarg($lcPath ).' '.escapeshellarg($locale).' > '.escapeshellarg($jsFile); shell_exec($cmd); } 

したがって、すべてのファイルを準備するには、ロケールフォルダー内のテキスト.poファイルを作成/変更し、BuildLocalesスクリプトを実行するだけです。

gettextをJavascriptに接続するには、htmlタグのlang属性を指定し、ヘッドにjsonファイルへのパスを持つリンク要素を追加し、jquery.gettext.jsをロードする必要があります。

ページのHTMLコードの先頭は次のようになります。

 <!DOCTYPE html> <html lang="ru"> ... <link href="/locale/ru/mydomain.json" lang="ru" rel="gettext"/> <script type="text/javascript" src="/js/jquery.gettext.js" /> ... 


その後、関数_(「Hello world!」)を呼び出すことができます。 おっと! 動作しません!

jquery.gettext.jsで何かを修正し、パッチを適用する必要があります。

 63,66c63,70 < try { < var messages = eval('(' + data + ')'); < } catch(e) { < return; --- > if (typeof(data) == 'object') { > var messages = data; > } else { > try { > var messages = eval('(' + data + ')'); > } catch(e) { > return; > } 

パッチを適用するのが面倒な人はjquery.gettext.jsを使用します。

ローストを楽しんだことを願っています。ご清聴ありがとうございました。

Source: https://habr.com/ru/post/J108348/


All Articles