Packages

ex_cldr

2.37.4
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 validity t.ex
Raw

lib/cldr/validity/t.ex

defmodule Cldr.Validity.T do
@moduledoc false
alias Cldr.Validity.U
@field_mapping %{
"language" => :language,
"m0" => :m0,
"s0" => :s0,
"d0" => :d0,
"i0" => :i0,
"k0" => :k0,
"t0" => :t0,
"h0" => :h0,
"x0" => :x0
}
@fields Map.values(@field_mapping)
@inverse_field_mapping Enum.map(@field_mapping, fn {k, v} -> {v, k} end) |> Map.new()
@validity_data Cldr.Config.validity(:t)
@dont_process_keys ["language"]
@valid_keys Map.keys(@validity_data) ++ @dont_process_keys
@process_keys @valid_keys -- @dont_process_keys
def fields do
@fields
end
def field_mapping do
@field_mapping
end
@doc """
Decodes and validates that a given value is valid
for a given key.
Returns both the canonical key
and the canonical value or an error.
"""
def decode("language" = key, {:ok, language_tag}) do
{:ok, {map(key), language_tag}}
end
def decode("language", {:error, error_language_tag}) do
{:error, error_language_tag}
end
def decode("x0" = key, private_use) do
{:ok, {map(key), private_use}}
end
def decode(key, value) do
with {:ok, value} <- valid(key, value) do
{:ok, {map(key), atomize(value)}}
else
{:error, _value} ->
{:error, U.invalid_value_error(key, value)}
end
end
@doc """
Encodes a key and value into the
form required for a string version
of a language tag.
"""
def encode(key, value) do
unmapped_key = unmap(key)
{unmapped_key, encode_key(unmapped_key, value)}
end
# Encode key functions take the form that is
# in the language tag locale struct and encodes it
# back to what is required in a textual form of
# the locale.
for {key, values} <- @validity_data, key in @process_keys do
inverted_values = Enum.map(values, &String.to_atom/1)
defp encode_key(unquote(key), value) when value in unquote(inverted_values) do
Atom.to_string(value)
end
end
defp encode_key(key, values) when is_list(values) do
values
|> Enum.map(&encode_key(key, &1))
|> Enum.join("-")
end
defp encode_key(_key, {year}) do
to_string(year)
end
defp encode_key(_key, {year, month}) do
to_string(year) <> pad(month) <> to_string(month)
end
defp encode_key(_key, {year, month, day}) do
to_string(year) <> pad(month) <> to_string(month) <> pad(day) <> to_string(day)
end
defp encode_key("language", nil) do
nil
end
defp encode_key("language", language) do
String.downcase(language.canonical_locale_name)
end
defp encode_key("x0", private_use) when is_list(private_use) do
Enum.join(private_use, "-")
end
defp encode_key("x0", private_use) do
private_use
end
# Check that the value provided
# is acceptable for the given key.
for {key, values} <- @validity_data, key in @process_keys do
defp valid(unquote(key), value) when value in unquote(values) do
{:ok, String.to_atom(value)}
end
end
defp valid(key, values) when is_list(values) do
case valid_list(key, values) do
{:ok, values} ->
# Dates sort to the end
Enum.sort(values, fn
<<digit_1::utf8, _rest_1::binary>>, <<digit_2::utf8, _rest_2::binary>>
when digit_1 >= ?0 and digit_1 <= ?9 and digit_2 >= ?0 and digit_2 <= ?9 ->
digit_1 < digit_2
<<digit_1::utf8, _rest::binary>>, _date_2 when digit_1 >= ?0 and digit_1 <= ?9 ->
false
_date_1, <<digit_1::utf8, _rest::binary>> when digit_1 >= ?0 and digit_1 <= ?9 ->
true
value_1, value_2 ->
value_1 < value_2
end)
|> wrap(:ok)
other ->
other
end
end
defp valid(key, value) when key in @valid_keys do
case Integer.parse(value) do
{_integer, ""} -> {:ok, make_date_tuple(value)}
_other -> {:error, U.invalid_value_error(key, value)}
end
end
defp valid("language", language) do
language
end
defp valid("x0", private_use) do
private_use
end
defp valid(key, _value) do
{:error, U.invalid_key_error(key)}
end
def valid_list(key, values) do
Enum.reduce_while(values, {:ok, []}, fn value, {:ok, acc} ->
# if we push a date tuple on a prior round then the
# date tuple isn't in last place which it is required to
# be so we return an error
if length(acc) > 0 && is_tuple(hd(acc)) do
{:halt, {:error, invalid_date_order(key, hd(acc))}}
else
case valid(key, value) do
{:ok, value} -> {:cont, {:ok, [value | acc]}}
{:error, _value} -> {:halt, {:error, U.invalid_value_error(key, value)}}
end
end
end)
end
def wrap(term, atom) do
{atom, term}
end
def pad(number) when number < 10, do: " "
def pad(_number), do: ""
defp make_date_tuple(<<year::binary-4, month::binary-2, day::binary-2>>) do
{String.to_integer(year), String.to_integer(month), String.to_integer(day)}
end
defp make_date_tuple(<<year::binary-4, month::binary-2>>) do
{String.to_integer(year), String.to_integer(month)}
end
defp make_date_tuple(<<year::binary-4>>) do
{String.to_integer(year)}
end
defp map(key) do
Map.fetch!(@field_mapping, key)
end
defp unmap(key) do
Map.fetch!(@inverse_field_mapping, key)
end
defp atomize(value) when is_atom(value) do
value
end
defp atomize(value) when is_binary(value) do
String.to_atom(value)
end
defp atomize(other) do
other
end
defp invalid_date_order(key, value) do
encoded = encode_key(key, value)
{Cldr.LanguageTag.ParseError,
"The date #{inspect(encoded)} must be the last value in a subtag"}
end
end