Packages
ex_cldr
0.0.15
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.
Retired package: Deprecated
Current section
Files
Jump to
Current section
Files
lib/cldr/number/plural_rule.ex
defmodule Cldr.Number.PluralRule do
@moduledoc """
Macro to define plural rule methods on a module.
Used to generate functions for `Cldr.Number.Ordinal` and `
Cldr.Number.Cardinal`
"""
defmacro __using__(opts) do
unless opts in [:cardinal, :ordinal] do
raise ArgumentError,
"Invalid option #{inspect opts}. :cardinal or :ordinal are the only valid options"
end
quote do
alias Cldr.Math
import Cldr.Digits, only: [number_of_integer_digits: 1, remove_trailing_zeros: 1]
import Cldr.Number.PluralRule.Compiler
import Cldr.Number.PluralRule.Transformer
@rules Cldr.Config.cldr_data_dir()
|> Path.join("/plural_rules.json")
|> File.read!
|> Poison.decode!
|> Map.get(Atom.to_string(unquote(opts)))
@doc """
The locales for which cardinal rules are defined
"""
@rules_locales @rules
|> Map.keys
|> Enum.sort
def known_locales do
@rules_locales
end
@doc """
The configured locales for which plural rules are defined
This is the intersection of the Cldr.known_locales and the locales for
which plural rules are defined. There are many Cldr locales which
don't have their own plural rules so this list is the intersection
of Cldr's configured locales and those that have rules.
"""
@configured_locales @rules_locales
|> MapSet.new
|> MapSet.intersection(MapSet.new(Cldr.known_locales()))
|> MapSet.to_list
|> Enum.sort
def configured_locales do
@configured_locales
end
@doc """
The plural rules defined in CLDR.
"""
@spec plural_rules :: Map.t
def plural_rules do
@rules
end
@doc """
Pluralize a number using plural rules and a substition map.
* `number` is an integer or a float
* `locale` is any locale returned by `Cldr.known_locales()`
* `substitutions` is a map that maps plural keys to a string. Per the
CLDR defintion of plural rules, the valid substitution keys are `:zero`,
`:one`, `:two`, `:few`, `:many` and `:other`.
See also `Cldr.Ordinal.plural_rule/3` and `Cldr.Cardinal.plural_rule/3`.
## Examples
iex> Cldr.Number.Ordinal.pluralize 1, "en", %{one: "one"}
"one"
iex> Cldr.Number.Ordinal.pluralize 2, "en", %{one: "one"}
nil
iex> Cldr.Number.Ordinal.pluralize 2, "en", %{one: "one", two: "two"}
"two"
"""
@default_substitution :other
@spec pluralize(number, Locale.t, %{}) :: String.t | nil
def pluralize(number, locale \\ Cldr.get_locale(), %{} = substitutions)
when is_number(number) do
plural = plural_rule(number, locale)
substitutions[plural] || substitutions[@default_substitution]
end
@doc """
Return the plural rules for a locale.
The rules are returned in AST form after parsing.
"""
@spec plural_rules_for(Cldr.locale) :: %{}
def plural_rules_for(locale) do
Enum.map plural_rules()[locale], fn({"pluralRule-count-" <> category, rule}) ->
{:ok, definition} = parse(rule)
{String.to_atom(category), definition}
end
end
# Plural Operand Meanings as defined in CLDR plural rules and used
# in the generated code
#
# Symbol Value
# n absolute value of the source number (integer and decimals).
# i integer digits of n.
# v number of visible fraction digits in n, with trailing zeros.
# w number of visible fraction digits in n, without trailing zeros.
# f visible fractional digits in n, with trailing zeros.
# t visible fractional digits in n, without trailing zeros.
@doc """
Lookup the plural cardinal category for a given number in a given locale
Identify which category (zero, one, two, few, many or other) a given number
in a given locale fits into. This category can then be used to format the
number or currency
"""
def plural_rule(number, locale \\ Cldr.get_locale(), rounding \\ Math.default_rounding())
def plural_rule(string, locale, rounding) when is_binary(string) do
plural_rule(Decimal.new(string), locale, rounding)
end
# Plural rule for an integer
def plural_rule(number, locale, _rounding) when is_integer(number) do
n = abs(number)
i = n
v = 0; w = 0; f = 0; t = 0
do_plural_rule(locale, n, i, v, w, f, t)
end
# Plural rule for a float
@lint {Credo.Check.Refactor.PipeChainStart, false}
def plural_rule(number, locale, rounding)
when is_float(number) and is_integer(rounding) and rounding > 0 do
plural_rule(Decimal.new(number), locale, rounding)
# n = Float.round(abs(number), rounding)
# i = trunc(n)
# v = rounding
# t = fraction_as_integer(n - i)
# w = number_of_integer_digits(t)
# f = trunc(t * :math.pow(10, v - w))
# do_plural_rule(locale, n, i, v, w, f, t)
end
# Plural rule for a %Decimal{}
def plural_rule(%Decimal{} = number, locale, rounding)
when is_integer(rounding) and rounding > 0 do
# n absolute value of the source number (integer and decimals).
n = Decimal.abs(number)
# i integer digits of n.
i = Decimal.round(n, 0, :floor)
# v number of visible fraction digits in n, with trailing zeros.
v = abs(n.exp)
# f visible fractional digits in n, with trailing zeros.
f = n
|> Decimal.sub(i)
|> Decimal.mult(Decimal.new(:math.pow(10, v)))
|> Decimal.round(0, :floor)
|> Decimal.to_integer
# t visible fractional digits in n, without trailing zeros.
t = remove_trailing_zeros(f)
# w number of visible fraction digits in n, without trailing zeros.
w = number_of_integer_digits(t)
i = Decimal.to_integer(i)
n = Math.to_float(n)
# IO.puts "n: #{inspect n}; i: #{inspect i}; v: #{inspect v}; w: #{inspect w}; f: #{inspect f}; t: #{inspect t}"
do_plural_rule(locale, n, i, v, w, f, t)
end
end
end
end