Support fallbacking to other languages
authorTusooa Zhu <tusooa@kazv.moe>
Sun, 6 Mar 2022 16:43:31 +0000 (11:43 -0500)
committerFloatingGhost <hannah@coffee-and-dreams.uk>
Wed, 29 Jun 2022 19:47:10 +0000 (20:47 +0100)
lib/pleroma/web/gettext.ex
mix.exs
mix.lock
priv/gettext/en_test/LC_MESSAGES/static_pages.po
test/pleroma/web/gettext_test.exs [new file with mode: 0644]

index 89feb0bb3f0e9fcfe6199f8573d1ffb0e0a2f30a..51e56939e4dad2b5c49d6d14b2357fe1307c8584 100644 (file)
@@ -118,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
@@ -149,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
diff --git a/mix.exs b/mix.exs
index 76e84c2b85dde370057bcdc935265872f24a392c..564db2d75bf88d339cc007acd029c7ebfdecd71f 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -123,7 +123,10 @@ defmodule Pleroma.Mixfile do
       {:ecto_sql, "~> 3.6.2"},
       {:postgrex, ">= 0.15.5"},
       {:oban, "~> 2.3.4"},
-      {:gettext, "~> 0.18"},
+      {:gettext,
+       git: "https://github.com/tusooa/gettext.git",
+       ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808",
+       override: true},
       {:bcrypt_elixir, "~> 2.2"},
       {:trailing_format_plug, "~> 0.0.7"},
       {:fast_sanitize, "~> 0.2.0"},
index 8c39d2199463b0b73aecc52e78d9cce0ad92af83..422bbea5ec6889463fa142168c6d673ce9c3c6ce 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -57,7 +57,7 @@
   "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
   "gen_stage": {:hex, :gen_stage, "0.14.3", "d0c66f1c87faa301c1a85a809a3ee9097a4264b2edf7644bf5c123237ef732bf", [:mix], [], "hexpm"},
   "gen_state_machine": {:hex, :gen_state_machine, "2.0.5", "9ac15ec6e66acac994cc442dcc2c6f9796cf380ec4b08267223014be1c728a95", [:mix], [], "hexpm"},
