Packages

ex_cldr

2.32.1
2.47.5 2.47.4 2.47.3 2.47.2 2.47.1 2.47.0 2.46.0 2.45.2 2.45.1 2.45.0 2.44.1 2.44.0 2.43.2 2.43.1 2.43.0 2.42.0 2.41.1 2.41.0 2.40.4 2.40.3 2.40.2 2.40.1 2.40.0 2.39.2 2.39.1 2.39.0 2.38.1 2.38.0 2.37.5 2.37.4 2.37.3 retired 2.37.2 2.37.1 2.37.0 2.36.0 2.35.1 2.35.0 retired 2.34.2 2.34.1 2.34.0 2.33.2 2.33.1 2.33.1-rc.0 2.33.0 2.32.1 2.32.0 2.31.0 2.30.0 2.29.0 2.28.0 2.27.1 2.27.0 retired 2.26.3 2.26.2 2.26.1 2.26.0 2.25.0 2.24.2 2.24.1 2.24.0 2.24.0-rc.6 2.24.0-rc.5 2.24.0-rc.4 2.24.0-rc.3 2.24.0-rc.2 2.24.0-rc.1 2.24.0-rc.0 2.23.2 2.23.1 2.23.0 2.22.1 2.22.0 2.21.0 2.20.0 2.20.0-rc.3 2.20.0-rc.2 2.20.0-rc.1 2.20.0-rc.0 2.19.1 2.19.0 2.18.2 2.18.1 2.18.0 2.18.0-rc.0 2.17.2 2.17.1 2.17.0 2.16.2 2.16.1 2.16.1-rc.0 2.16.0 2.15.0 2.14.1 2.14.0 2.14.0-rc.0 2.13.0 2.12.1 2.12.0 2.11.1 2.11.0 2.10.2 2.10.1 2.10.0 retired 2.9.0 2.8.1 2.8.0 2.7.2 2.7.1 2.7.0 2.6.2 2.6.1 2.6.0 2.5.0 2.4.3 2.4.2 2.4.1 2.4.0 2.3.2 2.3.1 2.3.0 2.2.7 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 2.2.1 2.2.0 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 2.0.0-rc.3 retired 2.0.0-rc.2 retired 2.0.0-rc.1 retired 2.0.0-rc.0 retired 1.8.2 1.8.1 1.8.0 1.7.1 1.7.0 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.2 1.5.1 1.5.0 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 retired 1.4.0-rc.3 retired 1.4.0-rc.2 retired 1.4.0-rc.1 retired 1.4.0-rc.0 retired 1.3.2 1.3.1 1.3.0 1.2.0 1.1.0 1.0.0 1.0.0-rc.3 retired 1.0.0-rc.2 retired 1.0.0-rc.1 retired 1.0.0-rc.0 retired 0.13.1 0.13.0 0.12.2 retired 0.12.1 retired 0.12.0 retired 0.11.0 retired 0.10.0 retired 0.9.0 retired 0.8.3 retired 0.8.2 retired 0.8.1 retired 0.8.0 retired 0.7.0 retired 0.6.2 retired 0.6.1 retired 0.6.0 retired 0.5.2 retired 0.5.1 retired 0.5.0 retired 0.4.2 retired 0.4.1 retired 0.4.0 retired 0.3.0 retired 0.2.1 retired 0.2.0 retired 0.1.3 retired 0.1.2 retired 0.1.1 retired 0.1.0 retired 0.0.20 retired 0.0.19 retired 0.0.18 retired 0.0.17 retired 0.0.16 retired 0.0.15 retired 0.0.14 retired 0.0.13 retired 0.0.12 retired 0.0.11 retired 0.0.10 retired 0.0.8 retired 0.0.7 retired 0.0.6 retired 0.0.5 retired 0.0.4 retired 0.0.3 retired

Common Locale Data Repository (CLDR) functions for Elixir to localize and format numbers, dates, lists, messages, languages, territories and units with support for over 700 locales for internationalized (i18n) and localized (L10N) applications.

Current section

Files

Jump to
ex_cldr lib cldr gettext plural.ex
Raw

lib/cldr/gettext/plural.ex

