I’m trying to come up with a solution for redirects and setting the right locale for my multi-lingual CMS.
Some clients have a domain for every language, others don’t, and there are cases where there is a bit of everything.
My table “language_variants” stores the following data
lv_id;language_id;is_root;domain;domain_redirect;route_code;is_default
8;1;true;localhost;;cs-cz;true
9;2;true;localhost.en;;en-gb;true
12;4;false;localhost.fr;localhost.en;fr-fr;false
13;3;false;localhost.de;localhost.en;de-de;false
14;1;false;localhost.cz;localhost;cs-cs;false
10;4;true;localhost.en;;fr-fr;false
11;3;true;localhost.en;;de-de;false
“domain_redirect” - if defined, immediately redirect here
“is_default” - it’s like a “base” language, if we go to www.example.com, we know we should use “en-gb”, but if we go to www.example.com/fr-fr, we should display the website in French
So far, my redirect plug looks like this
def call(conn, _header) do
host = conn.host
case DbContext.const_get_language_variants() do
{:ok, language_variants} ->
for language_variant <- language_variants do
item = Map.from_struct(language_variant)
%{
:domain => domain,
:is_default => is_default,
:domain_redirect => domain_redirect,
:route_code => lang
} = item
if host === domain do
cond do
!is_nil(domain_redirect) ->
Phoenix.Controller.redirect(conn, external: build_url(conn, domain_redirect, lang))
is_default && !Map.has_key?(conn.params, "locale") ->
Phoenix.Controller.redirect(conn, external: build_url(conn, domain, lang))
true ->
Plug.Conn.put_session(conn, :lang, lang)
end
end
end
{:error} = error ->
error
end
conn
end
defp build_url(conn, to, lang) do
host = conn.host
port = to_string(conn.port)
scheme = to_string(conn.scheme)
scheme <> "://" <> to <> ":" <> port <> "/" <> lang
end
end
- I am not convinced whether or not it’s better to use locale for just everything (including “is_default” rows) i.e. www.exmaple.com would always be www.exmaple.com/en-gb, I am not sure how I could deal with this in routes
- If a particular locale does not exist, should I redirect the user to the “default” one or throw just a 404?