-  "gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
+  "gettext": {:git, "https://github.com/tusooa/gettext.git", "72fb2496b6c5280ed911bdc3756890e7f38a4808", [ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808"]},
   "gun": {:hex, :gun, "2.0.0-rc.2", "7c489a32dedccb77b6e82d1f3c5a7dadfbfa004ec14e322cdb5e579c438632d2", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "6b9d1eae146410d727140dbf8b404b9631302ecc2066d1d12f22097ad7d254fc"},
   "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
   "hpax": {:hex, :hpax, "0.1.1", "2396c313683ada39e98c20a75a82911592b47e5c24391363343bde74f82396ca", [:mix], [], "hexpm", "0ae7d5a0b04a8a60caf7a39fcf3ec476f35cc2cc16c05abea730d3ce6ac6c826"},
index a3378089cdf9d773f1bd0ae743277340d4417d6c..1a3b7b355bd7605430329cb759c5e4e99b746b5d 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"PO-Revision-Date: 2022-03-01 21:15-0500\n"
+"PO-Revision-Date: 2022-03-06 11:27-0500\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -423,8 +423,8 @@ msgstr ""
 msgctxt "new followers count header"
 msgid "%{count} New Follower"
 msgid_plural "%{count} New Followers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "xx%{count} New Followerxx"
+msgstr[1] "xx%{count} New Followersxx"
 
 #, elixir-format
 #: lib/pleroma/emails/user_email.ex:356
@@ -466,7 +466,7 @@ msgstr ""
 #: lib/pleroma/emails/user_email.ex:310
 msgctxt "digest email subject"
 msgid "Your digest from %{instance_name}"
-msgstr ""
+msgstr "xxYour digest from %{instance_name}xx"
 
 #, elixir-format
 #: lib/pleroma/emails/user_email.ex:81
diff --git a/test/pleroma/web/gettext_test.exs b/test/pleroma/web/gettext_test.exs
new file mode 100644 (file)
index 0000000..9ede482
--- /dev/null
@@ -0,0 +1,162 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.GettextTest do
+  use ExUnit.Case
+
+  require Pleroma.Web.Gettext
+
+  test "put_locales/1: set the first in the list to Gettext's locale" do
+    Pleroma.Web.Gettext.put_locales(["zh_Hans", "en_test"])
+
+    assert "zh_Hans" == Gettext.get_locale(Pleroma.Web.Gettext)
+  end
+
+  test "with_locales/2: reset locale on exit" do
+    old_first_locale = Gettext.get_locale(Pleroma.Web.Gettext)
+    old_locales = Pleroma.Web.Gettext.get_locales()
+
+    Pleroma.Web.Gettext.with_locales ["zh_Hans", "en_test"] do
+      assert "zh_Hans" == Gettext.get_locale(Pleroma.Web.Gettext)
+      assert ["zh_Hans", "en_test"] == Pleroma.Web.Gettext.get_locales()
+    end
+
+    assert old_first_locale == Gettext.get_locale(Pleroma.Web.Gettext)
+    assert old_locales == Pleroma.Web.Gettext.get_locales()
+  end
+
+  describe "handle_missing_translation/5" do
+    test "fallback to next locale if some translation is not available" do
+      Pleroma.Web.Gettext.with_locales ["x_unsupported", "en_test"] do
+        assert "xxYour account is awaiting approvalxx" ==
+                 Pleroma.Web.Gettext.dpgettext(
+                   "static_pages",
+                   "approval pending email subject",
+                   "Your account is awaiting approval"
+                 )
+      end
+    end
+
+    test "duplicated locale in list should not result in infinite loops" do
+      Pleroma.Web.Gettext.with_locales ["x_unsupported", "x_unsupported", "en_test"] do
+        assert "xxYour account is awaiting approvalxx" ==
+                 Pleroma.Web.Gettext.dpgettext(
+                   "static_pages",
+                   "approval pending email subject",
+                   "Your account is awaiting approval"
+                 )
+      end
+    end
+
+    test "direct interpolation" do
+      Pleroma.Web.Gettext.with_locales ["en_test"] do
+        assert "xxYour digest from some instancexx" ==
+                 Pleroma.Web.Gettext.dpgettext(
+                   "static_pages",
+                   "digest email subject",
+                   "Your digest from %{instance_name}",
+                   instance_name: "some instance"
+                 )
+      end
+    end
+
+    test "fallback with interpolation" do
+      Pleroma.Web.Gettext.with_locales ["x_unsupported", "en_test"] do
+        assert "xxYour digest from some instancexx" ==
+                 Pleroma.Web.Gettext.dpgettext(
+                   "static_pages",
+                   "digest email subject",
+                   "Your digest from %{instance_name}",
+                   instance_name: "some instance"
+                 )
+      end
+    end
+
+    test "fallback to msgid" do
+      Pleroma.Web.Gettext.with_locales ["x_unsupported"] do
+        assert "Your digest from some instance" ==
+                 Pleroma.Web.Gettext.dpgettext(
+                   "static_pages",
+                   "digest email subject",
+                   "Your digest from %{instance_name}",
+                   instance_name: "some instance"
+                 )
+      end
+    end
+  end
+
+  describe "handle_missing_plural_translation/7" do
+    test "direct interpolation" do
+      Pleroma.Web.Gettext.with_locales ["en_test"] do
+        assert "xx1 New Followerxx" ==
+                 Pleroma.Web.Gettext.dpngettext(
+                   "static_pages",
+                   "new followers count header",
+                   "%{count} New Follower",
+                   "%{count} New Followers",
+                   1,
+                   count: 1
+                 )
+
+        assert "xx5 New Followersxx" ==
+                 Pleroma.Web.Gettext.dpngettext(
+                   "static_pages",
+                   "new followers count header",
+                   "%{count} New Follower",
+                   "%{count} New Followers",
+                   5,
+                   count: 5
+                 )
+      end
+    end
+
+    test "fallback with interpolation" do
+      Pleroma.Web.Gettext.with_locales ["x_unsupported", "en_test"] do
+        assert "xx1 New Followerxx" ==
+                 Pleroma.Web.Gettext.dpngettext(
+                   "static_pages",
+                   "new followers count header",
+                   "%{count} New Follower",
+                   "%{count} New Followers",
+                   1,
+                   count: 1
+                 )
+
+        assert "xx5 New Followersxx" ==
+                 Pleroma.Web.Gettext.dpngettext(
+                   "static_pages",
+                   "new followers count header",
+                   "%{count} New Follower",
+                   "%{count} New Followers",
+                   5,
+                   count: 5
+                 )
+      end
+    end
+
+    test "fallback to msgid" do
+      Pleroma.Web.Gettext.with_locales ["x_unsupported"] do
+        assert "1 New Follower" ==
+                 Pleroma.Web.Gettext.dpngettext(
+                   "static_pages",
+                   "new followers count header",
+                   "%{count} New Follower",
+                   "%{count} New Followers",
+                   1,
+                   count: 1
+                 )
+
+        assert "5 New Followers" ==
+                 Pleroma.Web.Gettext.dpngettext(
+                   "static_pages",
+                   "new followers count header",
+                   "%{count} New Follower",
+                   "%{count} New Followers",
+                   5,
+                   count: 5
+                 )
+      end
+    end
+  end
+end