Page MenuHomePhorge

Internationalization
Closed, ResolvedPublic

Description

Add a plug for internationalization, init the gettext generation.

Details

Ticket Type
Task

Revisions and Commits

Event Timeline

seigo raised the priority of this task from 40 to High.Nov 21 2016, 11:52 AM
seigo created this task.

To internationalize your Phoenix application, replace all the strings in your templates with the following function calls:

Simple strings

<%= gettext "Welcome to Phoenix" %>

Variable Interpolation

<%= gettext "Welcome to %{name}", name: "Phoenix" %>

Singular/Plural Handling

<%= ngettext "Products found", "%{count} products found", 1 %>

> Product found

<%= ngettext "Products found", "%{count} products found", 2 %>

> 2 products found

Domain Grouping

<%= dgettext "errors", "%{field} is not valid", field: "Name" %>
<%= dngettext "errors", "Product found", "%{count} products found", count %>

Extract all of the strings to .pot template files with:

$ mix gettext.extract

Update all your localizations with:

$ mix gettext.merge priv/gettext

Create new localizations with:

$ mix gettext.merge priv/gettext --locale {locale}

For example:

$ mix gettext.merge priv/gettext --locale fr
$ mix gettext.merge priv/gettext --locale en_UK

Edit localization .po files with PoEdit.
Locale Plug

To detect locales, create a plug like this:

defmodule MyApp.Locale do

import Plug.Conn

def init(opts), do: opts

def call(conn, _opts) do
  case conn.params["locale"] || get_session(conn, :locale) do
    nil -> 
      conn
    locale ->
      Gettext.put_locale(MyApp.Gettext, locale)
      put_session(conn, :locale, locale)
  end
end

end

And install it in your router like so:

pipeline :browser do

  1. ... plug MyApp.Locale

end

You can then visit http://localhost:4000/?locale=fr to change the strings to French, for example.

It would be nice to have a simple Makefile in the project's root that has entries like i18n so one can do make i18n and have the various mix commands run for you. I did similar for guam/egara to wrap the rebar commands, something similar here would be quite nice to avoid having to remember all the "right" steps for things like i18n generation.

Other ideas for this:

  • Support the Accept-Language header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
  • Eventually contribute this upstream, as it seems crazy this is not already available with Plug and/or Pheonix; this would mean having some basic configurability of the Plug (via params passed in on the "plug LocalePlug" line) to define what the session key is, what to look for in params (if anything), etc.