環境
- Phoenix 1.2
- Elixir 1.3.3
やること
Phoenix標準でサポートされている Gettext でi18nします
Gettextとは
po
ファイルやpot
ファイルで多言語化するライブラリです。
ソースファイル中のi18n用関数をmix taskのmix gettext.extract
、mix gettext.merge
からpo
ファイル, pot
ファイルを自動的に生成してくれます。
Installation
-
mix.exs
に依存を追加
def deps do
[{:gettext, "~> 0.8"}]
end
- application起動時にgettextも起動するよう変更
def application do
[applications: [:gettext, :logger]]
end
- 依存を更新
mix deps.get
Usage
- Gettext用のモジュールを作成
web/gettext.ex
defmodule MyApp.Gettext do
use Gettext, otp_app: :my_app
end
-
gettext
を使う
defmodule MyApp.FooBar do
import MyApp.Gettext
def foo do
gettext "foo"
end
def bar do
name = "shufo"
message = "How are you?"
gettext "Hello, %{name}. %{message}", name: name, message: message
end
end
-
pot
ファイル(多言語化のためのテンプレート)を生成
mix gettext.extract
priv/gettext/default.pot
に以下のようなファイルが生成される
## This file is a PO Template file.
##
## `msgid`s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run `mix gettext.extract` to bring this file up to
## date. Leave `msgstr`s empty as changing them here as no
## effect: edit them in PO (`.po`) files instead.
msgid ""
msgstr ""
"Language: INSERT LANGUAGE HERE\n"
#: web/foobar.ex:5
msgid "foo"
msgstr ""
#: web/foobar.ex:11
msgid "Hello, %{name}. %{message}"
msgstr ""
これを元に各po
ファイルを生成します
-
po
ファイル(実際に多言語化するための文言を書き込むファイル)を生成
mix gettext.merge priv/gettext --locale ja
priv/gettext/ja/LC_MESSAGES/default.po
に以下のようなファイルが生成されます
## `msgid`s in this file come from POT (.pot) files.
##
## Do not add, change, or remove `msgid`s manually here as
## they're tied to the ones in the corresponding POT file
## (with the same domain).
##
## Use `mix gettext.extract --merge` or `mix gettext.merge`
## to merge POT files into PO files.
msgid ""
msgstr ""
"Language: ja\n"
#: web/foobar.ex:5
msgid "foo"
msgstr "フー"
#: web/foobar.ex:11
msgid "Hello, %{name}. %{message}"
msgstr "こんにちは %{name} さん。%{message}"
Languageがja
となっているのが分かります。ここに実際の各言語の翻訳を書いていきます。
以降はgettext/1
をソース内に記述したら都度mix gettext.extract
でテンプレートを更新してmix gettext.merge priv/gettext
で各言語ファイルに展開するという作業をします。
デフォルト Locale
これだけではgettext
で翻訳を呼び出したとき日本語にならないのでデフォルトのlocaleとしてja
を設定します
config/config.exs
config :my_app, MyApp.Gettext,
default_locale: "ja"
これでデフォルトでlocaleがja
の翻訳ファイルが参照されるようになります。
Localeの切り替え
ユーザの条件やリクエスト時のパラメータによってlocaleを変更するにはPlug等で都度localeをセットします
web/plugs/locale.ex
defmodule MyApp.Plug.Locale do
import Plug.Conn
def init(opts), do: nil
def call(conn, _opts) do
case conn.params["locale"] || get_session(conn, :locale) do
nil -> conn
locale ->
Gettext.put_locale(StreamingChat.Gettext, locale)
conn |> put_session(:locale, locale)
end
end
end
web/router.ex
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
# 追加
plug MyApp.Plug.Locale
end
これでクエリパラメータにlocale
がある場合やセッションにlocaleが設定されている場合はそちらがlocaleとして設定され対応するpoファイルが読み込まれます
まとめ
- Gettextでi18nをした
-
mix gettext.extract
でテンプレートファイルを生成した後mix gettext.merge
で実際の多言語化ファイルを生成した - デフォルトのlocaleを設定した
- リクエストパラメータ等によってlocaleを変えるようにした