Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


This phoenix plug will help you with I18n url paths.
It can extract the preffered locale from the browsers accept-language header and redirect if an url without locale has been given.
It can extract the preffered locale from the browsers accept-language header and redirect if an url without locale has been given (only for GET method).
It will extract the locale from the url and check if that is valid and supported. If so it will assign it to ```conn.assigns.locale``` and set ```Gettext``` to that locale as well.
If it is not supported it will redirect to the default locale.

Expand Down
52 changes: 41 additions & 11 deletions lib/set_locale.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,55 @@ defmodule SetLocale do

def call(
%{
method: "GET",
request_path: request_path,
params: %{
"locale" => requested_locale
}
} = conn,
config
) do
), do: call_with_locale(conn, config, request_path, requested_locale)

def call(
%{
method: "HEAD",
request_path: request_path,
params: %{
"locale" => requested_locale
}
} = conn,
config
), do: call_with_locale(conn, config, request_path, requested_locale)

def call(
%{
method: "GET"
} = conn,
config
), do: call_without_locale(conn, config)

def call(
%{
method: "HEAD"
} = conn,
config
), do: call_without_locale(conn, config)

def call(conn, _config), do: conn

defp call_without_locale(conn, config) do
path = rewrite_path(conn, nil, config)

conn
|> redirect_to(path)
|> halt
end

defp call_with_locale(conn, config, request_path, requested_locale) do
if request_path != "/" and supported_locale?(requested_locale, config) do
if Enum.member?(config.additional_locales, requested_locale),
do: Gettext.put_locale(config.gettext, config.default_locale),
else: Gettext.put_locale(config.gettext, requested_locale)
do: Gettext.put_locale(config.gettext, config.default_locale),
else: Gettext.put_locale(config.gettext, requested_locale)
assign(conn, :locale, requested_locale)
else
path = rewrite_path(conn, requested_locale, config)
Expand All @@ -48,14 +86,6 @@ defmodule SetLocale do
end
end

def call(conn, config) do
path = rewrite_path(conn, nil, config)

conn
|> redirect_to(path)
|> halt
end

defp rewrite_path(%{request_path: request_path} = conn, requested_locale, config) do
locale = determine_locale(conn, requested_locale, config)

Expand Down
60 changes: 58 additions & 2 deletions test/set_locale_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ defmodule SetLocaleTest do
end

describe "when no locale is given and there is no cookie" do
test "when a root path is requested, it should redirect to default locale" do
test "when a root path is requested, it should redirect to default locale (GET metho)" do
assert Gettext.get_locale(MyGettext) == "en"

conn =
Expand All @@ -104,6 +104,17 @@ defmodule SetLocaleTest do
assert redirected_to(conn) == "/#{@default_locale}"
end

test "when a root path is requested, it should redirect to default locale (HEAD method)" do
assert Gettext.get_locale(MyGettext) == "en"

conn =
Phoenix.ConnTest.build_conn(:head, "/", %{})
|> Plug.Conn.fetch_cookies()
|> SetLocale.call(@default_options)

assert redirected_to(conn) == "/#{@default_locale}"
end

test "when headers contain accept-language, it should redirect to that locale if supported" do
assert Gettext.get_locale(MyGettext) == "en"

Expand Down Expand Up @@ -366,7 +377,7 @@ defmodule SetLocaleTest do
assert redirected_to(conn) == "/nl/foo/bar/baz"
end

test "should keep query strings as is" do
test "should keep query strings as is (GET method)" do
conn =
Phoenix.ConnTest.build_conn(:get, "/de-at/foo/bar?foo=bar&baz=true", %{
"locale" => "de-at"
Expand All @@ -377,6 +388,17 @@ defmodule SetLocaleTest do
assert redirected_to(conn) == "/#{@default_locale}/foo/bar?foo=bar&baz=true"
end

test "should keep query strings as is (HEAD method)" do
conn =
Phoenix.ConnTest.build_conn(:head, "/de-at/foo/bar?foo=bar&baz=true", %{
"locale" => "de-at"
})
|> Plug.Conn.fetch_cookies()
|> SetLocale.call(@default_options)

assert redirected_to(conn) == "/#{@default_locale}/foo/bar?foo=bar&baz=true"
end

test "it should allow non Gettext locales that are whitelisted via additional_locales option
and assign it, but should set Gettext to the default_locale" do
conn =
Expand All @@ -389,4 +411,38 @@ defmodule SetLocaleTest do
assert Gettext.get_locale(MyGettext) == @default_locale
end
end

describe "when the HTTP method is not get or head" do
test "POST not redirected" do
conn =
Phoenix.ConnTest.build_conn(:post, "/foo/bar")
|> Plug.Conn.put_resp_cookie(@cookie_key, "nl")
|> Plug.Conn.fetch_cookies()
|> SetLocale.call(@default_options_with_cookie)

assert conn.status == nil
end

test "PUT not redirected" do
conn =
Phoenix.ConnTest.build_conn(:put, "/foo/bar", %{"locale" => "foo"})
|> Plug.Conn.put_resp_cookie(@cookie_key, "nl")
|> Plug.Conn.fetch_cookies()
|> Plug.Conn.put_req_header("accept-language", "de, en-gb;q=0.8, en;q=0.7")
|> SetLocale.call(@default_options_with_cookie)

assert conn.status == nil
end

test "PATCH not redirected" do
conn =
Phoenix.ConnTest.build_conn(:path, "/foo/bar", %{"locale" => "foo"})
|> Plug.Conn.put_resp_cookie(@cookie_key, "nl")
|> Plug.Conn.fetch_cookies()
|> Plug.Conn.put_req_header("accept-language", "de, en-gb;q=0.8, en;q=0.7")
|> SetLocale.call(@default_options_with_cookie)

assert conn.status == nil
end
end
end