View Source PlugLocale.WebBrowser (plug_locale v0.1.1)
Puts locale into assigns
storage for Web browser environment.
The most common way of specifying the desired locale is via the URL. In general, there're three methods to do that:
- via domain name -
https://<locale>.example.com
, such as:https://en.example.com/welcome
https://zh.example.com/welcome
- via path -
https://example.com/<locale>
, such as:https://example.com/en/welcome
https://example.com/zh/welcome
- via querystring -
https://example.com?locale=<locale>
, such as:https://example.com/welcome?locale=en
https://example.com/welcome?locale=zh
Personally, I think method 2 is better,compared to the other two methods:
- method 1 is tedious for deployment.
- URLs generated by method 3 look very ugly and unprofessional.
Because of that, this plug will stick on method 2.
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.PlugWebBrowserLocalization do
use Plug.Builder
plug PlugLocale.WebBrowser,
default_locale: "en",
locales: ["en", "zh"],
route_identifier: :locale,
assign_key: :locale
plug :set_locale
def set_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 :browser do
plug :accepts, ["html"]
# ...
plug DemoWeb.PlugWebBrowserLocalization
# ...
end
scope "/", DemoWeb do
pipe_through :browser
get "/", PageController, :index
# ...
end
# Why using :locale?
# Because it is specified by `:route_identifier` option.
scope "/:locale", DemoWeb do
pipe_through :browser
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. SeePlugLocale.Sanitizer
for more details.:route_identifier
- the part for identifying locale in route. Default to:locale
.:assign_key
- the key for putting value intoassigns
storage. Default to the value of:route_identifier
option.:cookie_key
- the key for reading locale from cookie. Default to"preferred_locale"
.
How it works?
This plug will try to:
- extract locale from URL, and check if the locale is supported:
- If it succeeds, put locale into
assigns
storage。 - If it fails, jump to step 2.
- If it succeeds, put locale into
- detect locale from Web browser environment, then redirect to the path corresponding to detected locale.
Extract locale from URL
For example, the locale extracted from https://example.com/en/welcome
is en
.
Detect locale from Web browser environment
Local is detected from multiple places:
- cookie (whose key is specified by
:cookie_key
option) - HTTP request header -
referer
- HTTP request header -
accept-language
- default locale (which is specified by
:default_locale
option)
Examples
When:
:default_locale
option is set to"en"
:locales
option is set to["en", "zh"]
For users in an English-speaking environment:
https://example.com/en
will be responded directly.https://example.com/
will be redirected tohttps://example.com/en
.https://example.com/path
will be redirected tohttps://example.com/en/path
.https://example.com/unknown
will be redirected tohttps://example.com/en
.- ...
For users in an Chinese-speaking environment:
https://example.com/zh
will be responded directly.https://example.com/
will be redirected tohttps://example.com/zh
.https://example.com/path
will be redirected tohttps://example.com/zh/path
.https://example.com/unknown
will be redirected tohttps://example.com/zh
.- ...