Skip to content

Commit

Permalink
Allow plural forms to be set for gettext as a whole
Browse files Browse the repository at this point in the history
Closes #264.
Closes #179.
  • Loading branch information
josevalim committed Sep 25, 2020
1 parent f5f232b commit a850ce8
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 17 deletions.
4 changes: 3 additions & 1 deletion lib/gettext/compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,9 @@ defmodule Gettext.Compiler do
# Compiles all the `.po` files in the given directory (`dir`) into `lgettext/4`
# and `lngettext/6` function clauses.
defp compile_po_files(env, known_po_files, opts) do
plural_mod = Keyword.get(opts, :plural_forms, Gettext.Plural)
plural_mod =
Keyword.get(opts, :plural_forms) ||
Application.get_env(:gettext, :plural_forms, Gettext.Plural)

if Keyword.get(opts, :one_module_per_locale, false) do
known_po_files
Expand Down
3 changes: 2 additions & 1 deletion lib/gettext/merger.ex
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ defmodule Gettext.Merger do

defp put_plural_forms_opt(opts, headers, locale) do
Keyword.put_new_lazy(opts, :plural_forms, fn ->
read_plural_forms_from_headers(headers) || Gettext.Plural.nplurals(locale)
read_plural_forms_from_headers(headers) ||
Application.get_env(:gettext, :plural_forms, Gettext.Plural).nplurals(locale)
end)
end

Expand Down
25 changes: 21 additions & 4 deletions lib/gettext/plural.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,33 @@ defmodule Gettext.Plural do
def plural(locale, n), do: Gettext.Plural.plural(locale, n)
end
defmodule MyApp.Gettext do
use Gettext, otp_app: :my_app, plural_forms: MyApp.Plural
end
The mathematical expressions used in this module to determine the plural form
of a given number of elements are taken from [this
page](http://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html#f2)
as well as from [Mozilla's guide on "Localization and
plurals"](https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_and_Plurals).
Now that we have defined our custom plural forms, we can use them
in two ways. You can set it for all `:gettext` backends in your
config files:
config :gettext, :plural_forms, MyApp.Plural
Or to each specific backend:
defmodule MyApp.Gettext do
use Gettext, otp_app: :my_app, plural_forms: MyApp.Plural
end
Notice that tasks such as `mix gettext.merge` use the plural
backend configured under the `:gettext` application, so generally
speaking the first format is preferred.
Note some tasks also allow the number of plural forms to be given
explicitly, for example:
mix gettext.merge priv/gettext --locale=gsw_CH --plural-forms=2
### Unknown locales
Trying to call `Gettext.Plural` functions with unknown locales will result in
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ defmodule Gettext.Mixfile do
def application do
[
extra_applications: [:logger],
env: [default_locale: "en"],
env: [default_locale: "en", plural_forms: Gettext.Plural],
mod: {Gettext.Application, []}
]
end
Expand Down
29 changes: 19 additions & 10 deletions test/gettext_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,7 @@ defmodule GettextTest.TranslatorWithAllowedLocales do
end

defmodule GettextTest.TranslatorWithCustomPluralForms do
defmodule Plural do
@behaviour Gettext.Plural
def nplurals("elv"), do: 2
def nplurals(other), do: Gettext.Plural.nplurals(other)
# Opposite of Italian (where 1 is singular, everything else is plural)
def plural("it", 1), do: 1
def plural("it", _), do: 0
end

use Gettext, otp_app: :test_application, plural_forms: Plural
use Gettext, otp_app: :test_application, plural_forms: GettextTest.CustomPlural
end

defmodule GettextTest.TranslatorWithDefaultDomain do
Expand Down Expand Up @@ -177,6 +168,24 @@ defmodule GettextTest do
{:ok, "Una nuova email"}
end

test "using a custom Gettext.Plural module from app environment" do
Application.put_env(:gettext, :plural_forms, GettextTest.CustomPlural)

defmodule TranslatorWithAppPluralForms do
use Gettext, otp_app: :test_application
end

alias TranslatorWithAppPluralForms, as: T

assert T.lngettext("it", "default", nil, "One new email", "%{count} new emails", 1, %{}) ==
{:ok, "1 nuove email"}

assert T.lngettext("it", "default", nil, "One new email", "%{count} new emails", 2, %{}) ==
{:ok, "Una nuova email"}
after
Application.put_env(:gettext, :plural_forms, Gettext.Plural)
end

test "translations can be pluralized" do
import Translator, only: [lngettext: 7]

Expand Down
55 changes: 55 additions & 0 deletions test/mix/tasks/gettext.merge_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,61 @@ defmodule Mix.Tasks.Gettext.MergeTest do
assert String.starts_with?(new_po, "## \"msgid\"s in this file come from POT")
end

test "passing a dir and a --locale opt will update/create PO files in the locale dir with custom plural forms" do
write_file("new.pot", """
msgid "new"
msgstr ""
""")

output =
capture_io(fn ->
run([@priv_path, "--locale", "it", "--plural-forms", "3"])
end)

assert output =~ "Wrote tmp/gettext.merge/it/LC_MESSAGES/new.po"
new_po = read_file("it/LC_MESSAGES/new.po")

assert new_po =~ ~S"""
msgid ""
msgstr ""
"Language: it\n"
"Plural-Forms: nplurals=3\n"
msgid "new"
msgstr ""
"""
end


test "passing a dir and a --locale opt will update/create PO files in the locale dir with app env plural forms" do
Application.put_env(:gettext, :plural_forms, GettextTest.CustomPlural)

write_file("new.pot", """
msgid "new"
msgstr ""
""")

output =
capture_io(fn ->
run([@priv_path, "--locale", "elv"])
end)

assert output =~ "Wrote tmp/gettext.merge/elv/LC_MESSAGES/new.po"
new_po = read_file("elv/LC_MESSAGES/new.po")

assert new_po =~ ~S"""
msgid ""
msgstr ""
"Language: elv\n"
"Plural-Forms: nplurals=2\n"
msgid "new"
msgstr ""
"""
after
Application.put_env(:gettext, :plural_forms, Gettext.Plural)
end

test "passing just a dir merges with PO files in every locale" do
write_file("fr/LC_MESSAGES/foo.po", "")
write_file("it/LC_MESSAGES/foo.po", "")
Expand Down
9 changes: 9 additions & 0 deletions test/test_helper.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,13 @@
|> Path.join()
|> Code.prepend_path()

defmodule GettextTest.CustomPlural do
@behaviour Gettext.Plural
def nplurals("elv"), do: 2
def nplurals(other), do: Gettext.Plural.nplurals(other)
# Opposite of Italian (where 1 is singular, everything else is plural)
def plural("it", 1), do: 1
def plural("it", _), do: 0
end

ExUnit.start()

0 comments on commit a850ce8

Please sign in to comment.