defmodule Cldr.Gettext.Plural do
@moduledoc """
Implements a macro to define a CLDR-based Gettext plural
module
[gettext](https://hexdocs.pm/gettext) allows for user-defined
[plural forms](https://hexdocs.pm/gettext/Gettext.Plural.html#content) modules
to be configured for a [gettext backend](https://hexdocs.pm/gettext/Gettext.Backend.html#content).
To define a plural forms module that uses [CLDR plural rules](https://cldr.unicode.org/index/cldr-spec/plural-rules)
create a new module and then `use Cldr.Gettext.Plural`. For example:
defmodule MyApp.Gettext.Plural do
use Cldr.Gettext.Plural, cldr_backend: MyApp.Cldr
end
This module can then be used in the configuration of a `gettext` backend.
For example:
defmodule MyApp.Gettext do
use Gettext, plural_forms: MyApp.Gettext.Plural
end
"""
@doc """
Configure a module to be a [gettext plural](https://hexdocs.pm/gettext/Gettext.Plural.html#content)
module.
A CLDR-based `gettext` plural module is defined by including `use Cldr.Gettext.Plural`
as in this example:
defmodule MyApp.Gettext.Plural do
use Cldr.Gettext.Plural, cldr_backend: MyApp.Cldr
end
## Arguments
* `options` is a keyword list of options. The default is `[]`
## Options
* `:cldr_backend` is any CLDR [backend](https://hexdocs.pm/ex_cldr/readme.html#backend-module-configuration)
module. The default is `Cldr.default_backend!/0`.
"""
defmacro __using__(opts \\ []) do
backend = Keyword.get_lazy(opts, :cldr_backend, &Cldr.default_backend!/0)
quote location: :keep do
@behaviour Elixir.Gettext.Plural
alias Cldr.LanguageTag
alias Cldr.Locale
@rules Cldr.Config.cldr_data_dir()
|> Path.join("/plural_rules.json")
|> File.read!()
|> Cldr.Config.json_library().decode!
|> Map.get("cardinal")
|> Cldr.Config.normalize_plural_rules()
|> Map.new()
@nplurals_range [0, 1, 2, 3, 4, 5]
@gettext_nplurals @rules
|> Enum.map(fn {locale, rules} ->
{locale, Keyword.keys(rules) |> Enum.zip(@nplurals_range)}
end)
|> Map.new()
@doc """
Returns the number of plural forms for a given locale.
* `locale` is either a locale name in the list
`#{unquote(inspect(backend))}.known_locale_names/0` or
a `%LanguageTag{}` as returned by `Cldr.Locale.new/2`
## Examples
iex> #{inspect(__MODULE__)}.nplurals("pl")
4
iex> #{inspect(__MODULE__)}.nplurals("en")
2
"""
@spec nplurals(Locale.locale_name() | String.t()) :: pos_integer() | no_return()
def nplurals(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
nplurals(cldr_locale_name)
end
def nplurals(locale_name) when is_atom(locale_name) do
gettext_nplurals()
|> Map.fetch!(locale_name)
|> Enum.count()
end
def nplurals(locale_name) when is_binary(locale_name) do
locale_name = String.to_existing_atom(locale_name)
nplurals(locale_name)
rescue ArgumentError ->
raise KeyError, "Key #{inspect locale_name} not found"
end
@doc """
Returns the plural form of a number for a given
locale.
* `locale` is either a locale name in the list `#{unquote(inspect(backend))}.known_locale_names/0` or
a `%LanguageTag{}` as returned by `Cldr.Locale.new/2`
## Examples
iex> #{inspect(__MODULE__)}.plural("pl", 1)
0
iex> #{inspect(__MODULE__)}.plural("pl", 2)
1
iex> #{inspect(__MODULE__)}.plural("pl", 5)
2
iex> #{inspect(__MODULE__)}.plural("pl", 112)
2
iex> #{inspect(__MODULE__)}.plural("en", 1)
0
iex> #{inspect(__MODULE__)}.plural("en", 2)
1
iex> #{inspect(__MODULE__)}.plural("en", 112)
1
"""
@spec plural(String.t() | LanguageTag.t(), number()) ::
0 | pos_integer() | no_return()
def plural(%LanguageTag{cldr_locale_name: cldr_locale_name} = locale, n) do
rule = unquote(backend).Number.Cardinal.plural_rule(n, cldr_locale_name)
gettext_nplurals()
|> Map.get(cldr_locale_name)
|> Keyword.get(rule)
end
def plural(locale_name, n) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
plural(locale, n)
else
{:error, _reason} -> raise Elixir.Gettext.Plural.UnknownLocaleError, locale_name
end
end
defp gettext_nplurals do
@gettext_nplurals
end
end
end
end