Current section
Files
Jump to
Current section
Files
lib/plug_locale/header.ex
defmodule PlugLocale.Header do
@moduledoc """
Puts locale into `assigns` storage according to given HTTP request header.
> This is generally used by HTTP API for clients like mobile apps.
By default, the used HTTP request header is `x-client-locale`. Although
there's a standard HTTP header - `accept-language`, but it is better to
use a custom header, because it is simpler and has no historical baggage
to overcome.
## Usage
First, we need to integrate this plug with other libraries, or this plug
is useless. All you need is to construct a plug pipeline through
`Plug.Builder`. For example:
defmodule DemoWeb.PlugMobileClientLocalization do
use Plug.Builder
plug PlugLocale.Header,
default_locale: "en",
locales: ["en", "zh"]
plug :put_locale
def put_locale(conn, _opts) do
if locale = conn.assigns[:locale] do
# integrate with gettext
Gettext.put_locale(locale)
end
conn
end
end
Then, use it in router (following one is a Phoenix router, but `Plug.Router`
is supported, too):
defmodule DemoWeb.Router do
use DemoWeb, :router
pipeline :api do
plug :accepts, ["json"]
# ...
plug DemoWeb.PlugMobileClientLocalization
# ...
end
scope "/", DemoWeb do
pipe_through :api
get "/", PageController, :index
# ...
end
end
## Options
* `:default_locale` - the default locale.
* `:locales` - all the supported locales. Default to `[]`.
* `:sanitize_locale` - a function for sanitizing extracted or detected
locales. Default to `&PlugLocale.Sanitizer.sanitize/1` which does
nothing. See `PlugLocale.Sanitizer` for more details.
* `:header_name` - the header for getting locale.
Default to `"x-client-locale"`.
* `:assign_key` - the key for putting value into `assigns` storage.
Default to `:locale`.
"""
@behaviour Plug
import Plug.Conn
alias __MODULE__.Config
@impl true
def init(opts), do: Config.new!(opts)
@impl true
def call(conn, config) do
locale = get_locale_from_header(conn, config)
locale =
if locale do
locale = config.sanitize_locale.(locale)
if locale in config.locales, do: locale, else: config.default_locale
else
config.default_locale
end
assign(conn, config.assign_key, locale)
end
defp get_locale_from_header(conn, config) do
case get_req_header(conn, config.header_name) do
[locale | _] -> locale
_ -> nil
end
end
end