Support fallbacking to other languages
[akkoma] / lib / pleroma / web / gettext.ex
index e17451c09b53b8a441510a694411d381827e3f48..51e56939e4dad2b5c49d6d14b2357fe1307c8584 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,29 @@ 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)
@@ -65,7 +81,7 @@ defmodule Pleroma.Web.Gettext do
     end
   end
 
-  def get_locales() do
+  def get_locales do
     Process.get({Pleroma.Web.Gettext, :locales}, [])
   end
 
@@ -102,6 +118,7 @@ defmodule Pleroma.Web.Gettext do
         put_locales(prev_locales)
       else
         Process.delete({Pleroma.Web.Gettext, :locales})
+        Process.delete(Gettext)
       end
     end
   end
@@ -133,4 +150,56 @@ defmodule Pleroma.Web.Gettext do
       )
     end
   end
+
+  defp next_locale(locale, list) do
+    index = Enum.find_index(list, fn item -> item == locale end)
+
+    if not is_nil(index) do
+      Enum.at(list, index + 1)
+    else
+      nil
+    end
+  end
+
+  def handle_missing_translation(locale, domain, msgctxt, msgid, bindings) do
+    next = next_locale(locale, get_locales())
+
+    if is_nil(next) do
+      super(locale, domain, msgctxt, msgid, bindings)
+    else
+      {:ok,
+       Gettext.with_locale(next, fn ->
+         Gettext.dpgettext(Pleroma.Web.Gettext, domain, msgctxt, msgid, bindings)
+       end)}
+    end
+  end
+
+  def handle_missing_plural_translation(
+        locale,
+        domain,
+        msgctxt,
+        msgid,
+        msgid_plural,
+        n,
+        bindings
+      ) do
+    next = next_locale(locale, get_locales())
+
+    if is_nil(next) do
+      super(locale, domain, msgctxt, msgid, msgid_plural, n, bindings)
+    else
+      {:ok,
+       Gettext.with_locale(next, fn ->
+         Gettext.dpngettext(
+           Pleroma.Web.Gettext,
+           domain,
+           msgctxt,
+           msgid,
+           msgid_plural,
+           n,
+           bindings
+         )
+       end)}
+    end
+  end
 end