Elixir
ElixirDay 20

iexでの日本語版ヘルプの使い方

More than 1 year has passed since last update.

Elixir Advent Calendar 2014 20日目。前日は @ma2ge さんの excoveralls で Elixir プロジェクトのカバレッジレポートを取る でした。

はじめに

elixir自体はUTF-8を採用しているため、いわゆる国際化(i18n)されています。しかしながら、多言語化(m17n)はされておらず、基本は英語(en)のみです。iexにはドキュメントが豊富に揃っているのにもったいないと思い、地域化(l10n)してみました。今回は、その宣伝(すみません)をかねて、elixirリファレンスの日本語版を組み込む方法です。

準備

l10n_elixir というパッケージをcloneします。

air13:erl k-1$ git clone https://github.com/k1complete/l10n_elixir.git
Cloning into 'l10n_elixir'...
remote: Counting objects: 813, done.
remote: Total 813 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (813/813), 1.12 MiB | 229.00 KiB/s, done.
Resolving deltas: 100% (321/321), done.
Checking connectivity... done.
air13:erl k-1$ 

その後、ビルドすると、依存パッケージをダウンロードしながらビルドされます。

air13:l10n_elixir k-1$ mix deps.get
* Getting exgettext (https://github.com/k1complete/exgettext.git)
Cloning into '/Users/k-1/work/erl/l10n_elixir/deps/exgettext'...
remote: Counting objects: 403, done.
remote: Total 403 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (403/403), 202.85 KiB | 149.00 KiB/s, done.
Resolving deltas: 100% (200/200), done.
Checking connectivity... done.
* Getting l10n_iex (https://github.com/k1complete/l10n_iex.git)
Cloning into '/Users/k-1/work/erl/l10n_elixir/deps/l10n_iex'...
remote: Counting objects: 108, done.
remote: Total 108 (delta 0), reused 0 (delta 0)
(略)
==> l10n_elixir
Compiled lib/l10n_elixir.ex
Generated l10n_elixir.app
msgfmt for l10n_elixir
priv/po/ja.po /Users/k-1/work/erl/l10n_elixir/_build/dev/lib/l10n_elixir/priv/lang/ja/l10n_elixir.exmo
air13:l10n_elixir k-1$ 

つかってみる

ビルドできたので、ためしに使ってみます。試しで使うためには、先ほどビルドしたディレクトリでiex -S mixとすることで、現在のプロジェクト(つまりl10n_elixir)を読み込むことができますので、それを利用します。

air13:l10n_elixir k-1$ iex -S mix 
Erlang/OTP 17 [erts-6.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.1.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> h Enum.into/2            

                           def into(collection, list)                           

Inserts the given enumerable into a collectable.

Examples

┃ iex> Enum.into([1, 2], [0])
┃ [0, 1, 2]
┃ 
┃ iex> Enum.into([a: 1, b: 2], %{})
┃ %{a: 1, b: 2}

iex(2)> 

英語のままですが、これは、ヘルパを有効にしていないためです。以下のコマンドでヘルパを有効にした後、同じことをしてみましょう。

iex(2)> import Exgettext.Helper
nil
iex(3)> h Enum.into/2            

                           def into(collection, list)                           

collectableに与えられたenumerableを挿入します。

例

┃ iex> Enum.into([1, 2], [0])
┃ [0, 1, 2]
┃ 
┃ iex> Enum.into([a: 1, b: 2], %{})
┃ %{a: 1, b: 2}

iex(4)> 

なお、環境変数LANGが"ja"的になっていることが条件です。あるいは、Exgettext.setlocale/1で明示的に"ja"を指定します。
翻訳のアレが何ですが、もし、気に入ったら、_build/dev/lib配下の4つのアプリ

をiexが認識する場所におく事でいつでも使うことができます。
翻訳自体は拙作なので、githubを個別にチェックして突っ込んでもらえると幸いです。また、リリースタイミングでタグを打っていますが、ドキュメントのブレが大きいと翻訳されないものが出てきます。

なお、ex_docにパッチをいれて、日本語リファレンスのwebページを作成していますので、読めれば良いという人はこちらをご覧くださいませ(内容は同等です)。

仕組みについて

この仕組みは、国際化支援ライブラリGNU gettextを内部で利用していて、翻訳ファイルは.poファイルそのものです。
全体の流れは、以下のようになっています。

  • ビルド時にソースファイル中から翻訳ターゲット文字列を抜き出し、potファイル(翻訳テンプレート)を作成するマクロを作り、Sigil_T/2でマークアップする。さらに、@doc@moduledocもスキャンしておく。
  • .potファイルから.poファイルを作成したり、マージするタスクをmixタスクとして作成。
  • .poファイルをdetsファイルにコンパイルするコンパイラをmixタスクとして作成。
  • Sigil_T/2は、現在のロケールに従い、翻訳ファイルdetsを参照して置き換えるという内容になっているので、実行すると、翻訳された文字列が出力される。

これらをどうやって作ったかについては、

を参照してください。
以上、iexでの日本語版ヘルプを使う方法でした。

明日は @ryuone さんです。