Support multiple locales from userLanguage cookie
authorTusooa Zhu <tusooa@kazv.moe>
Thu, 3 Mar 2022 07:31:36 +0000 (02:31 -0500)
committerFloatingGhost <hannah@coffee-and-dreams.uk>
Wed, 29 Jun 2022 19:47:10 +0000 (20:47 +0100)
lib/pleroma/web/gettext.ex
lib/pleroma/web/plugs/set_locale_plug.ex
test/pleroma/web/plugs/set_locale_plug_test.exs

index e17451c09b53b8a441510a694411d381827e3f48..cd795008d07c5c1f8d69e64e3c4634508b1af84b 100644 (file)
@@ -37,7 +37,7 @@ defmodule Pleroma.Web.Gettext 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 @@ defmodule Pleroma.Web.Gettext 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)
index 936f65f5da346def07fc844bcdfbbacd0060a360..e78917199bf9e3695c579a4dd28ccae75ff83f28 100644 (file)
@@ -26,11 +26,12 @@ defmodule Pleroma.Web.Plugs.SetLocalePlug 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 @@ defmodule Pleroma.Web.Plugs.SetLocalePlug do
         []
 
       fe_lang ->
-        [fe_lang]
-        |> ensure_language_fallbacks()
+        String.split(fe_lang, ",")
     end
   end
 
@@ -67,7 +67,6 @@ defmodule Pleroma.Web.Plugs.SetLocalePlug do
         |> Enum.sort(&(&1.quality > &2.quality))
         |> Enum.map(& &1.tag)
         |> Enum.reject(&is_nil/1)
-        |> ensure_language_fallbacks()
 
       _ ->
         []
@@ -89,11 +88,4 @@ defmodule Pleroma.Web.Plugs.SetLocalePlug 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
index b0e7afffdc1fbc54cd0a2727c6e71a6775b9cb0c..ff04a859e95d007f2af2d9505218ae15c791ddaa 100644 (file)
@@ -75,6 +75,21 @@ defmodule Pleroma.Web.Plugs.SetLocalePlugTest 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