-
Notifications
You must be signed in to change notification settings - Fork 34
/
parser.ex
100 lines (75 loc) · 2.36 KB
/
parser.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
defmodule Cldr.LanguageTag.Parser do
@moduledoc """
Parses a CLDR language tag (also referred to as locale string).
The applicable specification is from [CLDR](http://unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers)
which is similar based upon [RFC5646](https://tools.ietf.org/html/rfc5646) with some variations.
"""
alias Cldr.LanguageTag
alias Cldr.Locale
@doc """
Parse a locale name into a `t:Cldr.LanguageTag`
* `locale_name` is a string representation of a language tag
as defined by [RFC5646](https://tools.ietf.org/html/rfc5646).
Returns
* `{:ok, language_tag}` or
* `{:error, reasons}`
"""
def parse(locale) do
case Cldr.Rfc5646.Parser.parse(normalize_locale_name(locale)) do
{:ok, language_tag} ->
language_tag
|> Keyword.put(:requested_locale_name, locale)
|> normalize_tag()
|> structify(LanguageTag)
|> wrap(:ok)
{:error, reason} ->
{:error, reason}
end
end
@doc """
Parse a locale name into a `t:Cldr.LanguageTag`
* `locale_name` is a string representation of a language tag
as defined by [RFC5646](https://tools.ietf.org/html/rfc5646).
Returns
* `language_tag` or
* raises an exception
"""
def parse!(locale) do
case parse(locale) do
{:ok, language_tag} -> language_tag
{:error, {exception, reason}} -> raise exception, reason
end
end
defp wrap(term, atom) do
{atom, term}
end
defp normalize_tag(language_tag) do
Enum.map(language_tag, &normalize_field/1)
end
def normalize_field({:language = field, language}) do
{field, Cldr.Validity.Language.normalize(language)}
end
def normalize_field({:script = field, script}) do
{field, Cldr.Validity.Script.normalize(script)}
end
def normalize_field({:territory = field, territory}) do
{field, Cldr.Validity.Territory.normalize(territory)}
end
def normalize_field({:language_variants = field, variants}) do
{field, Cldr.Validity.Variant.normalize(variants)}
end
# Everything is downcased before parsing
# and that's the canonical form so no need to
# do it again, just return the value
def normalize_field(other) do
other
end
defp normalize_locale_name(name) do
name
|> String.downcase()
|> Locale.locale_name_from_posix()
end
defp structify(list, module) do
struct(module, list)
end
end