From 07bd35227af9a4f3eefd2cf0a7cefc6ea2d110b3 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 3 Mar 2022 02:31:36 -0500 Subject: [PATCH] Support multiple locales from userLanguage cookie --- lib/pleroma/web/gettext.ex | 27 ++++++++++++++----- lib/pleroma/web/plugs/set_locale_plug.ex | 14 +++------- .../web/plugs/set_locale_plug_test.exs | 15 +++++++++++ 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/lib/pleroma/web/gettext.ex b/lib/pleroma/web/gettext.ex index e17451c09..cd795008d 100644 --- a/lib/pleroma/web/gettext.ex +++ b/lib/pleroma/web/gettext.ex @@ -37,7 +37,7 @@ def language_tag do def normalize_locale(locale) do if is_binary(locale) do - String.replace(locale, "-", "_") + String.replace(locale, "-", "_", global: true) else nil end @@ -51,13 +51,28 @@ def supports_locale?(locale) do def variant?(locale), do: String.contains?(locale, "_") - def supported_variants_of_locale(locale) do - cond do - variant?(locale) -> - [locale] + def language_for_variant(locale) do + Enum.at(String.split(locale, "_"), 0) + end + def ensure_fallbacks(locales) do + locales + |> Enum.flat_map(fn locale -> + others = other_supported_variants_of_locale(locale) + |> Enum.filter(fn l -> not Enum.member?(locales, l) end) + + [locale] ++ others + end) + end + + def other_supported_variants_of_locale(locale) do + cond do supports_locale?(locale) -> - [locale] + [] + + variant?(locale) -> + lang = language_for_variant(locale) + if supports_locale?(lang), do: [lang], else: [] true -> Gettext.known_locales(Pleroma.Web.Gettext) diff --git a/lib/pleroma/web/plugs/set_locale_plug.ex b/lib/pleroma/web/plugs/set_locale_plug.ex index 936f65f5d..e78917199 100644 --- a/lib/pleroma/web/plugs/set_locale_plug.ex +++ b/lib/pleroma/web/plugs/set_locale_plug.ex @@ -26,11 +26,12 @@ defp get_locales_from_header(conn) do |> extract_preferred_language() |> normalize_language_codes() |> all_supported() + |> Enum.uniq() end defp all_supported(locales) do locales - |> Enum.flat_map(&Pleroma.Web.Gettext.supported_variants_of_locale/1) + |> Pleroma.Web.Gettext.ensure_fallbacks() |> Enum.filter(&supported_locale?/1) end @@ -53,8 +54,7 @@ defp extract_frontend_language(conn) do [] fe_lang -> - [fe_lang] - |> ensure_language_fallbacks() + String.split(fe_lang, ",") end end @@ -67,7 +67,6 @@ defp extract_accept_language(conn) do |> Enum.sort(&(&1.quality > &2.quality)) |> Enum.map(& &1.tag) |> Enum.reject(&is_nil/1) - |> ensure_language_fallbacks() _ -> [] @@ -89,11 +88,4 @@ defp parse_language_option(string) do %{tag: captures["tag"], quality: quality} end - - defp ensure_language_fallbacks(tags) do - Enum.flat_map(tags, fn tag -> - [language | _] = String.split(tag, "-") - if Enum.member?(tags, language), do: [tag], else: [tag, language] - end) - end end diff --git a/test/pleroma/web/plugs/set_locale_plug_test.exs b/test/pleroma/web/plugs/set_locale_plug_test.exs index b0e7afffd..ff04a859e 100644 --- a/test/pleroma/web/plugs/set_locale_plug_test.exs +++ b/test/pleroma/web/plugs/set_locale_plug_test.exs @@ -75,6 +75,21 @@ test "it assigns all supported locales" do assert %{locale: "ru", locales: ["ru", "fr", "en"]} = conn.assigns end + test "it assigns all supported locales in cookie" do + conn = + :get + |> conn("/cofe") + |> put_req_cookie(SetLocalePlug.frontend_language_cookie_name(), "zh-Hans,uk,zh-Hant") + |> Conn.put_req_header( + "accept-language", + "ru, fr-CH, fr;q=0.9, en;q=0.8, x-unsupported;q=0.8, *;q=0.5" + ) + |> SetLocalePlug.call([]) + + assert "zh_Hans" == Gettext.get_locale() + assert %{locale: "zh_Hans", locales: ["zh_Hans", "uk", "zh_Hant", "ru", "fr", "en"]} = conn.assigns + end + test "fallback to some variant of the language if the unqualified language is not supported" do conn = :get