Ruby gettextを使った翻訳作業の流れ
Rakeを使った翻訳作業の流れ
code:shell
% rake -Tgettext
rake gettext # Update *.mo
rake gettext:mo:en:update # Update locale/en/LC_MESSAGES/pirka.mo
rake gettext:mo:update # Update *.mo
rake gettext:po:addlocale # Add a new locale rake gettext:po:en:update # Update po/en/pirka.po
rake gettext:po:update # Update *.po
rake gettext:pot:create # Create po/pirka.pot
設定
方法1:Gem::Specificationから設定する
code:rakelib/translate.rb
require "rubygems/specification"
require "gettext/tools/task"
GetText::Tools::Task.define do |t|
t.spec = Gem::Specification.load("pirka.gemspec")
end
この時、同時にpoディレクトリーと、一つだけ言語用のディレクトリー(po/enなど)を作っておく必要がある
必ず一つ言語を指定する必要があるから。
Rakefileで指定しない場合は、ディレクトリーの存在から推測してくれる
ディレクトリーはpo以外も指定できる。指定がない場合はpoになる。
方法2
(何か試したら書く)
ソースコードのマークアップ
ソースコード中の翻訳したい文字列を_()とかn_()で囲む
クラスにはinclude GetTextして、bindtextdomain()を設定する。ドメイン名は↑のRakeタスクで設定した物と同じ物を使う
code:app.rb
module Pirka
class App
include GetText
bindtextdomain "pirka"
DESCRIPTION = _("Pirka highlights source code syntax in EPUB files")
:
:
end
end
gemspecから設定した場合は、gem名になる
gem名がpirikaと小文字なんだけど、テクストドメインはそれと関係なく何でもいいと思い込んで、bindtextdomain "Pirka"とキャピタルケースにしてしまってハマった
翻訳作業用ファイルの生成
code:shell
% rake gettext
poとlocaleディレクトリーに必要なファイルを作ってくれる(localeディレクトリーも、オプションで変更できる)
特にpo/pirka.potを作ってくれる
以後言語を増やす時にこの*.potファイルをテンプレートとして増やすのでこれが大事
言語の追加
code:shell
poとlocaleに日本語用のファイルを作ってくれる
翻訳
po/ja/pirka.edit.poみたいな*.edit.poに翻訳を追加する
po/ja/pirka.poじゃないので注意
msgidが原文なのでこれをそのままにしつつ、
msgstrに日本語を書く
翻訳用ファイルの作成・更新
code:shell
% rake gettext
すると、po/ja/pirka.poにも翻訳文が反映される
これを元に*.moファイルが作られる
locale/ja/LC_MESSAGE/pirka.moにも反映される
これはバイナリーフォーマットの翻訳文が入ったファイルで、実際の翻訳時にはこれが使われる
確認はmsgunfmtコマンドでできる
これはgettextパッケージを入れると入ってくる
Ruby版のrmsgunfmtがあってもいいのでは?
code:shell
% msgunfmt locale/ja/LC_MESSAGES/pirka.mo
msgid ""
msgstr ""
"Project-Id-Version: pirka 0.1.6\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2020-01-12 02:38+0900\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Japanese\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"\n"
msgid "Pirka highlights source code syntax in EPUB files"
msgstr "PirkaはEPUBファイル中のソースコードをシンタックスハイライトします"
コミットする
*.poファイルをコミットする
*.potファイルと*.edit.poファイルと*.moファイルはコミットしない
*.moはコミットしないがgemパッケージには入れたい
これで、ソースコード中の_()とかが実行されるようになる
code:shell
% LANG=ja_JP.UTF-8 pirka -h
PirkaはEPUBファイル中のソースコードをシンタックスハイライトします
:
(snip)
:
チップス
文字列埋め込みは?
文字列への式の埋め込みではなくて、String#%とかを使う。
code:app.diff
+ $stdout.puts "library: %{path}" % {path: path}
必要であれば変数を別途翻訳対象にしておく:_(path) = ...
ヒアドキュメントは?
翻訳対象にしたいっすね……
翻訳者向けのコメントを埋め込むには?
%{path}はそのまま残してください、とか、埋め込みたいけど、# TRANSLATORS: ...が動いてない気がする
文字エンコーディングの扱い
難しいっすね。。。
WindowsでPowerShellでコードページが932の時_()の戻り値がWindows-31Jになって、String#%でUTF-8の日本語文字列と結合しようとしてエラーになる
逐一_()の戻り値のエンコーディングを見て、String#%(とか、とにかく一緒に扱うやつ)する時に引数の方をencodeするのがいいのかなあ
なんかおかしい気がするが・・・
全個所にこの処理入れるのは無駄作業っぽいのでうまいことやりたい。
_()の戻り値の文字列を拡張して、%を呼んだ時引数を自動でencodeするとか
_()の戻り値の方をスクリプトエンコーディングにエンコードして回るのもあり
これはラッパーを書けばいいから簡単かな
rxgettextで抜き取りたいから、ラッパーというよりは同名メソッドかな
_("...").encode(__ENCODING__)でうまくいきそう(コマンドラインアプリの場合)
テストケース
Windows
cp932
そのまま -> 日本語
LANG指定 -> 日本語
cp65001
そのまま -> 英語
LANG指定 -> 日本語
Linux
LANG=C -> 英語
日本語 -> 日本語
macOS
持ってない
_("Executing \\`%{command}\\`") % {command: command}がうまく動かない
なんだろう・・・
バックスラッシュの扱いがおかしそう
参考