20
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Phoenixで多言語化(i18n)

Posted at

環境

  • Phoenix 1.2
  • Elixir 1.3.3

やること

Phoenix標準でサポートされている Gettext でi18nします

Gettextとは

poファイルやpotファイルで多言語化するライブラリです。
ソースファイル中のi18n用関数をmix taskのmix gettext.extractmix 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を変えるようにした
20
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?