Skip to content

Commit

Permalink
feat: rename :sanitize_locale_by option :cast_locale_by
Browse files Browse the repository at this point in the history
  • Loading branch information
c4710n committed Dec 30, 2023
1 parent 7811d29 commit a94df77
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 80 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Changelog

## Unreleased

Breaking changes:

- rename `:sanitize_locale_by` option `:cast_locale_by`

## v0.3.0

Breaking changes:

- `:sanitize_locale` is renamed to `:sanitize_locale_by`
- rename `:sanitize_locale` option `:sanitize_locale_by`
70 changes: 58 additions & 12 deletions lib/plug_locale/header.ex
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,50 @@ defmodule PlugLocale.Header do
* `:default_locale` - the default locale.
* `:locales` - all the supported locales. Default to `[]`.
* `:sanitize_locale_by` - specify the function for sanitizing extracted or
detected locales. Default to `&PlugLocale.Sanitizer.sanitize/1` which does
nothing. See `PlugLocale.Sanitizer` for more details.
* `:cast_locale_by` - specify the function for casting extracted or
detected locales. Default to `nil`.
* `: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`.
### about `:cast_locale_by` option
By default, the value is `nil`, which means doing nothing. But, in practice,
you will need to use something meaningful.
A possible implementation:
defmodule DemoWeb.I18n do
def cast_locale(locale) do
case locale do
# explicit matching on supported locales
locale when locale in ["en", "zh"] ->
locale
# fuzzy matching on en locale
"en-" <> _ ->
"en"
# fuzzy matching on zh locale
"zh-" <> _ ->
"zh"
# fallback for unsupported locales
_ ->
"en"
end
end
end
Then, use above implementation for plug:
plug `#{inspect(__MODULE__)}`,
default_locale: "en",
locales: ["en", "zh"],
sanitize_locale_by: &DemoWeb.I18n.cast_locale/1,
# ...
"""

@behaviour Plug
Expand All @@ -83,16 +119,9 @@ defmodule PlugLocale.Header do
@impl true
def call(conn, config) do
locale = get_locale_from_header(conn, config)
casted_locale = cast_locale(config, locale, default: config.default_locale)

locale =
if locale do
locale = config.sanitize_locale_by.(locale)
if locale in config.locales, do: locale, else: config.default_locale
else
config.default_locale
end

assign(conn, config.assign_key, locale)
assign(conn, config.assign_key, casted_locale)
end

defp get_locale_from_header(conn, config) do
Expand All @@ -101,4 +130,21 @@ defmodule PlugLocale.Header do
_ -> nil
end
end

defp cast_locale(config, locale, opts \\ []) do
default = Keyword.get(opts, :default, nil)

if locale do
casted_locale =
if is_function(config.cast_locale_by, 1),
do: config.cast_locale_by.(locale),
else: locale

if casted_locale in config.locales,
do: casted_locale,
else: default
else
default
end
end
end
11 changes: 5 additions & 6 deletions lib/plug_locale/header/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule PlugLocale.Header.Config do
defstruct [
:default_locale,
:locales,
:sanitize_locale_by,
:cast_locale_by,
:header_name,
:assign_key
]
Expand All @@ -13,18 +13,17 @@ defmodule PlugLocale.Header.Config do
def new!(opts) when is_list(opts) do
default_locale = Keyword.get(opts, :default_locale)
locales = Keyword.get(opts, :locales, [])
sanitize_locale_by = Keyword.get(opts, :sanitize_locale_by, &PlugLocale.Sanitizer.sanitize/1)
cast_locale_by = Keyword.get(opts, :cast_locale_by, nil)
header_name = Keyword.get(opts, :header_name, "x-client-locale")
assign_key = Keyword.get(opts, :assign_key, :locale)

[
default_locale: default_locale,
locales: locales,
sanitize_locale_by: sanitize_locale_by,
cast_locale_by: cast_locale_by,
header_name: header_name,
assign_key: assign_key
]
|> validate!()
|> as_map!()
|> as_struct!()
end
Expand All @@ -43,14 +42,14 @@ defmodule PlugLocale.Header.Config do
defp as_map!(opts) do
default_locale = Keyword.fetch!(opts, :default_locale)
locales = Keyword.fetch!(opts, :locales)
sanitize_locale_by = Keyword.fetch!(opts, :sanitize_locale_by)
cast_locale_by = Keyword.fetch!(opts, :cast_locale_by)
header_name = Keyword.fetch!(opts, :header_name)
assign_key = Keyword.fetch!(opts, :assign_key)

%{
default_locale: default_locale,
locales: Enum.uniq([default_locale | locales]),
sanitize_locale_by: sanitize_locale_by,
cast_locale_by: cast_locale_by,
header_name: header_name,
assign_key: assign_key
}
Expand Down
50 changes: 0 additions & 50 deletions lib/plug_locale/sanitizer.ex

This file was deleted.

49 changes: 44 additions & 5 deletions lib/plug_locale/web_browser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,11 @@ defmodule PlugLocale.WebBrowser do
* `:default_locale` - the default locale.
* `:locales` - all the supported locales. Default to `[]`.
* `:detect_locale_from` - specify *the sources* and *the order of sources*
for detecting locale.
for detecting locale.
Available sources are `:query`, `:cookie`, `:referrer`, `:accept_language`.
Default to `[:cookie, :referrer, :accept_language]`.
* `:sanitize_locale_by` - specify the function for sanitizing extracted or
detected locales. Default to `&PlugLocale.Sanitizer.sanitize/1` which does
nothing. See `PlugLocale.Sanitizer` for more details.
* `:cast_locale_by` - specify the function for casting extracted or
detected locales. Default to `nil`.
* `:route_identifier` - the part for identifying locale in route.
Default to `:locale`.
* `:assign_key` - the key for putting value into `assigns` storage.
Expand All @@ -102,6 +101,43 @@ defmodule PlugLocale.WebBrowser do
* `:cookie_key` - the key for getting locale from cookie.
Default to `"preferred_locale"`.
### about `:cast_locale_by` option
By default, the value is `nil`, which means doing nothing. But, in practice,
you will need to use something meaningful.
A possible implementation:
defmodule DemoWeb.I18n do
def cast_locale(locale) do
case locale do
# explicit matching on supported locales
locale when locale in ["en", "zh"] ->
locale
# fuzzy matching on en locale
"en-" <> _ ->
"en"
# fuzzy matching on zh locale
"zh-" <> _ ->
"zh"
# fallback for unsupported locales
_ ->
"en"
end
end
end
Then, use above implementation for plug:
plug `#{inspect(__MODULE__)}`,
default_locale: "en",
locales: ["en", "zh"],
cast_locale_by: &DemoWeb.I18n.cast_locale/1,
# ...
## Helper functions
`#{inspect(__MODULE__)}` also provides some helper functions, which will be useful
Expand Down Expand Up @@ -426,7 +462,10 @@ defmodule PlugLocale.WebBrowser do
default = Keyword.get(opts, :default, nil)

if locale do
casted_locale = config.sanitize_locale_by.(locale)
casted_locale =
if is_function(config.cast_locale_by, 1),
do: config.cast_locale_by.(locale),
else: locale

if casted_locale in config.locales,
do: casted_locale,
Expand Down
11 changes: 5 additions & 6 deletions lib/plug_locale/web_browser/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule PlugLocale.WebBrowser.Config do
:default_locale,
:locales,
:detect_locale_from,
:sanitize_locale_by,
:cast_locale_by,
:route_identifier,
:path_param_key,
:assign_key,
Expand All @@ -21,7 +21,7 @@ defmodule PlugLocale.WebBrowser.Config do
detect_locale_from =
Keyword.get(opts, :detect_locale_from, [:cookie, :referrer, :accept_language])

sanitize_locale_by = Keyword.get(opts, :sanitize_locale_by, &PlugLocale.Sanitizer.sanitize/1)
cast_locale_by = Keyword.get(opts, :cast_locale_by, nil)
route_identifier = Keyword.get(opts, :route_identifier, :locale)
assign_key = Keyword.get(opts, :assign_key, route_identifier)
query_key = Keyword.get(opts, :query_key, to_string(route_identifier))
Expand All @@ -31,13 +31,12 @@ defmodule PlugLocale.WebBrowser.Config do
default_locale: default_locale,
locales: locales,
detect_locale_from: detect_locale_from,
sanitize_locale_by: sanitize_locale_by,
cast_locale_by: cast_locale_by,
route_identifier: route_identifier,
assign_key: assign_key,
query_key: query_key,
cookie_key: cookie_key
]
|> validate!()
|> as_map!()
|> as_struct!()
end
Expand All @@ -57,7 +56,7 @@ defmodule PlugLocale.WebBrowser.Config do
default_locale = Keyword.fetch!(opts, :default_locale)
locales = Keyword.fetch!(opts, :locales)
detect_locale_from = Keyword.fetch!(opts, :detect_locale_from)
sanitize_locale_by = Keyword.fetch!(opts, :sanitize_locale_by)
cast_locale_by = Keyword.fetch!(opts, :cast_locale_by)
route_identifier = Keyword.fetch!(opts, :route_identifier)
assign_key = Keyword.fetch!(opts, :assign_key)
query_key = Keyword.fetch!(opts, :query_key)
Expand All @@ -67,7 +66,7 @@ defmodule PlugLocale.WebBrowser.Config do
default_locale: default_locale,
locales: Enum.uniq([default_locale | locales]),
detect_locale_from: detect_locale_from,
sanitize_locale_by: sanitize_locale_by,
cast_locale_by: cast_locale_by,
route_identifier: route_identifier,
path_param_key: to_string(route_identifier),
assign_key: assign_key,
Expand Down

0 comments on commit a94df77

Please sign in to comment.