Skip to content

Commit

Permalink
feat: improve PlugLocale.WebBrowser helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
c4710n committed Dec 30, 2023
1 parent 0514840 commit c02d394
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 13 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
Breaking changes:

- rename `:sanitize_locale_by` option `:cast_locale_by`
- rename `PlugLocale.WebBrowser.build_localized_path` to `PlugLocale.WebBrowser.build_locale_path`

New Features:

- add `PlugLocale.WebBrowser.put_locale_resp_cookie/2` / `PlugLocale.WebBrowser.put_locale_resp_cookie/3`

## v0.3.0

Expand Down
47 changes: 35 additions & 12 deletions lib/plug_locale/web_browser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -145,23 +145,26 @@ defmodule PlugLocale.WebBrowser do
`#{inspect(__MODULE__)}` also provides some helper functions, which will be useful
when implementing UI components:
* `build_localized_path/2`
* `build_locale_path/2`
* `put_locale_resp_cookie/2` / `put_locale_resp_cookie/3`
Check out their docs for more details.
### an example UI component - simple locale switcher
```heex
<ul>
<li>
<a
href={PlugLocale.WebBrowser.build_localized_path(@conn, "en")}
href={PlugLocale.WebBrowser.build_locale_path(@conn, "en")}
aria-label="switch to locale - en"
>
English
</a>
</li>
<li>
<a
href={PlugLocale.WebBrowser.build_localized_path(@conn, "zh")}
href={PlugLocale.WebBrowser.build_locale_path(@conn, "zh")}
aria-label="switch to locale - zh"
>
中文
Expand Down Expand Up @@ -249,21 +252,41 @@ defmodule PlugLocale.WebBrowser do
@doc """
Builds a localized path for current path.
> Note: the locale passed to this function won't be casted by the function
> which is specified by `:cast_locale_by` option.
## Examples
# the request path of conn is /posts/7
iex> build_localized_path(conn, "en")
iex> build_locale_path(conn, "en")
"/en/posts/7"
# the request path of conn is /en/posts/7
iex> build_localized_path(conn, "zh")
iex> build_locale_path(conn, "zh")
"/zh/posts/7"
"""
@spec build_localized_path(Plug.Conn.t(), String.t()) :: String.t()
def build_localized_path(conn, locale) do
@spec build_locale_path(Plug.Conn.t(), String.t()) :: String.t()
def build_locale_path(%Plug.Conn{} = conn, locale) do
%{config: config} = Map.fetch!(conn.private, @private_key)
build_locale_path(conn, config, locale)
__build_locale_path__(conn, config, locale)
end

@doc """
Puts a response cookie for locale in the connection.
See `Plug.Conn.put_resp_cookie/4` for more details.
## Examples
iex> put_locale_resp_cookie(conn, "en")
iex> put_locale_resp_cookie(conn, "zh", max_age: 365 * 24 * 60 * 60)
"""
@spec put_locale_resp_cookie(Plug.Conn.t(), String.t()) :: Plug.Conn.t()
def put_locale_resp_cookie(%Plug.Conn{} = conn, locale, opts \\ []) do
%{config: %{cookie_key: key}} = Map.fetch!(conn.private, @private_key)
put_resp_cookie(conn, key, locale, opts)
end

defp continue(conn, config, locale) do
Expand All @@ -282,15 +305,15 @@ defmodule PlugLocale.WebBrowser do

locale = cast_locale(config, locale, default: config.default_locale)

path = build_locale_path(conn, config, locale)
path = __build_locale_path__(conn, config, locale)

conn
|> redirect_to(path)
|> halt()
end

# support for Phoenix
defp build_locale_path(
defp __build_locale_path__(
%Plug.Conn{private: %{phoenix_router: router}} = conn,
config,
locale
Expand All @@ -300,7 +323,7 @@ defmodule PlugLocale.WebBrowser do
end

# support for Plug
defp build_locale_path(
defp __build_locale_path__(
%Plug.Conn{private: %{plug_route: {_route, _callback}}} = conn,
config,
locale
Expand All @@ -309,7 +332,7 @@ defmodule PlugLocale.WebBrowser do
convert_route_info_to_locale_path(route_info, conn, config, locale)
end

defp build_locale_path(%Plug.Conn{} = conn, _config, locale) do
defp __build_locale_path__(%Plug.Conn{} = conn, _config, locale) do
build_path([locale | conn.path_info])
end

Expand Down
52 changes: 51 additions & 1 deletion test/plug_locale/web_browser_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,45 @@ defmodule PlugLocale.WebBrowserTest do
end
end

@opts DemoRouter.init([])
defmodule DemoRouterWithPuttingCookie do
use Plug.Router

plug :match

plug PlugLocale.WebBrowser,
default_locale: "en",
locales: ["en", "zh-Hans"],
detect_locale_from: [:query, :cookie, :referrer, :accept_language]

plug :put_cookie

plug :dispatch

def put_cookie(conn, _opts) do
if locale = conn.assigns[:locale] do
PlugLocale.WebBrowser.put_locale_resp_cookie(conn, locale, max_age: 3600)
else
conn
end
end

get "/posts/:id" do
%{"id" => id} = conn.params
send_resp(conn, 200, "post: #{id}")
end

get "/:locale/posts/:id" do
%{"id" => id} = conn.params
%{locale: locale} = conn.assigns
send_resp(conn, 200, "post: #{locale} - #{id}")
end

match _ do
send_resp(conn, 404, "oops")
end
end

@opts []

describe "path without locale" do
test "is redirected to a detected path - default locale" do
Expand Down Expand Up @@ -186,6 +224,18 @@ defmodule PlugLocale.WebBrowserTest do
assert log =~ ":cookies of conn is still unfetched"
end

test "build_locale_path/2" do
conn = conn(:get, "/en/posts/7")
conn = DemoRouter.call(conn, @opts)
assert "/zh-Hans/posts/7" == PlugLocale.WebBrowser.build_locale_path(conn, "zh-Hans")
end

test "put_locale_resp_cookie/2" do
conn = conn(:get, "/en/posts/7")
conn = DemoRouterWithPuttingCookie.call(conn, @opts)
assert %Plug.Conn{cookies: %{"locale" => "en"}} = fetch_cookies(conn)
end

# credo:disable-for-next-line
# TODO: add tests for Phoenix router
end

0 comments on commit c02d394

Please sign in to comment.