changed
CHANGELOG.md
|
@@ -1,12 +1,52 @@
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+ ## Cldr v2.26.0
|
4
|
+
|
5
|
+ This is the changelog for Cldr v2.26.0 released on February 21st, 2022. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-cldr/cldr/tags)
|
6
|
+
|
7
|
+ ### LanguageTag structure changes
|
8
|
+
|
9
|
+ * `Cldr.LanguageTag.t` has been revised with the `:cldr_locale_name` and `:rbnf_locale_name` now being atoms rather than binaries. This is unlikely to affect client code. The primary benefit, apart from a slightly improve
|
10
|
+
|
11
|
+ ### Bug Fixes
|
12
|
+
|
13
|
+ * Fix setting the default backend with `Cldr.put_default_backend/1` which wasn't actually being set.
|
14
|
+
|
15
|
+ * Fix `Config.message_formats` to default to an empty map, not an empty list.
|
16
|
+
|
17
|
+ * Fix `Cldr.Locale.parents/1` to return an `{:ok, list}` tuple on success rather than a bare list.
|
18
|
+
|
19
|
+ * Fix `<backend>.Cldr.Number.{Cardinal, Ordinal, Spellout}.pluralize/3` for non-integer `Decimal` numbers.
|
20
|
+
|
21
|
+ ### Enhancements
|
22
|
+
|
23
|
+ * Add `<backend>.Trans` module to support closer integration with the [trans](https://hex.pm/packages/trans) for database translations.
|
24
|
+
|
25
|
+ * Add `Cldr.Locale.fallback_locales/1` to return the list of recursively created parent locales, including the provided locale. This can be used to support resolving translations from a system that might be sparsely populated.
|
26
|
+
|
27
|
+ * Add `Cldr.Locale.fallback_locale_names/1` that returns the `:cldr_locale_name` component of the locales returned by `Cldr.Locale.fallback_locales/1`.
|
28
|
+
|
29
|
+ * Adds `Cldr.Locale.locale_from_territory/{1,2}` to derive a "best fit" locale for a given territory. Also adds `<backend>.Locale.locale_from_territory/1`.
|
30
|
+
|
31
|
+ * Adds `Cldr.Locale.locale_from_host/{2, 3}` to derive a "best fit" locale for a given host name. Also adds `<backend>.Locale.locale_from_host/2`.
|
32
|
+
|
33
|
+ * Adds `Cldr.Locale.territory_from_host/1` to return the territory for a given host name. Also adds `<backend>.Locale.territory_from_host/1`.
|
34
|
+
|
35
|
+ * Adds `Cldr.Locale.consider_as_tlds/0` to return a list of valid territory suffixes that are considered as generic TLDs instead. See https://developers.google.com/search/docs/advanced/crawling/managing-multi-regional-sites.
|
36
|
+
|
37
|
+ * Adds `Cldr.Locale.languages_for_territories/0` to return a mapping of territories to that territory's most spoken language.
|
38
|
+
|
39
|
+ * Adds `Cldr.put_gettext_locale/1` that sets the `gettext` locale for a given `t:Cldr.LanguageTag`.
|
40
|
+
|
41
|
+ * Adds `Cldr.TestHelper` module in `test/suport` to provide testing helpers. Initially provides `with_no_default_backend/1` function.
|
42
|
+
|
3
43
|
## Cldr v2.25.0
|
4
44
|
|
5
45
|
This is the changelog for Cldr v2.25.0 released on December 16th, 2021. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-cldr/cldr/tags)
|
6
46
|
|
7
47
|
### Bug Fixes
|
8
48
|
|
9
|
- * Fixes configuring locales when the default locale is in posix form (ie like `en_GB`) as apposed to BCP47 form (ie `en-GB`). In fixing this bug, forming the normalised list of configured locales is now also standarised. Thanks to @gazzer82 for the report. Closes #165
|
49
|
+ * Fixes configuring locales when the default locale is in posix form (ie like `en_GB`) as apposed to BCP47 form (ie `en-GB`). In fixing this bug, forming the normalised list of configured locales is now also standarised. Thanks to @gazzer82 for the report. Closes #165.
|
10
50
|
|
11
51
|
### Enhancements
|
changed
hex_metadata.config
|
@@ -13,8 +13,8 @@
|
13
13
|
<<"lib/cldr/config/rbnf_config.ex">>,<<"lib/cldr/exception.ex">>,
|
14
14
|
<<"lib/cldr/validity.ex">>,<<"lib/cldr/backend">>,
|
15
15
|
<<"lib/cldr/backend/compiler.ex">>,<<"lib/cldr/backend/cldr.ex">>,
|
16
|
- <<"lib/cldr/backend/locale.ex">>,<<"lib/cldr/protocol">>,
|
17
|
- <<"lib/cldr/protocol/display_name.ex">>,
|
16
|
+ <<"lib/cldr/backend/trans.ex">>,<<"lib/cldr/backend/locale.ex">>,
|
17
|
+ <<"lib/cldr/protocol">>,<<"lib/cldr/protocol/display_name.ex">>,
|
18
18
|
<<"lib/cldr/protocol/language_tag_chars.ex">>,
|
19
19
|
<<"lib/cldr/protocol/cldr_chars.ex">>,<<"lib/cldr/install.ex">>,
|
20
20
|
<<"lib/cldr/timezone.ex">>,<<"lib/cldr/validity">>,
|
|
@@ -23,8 +23,8 @@
|
23
23
|
<<"lib/cldr/validity/t.ex">>,<<"lib/cldr/validity/subdivision.ex">>,
|
24
24
|
<<"lib/cldr/validity/language.ex">>,<<"lib/cldr/gettext">>,
|
25
25
|
<<"lib/cldr/gettext/plural.ex">>,<<"lib/cldr/accept_language.ex">>,
|
26
|
- <<"lib/cldr/sigil.ex">>,<<"lib/cldr/substitution.ex">>,
|
27
|
- <<"lib/cldr/language_tag">>,<<"lib/cldr/language_tag/rfc5646">>,
|
26
|
+ <<"lib/cldr/substitution.ex">>,<<"lib/cldr/language_tag">>,
|
27
|
+ <<"lib/cldr/language_tag/rfc5646">>,
|
28
28
|
<<"lib/cldr/language_tag/rfc5646/rfc5646_grammar.ex">>,
|
29
29
|
<<"lib/cldr/language_tag/rfc5646/rfc5646_core.ex">>,
|
30
30
|
<<"lib/cldr/language_tag/rfc5646/rfc5646_helpers.ex">>,
|
|
@@ -33,7 +33,7 @@
|
33
33
|
<<"lib/cldr/language_tag/extensions/u.ex">>,
|
34
34
|
<<"lib/cldr/language_tag/extensions/t.ex">>,
|
35
35
|
<<"lib/cldr/language_tag/rfc5646_parser.ex">>,
|
36
|
- <<"lib/cldr/language_tag/parser.ex">>,
|
36
|
+ <<"lib/cldr/language_tag/sigil.ex">>,<<"lib/cldr/language_tag/parser.ex">>,
|
37
37
|
<<"lib/cldr/language_tag/rfc5646_parser.ex.exs">>,
|
38
38
|
<<"lib/cldr/language_tag.ex">>,<<"lib/cldr/plug">>,
|
39
39
|
<<"lib/cldr/plug/plug_put_session.ex">>,
|
|
@@ -71,10 +71,10 @@
|
71
71
|
{<<"licenses">>,[<<"Apache-2.0">>]}.
|
72
72
|
{<<"links">>,
|
73
73
|
[{<<"Changelog">>,
|
74
|
- <<"https://github.com/elixir-cldr/cldr/blob/v2.25.0/CHANGELOG.md">>},
|
74
|
+ <<"https://github.com/elixir-cldr/cldr/blob/v2.26.0/CHANGELOG.md">>},
|
75
75
|
{<<"GitHub">>,<<"https://github.com/elixir-cldr/cldr">>},
|
76
76
|
{<<"Readme">>,
|
77
|
- <<"https://github.com/elixir-cldr/cldr/blob/v2.25.0/README.md">>}]}.
|
77
|
+ <<"https://github.com/elixir-cldr/cldr/blob/v2.26.0/README.md">>}]}.
|
78
78
|
{<<"name">>,<<"ex_cldr">>}.
|
79
79
|
{<<"requirements">>,
|
80
80
|
[[{<<"app">>,<<"cldr_utils">>},
|
|
@@ -111,10 +111,10 @@
|
111
111
|
{<<"name">>,<<"gettext">>},
|
112
112
|
{<<"optional">>,true},
|
113
113
|
{<<"repository">>,<<"hexpm">>},
|
114
|
- {<<"requirement">>,<<"~> 0.13">>}],
|
114
|
+ {<<"requirement">>,<<"~> 0.19">>}],
|
115
115
|
[{<<"app">>,<<"plug">>},
|
116
116
|
{<<"name">>,<<"plug">>},
|
117
117
|
{<<"optional">>,true},
|
118
118
|
{<<"repository">>,<<"hexpm">>},
|
119
119
|
{<<"requirement">>,<<"~> 1.9">>}]]}.
|
120
|
- {<<"version">>,<<"2.25.0">>}.
|
120
|
+ {<<"version">>,<<"2.26.0">>}.
|
changed
lib/cldr.ex
|
@@ -36,6 +36,8 @@ defmodule Cldr do
|
36
36
|
|
37
37
|
@type backend :: module()
|
38
38
|
|
39
|
+ defguard is_locale_name(locale_name) when is_atom(locale_name) or is_binary(locale_name)
|
40
|
+
|
39
41
|
alias Cldr.Config
|
40
42
|
alias Cldr.Locale
|
41
43
|
alias Cldr.Locale.Loader
|
|
@@ -133,12 +135,12 @@ defmodule Cldr do
|
133
135
|
%Cldr.LanguageTag{
|
134
136
|
backend: TestBackend.Cldr,
|
135
137
|
canonical_locale_name: "pl",
|
136
|
- cldr_locale_name: "pl",
|
138
|
+ cldr_locale_name: :pl,
|
137
139
|
extensions: %{},
|
138
140
|
language: "pl",
|
139
141
|
locale: %{},
|
140
142
|
private_use: [],
|
141
|
- rbnf_locale_name: "pl",
|
143
|
+ rbnf_locale_name: :pl,
|
142
144
|
territory: :PL,
|
143
145
|
requested_locale_name: "pl",
|
144
146
|
script: :Latn,
|
|
@@ -198,14 +200,14 @@ defmodule Cldr do
|
198
200
|
%Cldr.LanguageTag{
|
199
201
|
backend: TestBackend.Cldr,
|
200
202
|
canonical_locale_name: "en",
|
201
|
- cldr_locale_name: "en",
|
203
|
+ cldr_locale_name: :en,
|
202
204
|
language_subtags: [],
|
203
205
|
extensions: %{},
|
204
206
|
gettext_locale_name: "en",
|
205
207
|
language: "en",
|
206
208
|
locale: %{},
|
207
209
|
private_use: [],
|
208
|
- rbnf_locale_name: "en",
|
210
|
+ rbnf_locale_name: :en,
|
209
211
|
requested_locale_name: "en",
|
210
212
|
script: :Latn,
|
211
213
|
territory: :US,
|
|
@@ -223,7 +225,7 @@ defmodule Cldr do
|
223
225
|
|
224
226
|
def put_locale(backend \\ nil, locale)
|
225
227
|
|
226
|
- def put_locale(nil, locale) when is_binary(locale) do
|
228
|
+ def put_locale(nil, locale) when is_locale_name(locale) do
|
227
229
|
backend = default_backend!()
|
228
230
|
|
229
231
|
with {:ok, locale} <- backend.validate_locale(locale) do
|
|
@@ -231,9 +233,9 @@ defmodule Cldr do
|
231
233
|
end
|
232
234
|
end
|
233
235
|
|
234
|
- def put_locale(backend, locale) when is_atom(backend) and is_binary(locale) do
|
236
|
+ def put_locale(backend, locale_name) when is_atom(backend) and is_locale_name(locale_name) do
|
235
237
|
with {:ok, backend} <- validate_backend(backend),
|
236
|
- {:ok, locale} <- backend.validate_locale(locale) do
|
238
|
+ {:ok, locale} <- backend.validate_locale(locale_name) do
|
237
239
|
put_locale(locale)
|
238
240
|
end
|
239
241
|
end
|
|
@@ -253,6 +255,57 @@ defmodule Cldr do
|
253
255
|
put_locale(locale)
|
254
256
|
end
|
255
257
|
|
258
|
+ if Code.ensure_loaded?(Gettext) do
|
259
|
+ @doc """
|
260
|
+ Set the current process's Gettext locale from a
|
261
|
+ `t:Cldr.LanguageTag`.
|
262
|
+
|
263
|
+ ## Arguments
|
264
|
+
|
265
|
+ * `locale` is a `Cldr.LanguageTag` struct returned by `Cldr.Locale.new!/2`.
|
266
|
+
|
267
|
+ ## Returns
|
268
|
+
|
269
|
+ * `{:ok, gettext_locale_name}` or
|
270
|
+
|
271
|
+ * `{:error, {exception, reason}}`
|
272
|
+
|
273
|
+ ## Behaviour
|
274
|
+
|
275
|
+ 1. If the `locale.gettext_locale_name` is `nil` then an error
|
276
|
+ is returned.
|
277
|
+
|
278
|
+ 2. The `gettext` locale for the `gettext_backend` configured for the
|
279
|
+ CLDR backend defined by the `t:Cldr.LanguageTag` is set.
|
280
|
+
|
281
|
+ ## Examples
|
282
|
+
|
283
|
+ iex> import Cldr.LanguageTag.Sigil
|
284
|
+ iex> Cldr.put_gettext_locale(~l"en")
|
285
|
+ {:ok, "en"}
|
286
|
+
|
287
|
+ iex> import Cldr.LanguageTag.Sigil
|
288
|
+ iex> Cldr.put_gettext_locale(~l"de")
|
289
|
+ {:error,
|
290
|
+ {Cldr.UnknownLocaleError,
|
291
|
+ "Locale #Cldr.LanguageTag<de [validated]> does not map to a known gettext locale name"}}
|
292
|
+
|
293
|
+ """
|
294
|
+ @spec put_gettext_locale(LanguageTag.t()) ::
|
295
|
+ {:ok, binary() | nil} | {:error, {module(), String.t()}}
|
296
|
+
|
297
|
+ def put_gettext_locale(%LanguageTag{gettext_locale_name: nil} = locale) do
|
298
|
+ {:error, {Cldr.UnknownLocaleError, "Locale #{inspect locale} does not map to a known gettext locale name"}}
|
299
|
+ end
|
300
|
+
|
301
|
+ def put_gettext_locale(%LanguageTag{gettext_locale_name: gettext_locale_name} = locale) do
|
302
|
+ gettext_backend = locale.backend.__cldr__(:gettext)
|
303
|
+ _ = Gettext.put_locale(gettext_backend, gettext_locale_name)
|
304
|
+ {:ok, gettext_locale_name}
|
305
|
+ end
|
306
|
+
|
307
|
+ end
|
308
|
+
|
256
309
|
@doc """
|
257
310
|
Set's the system default locale.
|
258
311
|
|
|
@@ -321,14 +374,14 @@ defmodule Cldr do
|
321
374
|
%Cldr.LanguageTag{
|
322
375
|
backend: TestBackend.Cldr,
|
323
376
|
canonical_locale_name: "en-001",
|
324
|
- cldr_locale_name: "en-001",
|
377
|
+ cldr_locale_name: :"en-001",
|
325
378
|
language_subtags: [],
|
326
379
|
extensions: %{},
|
327
380
|
gettext_locale_name: "en",
|
328
381
|
language: "en",
|
329
382
|
locale: %{},
|
330
383
|
private_use: [],
|
331
|
- rbnf_locale_name: "en",
|
384
|
+ rbnf_locale_name: :en,
|
332
385
|
requested_locale_name: "en-001",
|
333
386
|
script: :Latn,
|
334
387
|
territory: :"001",
|
|
@@ -372,14 +425,14 @@ defmodule Cldr do
|
372
425
|
%Cldr.LanguageTag{
|
373
426
|
backend: TestBackend.Cldr,
|
374
427
|
canonical_locale_name: "en-001",
|
375
|
- cldr_locale_name: "en-001",
|
428
|
+ cldr_locale_name: :"en-001",
|
376
429
|
language_subtags: [],
|
377
430
|
extensions: %{},
|
378
431
|
gettext_locale_name: "en",
|
379
432
|
language: "en",
|
380
433
|
locale: %{},
|
381
434
|
private_use: [],
|
382
|
- rbnf_locale_name: "en",
|
435
|
+ rbnf_locale_name: :en,
|
383
436
|
requested_locale_name: "en-001",
|
384
437
|
script: :Latn,
|
385
438
|
territory: :"001",
|
|
@@ -460,7 +513,7 @@ defmodule Cldr do
|
460
513
|
## Arguments
|
461
514
|
|
462
515
|
* `backend` is any module that includes `use Cldr` and therefore
|
463
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`
|
516
|
+ is a `Cldr` backend module.
|
464
517
|
|
465
518
|
## Returns
|
466
519
|
|
|
@@ -471,6 +524,7 @@ defmodule Cldr do
|
471
524
|
"""
|
472
525
|
def put_default_backend(backend) do
|
473
526
|
with {:ok, backend} <- validate_backend(backend) do
|
527
|
+ :ok = Application.put_env(Cldr.Config.app_name(), :default_backend, backend)
|
474
528
|
{:ok, backend}
|
475
529
|
end
|
476
530
|
end
|
|
@@ -539,7 +593,8 @@ defmodule Cldr do
|
539
593
|
|
540
594
|
## Arguments
|
541
595
|
|
542
|
- * `backend` is any module
|
596
|
+ * `backend` is any module name that may be a
|
597
|
+ `CLDR` backend module.
|
543
598
|
|
544
599
|
## Returns
|
545
600
|
|
|
@@ -594,8 +649,8 @@ defmodule Cldr do
|
594
649
|
or a `Cldr.LanguageTag` struct returned by `Cldr.Locale.new!/2`
|
595
650
|
|
596
651
|
* `backend` is any module that includes `use Cldr` and therefore
|
597
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
598
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
652
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
653
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
599
654
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
600
655
|
`config.exs`.
|
601
656
|
|
|
@@ -607,18 +662,18 @@ defmodule Cldr do
|
607
662
|
|
608
663
|
## Examples
|
609
664
|
|
610
|
- iex> Cldr.validate_locale("en", TestBackend.Cldr)
|
665
|
+ iex> Cldr.validate_locale(:en, TestBackend.Cldr)
|
611
666
|
{:ok,
|
612
667
|
%Cldr.LanguageTag{
|
613
668
|
backend: TestBackend.Cldr,
|
614
669
|
canonical_locale_name: "en",
|
615
|
- cldr_locale_name: "en",
|
670
|
+ cldr_locale_name: :en,
|
616
671
|
extensions: %{},
|
617
672
|
gettext_locale_name: "en",
|
618
673
|
language: "en",
|
619
674
|
locale: %{},
|
620
675
|
private_use: [],
|
621
|
- rbnf_locale_name: "en",
|
676
|
+ rbnf_locale_name: :en,
|
622
677
|
requested_locale_name: "en",
|
623
678
|
script: :Latn,
|
624
679
|
territory: :US,
|
|
@@ -626,11 +681,30 @@ defmodule Cldr do
|
626
681
|
language_variants: []
|
627
682
|
}}
|
628
683
|
|
684
|
+ iex> Cldr.validate_locale(:af, TestBackend.Cldr)
|
685
|
+ {:ok,
|
686
|
+ %Cldr.LanguageTag{
|
687
|
+ backend: TestBackend.Cldr,
|
688
|
+ canonical_locale_name: "af",
|
689
|
+ cldr_locale_name: :af,
|
690
|
+ extensions: %{},
|
691
|
+ gettext_locale_name: nil,
|
692
|
+ language: "af",
|
693
|
+ locale: %{},
|
694
|
+ private_use: [],
|
695
|
+ rbnf_locale_name: :af,
|
696
|
+ requested_locale_name: "af",
|
697
|
+ script: :Latn,
|
698
|
+ territory: :ZA,
|
699
|
+ transform: %{},
|
700
|
+ language_variants: []
|
701
|
+ }}
|
702
|
+
|
629
703
|
iex> Cldr.validate_locale("zzz", TestBackend.Cldr)
|
630
704
|
{:error, {Cldr.InvalidLanguageError, "The language \\"zzz\\" is invalid"}}
|
631
705
|
|
632
706
|
"""
|
633
|
- @spec validate_locale(Locale.locale_name() | LanguageTag.t(), backend()) ::
|
707
|
+ @spec validate_locale(Locale.locale_name() | LanguageTag.t() | String.t(), backend()) ::
|
634
708
|
{:ok, LanguageTag.t()} | {:error, {module(), String.t()}}
|
635
709
|
|
636
710
|
def validate_locale(locale, backend \\ nil)
|
|
@@ -671,8 +745,8 @@ defmodule Cldr do
|
671
745
|
## Arguments
|
672
746
|
|
673
747
|
* `backend` is any module that includes `use Cldr` and therefore
|
674
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
675
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
748
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
749
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
676
750
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
677
751
|
`config.exs`.
|
678
752
|
|
|
@@ -693,8 +767,8 @@ defmodule Cldr do
|
693
767
|
## Arguments
|
694
768
|
|
695
769
|
* `backend` is any module that includes `use Cldr` and therefore
|
696
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
697
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
770
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
771
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
698
772
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
699
773
|
`config.exs`.
|
700
774
|
|
|
@@ -717,8 +791,8 @@ defmodule Cldr do
|
717
791
|
## Arguments
|
718
792
|
|
719
793
|
* `backend` is any module that includes `use Cldr` and therefore
|
720
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
721
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
794
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
795
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
722
796
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
723
797
|
`config.exs`.
|
724
798
|
|
|
@@ -755,8 +829,8 @@ defmodule Cldr do
|
755
829
|
## Arguments
|
756
830
|
|
757
831
|
* `backend` is any module that includes `use Cldr` and therefore
|
758
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
759
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
832
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
833
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
760
834
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
761
835
|
`config.exs`.
|
762
836
|
|
|
@@ -778,23 +852,25 @@ defmodule Cldr do
|
778
852
|
* `locale` is any valid locale name returned by `Cldr.known_locale_names/1`
|
779
853
|
|
780
854
|
* `backend` is any module that includes `use Cldr` and therefore
|
781
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
782
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
855
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
856
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
783
857
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
784
858
|
`config.exs`.
|
785
859
|
|
786
860
|
## Examples
|
787
861
|
|
788
|
- iex> Cldr.known_locale_name("en-AU", TestBackend.Cldr)
|
789
|
- "en-AU"
|
862
|
+ iex> Cldr.known_locale_name(:"en-AU", TestBackend.Cldr)
|
863
|
+ :"en-AU"
|
790
864
|
|
791
|
- iex> Cldr.known_locale_name("en-SA", TestBackend.Cldr)
|
865
|
+ iex> Cldr.known_locale_name(:"en-SA", TestBackend.Cldr)
|
792
866
|
nil
|
793
867
|
|
794
868
|
"""
|
795
|
- @spec known_locale_name(Locale.locale_name(), backend()) :: String.t() | nil
|
869
|
+ @spec known_locale_name(Locale.locale_name() | String.t(), backend()) :: atom() | nil
|
870
|
+
|
796
871
|
def known_locale_name(locale_name, backend \\ default_backend!())
|
797
|
- when is_binary(locale_name) do
|
872
|
+
|
873
|
+ def known_locale_name(locale_name, backend) when is_atom(locale_name) do
|
798
874
|
if name = backend.known_locale_name(locale_name) do
|
799
875
|
name
|
800
876
|
else
|
|
@@ -802,6 +878,14 @@ defmodule Cldr do
|
802
878
|
end
|
803
879
|
end
|
804
880
|
|
881
|
+ # TODO remove when we get to Cldr 3.0
|
882
|
+ def known_locale_name(locale_name, backend) when is_binary(locale_name) do
|
883
|
+ locale_name = String.to_existing_atom(locale_name)
|
884
|
+ known_locale_name(locale_name, backend)
|
885
|
+ rescue ArgumentError ->
|
886
|
+ nil
|
887
|
+ end
|
888
|
+
|
805
889
|
@doc """
|
806
890
|
Returns a boolean indicating if the specified locale
|
807
891
|
name is configured and available in Cldr.
|
|
@@ -811,23 +895,22 @@ defmodule Cldr do
|
811
895
|
* `locale` is any valid locale name returned by `Cldr.known_locale_names/1`
|
812
896
|
|
813
897
|
* `backend` is any module that includes `use Cldr` and therefore
|
814
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
815
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
898
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
899
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
816
900
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
817
901
|
`config.exs`.
|
818
902
|
|
819
903
|
## Examples
|
820
904
|
|
821
|
- iex> Cldr.known_locale_name?("en", TestBackend.Cldr)
|
905
|
+ iex> Cldr.known_locale_name?(:en, TestBackend.Cldr)
|
822
906
|
true
|
823
907
|
|
824
|
- iex> Cldr.known_locale_name?("!!", TestBackend.Cldr)
|
908
|
+ iex> Cldr.known_locale_name?(:"!!", TestBackend.Cldr)
|
825
909
|
false
|
826
910
|
|
827
911
|
"""
|
828
912
|
@spec known_locale_name?(Locale.locale_name(), backend()) :: boolean
|
829
|
- def known_locale_name?(locale_name, backend \\ default_backend!())
|
830
|
- when is_binary(locale_name) do
|
913
|
+ def known_locale_name?(locale_name, backend \\ default_backend!()) when is_atom(locale_name) do
|
831
914
|
locale_name in backend.known_locale_names
|
832
915
|
end
|
833
916
|
|
|
@@ -841,23 +924,22 @@ defmodule Cldr do
|
841
924
|
* `locale` is any valid locale name returned by `Cldr.known_locale_names/1`
|
842
925
|
|
843
926
|
* `backend` is any module that includes `use Cldr` and therefore
|
844
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
845
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
927
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
928
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
846
929
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
847
930
|
`config.exs`.
|
848
931
|
|
849
932
|
## Examples
|
850
933
|
|
851
|
- iex> Cldr.known_rbnf_locale_name?("en", TestBackend.Cldr)
|
934
|
+ iex> Cldr.known_rbnf_locale_name?(:en, TestBackend.Cldr)
|
852
935
|
true
|
853
936
|
|
854
|
- iex> Cldr.known_rbnf_locale_name?("!!", TestBackend.Cldr)
|
937
|
+ iex> Cldr.known_rbnf_locale_name?(:"!!", TestBackend.Cldr)
|
855
938
|
false
|
856
939
|
|
857
940
|
"""
|
858
941
|
@spec known_rbnf_locale_name?(Locale.locale_name(), backend()) :: boolean
|
859
|
- def known_rbnf_locale_name?(locale_name, backend \\ default_backend!())
|
860
|
- when is_binary(locale_name) do
|
942
|
+ def known_rbnf_locale_name?(locale_name, backend \\ default_backend!()) do
|
861
943
|
locale_name in backend.known_rbnf_locale_names
|
862
944
|
end
|
863
945
|
|
|
@@ -870,8 +952,8 @@ defmodule Cldr do
|
870
952
|
* `locale` is any valid locale name returned by `Cldr.known_locale_names/1`
|
871
953
|
|
872
954
|
* `backend` is any module that includes `use Cldr` and therefore
|
873
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
874
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
955
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
956
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
875
957
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
876
958
|
`config.exs`.
|
877
959
|
|
|
@@ -884,7 +966,7 @@ defmodule Cldr do
|
884
966
|
false
|
885
967
|
|
886
968
|
"""
|
887
|
- @spec known_gettext_locale_name?(Locale.locale_name(), backend) :: boolean
|
969
|
+ @spec known_gettext_locale_name?(String.t(), backend) :: boolean
|
888
970
|
def known_gettext_locale_name?(locale_name, backend \\ default_backend!())
|
889
971
|
when is_binary(locale_name) do
|
890
972
|
locale_name in backend.known_gettext_locale_names
|
|
@@ -900,23 +982,22 @@ defmodule Cldr do
|
900
982
|
* `locale` is any valid locale name returned by `Cldr.known_locale_names/1`
|
901
983
|
|
902
984
|
* `backend` is any module that includes `use Cldr` and therefore
|
903
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
904
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
985
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
986
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
905
987
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
906
988
|
`config.exs`.
|
907
989
|
|
908
990
|
## Examples
|
909
991
|
|
910
|
- iex> Cldr.known_rbnf_locale_name("en", TestBackend.Cldr)
|
911
|
- "en"
|
992
|
+ iex> Cldr.known_rbnf_locale_name(:en, TestBackend.Cldr)
|
993
|
+ :en
|
912
994
|
|
913
|
- iex> Cldr.known_rbnf_locale_name("en-SA", TestBackend.Cldr)
|
995
|
+ iex> Cldr.known_rbnf_locale_name(:"en-SA", TestBackend.Cldr)
|
914
996
|
false
|
915
997
|
|
916
998
|
"""
|
917
999
|
@spec known_rbnf_locale_name(Locale.locale_name(), backend()) :: String.t() | false
|
918
|
- def known_rbnf_locale_name(locale_name, backend \\ default_backend!())
|
919
|
- when is_binary(locale_name) do
|
1000
|
+ def known_rbnf_locale_name(locale_name, backend \\ default_backend!()) do
|
920
1001
|
if backend.known_rbnf_locale_name?(locale_name) do
|
921
1002
|
locale_name
|
922
1003
|
else
|
|
@@ -934,8 +1015,8 @@ defmodule Cldr do
|
934
1015
|
* `locale` is any valid locale name returned by `Cldr.known_locale_names/1`
|
935
1016
|
|
936
1017
|
* `backend` is any module that includes `use Cldr` and therefore
|
937
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
938
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
1018
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
1019
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
939
1020
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
940
1021
|
`config.exs`.
|
941
1022
|
|
|
@@ -948,7 +1029,7 @@ defmodule Cldr do
|
948
1029
|
false
|
949
1030
|
|
950
1031
|
"""
|
951
|
- @spec known_gettext_locale_name(Locale.locale_name(), backend()) :: String.t() | false
|
1032
|
+ @spec known_gettext_locale_name(String.t(), backend()) :: String.t() | false
|
952
1033
|
def known_gettext_locale_name(locale_name, backend \\ default_backend!())
|
953
1034
|
when is_binary(locale_name) do
|
954
1035
|
backend.known_gettext_locale_name(locale_name)
|
|
@@ -969,22 +1050,28 @@ defmodule Cldr do
|
969
1050
|
|
970
1051
|
## Examples
|
971
1052
|
|
972
|
- iex> Cldr.available_locale_name?("en-AU")
|
1053
|
+ iex> Cldr.available_locale_name?(:"en-AU")
|
973
1054
|
true
|
974
1055
|
|
975
|
- iex> Cldr.available_locale_name?("en-SA")
|
1056
|
+ iex> Cldr.available_locale_name?(:"en-SA")
|
976
1057
|
false
|
977
1058
|
|
978
1059
|
"""
|
1060
|
+ @all_locale_names Config.all_locale_names()
|
1061
|
+
|
979
1062
|
@spec available_locale_name?(Locale.locale_name() | LanguageTag.t()) :: boolean
|
980
|
- def available_locale_name?(locale_name) when is_binary(locale_name) do
|
981
|
- locale_name in Config.all_locale_names()
|
1063
|
+ def available_locale_name?(locale_name) when is_atom(locale_name) do
|
1064
|
+ locale_name in @all_locale_names
|
982
1065
|
end
|
983
1066
|
|
984
1067
|
def available_locale_name?(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
|
985
1068
|
available_locale_name?(cldr_locale_name)
|
986
1069
|
end
|
987
1070
|
|
1071
|
+ def available_locale_name?(_other) do
|
1072
|
+ false
|
1073
|
+ end
|
1074
|
+
|
988
1075
|
@doc """
|
989
1076
|
Add locale-specific quotation marks around a string.
|
990
1077
|
|
|
@@ -993,8 +1080,8 @@ defmodule Cldr do
|
993
1080
|
* `string` is any valid Elixir string
|
994
1081
|
|
995
1082
|
* `backend` is any module that includes `use Cldr` and therefore
|
996
|
- is a `Cldr` backend module. The default is `Cldr.default_backend/0`.
|
997
|
- Note that `Cldr.default_backend/0` will raise an exception if
|
1083
|
+ is a `Cldr` backend module. The default is `Cldr.default_backend!/0`.
|
1084
|
+ Note that `Cldr.default_backend!/0` will raise an exception if
|
998
1085
|
no `:default_backend` is configured under the `:ex_cldr` key in
|
999
1086
|
`config.exs`.
|
1000
1087
|
|
|
@@ -1444,7 +1531,7 @@ defmodule Cldr do
|
1444
1531
|
|
1445
1532
|
"""
|
1446
1533
|
@spec validate_territory(atom() | String.t()) ::
|
1447
|
- {:ok, atom()} | {:error, {module(), String.t()}}
|
1534
|
+ {:ok, Locale.territory_code()} | {:error, {module(), String.t()}}
|
1448
1535
|
|
1449
1536
|
def validate_territory(territory) when is_atom(territory) and territory in @known_territories do
|
1450
1537
|
{:ok, territory}
|
|
@@ -1631,7 +1718,7 @@ defmodule Cldr do
|
1631
1718
|
{:ok, [:CA, :"021", :"019", :"001"]}
|
1632
1719
|
|
1633
1720
|
"""
|
1634
|
- def territory_chain(locale_name, backend) when is_binary(locale_name) and is_atom(backend) do
|
1721
|
+ def territory_chain(locale_name, backend) when is_atom(backend) do
|
1635
1722
|
with {:ok, locale} <- validate_locale(locale_name, backend) do
|
1636
1723
|
territory_chain(locale)
|
1637
1724
|
end
|
changed
lib/cldr/accept_language.ex
|
@@ -98,14 +98,14 @@ defmodule Cldr.AcceptLanguage do
|
98
98
|
%Cldr.LanguageTag{
|
99
99
|
backend: TestBackend.Cldr,
|
100
100
|
canonical_locale_name: "da",
|
101
|
- cldr_locale_name: "da",
|
101
|
+ cldr_locale_name: :da,
|
102
102
|
language_subtags: [],
|
103
103
|
extensions: %{},
|
104
104
|
gettext_locale_name: nil,
|
105
105
|
language: "da",
|
106
106
|
locale: %{},
|
107
107
|
private_use: [],
|
108
|
- rbnf_locale_name: "da",
|
108
|
+ rbnf_locale_name: :da,
|
109
109
|
requested_locale_name: "da",
|
110
110
|
script: :Latn,
|
111
111
|
territory: :DK,
|
|
@@ -116,14 +116,14 @@ defmodule Cldr.AcceptLanguage do
|
116
116
|
%Cldr.LanguageTag{
|
117
117
|
backend: TestBackend.Cldr,
|
118
118
|
canonical_locale_name: "zh-TW",
|
119
|
- cldr_locale_name: "zh-Hant",
|
119
|
+ cldr_locale_name: :"zh-Hant",
|
120
120
|
language_subtags: [],
|
121
121
|
extensions: %{},
|
122
122
|
gettext_locale_name: nil,
|
123
123
|
language: "zh",
|
124
124
|
locale: %{},
|
125
125
|
private_use: [],
|
126
|
- rbnf_locale_name: "zh-Hant",
|
126
|
+ rbnf_locale_name: :"zh-Hant",
|
127
127
|
requested_locale_name: "zh-TW",
|
128
128
|
script: :Hant,
|
129
129
|
territory: :TW,
|
|
@@ -144,14 +144,14 @@ defmodule Cldr.AcceptLanguage do
|
144
144
|
%Cldr.LanguageTag{
|
145
145
|
backend: TestBackend.Cldr,
|
146
146
|
canonical_locale_name: "da",
|
147
|
- cldr_locale_name: "da",
|
147
|
+ cldr_locale_name: :da,
|
148
148
|
language_subtags: [],
|
149
149
|
extensions: %{},
|
150
150
|
gettext_locale_name: nil,
|
151
151
|
language: "da",
|
152
152
|
locale: %{},
|
153
153
|
private_use: [],
|
154
|
- rbnf_locale_name: "da",
|
154
|
+ rbnf_locale_name: :da,
|
155
155
|
requested_locale_name: "da",
|
156
156
|
script: :Latn,
|
157
157
|
territory: :DK,
|
|
@@ -162,14 +162,14 @@ defmodule Cldr.AcceptLanguage do
|
162
162
|
%Cldr.LanguageTag{
|
163
163
|
backend: TestBackend.Cldr,
|
164
164
|
canonical_locale_name: "zh-TW",
|
165
|
- cldr_locale_name: "zh-Hant",
|
165
|
+ cldr_locale_name: :"zh-Hant",
|
166
166
|
language_subtags: [],
|
167
167
|
extensions: %{},
|
168
168
|
gettext_locale_name: nil,
|
169
169
|
language: "zh",
|
170
170
|
locale: %{},
|
171
171
|
private_use: [],
|
172
|
- rbnf_locale_name: "zh-Hant",
|
172
|
+ rbnf_locale_name: :"zh-Hant",
|
173
173
|
requested_locale_name: "zh-TW",
|
174
174
|
script: :Hant,
|
175
175
|
territory: :TW,
|
|
@@ -237,14 +237,14 @@ defmodule Cldr.AcceptLanguage do
|
237
237
|
%Cldr.LanguageTag{
|
238
238
|
backend: TestBackend.Cldr,
|
239
239
|
canonical_locale_name: "da",
|
240
|
- cldr_locale_name: "da",
|
240
|
+ cldr_locale_name: :da,
|
241
241
|
language_subtags: [],
|
242
242
|
extensions: %{},
|
243
243
|
gettext_locale_name: nil,
|
244
244
|
language: "da",
|
245
245
|
locale: %{},
|
246
246
|
private_use: [],
|
247
|
- rbnf_locale_name: "da",
|
247
|
+ rbnf_locale_name: :da,
|
248
248
|
requested_locale_name: "da",
|
249
249
|
script: :Latn,
|
250
250
|
territory: :DK,
|
|
@@ -255,14 +255,14 @@ defmodule Cldr.AcceptLanguage do
|
255
255
|
%Cldr.LanguageTag{
|
256
256
|
backend: TestBackend.Cldr,
|
257
257
|
canonical_locale_name: "zh-TW",
|
258
|
- cldr_locale_name: "zh-Hant",
|
258
|
+ cldr_locale_name: :"zh-Hant",
|
259
259
|
language_subtags: [],
|
260
260
|
extensions: %{},
|
261
261
|
gettext_locale_name: nil,
|
262
262
|
language: "zh",
|
263
263
|
locale: %{},
|
264
264
|
private_use: [],
|
265
|
- rbnf_locale_name: "zh-Hant",
|
265
|
+ rbnf_locale_name: :"zh-Hant",
|
266
266
|
requested_locale_name: "zh-TW",
|
267
267
|
script: :Hant,
|
268
268
|
territory: :TW,
|
|
@@ -281,14 +281,14 @@ defmodule Cldr.AcceptLanguage do
|
281
281
|
%Cldr.LanguageTag{
|
282
282
|
backend: TestBackend.Cldr,
|
283
283
|
canonical_locale_name: "da",
|
284
|
- cldr_locale_name: "da",
|
284
|
+ cldr_locale_name: :da,
|
285
285
|
language_subtags: [],
|
286
286
|
extensions: %{},
|
287
287
|
gettext_locale_name: nil,
|
288
288
|
language: "da",
|
289
289
|
locale: %{},
|
290
290
|
private_use: [],
|
291
|
- rbnf_locale_name: "da",
|
291
|
+ rbnf_locale_name: :da,
|
292
292
|
requested_locale_name: "da",
|
293
293
|
script: :Latn,
|
294
294
|
territory: :DK,
|
|
@@ -299,14 +299,14 @@ defmodule Cldr.AcceptLanguage do
|
299
299
|
%Cldr.LanguageTag{
|
300
300
|
backend: TestBackend.Cldr,
|
301
301
|
canonical_locale_name: "zh-TW",
|
302
|
- cldr_locale_name: "zh-Hant",
|
302
|
+ cldr_locale_name: :"zh-Hant",
|
303
303
|
language_subtags: [],
|
304
304
|
extensions: %{},
|
305
305
|
gettext_locale_name: nil,
|
306
306
|
language: "zh",
|
307
307
|
locale: %{},
|
308
308
|
private_use: [],
|
309
|
- rbnf_locale_name: "zh-Hant",
|
309
|
+ rbnf_locale_name: :"zh-Hant",
|
310
310
|
requested_locale_name: "zh-TW",
|
311
311
|
script: :Hant,
|
312
312
|
territory: :TW,
|
|
@@ -345,14 +345,14 @@ defmodule Cldr.AcceptLanguage do
|
345
345
|
%Cldr.LanguageTag{
|
346
346
|
backend: TestBackend.Cldr,
|
347
347
|
canonical_locale_name: "zh-TW",
|
348
|
- cldr_locale_name: "zh-Hant",
|
348
|
+ cldr_locale_name: :"zh-Hant",
|
349
349
|
language_subtags: [],
|
350
350
|
extensions: %{},
|
351
351
|
gettext_locale_name: nil,
|
352
352
|
language: "zh",
|
353
353
|
locale: %{},
|
354
354
|
private_use: [],
|
355
|
- rbnf_locale_name: "zh-Hant",
|
355
|
+ rbnf_locale_name: :"zh-Hant",
|
356
356
|
requested_locale_name: "zh-TW",
|
357
357
|
script: :Hant,
|
358
358
|
territory: :TW,
|
|
@@ -360,19 +360,19 @@ defmodule Cldr.AcceptLanguage do
|
360
360
|
language_variants: []
|
361
361
|
}}
|
362
362
|
|
363
|
- iex(4)> Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
|
363
|
+ iex> Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
|
364
364
|
{:ok,
|
365
365
|
%Cldr.LanguageTag{
|
366
366
|
backend: TestBackend.Cldr,
|
367
367
|
canonical_locale_name: "zh-TW",
|
368
|
- cldr_locale_name: "zh-Hant",
|
368
|
+ cldr_locale_name: :"zh-Hant",
|
369
369
|
language_subtags: [],
|
370
370
|
extensions: %{},
|
371
371
|
gettext_locale_name: nil,
|
372
372
|
language: "zh",
|
373
373
|
locale: %{},
|
374
374
|
private_use: [],
|
375
|
- rbnf_locale_name: "zh-Hant",
|
375
|
+ rbnf_locale_name: :"zh-Hant",
|
376
376
|
requested_locale_name: "zh-TW",
|
377
377
|
script: :Hant,
|
378
378
|
territory: :TW,
|
changed
lib/cldr/backend/cldr.ex
|
@@ -14,8 +14,12 @@ defmodule Cldr.Backend do
|
14
14
|
in this module or in `Gettext`.
|
15
15
|
|
16
16
|
"""
|
17
|
- @omit_locales ["und"]
|
18
|
- @known_locale_names Cldr.Locale.Loader.known_locale_names(config) -- @omit_locales
|
17
|
+
|
18
|
+ alias Cldr.{Locale, Config, LanguageTag}
|
19
|
+
|
20
|
+ @omit_locales [Config.root_locale_name()]
|
21
|
+ @known_locale_names Locale.Loader.known_locale_names(config) -- @omit_locales
|
22
|
+
|
19
23
|
def known_locale_names do
|
20
24
|
@known_locale_names
|
21
25
|
end
|
|
@@ -29,14 +33,14 @@ defmodule Cldr.Backend do
|
29
33
|
%Cldr.LanguageTag{
|
30
34
|
backend: #{inspect(__MODULE__)},
|
31
35
|
canonical_locale_name: "en-001",
|
32
|
- cldr_locale_name: "en-001",
|
36
|
+ cldr_locale_name: :"en-001",
|
33
37
|
language_subtags: [],
|
34
38
|
extensions: %{},
|
35
39
|
gettext_locale_name: "en",
|
36
40
|
language: "en",
|
37
41
|
locale: %{},
|
38
42
|
private_use: [],
|
39
|
- rbnf_locale_name: "en",
|
43
|
+ rbnf_locale_name: :en,
|
40
44
|
requested_locale_name: "en-001",
|
41
45
|
script: :Latn,
|
42
46
|
territory: :"001",
|
|
@@ -46,12 +50,12 @@ defmodule Cldr.Backend do
|
46
50
|
|
47
51
|
"""
|
48
52
|
@default_locale config
|
49
|
- |> Cldr.Config.default_locale_name()
|
50
|
- |> Cldr.Config.language_tag()
|
53
|
+ |> Config.default_locale_name()
|
54
|
+ |> Config.language_tag()
|
51
55
|
|> Map.put(:backend, __MODULE__)
|
52
56
|
|
53
57
|
@compile {:inline, default_locale: 0}
|
54
|
- @spec default_locale :: Cldr.LanguageTag.t() | no_return()
|
58
|
+ @spec default_locale :: LanguageTag.t() | no_return()
|
55
59
|
def default_locale do
|
56
60
|
Cldr.Locale.put_gettext_locale_name(@default_locale)
|
57
61
|
end
|
|
@@ -66,10 +70,9 @@ defmodule Cldr.Backend do
|
66
70
|
:"001"
|
67
71
|
|
68
72
|
"""
|
69
|
- @default_territory @default_locale |> Cldr.Locale.territory_from_locale()
|
70
|
- @spec default_territory() :: Cldr.Locale.territory()
|
73
|
+ @spec default_territory() :: Locale.territory_code()
|
71
74
|
def default_territory do
|
72
|
- @default_territory
|
75
|
+ Cldr.Locale.territory_from_locale(@default_locale)
|
73
76
|
end
|
74
77
|
|
75
78
|
@doc """
|
|
@@ -81,7 +84,7 @@ defmodule Cldr.Backend do
|
81
84
|
return an empty list.
|
82
85
|
|
83
86
|
"""
|
84
|
- @unknown_locale_names Cldr.Config.unknown_locale_names(config)
|
87
|
+ @unknown_locale_names Config.unknown_locale_names(config)
|
85
88
|
@spec unknown_locale_names() :: [Locale.locale_name()]
|
86
89
|
def unknown_locale_names do
|
87
90
|
@unknown_locale_names
|
|
@@ -92,7 +95,8 @@ defmodule Cldr.Backend do
|
92
95
|
formats (RBNF).
|
93
96
|
|
94
97
|
"""
|
95
|
- @known_rbnf_locale_names Cldr.Locale.Loader.known_rbnf_locale_names(config)
|
98
|
+ @known_rbnf_locale_names Locale.Loader.known_rbnf_locale_names(config)
|
99
|
+
|
96
100
|
@spec known_rbnf_locale_names() :: [Locale.locale_name()]
|
97
101
|
def known_rbnf_locale_names do
|
98
102
|
@known_rbnf_locale_names
|
|
@@ -104,8 +108,9 @@ defmodule Cldr.Backend do
|
104
108
|
with `Cldr` locale names.
|
105
109
|
|
106
110
|
"""
|
107
|
- @known_gettext_locale_names Cldr.Config.known_gettext_locale_names(config)
|
108
|
- @spec known_gettext_locale_names() :: [Locale.locale_name()]
|
111
|
+ @known_gettext_locale_names Config.known_gettext_locale_names(config)
|
112
|
+
|
113
|
+ @spec known_gettext_locale_names() :: [String.t()]
|
109
114
|
def known_gettext_locale_names do
|
110
115
|
@known_gettext_locale_names
|
111
116
|
end
|
|
@@ -120,15 +125,15 @@ defmodule Cldr.Backend do
|
120
125
|
|
121
126
|
## Examples
|
122
127
|
|
123
|
- iex> #{inspect(__MODULE__)}.known_locale_name?("en")
|
128
|
+ iex> #{inspect(__MODULE__)}.known_locale_name?(:en)
|
124
129
|
true
|
125
130
|
|
126
|
- iex> #{inspect(__MODULE__)}.known_locale_name?("!!")
|
131
|
+ iex> #{inspect(__MODULE__)}.known_locale_name?(:"!!")
|
127
132
|
false
|
128
133
|
|
129
134
|
"""
|
130
135
|
@spec known_locale_name?(Locale.locale_name()) :: boolean
|
131
|
- def known_locale_name?(locale_name) when is_binary(locale_name) do
|
136
|
+ def known_locale_name?(locale_name) when is_atom(locale_name) do
|
132
137
|
locale_name in known_locale_names()
|
133
138
|
end
|
134
139
|
|
|
@@ -143,15 +148,15 @@ defmodule Cldr.Backend do
|
143
148
|
|
144
149
|
## Examples
|
145
150
|
|
146
|
- iex> #{inspect(__MODULE__)}.known_rbnf_locale_name?("en")
|
151
|
+ iex> #{inspect(__MODULE__)}.known_rbnf_locale_name?(:en)
|
147
152
|
true
|
148
153
|
|
149
|
- iex> #{inspect(__MODULE__)}.known_rbnf_locale_name?("!!")
|
154
|
+ iex> #{inspect(__MODULE__)}.known_rbnf_locale_name?(:"!!")
|
150
155
|
false
|
151
156
|
|
152
157
|
"""
|
153
158
|
@spec known_rbnf_locale_name?(Locale.locale_name()) :: boolean
|
154
|
- def known_rbnf_locale_name?(locale_name) when is_binary(locale_name) do
|
159
|
+ def known_rbnf_locale_name?(locale_name) when is_atom(locale_name) do
|
155
160
|
locale_name in known_rbnf_locale_names()
|
156
161
|
end
|
157
162
|
|
|
@@ -161,7 +166,8 @@ defmodule Cldr.Backend do
|
161
166
|
|
162
167
|
## Arguments
|
163
168
|
|
164
|
- * `locale` is any valid locale name returned by `#{inspect(__MODULE__)}.known_locale_names/0`
|
169
|
+ * `locale` is any valid locale name returned by
|
170
|
+ `#{inspect(__MODULE__)}.known_locale_names/0`
|
165
171
|
|
166
172
|
## Examples
|
167
173
|
|
|
@@ -172,7 +178,7 @@ defmodule Cldr.Backend do
|
172
178
|
false
|
173
179
|
|
174
180
|
"""
|
175
|
- @spec known_gettext_locale_name?(Locale.locale_name()) :: boolean
|
181
|
+ @spec known_gettext_locale_name?(String.t()) :: boolean
|
176
182
|
def known_gettext_locale_name?(locale_name) when is_binary(locale_name) do
|
177
183
|
locale_name in known_gettext_locale_names()
|
178
184
|
end
|
|
@@ -186,19 +192,20 @@ defmodule Cldr.Backend do
|
186
192
|
|
187
193
|
## Arguments
|
188
194
|
|
189
|
- * `locale` is any valid locale name returned by `#{inspect(__MODULE__)}.known_locale_names/0`
|
195
|
+ * `locale` is any valid locale name returned by
|
196
|
+ `#{inspect(__MODULE__)}.known_locale_names/0`
|
190
197
|
|
191
198
|
## Examples
|
192
199
|
|
193
|
- iex> #{inspect(__MODULE__)}.known_locale_name "en-AU"
|
194
|
- "en-AU"
|
200
|
+ iex> #{inspect(__MODULE__)}.known_locale_name :"en-AU"
|
201
|
+ :"en-AU"
|
195
202
|
|
196
|
- iex> #{inspect(__MODULE__)}.known_locale_name "en-SA"
|
203
|
+ iex> #{inspect(__MODULE__)}.known_locale_name :"en-SA"
|
197
204
|
false
|
198
205
|
|
199
206
|
"""
|
200
207
|
@spec known_locale_name(Locale.locale_name()) :: String.t() | false
|
201
|
- def known_locale_name(locale_name) when is_binary(locale_name) do
|
208
|
+ def known_locale_name(locale_name) when is_atom(locale_name) do
|
202
209
|
if known_locale_name?(locale_name) do
|
203
210
|
locale_name
|
204
211
|
else
|
|
@@ -213,19 +220,20 @@ defmodule Cldr.Backend do
|
213
220
|
|
214
221
|
## Arguments
|
215
222
|
|
216
|
- * `locale` is any valid locale name returned by `#{inspect(__MODULE__)}.known_locale_names/0`
|
223
|
+ * `locale` is any valid locale name returned by
|
224
|
+ `#{inspect(__MODULE__)}.known_locale_names/0`
|
217
225
|
|
218
226
|
## Examples
|
219
227
|
|
220
|
- iex> #{inspect(__MODULE__)}.known_rbnf_locale_name "en"
|
221
|
- "en"
|
228
|
+ iex> #{inspect(__MODULE__)}.known_rbnf_locale_name :en
|
229
|
+ :en
|
222
230
|
|
223
|
- iex> #{inspect(__MODULE__)}.known_rbnf_locale_name "en-SA"
|
231
|
+ iex> #{inspect(__MODULE__)}.known_rbnf_locale_name :"en-SA"
|
224
232
|
false
|
225
233
|
|
226
234
|
"""
|
227
235
|
@spec known_rbnf_locale_name(Locale.locale_name()) :: String.t() | false
|
228
|
- def known_rbnf_locale_name(locale_name) when is_binary(locale_name) do
|
236
|
+ def known_rbnf_locale_name(locale_name) when is_atom(locale_name) do
|
229
237
|
if known_rbnf_locale_name?(locale_name) do
|
230
238
|
locale_name
|
231
239
|
else
|
|
@@ -252,7 +260,7 @@ defmodule Cldr.Backend do
|
252
260
|
false
|
253
261
|
|
254
262
|
"""
|
255
|
- @spec known_gettext_locale_name(Locale.locale_name()) :: String.t() | false
|
263
|
+ @spec known_gettext_locale_name(String.t()) :: String.t() | false
|
256
264
|
def known_gettext_locale_name(locale_name) when is_binary(locale_name) do
|
257
265
|
if known_gettext_locale_name?(locale_name) do
|
258
266
|
locale_name
|
|
@@ -272,12 +280,12 @@ defmodule Cldr.Backend do
|
272
280
|
%Cldr.LanguageTag{
|
273
281
|
backend: #{__MODULE__},
|
274
282
|
canonical_locale_name: "pl",
|
275
|
- cldr_locale_name: "pl",
|
283
|
+ cldr_locale_name: :pl,
|
276
284
|
extensions: %{},
|
277
285
|
language: "pl",
|
278
286
|
locale: %{},
|
279
287
|
private_use: [],
|
280
|
- rbnf_locale_name: "pl",
|
288
|
+ rbnf_locale_name: :pl,
|
281
289
|
territory: :PL,
|
282
290
|
requested_locale_name: "pl",
|
283
291
|
script: :Latn,
|
|
@@ -310,14 +318,14 @@ defmodule Cldr.Backend do
|
310
318
|
%Cldr.LanguageTag{
|
311
319
|
backend: #{inspect(__MODULE__)},
|
312
320
|
canonical_locale_name: "en",
|
313
|
- cldr_locale_name: "en",
|
321
|
+ cldr_locale_name: :en,
|
314
322
|
language_subtags: [],
|
315
323
|
extensions: %{},
|
316
324
|
gettext_locale_name: "en",
|
317
325
|
language: "en",
|
318
326
|
locale: %{},
|
319
327
|
private_use: [],
|
320
|
- rbnf_locale_name: "en",
|
328
|
+ rbnf_locale_name: :en,
|
321
329
|
requested_locale_name: "en",
|
322
330
|
script: :Latn,
|
323
331
|
territory: :US,
|
|
@@ -358,7 +366,7 @@ defmodule Cldr.Backend do
|
358
366
|
iex> #{inspect(__MODULE__)}.quote "Quoted String"
|
359
367
|
"“Quoted String”"
|
360
368
|
|
361
|
- iex> #{inspect(__MODULE__)}.quote "Quoted String", locale: "ja"
|
369
|
+ iex> #{inspect(__MODULE__)}.quote "Quoted String", locale: :ja
|
362
370
|
"「Quoted String」"
|
363
371
|
|
364
372
|
"""
|
|
@@ -408,13 +416,13 @@ defmodule Cldr.Backend do
|
408
416
|
iex> #{inspect(__MODULE__)}.ellipsis "And furthermore"
|
409
417
|
"And furthermore…"
|
410
418
|
|
411
|
- iex> #{inspect(__MODULE__)}.ellipsis ["And furthermore", "there is much to be done"], locale: "ja"
|
419
|
+ iex> #{inspect(__MODULE__)}.ellipsis ["And furthermore", "there is much to be done"], locale: :ja
|
412
420
|
"And furthermore…there is much to be done"
|
413
421
|
|
414
422
|
iex> #{inspect(__MODULE__)}.ellipsis "And furthermore", format: :word
|
415
423
|
"And furthermore …"
|
416
424
|
|
417
|
- iex> #{inspect(__MODULE__)}.ellipsis ["And furthermore", "there is much to be done"], locale: "ja", format: :word
|
425
|
+ iex> #{inspect(__MODULE__)}.ellipsis ["And furthermore", "there is much to be done"], locale: :ja, format: :word
|
418
426
|
"And furthermore … there is much to be done"
|
419
427
|
|
420
428
|
"""
|
|
@@ -505,18 +513,18 @@ defmodule Cldr.Backend do
|
505
513
|
|
506
514
|
## Examples
|
507
515
|
|
508
|
- iex> #{inspect(__MODULE__)}.validate_locale("en")
|
516
|
+ iex> #{inspect(__MODULE__)}.validate_locale(:en)
|
509
517
|
{:ok,
|
510
518
|
%Cldr.LanguageTag{
|
511
519
|
backend: #{inspect(__MODULE__)},
|
512
520
|
canonical_locale_name: "en",
|
513
|
- cldr_locale_name: "en",
|
521
|
+ cldr_locale_name: :en,
|
514
522
|
extensions: %{},
|
515
523
|
gettext_locale_name: "en",
|
516
524
|
language: "en",
|
517
525
|
locale: %{},
|
518
526
|
private_use: [],
|
519
|
- rbnf_locale_name: "en",
|
527
|
+ rbnf_locale_name: :en,
|
520
528
|
requested_locale_name: "en",
|
521
529
|
script: :Latn,
|
522
530
|
territory: :US,
|
|
@@ -530,13 +538,13 @@ defmodule Cldr.Backend do
|
530
538
|
%Cldr.LanguageTag{
|
531
539
|
backend: #{inspect(__MODULE__)},
|
532
540
|
canonical_locale_name: "en-001",
|
533
|
- cldr_locale_name: "en-001",
|
541
|
+ cldr_locale_name: :"en-001",
|
534
542
|
extensions: %{},
|
535
543
|
gettext_locale_name: "en",
|
536
544
|
language: "en",
|
537
545
|
locale: %{},
|
538
546
|
private_use: [],
|
539
|
- rbnf_locale_name: "en",
|
547
|
+ rbnf_locale_name: :en,
|
540
548
|
requested_locale_name: "en-001",
|
541
549
|
script: :Latn,
|
542
550
|
territory: :"001",
|
|
@@ -548,7 +556,7 @@ defmodule Cldr.Backend do
|
548
556
|
{:error, {Cldr.InvalidLanguageError, "The language \\"zzz\\" is invalid"}}
|
549
557
|
|
550
558
|
"""
|
551
|
- @spec validate_locale(Locale.locale_name() | LanguageTag.t()) ::
|
559
|
+ @spec validate_locale(Locale.locale_name() | LanguageTag.t() | String.t()) ::
|
552
560
|
{:ok, LanguageTag.t()} | {:error, {module(), String.t()}}
|
553
561
|
|
554
562
|
def validate_locale(%LanguageTag{cldr_locale_name: nil} = locale) do
|
|
@@ -573,6 +581,19 @@ defmodule Cldr.Backend do
|
573
581
|
end
|
574
582
|
end
|
575
583
|
|
584
|
+ def validate_locale(locale_name) when is_atom(locale_name) do
|
585
|
+ locale =
|
586
|
+ locale_name
|
587
|
+ |> Atom.to_string()
|
588
|
+ |> validate_locale
|
589
|
+
|
590
|
+ case locale do
|
591
|
+ {:error, {Cldr.UnknownLocaleError, _}} -> {:error, Locale.locale_error(locale_name)}
|
592
|
+ {:error, reason} -> {:error, reason}
|
593
|
+ {:ok, locale} -> {:ok, locale}
|
594
|
+ end
|
595
|
+ end
|
596
|
+
|
576
597
|
def validate_locale(locale) do
|
577
598
|
{:error, Locale.locale_error(locale)}
|
578
599
|
end
|
|
@@ -602,6 +623,7 @@ defmodule Cldr.Backend do
|
602
623
|
# are not supported in Erlang's re
|
603
624
|
|
604
625
|
@remove_compounds Regex.compile!("{.*}", [:ungreedy])
|
626
|
+
|
605
627
|
for locale_name <- Cldr.Locale.Loader.known_locale_names(config) do
|
606
628
|
lenient_parse =
|
607
629
|
locale_name
|
|
@@ -632,6 +654,7 @@ defmodule Cldr.Backend do
|
632
654
|
# parsed language tag for performance reasons and only
|
633
655
|
# add the gettext locale name (if there is one) and the
|
634
656
|
# backend module.
|
657
|
+
|
635
658
|
for locale_name <- Cldr.Locale.Loader.known_locale_names(config),
|
636
659
|
not is_nil(Cldr.Config.language_tag(locale_name)) do
|
637
660
|
|
|
@@ -641,7 +664,10 @@ defmodule Cldr.Backend do
|
641
664
|
|> Cldr.Locale.put_gettext_locale_name(config)
|
642
665
|
|> Map.put(:backend, __MODULE__)
|
643
666
|
|
644
|
- locale_name = String.downcase(locale_name)
|
667
|
+ locale_name =
|
668
|
+ locale_name
|
669
|
+ |> Atom.to_string()
|
670
|
+ |> String.downcase()
|
645
671
|
|
646
672
|
defp do_validate_locale(unquote(locale_name)) do
|
647
673
|
{:ok, unquote(Macro.escape(language_tag))}
|
changed
lib/cldr/backend/compiler.ex
|
@@ -45,6 +45,7 @@ defmodule Cldr.Backend.Compiler do
|
45
45
|
|
46
46
|
unquote(Cldr.Backend.define_backend_functions(config))
|
47
47
|
unquote(Cldr.Locale.Backend.define_locale_backend(config))
|
48
|
+ unquote(Cldr.Trans.Backend.define_locale_backend(config))
|
48
49
|
unquote(Cldr.Number.PluralRule.define_ordinal_and_cardinal_modules(config))
|
49
50
|
unquote(Cldr.Number.PluralRule.define_plural_ranges(config))
|
50
51
|
unquote(Cldr.Config.define_provider_modules(config))
|
changed
lib/cldr/backend/locale.ex
|
@@ -14,8 +14,10 @@ defmodule Cldr.Locale.Backend do
|
14
14
|
"""
|
15
15
|
end
|
16
16
|
|
17
|
- def new(locale_name), do: Cldr.Locale.new(locale_name, unquote(config.backend))
|
18
|
- def new!(locale_name), do: Cldr.Locale.new!(locale_name, unquote(config.backend))
|
17
|
+ alias Cldr.{Locale, LanguageTag}
|
18
|
+
|
19
|
+ def new(locale_name), do: Locale.new(locale_name, unquote(config.backend))
|
20
|
+ def new!(locale_name), do: Locale.new!(locale_name, unquote(config.backend))
|
19
21
|
|
20
22
|
@doc """
|
21
23
|
Returns the territory from a language tag or
|
|
@@ -41,17 +43,17 @@ defmodule Cldr.Locale.Backend do
|
41
43
|
:GB
|
42
44
|
|
43
45
|
"""
|
44
|
- @spec territory_from_locale(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
|
45
|
- Cldr.Locale.territory()
|
46
|
+ @spec territory_from_locale(LanguageTag.t() | Locale.locale_name()) ::
|
47
|
+ Locale.territory_code()
|
46
48
|
|
47
49
|
@doc since: "2.18.2"
|
48
50
|
|
49
|
- def territory_from_locale(locale) when is_binary(locale) do
|
50
|
- Cldr.Locale.territory_from_locale(locale, unquote(config.backend))
|
51
|
+ def territory_from_locale(%LanguageTag{} = locale) do
|
52
|
+ Locale.territory_from_locale(locale)
|
51
53
|
end
|
52
54
|
|
53
|
- def territory_from_locale(%LanguageTag{} = locale) do
|
54
|
- Cldr.Locale.territory_from_locale(locale)
|
55
|
+ def territory_from_locale(locale) do
|
56
|
+ Locale.territory_from_locale(locale, unquote(config.backend))
|
55
57
|
end
|
56
58
|
|
57
59
|
@doc """
|
|
@@ -79,17 +81,332 @@ defmodule Cldr.Locale.Backend do
|
79
81
|
"""
|
80
82
|
@doc since: "2.19.0"
|
81
83
|
|
82
|
- @spec timezone_from_locale(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
|
84
|
+ @spec timezone_from_locale(LanguageTag.t() | Locale.locale_name()) ::
|
83
85
|
String.t() | {:error, {module(), String.t()}}
|
84
86
|
|
85
|
- def timezone_from_locale(locale) when is_binary(locale) do
|
86
|
- Cldr.Locale.timezone_from_locale(locale, unquote(config.backend))
|
87
|
- end
|
88
|
-
|
89
87
|
def timezone_from_locale(%LanguageTag{} = locale) do
|
90
|
- Cldr.Locale.timezone_from_locale(locale)
|
88
|
+ Locale.timezone_from_locale(locale)
|
91
89
|
end
|
92
90
|
|
91
|
+ def timezone_from_locale(locale) do
|
92
|
+ Locale.timezone_from_locale(locale, unquote(config.backend))
|
93
|
+ end
|
94
|
+
|
95
|
+ @doc """
|
96
|
+ Returns the "best fit" locale for a given territory.
|
97
|
+
|
98
|
+ Using the population percentage data from CLDR, the
|
99
|
+ language most commonly spoken in the given territory
|
100
|
+ is used to form a locale name which is then validated
|
101
|
+ against the given backend.
|
102
|
+
|
103
|
+ First a territory-specific locale is validated and if
|
104
|
+ that fails, the base language only is validate.
|
105
|
+
|
106
|
+ For example, if the territory is `AU` then then the
|
107
|
+ language most spoken is "en". First, the locale "en-AU"
|
108
|
+ is validated and if that fails, "en" is validated.
|
109
|
+
|
110
|
+ ## Arguments
|
111
|
+
|
112
|
+ * `territory` is any ISO 3166 Alpha-2 territory
|
113
|
+ code that can be validated by `Cldr.validate_territory/1`
|
114
|
+
|
115
|
+ ## Returns
|
116
|
+
|
117
|
+ * `{:ok, language_tag}` or
|
118
|
+
|
119
|
+ * `{:error, {exception, reason}}`
|
120
|
+
|
121
|
+ ## Examples
|
122
|
+
|
123
|
+ iex> #{inspect(__MODULE__)}.locale_for_territory(:AU)
|
124
|
+ #{config.backend}.validate_locale(:"en-AU")
|
125
|
+
|
126
|
+ iex> #{inspect(__MODULE__)}.locale_for_territory(:US)
|
127
|
+ #{config.backend}.validate_locale(:"en-US")
|
128
|
+
|
129
|
+ iex> #{inspect(__MODULE__)}.locale_for_territory(:ZZ)
|
130
|
+ {:error, {Cldr.UnknownTerritoryError, "The territory :ZZ is unknown"}}
|
131
|
+
|
132
|
+ """
|
133
|
+ @doc since: "2.26.0"
|
134
|
+ @spec locale_for_territory(Locale.territory_code()) ::
|
135
|
+ {:ok, LanguageTag.t()} | {:error, {module(), String.t()}}
|
136
|
+
|
137
|
+ def locale_for_territory(territory) do
|
138
|
+ Locale.locale_for_territory(territory)
|
139
|
+ end
|
140
|
+
|
141
|
+ @doc """
|
142
|
+ Returns a "best fit" locale for a host name.
|
143
|
+
|
144
|
+ ## Arguments
|
145
|
+
|
146
|
+ * `host` is any valid host name
|
147
|
+
|
148
|
+ * `options` is a keyword list of options. The default
|
149
|
+ is `[]`.
|
150
|
+
|
151
|
+ ## Options
|
152
|
+
|
153
|
+ * `:tlds` is a list of territory codes as upper-cased
|
154
|
+ atoms that are to be considered as top-level domains.
|
155
|
+ See `Cldr.Locale.locale_from_host/2` for the default
|
156
|
+ list.
|
157
|
+
|
158
|
+ ## Returns
|
159
|
+
|
160
|
+ * `{:ok, langauge_tag}` or
|
161
|
+
|
162
|
+ * `{:error, {exception, reason}}`
|
163
|
+
|
164
|
+ ## Notes
|
165
|
+
|
166
|
+ Certain top-level domains have become associated with content
|
167
|
+ underlated to the territory for who the domain is registered.
|
168
|
+ Therefore Google (and perhaps others) do not associate these
|
169
|
+ TLDs as belonging to the territory but rather are considered
|
170
|
+ generic top-level domain names.
|
171
|
+
|
172
|
+ ## Examples
|
173
|
+
|
174
|
+ iex> #{inspect(__MODULE__)}.locale_from_host "a.b.com.au"
|
175
|
+ #{config.backend}.validate_locale(:"en-AU")
|
176
|
+
|
177
|
+ iex> #{inspect(__MODULE__)}.locale_from_host("a.b.com.tv")
|
178
|
+ {:error,
|
179
|
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \\"tv\\""}}
|
180
|
+
|
181
|
+ iex> #{inspect(__MODULE__)}.locale_from_host("a.b.com")
|
182
|
+ {:error,
|
183
|
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \\"com\\""}}
|
184
|
+
|
185
|
+ """
|
186
|
+ @doc since: "2.26.0"
|
187
|
+ @spec locale_from_host(String.t(), Keyword.t()) ::
|
188
|
+ {:ok, LanguageTag.t()} | {:error, {module(), String.t()}}
|
189
|
+
|
190
|
+ def locale_from_host(host, options \\ []) do
|
191
|
+ Locale.locale_from_host(host, unquote(config.backend), options)
|
192
|
+ end
|
193
|
+
|
194
|
+ @doc """
|
195
|
+ Returns the last segment of a host that might
|
196
|
+ be a territory.
|
197
|
+
|
198
|
+ ## Arguments
|
199
|
+
|
200
|
+ * `host` is any valid host name
|
201
|
+
|
202
|
+ ## Returns
|
203
|
+
|
204
|
+ * `{:ok, territory}` or
|
205
|
+
|
206
|
+ * `{:error, {exception, reason}}`
|
207
|
+
|
208
|
+ ## Examples
|
209
|
+
|
210
|
+ iex> Cldr.Locale.territory_from_host("a.b.com.au")
|
211
|
+ {:ok, :AU}
|
212
|
+
|
213
|
+ iex> Cldr.Locale.territory_from_host("a.b.com")
|
214
|
+ {:error,
|
215
|
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \\"com\\""}}
|
216
|
+
|
217
|
+ """
|
218
|
+ @doc since: "2.26.0"
|
219
|
+ @spec territory_from_host(String.t()) ::
|
220
|
+ {:ok, Locale.territory_code()} | {:error, {module(), String.t()}}
|
221
|
+
|
222
|
+ def territory_from_host(host) do
|
223
|
+ Cldr.Locale.territory_from_host(host)
|
224
|
+ end
|
225
|
+
|
226
|
+ @doc """
|
227
|
+ Returns the list of fallback locales, starting
|
228
|
+ with the provided locale.
|
229
|
+
|
230
|
+ Fallbacks are a list of locate names which can
|
231
|
+ be used to resolve translation or other localization
|
232
|
+ data if such localised data does not exist for
|
233
|
+ this specific locale. After locale-specific fallbacks
|
234
|
+ are determined, the the default locale and its fallbacks
|
235
|
+ are added to the chain.
|
236
|
+
|
237
|
+ ## Arguments
|
238
|
+
|
239
|
+ * `locale` is any `LanguageTag.t`
|
240
|
+
|
241
|
+ ## Returns
|
242
|
+
|
243
|
+ * `{:ok, list_of_locales}` or
|
244
|
+
|
245
|
+ * `{:error, {exception, reason}}`
|
246
|
+
|
247
|
+ ## Examples
|
248
|
+
|
249
|
+ In these examples the default locale is `:"en-001"`.
|
250
|
+
|
251
|
+ #{inspect __MODULE__}.fallback_locales(#{inspect __MODULE__}.new!("fr-CA"))
|
252
|
+ => {:ok,
|
253
|
+ [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
|
254
|
+ #Cldr.LanguageTag<en [validated]>]}
|
255
|
+
|
256
|
+ # Fallbacks are typically formed by progressively
|
257
|
+ # stripping variant, territory and script from the
|
258
|
+ # given locale name. But not always - there are
|
259
|
+ # certain fallbacks that take a different path.
|
260
|
+
|
261
|
+ #{inspect __MODULE__}.fallback_locales(#{inspect __MODULE__}.new!("nb"))
|
262
|
+ => {:ok,
|
263
|
+ [#Cldr.LanguageTag<nb [validated]>, #Cldr.LanguageTag<no [validated]>,
|
264
|
+ #Cldr.LanguageTag<en [validated]>]}
|
265
|
+
|
266
|
+ """
|
267
|
+ @spec fallback_locales(LanguageTag.t() | Cldr.Locale.locale_reference) ::
|
268
|
+ {:ok, [LanguageTag.t(), ...]} | {:error, {module(), binary()}}
|
269
|
+
|
270
|
+ @doc since: "2.26.0"
|
271
|
+ def fallback_locales(%LanguageTag{} = locale) do
|
272
|
+ Cldr.Locale.fallback_locales(locale)
|
273
|
+ end
|
274
|
+
|
275
|
+ @doc """
|
276
|
+ Returns the list of fallback locales, starting
|
277
|
+ with the provided locale name.
|
278
|
+
|
279
|
+ Fallbacks are a list of locate names which can
|
280
|
+ be used to resolve translation or other localization
|
281
|
+ data if such localised data does not exist for
|
282
|
+ this specific locale. After locale-specific fallbacks
|
283
|
+ are determined, the the default locale and its fallbacks
|
284
|
+ are added to the chain.
|
285
|
+
|
286
|
+ ## Arguments
|
287
|
+
|
288
|
+ * `locale_name` is any locale name returned by
|
289
|
+ `#{inspect config.backend}.known_locale_names/0`
|
290
|
+
|
291
|
+ ## Returns
|
292
|
+
|
293
|
+ * `{:ok, list_of_locales}` or
|
294
|
+
|
295
|
+ * `{:error, {exception, reason}}`
|
296
|
+
|
297
|
+ ## Examples
|
298
|
+
|
299
|
+ In these examples the default locale is `:"en-001"`.
|
300
|
+
|
301
|
+ #{inspect __MODULE__}.fallback_locales(:"fr-CA")
|
302
|
+ => {:ok,
|
303
|
+ [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
|
304
|
+ #Cldr.LanguageTag<en [validated]>]}
|
305
|
+
|
306
|
+ # Fallbacks are typically formed by progressively
|
307
|
+ # stripping variant, territory and script from the
|
308
|
+ # given locale name. But not always - there are
|
309
|
+ # certain fallbacks that take a different path.
|
310
|
+
|
311
|
+ #{inspect __MODULE__}.fallback_locales(:nb))
|
312
|
+ => {:ok,
|
313
|
+ [#Cldr.LanguageTag<nb [validated]>, #Cldr.LanguageTag<no [validated]>,
|
314
|
+ #Cldr.LanguageTag<en [validated]>]}
|
315
|
+
|
316
|
+ """
|
317
|
+
|
318
|
+ @doc since: "2.26.0"
|
319
|
+ def fallback_locales(locale_name) do
|
320
|
+ Cldr.Locale.fallback_locales(locale_name, unquote(config.backend))
|
321
|
+ end
|
322
|
+
|
323
|
+ @doc """
|
324
|
+ Returns the list of fallback locale names, starting
|
325
|
+ with the provided locale.
|
326
|
+
|
327
|
+ Fallbacks are a list of locate names which can
|
328
|
+ be used to resolve translation or other localization
|
329
|
+ data if such localised data does not exist for
|
330
|
+ this specific locale. After locale-specific fallbacks
|
331
|
+ are determined, the the default locale and its fallbacks
|
332
|
+ are added to the chain.
|
333
|
+
|
334
|
+ ## Arguments
|
335
|
+
|
336
|
+ * `locale` is any `Cldr,LangaugeTag.t`
|
337
|
+
|
338
|
+ ## Returns
|
339
|
+
|
340
|
+ * `{:ok, list_of_locale_names}` or
|
341
|
+
|
342
|
+ * `{:error, {exception, reason}}`
|
343
|
+
|
344
|
+ ## Examples
|
345
|
+
|
346
|
+ In these examples the default locale is `:"en-001"`.
|
347
|
+
|
348
|
+ iex> #{inspect __MODULE__}.fallback_locale_names(#{inspect __MODULE__}.new!("fr-CA"))
|
349
|
+ {:ok, [:"fr-CA", :fr, :"en-001", :en]}
|
350
|
+
|
351
|
+ # Fallbacks are typically formed by progressively
|
352
|
+ # stripping variant, territory and script from the
|
353
|
+ # given locale name. But not always - there are
|
354
|
+ # certain fallbacks that take a different path.
|
355
|
+
|
356
|
+ iex> #{inspect __MODULE__}.fallback_locale_names(#{inspect __MODULE__}.new!("nb"))
|
357
|
+ {:ok, [:nb, :no, :"en-001", :en]}
|
358
|
+
|
359
|
+ """
|
360
|
+ @spec fallback_locale_names(LanguageTag.t() | Cldr.Locale.locale_reference) ::
|
361
|
+ {:ok, [Cldr.Locale.locale_name, ...]} | {:error, {module(), binary()}}
|
362
|
+
|
363
|
+ @doc since: "2.26.0"
|
364
|
+ def fallback_locale_names(%LanguageTag{} = locale) do
|
365
|
+ Cldr.Locale.fallback_locale_names(locale)
|
366
|
+ end
|
367
|
+
|
368
|
+ @doc """
|
369
|
+ Returns the list of fallback locale names, starting
|
370
|
+ with the provided locale name.
|
371
|
+
|
372
|
+ Fallbacks are a list of locate names which can
|
373
|
+ be used to resolve translation or other localization
|
374
|
+ data if such localised data does not exist for
|
375
|
+ this specific locale. After locale-specific fallbacks
|
376
|
+ are determined, the the default locale and its fallbacks
|
377
|
+ are added to the chain.
|
378
|
+
|
379
|
+ ## Arguments
|
380
|
+
|
381
|
+ * `locale_name` is any locale name returned by
|
382
|
+ `#{inspect config.backend}.known_locale_names/0`
|
383
|
+
|
384
|
+ ## Returns
|
385
|
+
|
386
|
+ * `{:ok, list_of_locale_names}` or
|
387
|
+
|
388
|
+ * `{:error, {exception, reason}}`
|
389
|
+
|
390
|
+ ## Examples
|
391
|
+
|
392
|
+ In these examples the default locale is `:"en-001"`.
|
393
|
+
|
394
|
+ iex> #{inspect __MODULE__}.fallback_locale_names(:"fr-CA")
|
395
|
+ {:ok, [:"fr-CA", :fr, :"en-001", :en]}
|
396
|
+
|
397
|
+ # Fallbacks are typically formed by progressively
|
398
|
+ # stripping variant, territory and script from the
|
399
|
+ # given locale name. But not always - there are
|
400
|
+ # certain fallbacks that take a different path.
|
401
|
+
|
402
|
+ iex> #{inspect __MODULE__}.fallback_locale_names(:nb)
|
403
|
+ {:ok, [:nb, :no, :"en-001", :en]}
|
404
|
+
|
405
|
+ """
|
406
|
+ @doc since: "2.26.0"
|
407
|
+ def fallback_locale_names(locale_name) do
|
408
|
+ Cldr.Locale.fallback_locale_names(locale_name, unquote(config.backend))
|
409
|
+ end
|
93
410
|
end
|
94
411
|
end
|
95
412
|
end
|
added
lib/cldr/backend/trans.ex
|
@@ -0,0 +1,81 @@
|
1
|
+ defmodule Cldr.Trans.Backend do
|
2
|
+ @moduledoc false
|
3
|
+
|
4
|
+ def define_locale_backend(config) do
|
5
|
+ quote location: :keep, bind_quoted: [config: Macro.escape(config), backend: config.backend] do
|
6
|
+ defmodule Trans do
|
7
|
+ @moduledoc false
|
8
|
+ if Cldr.Config.include_module_docs?(config.generate_docs) do
|
9
|
+ @moduledoc """
|
10
|
+ Backend module to generate translation schemas
|
11
|
+ for user of the [trans](https://hex.pm/packages/trans)
|
12
|
+ library.
|
13
|
+
|
14
|
+ WHen defining structured translations for Ecto schemas
|
15
|
+ the `Trans` documentation shows the following example
|
16
|
+
|
17
|
+ defmodule MyApp.Article do
|
18
|
+ use Ecto.Schema
|
19
|
+ use Trans, translates: [:title, :body]
|
20
|
+
|
21
|
+ schema "articles" do
|
22
|
+ field :title, :string
|
23
|
+ field :body, :string
|
24
|
+ embeds_one :translations, Translations, on_replace: :update, primary_key: false do
|
25
|
+ embeds_one :es, MyApp.Article.Translation, on_replace: :update
|
26
|
+ embeds_one :fr, MyApp.Article.Translation, on_replace: :update
|
27
|
+ end
|
28
|
+ end
|
29
|
+ end
|
30
|
+
|
31
|
+ Using the `translate/3` macro in this module, the following
|
32
|
+ will configure structued translations for all locales configured
|
33
|
+ in this backend. An example is:
|
34
|
+
|
35
|
+ defmodule MyApp.Article do
|
36
|
+ use Ecto.Schema
|
37
|
+ use Trans, translates: [:title, :body]
|
38
|
+ use MyApp.Cldr.Trans
|
39
|
+
|
40
|
+ schema "articles" do
|
41
|
+ field :title, :string
|
42
|
+ field :body, :string
|
43
|
+
|
44
|
+ # The translation module name and the options
|
45
|
+ # may be ommitted - the defaults are those shown
|
46
|
+ translations :translations, Translations, on_replace: :update, primary_key: false
|
47
|
+ end
|
48
|
+ end
|
49
|
+
|
50
|
+ """
|
51
|
+ end
|
52
|
+
|
53
|
+ defmacro __using__(_opts) do
|
54
|
+ backend = unquote(backend)
|
55
|
+
|
56
|
+ quote do
|
57
|
+ import unquote(backend).Trans
|
58
|
+ end
|
59
|
+ end
|
60
|
+
|
61
|
+ @doc false
|
62
|
+ def default_trans_options do
|
63
|
+ [on_replace: :update, primary_key: false]
|
64
|
+ end
|
65
|
+
|
66
|
+ defmacro translations(field_name, translation_module, options \\ []) do
|
67
|
+ options = Keyword.merge(unquote(backend).Trans.default_trans_options(), options)
|
68
|
+ backend = unquote(backend)
|
69
|
+
|
70
|
+ quote do
|
71
|
+ embeds_one unquote(field_name), Translations, unquote(options) do
|
72
|
+ for locale_name <- unquote(backend).known_locale_names() do
|
73
|
+ embeds_one locale_name, unquote(translation_module), on_replace: :update
|
74
|
+ end
|
75
|
+ end
|
76
|
+ end
|
77
|
+ end
|
78
|
+ end
|
79
|
+ end
|
80
|
+ end
|
81
|
+ end
|
changed
lib/cldr/config/config.ex
|
@@ -26,7 +26,7 @@ defmodule Cldr.Config do
|
26
26
|
otp_app: nil,
|
27
27
|
generate_docs: true,
|
28
28
|
supress_warnings: false,
|
29
|
- message_formats: [],
|
29
|
+ message_formats: %{},
|
30
30
|
force_locale_download: false
|
31
31
|
|
32
32
|
@type t :: %__MODULE__{
|
|
@@ -50,7 +50,7 @@ defmodule Cldr.Config do
|
50
50
|
|
51
51
|
@type number_system :: atom() | String.t()
|
52
52
|
|
53
|
- @default_locale_name "en-001"
|
53
|
+ @default_locale_name :"en-001"
|
54
54
|
|
55
55
|
@cldr_modules [
|
56
56
|
"number_formats",
|
|
@@ -72,7 +72,7 @@ defmodule Cldr.Config do
|
72
72
|
"subdivisions"
|
73
73
|
]
|
74
74
|
|
75
|
- @root_locale_name "und"
|
75
|
+ @root_locale_name :und
|
76
76
|
|
77
77
|
@doc false
|
78
78
|
# Integer keys cater for 60 year cycles and 239 japanese eras
|
|
@@ -345,6 +345,7 @@ defmodule Cldr.Config do
|
345
345
|
@default_locale_name
|
346
346
|
|
347
347
|
locale_name_from_posix(default)
|
348
|
+ |> String.to_atom
|
348
349
|
end
|
349
350
|
|
350
351
|
@doc """
|
|
@@ -432,6 +433,7 @@ defmodule Cldr.Config do
|
432
433
|
Path.join(cldr_data_dir(), @available_locales_file)
|
433
434
|
|> File.read!()
|
434
435
|
|> json_library().decode!
|
436
|
+ |> Enum.map(&String.to_atom/1)
|
435
437
|
|> Enum.sort()
|
436
438
|
end
|
437
439
|
|
|
@@ -541,7 +543,7 @@ defmodule Cldr.Config do
|
541
543
|
if inherited = Map.get(parent_locales(), locale_name) do
|
542
544
|
inherited
|
543
545
|
else
|
544
|
- {:ok, locale} = Cldr.LanguageTag.Parser.parse(locale_name)
|
546
|
+ {:ok, locale} = Cldr.LanguageTag.Parser.parse(to_string(locale_name))
|
545
547
|
first_match(locale.language, locale.script, locale.territory, fun)
|
546
548
|
end
|
547
549
|
end
|
|
@@ -967,7 +969,7 @@ defmodule Cldr.Config do
|
967
969
|
@spec known_number_systems_like(Locale.locale_name(), number_system(), t()) ::
|
968
970
|
{:ok, list()} | {:error, {module(), String.t()}}
|
969
971
|
|
970
|
- def known_number_systems_like(locale_name, number_system, config) do
|
972
|
+ def known_number_systems_like(locale_name, number_system, config) when is_atom(locale_name) do
|
971
973
|
with {:ok, %{digits: digits}} <- number_system_for(locale_name, number_system, config),
|
972
974
|
{:ok, symbols} <- number_symbols_for(locale_name, number_system, config),
|
973
975
|
{:ok, names} <- number_system_names_for(locale_name, config) do
|
|
@@ -1015,13 +1017,14 @@ defmodule Cldr.Config do
|
1015
1017
|
|
1016
1018
|
## Example
|
1017
1019
|
|
1018
|
- iex> Cldr.Config.number_systems_for("en", %Cldr.Config{locales: ["en", "de"]})
|
1020
|
+ iex> Cldr.Config.number_systems_for(:en, %Cldr.Config{locales: ["en", "de"]})
|
1019
1021
|
{:ok, %{default: :latn, native: :latn}}
|
1022
|
+
|
1020
1023
|
"""
|
1021
1024
|
@spec number_systems_for(Locale.locale_name(), t()) ::
|
1022
1025
|
{:ok, map()} | {:error, {module(), String.t()}}
|
1023
1026
|
|
1024
|
- def number_systems_for(locale_name, %__MODULE__{} = config) do
|
1027
|
+ def number_systems_for(locale_name, %__MODULE__{} = config) when is_atom(locale_name) do
|
1025
1028
|
if known_locale_name(locale_name, config) do
|
1026
1029
|
number_systems =
|
1027
1030
|
locale_name
|
|
@@ -1040,7 +1043,7 @@ defmodule Cldr.Config do
|
1040
1043
|
|
1041
1044
|
## Example
|
1042
1045
|
|
1043
|
- iex> Cldr.Config.number_systems_for!("de", %Cldr.Config{locales: ["en", "de"]})
|
1046
|
+ iex> Cldr.Config.number_systems_for!(:de, %Cldr.Config{locales: ["en", "de"]})
|
1044
1047
|
%{default: :latn, native: :latn}
|
1045
1048
|
|
1046
1049
|
"""
|
|
@@ -1058,7 +1061,7 @@ defmodule Cldr.Config do
|
1058
1061
|
|
1059
1062
|
## Example
|
1060
1063
|
|
1061
|
- iex> Cldr.Config.number_system_for("th", :thai, %Cldr.Config{locales: ["th", "de"]})
|
1064
|
+ iex> Cldr.Config.number_system_for(:th, :thai, %Cldr.Config{locales: ["th", "de"]})
|
1062
1065
|
{:ok, %{digits: "๐๑๒๓๔๕๖๗๘๙", type: :numeric}}
|
1063
1066
|
|
1064
1067
|
"""
|
|
@@ -1076,7 +1079,7 @@ defmodule Cldr.Config do
|
1076
1079
|
|
1077
1080
|
## Example
|
1078
1081
|
|
1079
|
- iex> Cldr.Config.number_system_names_for("th", %Cldr.Config{locales: ["en", "th"]})
|
1082
|
+ iex> Cldr.Config.number_system_names_for(:th, %Cldr.Config{locales: ["en", "th"]})
|
1080
1083
|
{:ok, [:latn, :thai]}
|
1081
1084
|
|
1082
1085
|
"""
|
|
@@ -1136,16 +1139,16 @@ defmodule Cldr.Config do
|
1136
1139
|
|
1137
1140
|
## Examples
|
1138
1141
|
|
1139
|
- iex> Cldr.Config.system_name_from(:default, "en", TestBackend.Cldr)
|
1142
|
+ iex> Cldr.Config.system_name_from(:default, :en, TestBackend.Cldr)
|
1140
1143
|
{:ok, :latn}
|
1141
1144
|
|
1142
|
- iex> Cldr.Config.system_name_from("latn", "en", TestBackend.Cldr)
|
1145
|
+ iex> Cldr.Config.system_name_from("latn", :en, TestBackend.Cldr)
|
1143
1146
|
{:ok, :latn}
|
1144
1147
|
|
1145
|
- iex> Cldr.Config.system_name_from(:native, "en", TestBackend.Cldr)
|
1148
|
+ iex> Cldr.Config.system_name_from(:native, :en, TestBackend.Cldr)
|
1146
1149
|
{:ok, :latn}
|
1147
1150
|
|
1148
|
- iex> Cldr.Config.system_name_from(:nope, "en", TestBackend.Cldr)
|
1151
|
+ iex> Cldr.Config.system_name_from(:nope, :en, TestBackend.Cldr)
|
1149
1152
|
{
|
1150
1153
|
:error,
|
1151
1154
|
{Cldr.UnknownNumberSystemError, "The number system :nope is unknown"}
|
|
@@ -1442,24 +1445,30 @@ defmodule Cldr.Config do
|
1442
1445
|
## Examples
|
1443
1446
|
|
1444
1447
|
iex> Cldr.Config.expand_locale_names(["en-A+"])
|
1445
|
- ["en", "en-AE", "en-AG", "en-AI", "en-AS", "en-AT", "en-AU"]
|
1448
|
+ [:en, :"en-AE", :"en-AG", :"en-AI", :"en-AS", :"en-AT", :"en-AU"]
|
1446
1449
|
|
1447
1450
|
iex> Cldr.Config.expand_locale_names(["fr-*"])
|
1448
|
- ["fr", "fr-BE", "fr-BF", "fr-BI", "fr-BJ", "fr-BL", "fr-CA", "fr-CD", "fr-CF",
|
1449
|
- "fr-CG", "fr-CH", "fr-CI", "fr-CM", "fr-DJ", "fr-DZ", "fr-GA", "fr-GF",
|
1450
|
- "fr-GN", "fr-GP", "fr-GQ", "fr-HT", "fr-KM", "fr-LU", "fr-MA", "fr-MC",
|
1451
|
- "fr-MF", "fr-MG", "fr-ML", "fr-MQ", "fr-MR", "fr-MU", "fr-NC", "fr-NE",
|
1452
|
- "fr-PF", "fr-PM", "fr-RE", "fr-RW", "fr-SC", "fr-SN", "fr-SY", "fr-TD",
|
1453
|
- "fr-TG", "fr-TN", "fr-VU", "fr-WF", "fr-YT"]
|
1451
|
+ [
|
1452
|
+ :fr, :"fr-BE", :"fr-BF", :"fr-BI", :"fr-BJ", :"fr-BL", :"fr-CA",
|
1453
|
+ :"fr-CD", :"fr-CF", :"fr-CG", :"fr-CH", :"fr-CI", :"fr-CM", :"fr-DJ",
|
1454
|
+ :"fr-DZ", :"fr-GA", :"fr-GF", :"fr-GN", :"fr-GP", :"fr-GQ", :"fr-HT",
|
1455
|
+ :"fr-KM", :"fr-LU", :"fr-MA", :"fr-MC", :"fr-MF", :"fr-MG", :"fr-ML",
|
1456
|
+ :"fr-MQ", :"fr-MR", :"fr-MU", :"fr-NC", :"fr-NE", :"fr-PF", :"fr-PM",
|
1457
|
+ :"fr-RE", :"fr-RW", :"fr-SC", :"fr-SN", :"fr-SY", :"fr-TD", :"fr-TG",
|
1458
|
+ :"fr-TN", :"fr-VU", :"fr-WF", :"fr-YT"
|
1459
|
+ ]
|
1460
|
+
|
1454
1461
|
"""
|
1455
1462
|
@wildcard_matchers ["*", "+", ".", "["]
|
1456
|
- @spec expand_locale_names([Locale.locale_name(), ...]) :: [Locale.locale_name(), ...]
|
1463
|
+ @spec expand_locale_names([Locale.locale_name() | String.t(), ...]) :: [Locale.locale_name(), ...]
|
1457
1464
|
def expand_locale_names(locale_names) do
|
1458
1465
|
Enum.map(locale_names, fn locale_name ->
|
1466
|
+ locale_name = to_string(locale_name)
|
1467
|
+
|
1459
1468
|
if String.contains?(locale_name, @wildcard_matchers) do
|
1460
1469
|
case Regex.compile(locale_name) do
|
1461
1470
|
{:ok, regex} ->
|
1462
|
- Enum.filter(all_locale_names(), &Regex.match?(regex, &1))
|
1471
|
+ Enum.filter(all_locale_names(), &match_name?(regex, &1))
|
1463
1472
|
|
1464
1473
|
{:error, reason} ->
|
1465
1474
|
raise ArgumentError,
|
|
@@ -1471,15 +1480,19 @@ defmodule Cldr.Config do
|
1471
1480
|
end)
|
1472
1481
|
|> List.flatten()
|
1473
1482
|
|> Enum.map(fn locale_name ->
|
1474
|
- case String.split(locale_name, "-") do
|
1475
|
- [language] -> language
|
1476
|
- [language | _rest] -> [language, locale_name]
|
1483
|
+ case String.split(to_string(locale_name), "-") do
|
1484
|
+ [language] -> String.to_atom(language)
|
1485
|
+ [language | _rest] -> [String.to_atom(language), locale_name]
|
1477
1486
|
end
|
1478
1487
|
end)
|
1479
1488
|
|> List.flatten()
|
1480
1489
|
|> Enum.uniq()
|
1481
1490
|
end
|
1482
1491
|
|
1492
|
+ defp match_name?(regex, locale_name) do
|
1493
|
+ Regex.match?(regex, Atom.to_string(locale_name))
|
1494
|
+ end
|
1495
|
+
|
1483
1496
|
def canonical_name(locale_name) do
|
1484
1497
|
name =
|
1485
1498
|
locale_name
|
|
@@ -1491,7 +1504,7 @@ defmodule Cldr.Config do
|
1491
1504
|
|
1492
1505
|
defp known_locales_map do
|
1493
1506
|
all_locale_names()
|
1494
|
- |> Enum.map(fn x -> {String.downcase(x), x} end)
|
1507
|
+ |> Enum.map(fn x -> {Atom.to_string(x) |> String.downcase(), x} end)
|
1495
1508
|
|> Map.new()
|
1496
1509
|
end
|
1497
1510
|
|
|
@@ -1511,7 +1524,7 @@ defmodule Cldr.Config do
|
1511
1524
|
* `{:error, :not_found}`
|
1512
1525
|
|
1513
1526
|
"""
|
1514
|
- @spec locale_path(String.t(), Cldr.backend() | t()) ::
|
1527
|
+ @spec locale_path(Cldr.Locale.locale_name() | String.t(), Cldr.backend() | t()) ::
|
1515
1528
|
{:ok, String.t()} | {:error, :not_found}
|
1516
1529
|
|
1517
1530
|
def locale_path(locale, %{data_dir: _} = config) do
|
|
@@ -1745,7 +1758,9 @@ defmodule Cldr.Config do
|
1745
1758
|
{:error, {Cldr.UnknownTerritoryError, "The territory \\"abc\\" is unknown"}}
|
1746
1759
|
|
1747
1760
|
"""
|
1748
|
- @spec territory(Cldr.Locale.territory() | String.t()) :: %{} | {:error, {module(), String.t()}}
|
1761
|
+ @spec territory(Locale.territory_reference() | String.t()) ::
|
1762
|
+ %{} | {:error, {module(), String.t()}}
|
1763
|
+
|
1749
1764
|
def territory(territory) do
|
1750
1765
|
with {:ok, territory_code} <- Cldr.validate_territory(territory) do
|
1751
1766
|
territories()
|
|
@@ -1756,6 +1771,37 @@ defmodule Cldr.Config do
|
1756
1771
|
@deprecated "Use Cldr.Config.territories/1"
|
1757
1772
|
defdelegate territory_info(territory), to: __MODULE__, as: :territory
|
1758
1773
|
|
1774
|
+ @doc """
|
1775
|
+ Return the mapping from a territory to a language tag.
|
1776
|
+
|
1777
|
+ This is used to derive a locale from a territory.
|
1778
|
+
|
1779
|
+ """
|
1780
|
+ def language_tag_for_territory do
|
1781
|
+ territories()
|
1782
|
+ |> Enum.map(fn {territory, data} ->
|
1783
|
+ {territory, Map.get(data, :language_population, %{})}
|
1784
|
+ end)
|
1785
|
+ |> Enum.map(fn {territory, data} ->
|
1786
|
+ {territory, extract_population(data) |> Enum.sort(&population_sorter/2) |> get_head}
|
1787
|
+ end)
|
1788
|
+ |> Map.new()
|
1789
|
+ end
|
1790
|
+
|
1791
|
+ defp extract_population(data) do
|
1792
|
+ Enum.map(data, fn
|
1793
|
+ {language, population} -> {language, population.population_percent}
|
1794
|
+ end)
|
1795
|
+ |> Enum.reject(&is_nil/1)
|
1796
|
+ end
|
1797
|
+
|
1798
|
+ defp population_sorter(a, b) do
|
1799
|
+ elem(a, 1) >= elem(b, 1)
|
1800
|
+ end
|
1801
|
+
|
1802
|
+ defp get_head([]), do: nil
|
1803
|
+ defp get_head([{language, _percent} | _rest]), do: language
|
1804
|
+
|
1759
1805
|
@doc """
|
1760
1806
|
Returns a map of locale names to
|
1761
1807
|
its parent locale name.
|
|
@@ -1770,6 +1816,8 @@ defmodule Cldr.Config do
|
1770
1816
|
|> Path.join("parent_locales.json")
|
1771
1817
|
|> File.read!()
|
1772
1818
|
|> json_library().decode!
|
1819
|
+ |> Cldr.Map.atomize_keys()
|
1820
|
+ |> Cldr.Map.atomize_values()
|
1773
1821
|
end
|
1774
1822
|
|
1775
1823
|
@doc """
|
|
@@ -1808,7 +1856,7 @@ defmodule Cldr.Config do
|
1808
1856
|
|> File.read!()
|
1809
1857
|
|> json_library().decode!
|
1810
1858
|
|> Enum.map(fn {k, v} ->
|
1811
|
- {k, struct(Cldr.LanguageTag, normalize_territory_and_region(v))}
|
1859
|
+ {String.to_atom(k), struct(Cldr.LanguageTag, normalize_territory_and_region(v))}
|
1812
1860
|
end)
|
1813
1861
|
|> Map.new()
|
1814
1862
|
end
|
|
@@ -2071,7 +2119,7 @@ defmodule Cldr.Config do
|
2071
2119
|
:islamic_rgsa, :islamic_tbla, :islamic_umalqura, :japanese, :persian, :roc]
|
2072
2120
|
|
2073
2121
|
"""
|
2074
|
- def calendars_for_locale(locale_name, %{} = config) when is_binary(locale_name) do
|
2122
|
+ def calendars_for_locale(locale_name, %{} = config) when is_atom(locale_name) do
|
2075
2123
|
Cldr.maybe_log("Cldr.Config getting calendar data for locale #{inspect(locale_name)}")
|
2076
2124
|
|
2077
2125
|
locale_name
|
|
@@ -2081,6 +2129,12 @@ defmodule Cldr.Config do
|
2081
2129
|
|> Map.keys()
|
2082
2130
|
end
|
2083
2131
|
|
2132
|
+ def calendars_for_locale(locale_name, %{} = config) when is_binary(locale_name) do
|
2133
|
+ locale_name
|
2134
|
+ |> String.to_existing_atom()
|
2135
|
+ |> calendars_for_locale(config)
|
2136
|
+ end
|
2137
|
+
|
2084
2138
|
def calendars_for_locale(locale_name, backend) when is_atom(backend) do
|
2085
2139
|
calendars_for_locale(locale_name, backend.__cldr__(:config))
|
2086
2140
|
end
|
|
@@ -2191,6 +2245,7 @@ defmodule Cldr.Config do
|
2191
2245
|
locale_name =
|
2192
2246
|
locale_name
|
2193
2247
|
|> locale_name_from_posix
|
2248
|
+ |> String.to_atom
|
2194
2249
|
|
2195
2250
|
module = Module.concat(backend, Rbnf) |> Module.concat(ruleset_module)
|
2196
2251
|
{module, function, locale_name}
|
|
@@ -2211,7 +2266,11 @@ defmodule Cldr.Config do
|
2211
2266
|
"""
|
2212
2267
|
def locale_name_from_posix(nil), do: nil
|
2213
2268
|
def locale_name_from_posix(name) when is_binary(name), do: String.replace(name, "_", "-")
|
2214
|
- def locale_name_from_posix(other), do: other
|
2269
|
+ def locale_name_from_posix(name) when is_atom(name) do
|
2270
|
+ name
|
2271
|
+ |> Atom.to_string()
|
2272
|
+ |> locale_name_from_posix()
|
2273
|
+ end
|
2215
2274
|
|
2216
2275
|
@doc """
|
2217
2276
|
Transforms a locale name from the CLDR format to the Posix format
|
|
@@ -2308,8 +2367,9 @@ defmodule Cldr.Config do
|
2308
2367
|
end
|
2309
2368
|
|
2310
2369
|
defp remove_gettext_only_locales(%{locales: locales, gettext: gettext} = config) do
|
2370
|
+ locales = if locales == :all, do: all_locale_names(), else: locales
|
2311
2371
|
gettext_locales = known_gettext_locale_names(config)
|
2312
|
- unknown_locales = Enum.filter(gettext_locales, &(&1 not in all_locale_names()))
|
2372
|
+ unknown_locales = Enum.filter(gettext_locales, &(String.to_atom(&1) not in all_locale_names()))
|
2313
2373
|
|
2314
2374
|
case unknown_locales do
|
2315
2375
|
[] ->
|
|
@@ -2477,9 +2537,6 @@ defmodule Cldr.Config do
|
2477
2537
|
locales = configured_locale_names(config)
|
2478
2538
|
default = default_locale_name(config)
|
2479
2539
|
|
2480
|
- # locales = config[:locales] || [config[:default_locale] || @default_locale_name]
|
2481
|
- # default = config[:default_locale] || hd(locales)
|
2482
|
-
|
2483
2540
|
locales =
|
2484
2541
|
(locales ++ gettext ++ [default, @root_locale_name])
|
2485
2542
|
|> Enum.reject(&is_nil/1)
|
|
@@ -2502,7 +2559,7 @@ defmodule Cldr.Config do
|
2502
2559
|
end)
|
2503
2560
|
|> Enum.sort(&plural_sorter/2)
|
2504
2561
|
|
2505
|
- {locale, sorted_rules}
|
2562
|
+ {String.to_atom(locale), sorted_rules}
|
2506
2563
|
end
|
2507
2564
|
|
2508
2565
|
defp plural_sorter({:zero, _}, _), do: true
|
changed
lib/cldr/config/rbnf_config.ex
|
@@ -88,7 +88,7 @@ defmodule Cldr.Rbnf.Config do
|
88
88
|
[:OrdinalRules, :SpelloutRules]
|
89
89
|
|
90
90
|
"""
|
91
|
- @spec for_locale(Locale.locale_name()) ::
|
91
|
+ @spec for_locale(Locale.locale_name() | String.t()) ::
|
92
92
|
{:ok, map()} | {:error, {Cldr.Rbnf.NotAvailable, String.t()}}
|
93
93
|
|
94
94
|
# TODO Use fallback paths to find RBNF data
|
changed
lib/cldr/gettext/plural.ex
|
@@ -75,7 +75,8 @@ defmodule Cldr.Gettext.Plural do
|
75
75
|
@doc """
|
76
76
|
Returns the number of plural forms for a given locale.
|
77
77
|
|
78
|
- * `locale` is either a locale name in the list `#{unquote(inspect(backend))}.known_locale_names/0` or
|
78
|
+ * `locale` is either a locale name in the list
|
79
|
+ `#{unquote(inspect(backend))}.known_locale_names/0` or
|
79
80
|
a `%LanguageTag{}` as returned by `Cldr.Locale.new/2`
|
80
81
|
|
81
82
|
## Examples
|
|
@@ -87,18 +88,25 @@ defmodule Cldr.Gettext.Plural do
|
87
88
|
2
|
88
89
|
|
89
90
|
"""
|
90
|
- @spec nplurals(Locale.locale_name()) :: pos_integer() | no_return()
|
91
|
+ @spec nplurals(Locale.locale_name() | String.t()) :: pos_integer() | no_return()
|
91
92
|
|
92
93
|
def nplurals(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
|
93
94
|
nplurals(cldr_locale_name)
|
94
95
|
end
|
95
96
|
|
96
|
- def nplurals(locale_name) when is_binary(locale_name) do
|
97
|
+ def nplurals(locale_name) when is_atom(locale_name) do
|
97
98
|
gettext_nplurals()
|
98
99
|
|> Map.fetch!(locale_name)
|
99
100
|
|> Enum.count()
|
100
101
|
end
|
101
102
|
|
103
|
+ def nplurals(locale_name) when is_binary(locale_name) do
|
104
|
+ locale_name = String.to_existing_atom(locale_name)
|
105
|
+ nplurals(locale_name)
|
106
|
+ rescue ArgumentError ->
|
107
|
+ raise KeyError, "Key #{inspect locale_name} not found"
|
108
|
+ end
|
109
|
+
|
102
110
|
@doc """
|
103
111
|
Returns the plural form of a number for a given
|
104
112
|
locale.
|
|
@@ -130,7 +138,7 @@ defmodule Cldr.Gettext.Plural do
|
130
138
|
1
|
131
139
|
|
132
140
|
"""
|
133
|
- @spec plural(Locale.locale_name() | LanguageTag.t(), number()) ::
|
141
|
+ @spec plural(String.t() | LanguageTag.t(), number()) ::
|
134
142
|
0 | pos_integer() | no_return()
|
135
143
|
|
136
144
|
def plural(%LanguageTag{cldr_locale_name: cldr_locale_name} = locale, n) do
|
|
@@ -141,7 +149,7 @@ defmodule Cldr.Gettext.Plural do
|
141
149
|
|> Keyword.get(rule)
|
142
150
|
end
|
143
151
|
|
144
|
- def plural(locale_name, n) when is_binary(locale_name) do
|
152
|
+ def plural(locale_name, n) do
|
145
153
|
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
|
146
154
|
plural(locale, n)
|
147
155
|
else
|
changed
lib/cldr/language_tag.ex
|
@@ -152,7 +152,8 @@ defmodule Cldr.LanguageTag do
|
152
152
|
"""
|
153
153
|
import Kernel, except: [to_string: 1]
|
154
154
|
|
155
|
- alias Cldr.LanguageTag.Parser
|
155
|
+ alias Cldr.Locale
|
156
|
+ alias Cldr.LanguageTag.{Parser, U, T}
|
156
157
|
|
157
158
|
if Code.ensure_loaded?(Jason) do
|
158
159
|
@derive Jason.Encoder
|
|
@@ -175,19 +176,19 @@ defmodule Cldr.LanguageTag do
|
175
176
|
backend: nil
|
176
177
|
|
177
178
|
@type t :: %__MODULE__{
|
178
|
- language: String.t(),
|
179
|
+ language: Locale.language(),
|
179
180
|
language_subtags: [String.t()],
|
180
|
- script: Cldr.Locale.script(),
|
181
|
- territory: Cldr.Locale.territory(),
|
182
|
- language_variants: [String.t()] | [],
|
183
|
- locale: Cldr.LanguageTag.U.t() | %{},
|
184
|
- transform: map(),
|
181
|
+ script: Locale.script(),
|
182
|
+ territory: Locale.territory_code(),
|
183
|
+ language_variants: [String.t()],
|
184
|
+ locale: U.t() | %{},
|
185
|
+ transform: T.t() | %{},
|
185
186
|
extensions: map(),
|
186
187
|
private_use: [String.t()],
|
187
188
|
requested_locale_name: String.t(),
|
188
189
|
canonical_locale_name: String.t(),
|
189
|
- cldr_locale_name: String.t() | nil,
|
190
|
- rbnf_locale_name: String.t() | nil,
|
190
|
+ cldr_locale_name: Locale.locale_name(),
|
191
|
+ rbnf_locale_name: Locale.locale_name(),
|
191
192
|
gettext_locale_name: String.t() | nil,
|
192
193
|
backend: Cldr.backend()
|
193
194
|
}
|
|
@@ -206,6 +207,7 @@ defmodule Cldr.LanguageTag do
|
206
207
|
* `{:error, reason}`
|
207
208
|
|
208
209
|
"""
|
210
|
+ @spec parse(String.t()) :: {:ok, t()} | {:error, {module(), String.t()}}
|
209
211
|
def parse(locale_name) when is_binary(locale_name) do
|
210
212
|
Parser.parse(locale_name)
|
211
213
|
end
|
|
@@ -224,7 +226,7 @@ defmodule Cldr.LanguageTag do
|
224
226
|
* raises an exception
|
225
227
|
|
226
228
|
"""
|
227
|
- @spec parse!(Cldr.Locale.locale_name()) :: t() | none()
|
229
|
+ @spec parse!(String.t()) :: t() | none()
|
228
230
|
def parse!(locale_string) when is_binary(locale_string) do
|
229
231
|
Parser.parse!(locale_string)
|
230
232
|
end
|
added
lib/cldr/language_tag/sigil.ex
|
@@ -0,0 +1,87 @@
|
1
|
+ defmodule Cldr.LanguageTag.Sigil do
|
2
|
+ @moduledoc """
|
3
|
+ Implements a `sigil_l/2` macro to
|
4
|
+ constructing `t:Cldr.LanguageTag` structs.
|
5
|
+
|
6
|
+ """
|
7
|
+
|
8
|
+ @doc """
|
9
|
+ Handles sigil `~l` for language tags.
|
10
|
+
|
11
|
+ ## Arguments
|
12
|
+
|
13
|
+ * `locale_name` is either a [BCP 47](https://unicode-org.github.io/cldr/ldml/tr35.html#Identifiers)
|
14
|
+ locale name as a string or
|
15
|
+
|
16
|
+ * `locale_name` | `backend` where backend is a backend module name
|
17
|
+
|
18
|
+ ## Options
|
19
|
+
|
20
|
+ * `u` Will parse the locale but will not add
|
21
|
+ likely subtags and its not guaranteed that this
|
22
|
+ language tag is known to the backend module.
|
23
|
+
|
24
|
+ ## Returns
|
25
|
+
|
26
|
+ * a `t:Cldr.LanguageTag` struct or
|
27
|
+
|
28
|
+ * raises an exception
|
29
|
+
|
30
|
+ ## Examples
|
31
|
+
|
32
|
+ iex> import Cldr.LanguageTag.Sigil
|
33
|
+ iex> ~l(en-US-u-ca-gregory)
|
34
|
+ #Cldr.LanguageTag<en-US-u-ca-gregory [validated]>
|
35
|
+
|
36
|
+ iex> import Cldr.LanguageTag.Sigil
|
37
|
+ iex> ~l(en-US-u-ca-gregory|MyApp.Cldr)
|
38
|
+ #Cldr.LanguageTag<en-US-u-ca-gregory [validated]>
|
39
|
+
|
40
|
+ """
|
41
|
+ defmacro sigil_l(locale_name, 'u') do
|
42
|
+ {:<<>>, [_], [locale_name]} = locale_name
|
43
|
+
|
44
|
+ case parse_locale(String.split(locale_name, "|")) do
|
45
|
+ {:ok, locale_name} ->
|
46
|
+ quote do
|
47
|
+ unquote(Macro.escape(locale_name))
|
48
|
+ end
|
49
|
+
|
50
|
+ {:error, {exception, reason}} ->
|
51
|
+ raise exception, reason
|
52
|
+ end
|
53
|
+ end
|
54
|
+
|
55
|
+ defmacro sigil_l(locale_name, _opts) do
|
56
|
+ {:<<>>, [_], [locale_name]} = locale_name
|
57
|
+
|
58
|
+ case validate_locale(String.split(locale_name, "|")) do
|
59
|
+ {:ok, locale_name} ->
|
60
|
+ quote do
|
61
|
+ unquote(Macro.escape(locale_name))
|
62
|
+ end
|
63
|
+
|
64
|
+ {:error, {exception, reason}} ->
|
65
|
+ raise exception, reason
|
66
|
+ end
|
67
|
+ end
|
68
|
+
|
69
|
+ defp validate_locale([locale_name, backend]) do
|
70
|
+ backend = Module.concat([backend])
|
71
|
+ Cldr.validate_locale(locale_name, backend)
|
72
|
+ end
|
73
|
+
|
74
|
+ defp validate_locale([locale_name]) do
|
75
|
+ Cldr.validate_locale(locale_name)
|
76
|
+ end
|
77
|
+
|
78
|
+ @opts [add_likely_subtags: false]
|
79
|
+ defp parse_locale([locale_name, backend]) do
|
80
|
+ backend = Module.concat([backend])
|
81
|
+ Cldr.Locale.canonical_language_tag(locale_name, backend, @opts)
|
82
|
+ end
|
83
|
+
|
84
|
+ defp parse_locale([locale_name]) do
|
85
|
+ Cldr.Locale.canonical_language_tag(locale_name, Cldr.default_backend!(), @opts)
|
86
|
+ end
|
87
|
+ end
|
changed
lib/cldr/locale.ex
|
@@ -47,13 +47,13 @@ defmodule Cldr.Locale do
|
47
47
|
{:ok, %Cldr.LanguageTag{
|
48
48
|
backend: TestBackend.Cldr,
|
49
49
|
canonical_locale_name: "en-ES",
|
50
|
- cldr_locale_name: "en",
|
50
|
+ cldr_locale_name: :en,
|
51
51
|
extensions: %{},
|
52
52
|
gettext_locale_name: "en",
|
53
53
|
language: "en",
|
54
54
|
locale: %{},
|
55
55
|
private_use: [],
|
56
|
- rbnf_locale_name: "en",
|
56
|
+ rbnf_locale_name: :en,
|
57
57
|
requested_locale_name: "en-ES",
|
58
58
|
script: :Latn,
|
59
59
|
territory: :ES,
|
|
@@ -98,12 +98,12 @@ defmodule Cldr.Locale do
|
98
98
|
language_subtags: [],
|
99
99
|
language_variants: [],
|
100
100
|
locale: %{}, private_use: [],
|
101
|
- rbnf_locale_name: "ro",
|
101
|
+ rbnf_locale_name: :ro,
|
102
102
|
requested_locale_name: "mo",
|
103
103
|
script: :Latn,
|
104
104
|
transform: %{},
|
105
105
|
canonical_locale_name: "ro",
|
106
|
- cldr_locale_name: "ro",
|
106
|
+ cldr_locale_name: :ro,
|
107
107
|
territory: :RO
|
108
108
|
}}
|
109
109
|
|
|
@@ -119,13 +119,13 @@ defmodule Cldr.Locale do
|
119
119
|
{:ok, %Cldr.LanguageTag{
|
120
120
|
backend: TestBackend.Cldr,
|
121
121
|
canonical_locale_name: "en",
|
122
|
- cldr_locale_name: "en",
|
122
|
+ cldr_locale_name: :en,
|
123
123
|
extensions: %{},
|
124
124
|
gettext_locale_name: "en",
|
125
125
|
language: "en",
|
126
126
|
locale: %{},
|
127
127
|
private_use: [],
|
128
|
- rbnf_locale_name: "en",
|
128
|
+ rbnf_locale_name: :en,
|
129
129
|
requested_locale_name: "en",
|
130
130
|
script: :Latn,
|
131
131
|
territory: :US,
|
|
@@ -151,13 +151,13 @@ defmodule Cldr.Locale do
|
151
151
|
{:ok, %Cldr.LanguageTag{
|
152
152
|
backend: TestBackend.Cldr,
|
153
153
|
canonical_locale_name: "en-XX",
|
154
|
- cldr_locale_name: "en",
|
154
|
+ cldr_locale_name: :en,
|
155
155
|
extensions: %{},
|
156
156
|
gettext_locale_name: "en",
|
157
157
|
language: "en",
|
158
158
|
locale: %{},
|
159
159
|
private_use: [],
|
160
|
- rbnf_locale_name: "en",
|
160
|
+ rbnf_locale_name: :en,
|
161
161
|
requested_locale_name: "en-XX",
|
162
162
|
script: :Latn,
|
163
163
|
territory: :XX,
|
|
@@ -190,7 +190,7 @@ defmodule Cldr.Locale do
|
190
190
|
%Cldr.LanguageTag{
|
191
191
|
backend: MyApp.Cldr,
|
192
192
|
canonical_locale_name: "en-AU-u-cf-account-tz-ausyd",
|
193
|
- cldr_locale_name: "en-AU",
|
193
|
+ cldr_locale_name: :"en-AU",
|
194
194
|
extensions: %{},
|
195
195
|
gettext_locale_name: "en",
|
196
196
|
language: "en",
|
|
@@ -225,7 +225,7 @@ defmodule Cldr.Locale do
|
225
225
|
vt: nil
|
226
226
|
},
|
227
227
|
private_use: '',
|
228
|
- rbnf_locale_name: "en",
|
228
|
+ rbnf_locale_name: :en,
|
229
229
|
requested_locale_name: "en-AU",
|
230
230
|
script: :Latn,
|
231
231
|
territory: :AU,
|
|
@@ -239,17 +239,23 @@ defmodule Cldr.Locale do
|
239
239
|
|
240
240
|
import Cldr.Helpers, only: [empty?: 1]
|
241
241
|
|
242
|
- @typedoc "The name of a locale in a string format"
|
243
|
- @type locale_name() :: String.t()
|
242
|
+ @typedoc "The name of a locale"
|
243
|
+ @type locale_name() :: atom()
|
244
244
|
|
245
|
- @typedoc "The name of a language a string format"
|
245
|
+ @typedoc "A reference to a locale"
|
246
|
+ @type locale_reference :: LanguageTag.t() | locale_name() | String.t()
|
247
|
+
|
248
|
+ @typedoc "The name of a language"
|
246
249
|
@type language :: String.t() | nil
|
247
250
|
|
248
|
- @typedoc "The name of a script in an atom format"
|
251
|
+ @typedoc "The name of a script"
|
249
252
|
@type script :: atom() | String.t() | nil
|
250
253
|
|
251
|
- @typedoc "The name of a territory in an atom format"
|
252
|
- @type territory :: atom() | String.t() | nil
|
254
|
+ @typedoc "The name of a territory"
|
255
|
+ @type territory_reference :: atom() | String.t() | nil
|
256
|
+
|
257
|
+ @typedoc "A territory code as an ISO3166 Alpha-2 in atom form"
|
258
|
+ @type territory_code :: atom()
|
253
259
|
|
254
260
|
@typedoc "The list of language variants as strings"
|
255
261
|
@type variants :: [String.t()] | []
|
|
@@ -257,8 +263,9 @@ defmodule Cldr.Locale do
|
257
263
|
@typedoc "The list of language subtags as strings"
|
258
264
|
@type subtags :: [String.t(), ...] | []
|
259
265
|
|
260
|
- @root_locale "und"
|
261
|
- @root_rbnf_locale_name "und"
|
266
|
+ @root_locale Cldr.Config.root_locale_name()
|
267
|
+ @root_language Atom.to_string(@root_locale)
|
268
|
+ @root_rbnf_locale_name Cldr.Config.root_locale_name()
|
262
269
|
|
263
270
|
defdelegate new(locale_name, backend), to: __MODULE__, as: :canonical_language_tag
|
264
271
|
defdelegate new!(locale_name, backend), to: __MODULE__, as: :canonical_language_tag!
|
|
@@ -295,15 +302,36 @@ defmodule Cldr.Locale do
|
295
302
|
Returns a list of all the parent locales
|
296
303
|
for a given locale.
|
297
304
|
|
305
|
+ ## Examples
|
306
|
+
|
307
|
+ Cldr.Locale.parents "fr-ca"
|
308
|
+ => {:ok, [#Cldr.LanguageTag<fr [validated]>, #Cldr.LanguageTag<en [validated]>]}
|
309
|
+
|
298
310
|
"""
|
299
|
- @spec parents(LanguageTag.t()) :: list(LanguageTag.t())
|
300
|
- def parents(%LanguageTag{} = locale, acc \\ []) do
|
311
|
+ @spec parents(LanguageTag.t()) ::
|
312
|
+ {:ok, list(LanguageTag.t())} | {:error, {module(), String.t()}}
|
313
|
+
|
314
|
+ def parents(locale, acc \\ [])
|
315
|
+
|
316
|
+ def parents(%LanguageTag{} = locale, acc) do
|
301
317
|
case parent(locale) do
|
302
|
- {:error, _} -> Enum.reverse(acc)
|
318
|
+ {:error, _} -> {:ok, Enum.reverse(acc)}
|
303
319
|
{:ok, locale} -> parents(locale, [locale | acc])
|
304
320
|
end
|
305
321
|
end
|
306
322
|
|
323
|
+ def parents(locale, []) do
|
324
|
+ with {:ok, locale} <- Cldr.validate_locale(locale, Cldr.default_backend!()) do
|
325
|
+ parents(locale)
|
326
|
+ end
|
327
|
+ end
|
328
|
+
|
329
|
+ def parents(locale, backend) when is_atom(backend) do
|
330
|
+ with {:ok, locale} <- Cldr.validate_locale(locale, backend) do
|
331
|
+ parents(locale)
|
332
|
+ end
|
333
|
+ end
|
334
|
+
|
307
335
|
@doc """
|
308
336
|
Returns the parent for a given locale.
|
309
337
|
|
|
@@ -340,9 +368,7 @@ defmodule Cldr.Locale do
|
340
368
|
if parent = Map.get(parent_locale_map(), child.cldr_locale_name) do
|
341
369
|
Cldr.validate_locale(parent, backend)
|
342
370
|
else
|
343
|
- {:ok, locale} = Cldr.LanguageTag.parse(child.cldr_locale_name)
|
344
|
-
|
345
|
- locale
|
371
|
+ child
|
346
372
|
|> find_parent(backend)
|
347
373
|
|> return_parent_or_default(child, backend)
|
348
374
|
|> transfer_extensions(child)
|
|
@@ -352,7 +378,7 @@ defmodule Cldr.Locale do
|
352
378
|
@spec parent(locale_name(), Cldr.backend()) ::
|
353
379
|
{:ok, LanguageTag.t()} | {:error, {module(), binary()}}
|
354
380
|
|
355
|
- def parent(locale_name, backend \\ Cldr.default_backend!()) when is_binary(locale_name) do
|
381
|
+ def parent(locale_name, backend \\ Cldr.default_backend!()) do
|
356
382
|
with {:ok, locale} <- Cldr.validate_locale(locale_name, backend) do
|
357
383
|
parent(locale)
|
358
384
|
end
|
|
@@ -375,16 +401,31 @@ defmodule Cldr.Locale do
|
375
401
|
|> known_locale(backend)
|
376
402
|
end
|
377
403
|
|
378
|
- defp known_locale(locale_name, _tags \\ [], backend) do
|
404
|
+ defp known_locale(locale_name, tags \\ [], backend)
|
405
|
+
|
406
|
+ defp known_locale(nil, _tags, _backend) do
|
407
|
+ nil
|
408
|
+ end
|
409
|
+
|
410
|
+ defp known_locale(locale_name, tags, backend) when is_binary(locale_name) do
|
411
|
+ locale_name = String.to_existing_atom(locale_name)
|
412
|
+ known_locale(locale_name, tags, backend)
|
413
|
+ rescue ArgumentError ->
|
414
|
+ nil
|
415
|
+ end
|
416
|
+
|
417
|
+ defp known_locale(locale_name, _tags, backend) when is_atom(locale_name) do
|
379
418
|
Enum.find(backend.known_locale_names(), &(locale_name == &1))
|
380
419
|
end
|
381
420
|
|
382
421
|
def known_rbnf_locale_name(locale_name, _tags \\ [], backend) do
|
422
|
+ locale_name = String.to_existing_atom(locale_name)
|
383
423
|
Cldr.known_rbnf_locale_name(locale_name, backend)
|
424
|
+ rescue ArgumentError ->
|
425
|
+ nil
|
384
426
|
end
|
385
427
|
|
386
|
- # If the language of the parent then return an error
|
387
|
- defp return_parent_or_default(parent, child, backend) when is_nil(parent) do
|
428
|
+ defp return_parent_or_default(parent, %LanguageTag{cldr_locale_name: parent} = child, backend) do
|
388
429
|
default_locale = Cldr.default_locale(backend)
|
389
430
|
|
390
431
|
if child.language == default_locale.language do
|
|
@@ -410,6 +451,433 @@ defmodule Cldr.Locale do
|
410
451
|
{Cldr.NoParentError, "The locale #{inspect(locale_name)} has no parent locale"}
|
411
452
|
end
|
412
453
|
|
454
|
+ @doc """
|
455
|
+ Returns the list of fallback locales, starting the
|
456
|
+ the provided locale.
|
457
|
+
|
458
|
+ Fallbacks are a list of locate names which can
|
459
|
+ be used to resolve translation or other localization
|
460
|
+ data if such localised data does not exist for
|
461
|
+ this specific locale. After locale-specific fallbacks
|
462
|
+ are determined, the the default locale and its fallbacks
|
463
|
+ are added to the chain.
|
464
|
+
|
465
|
+ ## Arguments
|
466
|
+
|
467
|
+ * `locale` is any `LanguageTag.t`
|
468
|
+
|
469
|
+ ## Returns
|
470
|
+
|
471
|
+ * `{:ok, list_of_locales}` or
|
472
|
+
|
473
|
+ * `{:error, {exception, reason}}`
|
474
|
+
|
475
|
+ ## Examples
|
476
|
+
|
477
|
+ In these examples the default locale is `:"en-001"`.
|
478
|
+
|
479
|
+ Cldr.Locale.fallback_locales(Cldr.Locale.new!("fr-CA", MyApp.Cldr))
|
480
|
+ => {:ok,
|
481
|
+ [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
|
482
|
+ #Cldr.LanguageTag<en [validated]>]}
|
483
|
+
|
484
|
+ # Fallbacks are typically formed by progressively
|
485
|
+ # stripping variant, territory and script from the
|
486
|
+ # given locale name. But not always - there are
|
487
|
+ # certain fallbacks that take a different path.
|
488
|
+
|
489
|
+ Cldr.Locale.fallback_locales(Cldr.Locale.new!("nb", MyApp.Cldr))
|
490
|
+ => {:ok,
|
491
|
+ [#Cldr.LanguageTag<nb [validated]>, #Cldr.LanguageTag<no [validated]>,
|
492
|
+ #Cldr.LanguageTag<en [validated]>]}
|
493
|
+
|
494
|
+ """
|
495
|
+ @spec fallback_locales(LanguageTag.t()) ::
|
496
|
+ {:ok, [LanguageTag.t(), ...]} | {:error, {module(), binary()}}
|
497
|
+
|
498
|
+ @doc since: "2.26.0"
|
499
|
+ def fallback_locales(%LanguageTag{} = locale) do
|
500
|
+ with {:ok, parents} <- parents(locale) do
|
501
|
+ {:ok, [locale | parents]}
|
502
|
+ end
|
503
|
+ end
|
504
|
+
|
505
|
+ @doc """
|
506
|
+ Returns the list of fallback locales, starting the
|
507
|
+ the provided locale.
|
508
|
+
|
509
|
+ Fallbacks are a list of locate names which can
|
510
|
+ be used to resolve translation or other localization
|
511
|
+ data if such localised data does not exist for
|
512
|
+ this specific locale. After locale-specific fallbacks
|
513
|
+ are determined, the the default locale and its fallbacks
|
514
|
+ are added to the chain.
|
515
|
+
|
516
|
+ ## Arguments
|
517
|
+
|
518
|
+ * `locale_name` is any locale name returned by
|
519
|
+ `Cldr.known_locale_names/1`
|
520
|
+
|
521
|
+ * `backend` is any module that includes `use Cldr` and therefore
|
522
|
+ is a `Cldr` backend module. The default is
|
523
|
+ `Cldr.default_locale/0`.
|
524
|
+
|
525
|
+ ## Returns
|
526
|
+
|
527
|
+ * `{:ok, list_of_locales}` or
|
528
|
+
|
529
|
+ * `{:error, {exception, reason}}`
|
530
|
+
|
531
|
+ ## Examples
|
532
|
+
|
533
|
+ In these examples the default locale is `:"en-001"`.
|
534
|
+
|
535
|
+ Cldr.Locale.fallback_locales(:"fr-CA")
|
536
|
+ => {:ok,
|
537
|
+ [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
|
538
|
+ #Cldr.LanguageTag<en [validated]>]}
|
539
|
+
|
540
|
+ # Fallbacks are typically formed by progressively
|
541
|
+ # stripping variant, territory and script from the
|
542
|
+ # given locale name. But not always - there are
|
543
|
+ # certain fallbacks that take a different path.
|
544
|
+
|
545
|
+ Cldr.Locale.fallback_locales(:nb)
|
546
|
+ => {:ok,
|
547
|
+ [#Cldr.LanguageTag<nb [validated]>, #Cldr.LanguageTag<no [validated]>,
|
548
|
+ #Cldr.LanguageTag<en [validated]>]}
|
549
|
+
|
550
|
+ """
|
551
|
+ @spec fallback_locales(locale_reference, Cldr.backend) ::
|
552
|
+ {:ok, [LanguageTag.t(), ...]} | {:error, {module(), binary()}}
|
553
|
+
|
554
|
+ @doc since: "2.26.0"
|
555
|
+ def fallback_locales(locale_name, backend \\ Cldr.default_backend!()) do
|
556
|
+ with {:ok, locale} <- Cldr.validate_locale(locale_name, backend) do
|
557
|
+ fallback_locales(locale)
|
558
|
+ end
|
559
|
+ end
|
560
|
+
|
561
|
+ @doc """
|
562
|
+ Returns the list of fallback locale names, starting the
|
563
|
+ the provided locale.
|
564
|
+
|
565
|
+ Fallbacks are a list of locate names which can
|
566
|
+ be used to resolve translation or other localization
|
567
|
+ data if such localised data does not exist for
|
568
|
+ this specific locale. After locale-specific fallbacks
|
569
|
+ are determined, the the default locale and its fallbacks
|
570
|
+ are added to the chain.
|
571
|
+
|
572
|
+ ## Arguments
|
573
|
+
|
574
|
+ * `locale` is any `LanguageTag.t`
|
575
|
+
|
576
|
+ ## Returns
|
577
|
+
|
578
|
+ * `{:ok, list_of_locale_names}` or
|
579
|
+
|
580
|
+ * `{:error, {exception, reason}}`
|
581
|
+
|
582
|
+ ## Examples
|
583
|
+
|
584
|
+ In these examples the default locale is `:"en-001"`.
|
585
|
+
|
586
|
+ iex> Cldr.Locale.fallback_locale_names(Cldr.Locale.new!("fr-CA", MyApp.Cldr))
|
587
|
+ {:ok, [:"fr-CA", :fr, :"en-001", :en]}
|
588
|
+
|
589
|
+ # Fallbacks are typically formed by progressively
|
590
|
+ # stripping variant, territory and script from the
|
591
|
+ # given locale name. But not always - there are
|
592
|
+ # certain fallbacks that take a different path.
|
593
|
+
|
594
|
+ iex> Cldr.Locale.fallback_locale_names(Cldr.Locale.new!("nb", MyApp.Cldr))
|
595
|
+ {:ok, [:nb, :no, :"en-001", :en]}
|
596
|
+
|
597
|
+ """
|
598
|
+ @spec fallback_locale_names(LanguageTag.t()) ::
|
599
|
+ {:ok, [locale_name, ...]} | {:error, {module(), binary()}}
|
600
|
+
|
601
|
+ @doc since: "2.26.0"
|
602
|
+ def fallback_locale_names(%LanguageTag{} = locale) do
|
603
|
+ with {:ok, fallbacks} <- fallback_locales(locale) do
|
604
|
+ locale_names = Enum.map(fallbacks, &Map.get(&1, :cldr_locale_name))
|
605
|
+ {:ok, locale_names}
|
606
|
+ end
|
607
|
+ end
|
608
|
+
|
609
|
+ @doc """
|
610
|
+ Returns the list of fallback locale names, starting the
|
611
|
+ the provided locale name.
|
612
|
+
|
613
|
+ Fallbacks are a list of locate names which can
|
614
|
+ be used to resolve translation or other localization
|
615
|
+ data if such localised data does not exist for
|
616
|
+ this specific locale. After locale-specific fallbacks
|
617
|
+ are determined, the the default locale and its fallbacks
|
618
|
+ are added to the chain.
|
619
|
+
|
620
|
+ ## Arguments
|
621
|
+
|
622
|
+ * `locale_name` is any locale name returned by
|
623
|
+ `Cldr.known_locale_names/1`
|
624
|
+
|
625
|
+ * `backend` is any module that includes `use Cldr` and therefore
|
626
|
+ is a `Cldr` backend module. The default is
|
627
|
+ `Cldr.default_locale/0`.
|
628
|
+
|
629
|
+ ## Returns
|
630
|
+
|
631
|
+ * `{:ok, list_of_locale_names}` or
|
632
|
+
|
633
|
+ * `{:error, {exception, reason}}`
|
634
|
+
|
635
|
+ ## Examples
|
636
|
+
|
637
|
+ In these examples the default locale is `:"en-001"`.
|
638
|
+
|
639
|
+ iex> Cldr.Locale.fallback_locale_names(:"fr-CA")
|
640
|
+ {:ok, [:"fr-CA", :fr, :"en-001", :en]}
|
641
|
+
|
642
|
+ # Fallbacks are typically formed by progressively
|
643
|
+ # stripping variant, territory and script from the
|
644
|
+ # given locale name. But not always - there are
|
645
|
+ # certain fallbacks that take a different path.
|
646
|
+
|
647
|
+ iex> Cldr.Locale.fallback_locale_names(:nb)
|
648
|
+ {:ok, [:nb, :no, :"en-001", :en]}
|
649
|
+
|
650
|
+ """
|
651
|
+ @spec fallback_locale_names(locale_reference, Cldr.backend()) ::
|
652
|
+ {:ok, [locale_name, ...]} | {:error, {module(), binary()}}
|
653
|
+
|
654
|
+ @doc since: "2.26.0"
|
655
|
+ def fallback_locale_names(locale_name, backend \\ Cldr.default_backend!()) do
|
656
|
+ with {:ok, locale} <- Cldr.validate_locale(locale_name, backend) do
|
657
|
+ fallback_locale_names(locale)
|
658
|
+ end
|
659
|
+ end
|
660
|
+
|
661
|
+ @doc """
|
662
|
+ Returns a map of a territory code to its
|
663
|
+ most-spoken language.
|
664
|
+
|
665
|
+ ## Example
|
666
|
+
|
667
|
+ Cldr.Locale.languages_for_territories()
|
668
|
+ => %{
|
669
|
+ AQ: "und",
|
670
|
+ PE: "es",
|
671
|
+ SR: "nl",
|
672
|
+ NU: "en",
|
673
|
+ ...
|
674
|
+ }
|
675
|
+
|
676
|
+ """
|
677
|
+ @language_for_territory Cldr.Config.language_tag_for_territory()
|
678
|
+ @doc since: "2.26.0"
|
679
|
+ def languages_for_territories do
|
680
|
+ @language_for_territory
|
681
|
+ end
|
682
|
+
|
683
|
+ @doc """
|
684
|
+ Returns the "best fit" locale for a given territory.
|
685
|
+
|
686
|
+ Using the population percentage data from CLDR, the
|
687
|
+ language most commonly spoken in the given territory
|
688
|
+ is used to form a locale name which is then validated
|
689
|
+ against the given backend.
|
690
|
+
|
691
|
+ First a territory-specific locale is validated and if
|
692
|
+ that fails, the base language only is validate.
|
693
|
+
|
694
|
+ For example, if the territory is `AU` then then the
|
695
|
+ language most spoken is "en". First, the locale "en-AU"
|
696
|
+ is validated and if that fails, "en" is validated.
|
697
|
+
|
698
|
+ ## Arguments
|
699
|
+
|
700
|
+ * `territory` is any ISO 3166 Alpha-2 territory
|
701
|
+ code that can be validated by `Cldr.validate_territory/1`
|
702
|
+
|
703
|
+ * `backend` is any module that includes `use Cldr` and therefore
|
704
|
+ is a `Cldr` backend module.
|
705
|
+
|
706
|
+ ## Returns
|
707
|
+
|
708
|
+ * `{:ok, language_tag}` or
|
709
|
+
|
710
|
+ * `{:error, {exception, reason}}`
|
711
|
+
|
712
|
+ ## Examples
|
713
|
+
|
714
|
+ iex> Cldr.Locale.locale_for_territory(:AU, TestBackend.Cldr)
|
715
|
+ Cldr.validate_locale(:"en-AU", TestBackend.Cldr)
|
716
|
+
|
717
|
+ iex> Cldr.Locale.locale_for_territory(:US, TestBackend.Cldr)
|
718
|
+ Cldr.validate_locale(:"en-US", TestBackend.Cldr)
|
719
|
+
|
720
|
+ iex> Cldr.Locale.locale_for_territory(:ZZ)
|
721
|
+ {:error, {Cldr.UnknownTerritoryError, "The territory :ZZ is unknown"}}
|
722
|
+
|
723
|
+ """
|
724
|
+ @doc since: "2.26.0"
|
725
|
+ @spec locale_for_territory(territory_code(), Cldr.backend()) ::
|
726
|
+ {:ok, LanguageTag.t()} | {:error, {module(), String.t()}}
|
727
|
+
|
728
|
+ def locale_for_territory(territory, backend \\ Cldr.default_backend!()) do
|
729
|
+ with {:ok, territory} <- Cldr.validate_territory(territory) do
|
730
|
+ case Map.get(languages_for_territories(), territory) do
|
731
|
+ nil ->
|
732
|
+ {:error, no_locale_for_territory_error(territory)}
|
733
|
+ language ->
|
734
|
+ validate_locale(language, territory, backend)
|
735
|
+ end
|
736
|
+ end
|
737
|
+ end
|
738
|
+
|
739
|
+ # See first if there is a territory specific version of this
|
740
|
+ # language, otherwise the base language itself
|
741
|
+
|
742
|
+ defp validate_locale(language, nil, backend) do
|
743
|
+ Cldr.validate_locale(language, backend)
|
744
|
+ end
|
745
|
+
|
746
|
+ defp validate_locale(language, territory, backend) do
|
747
|
+ case Cldr.validate_locale("#{language}-#{to_string(territory)}", backend) do
|
748
|
+ {:ok, locale} -> {:ok, locale}
|
749
|
+ {:error, _} -> validate_locale(language, nil, backend)
|
750
|
+ end
|
751
|
+ end
|
752
|
+
|
753
|
+ @consider_as_tld [
|
754
|
+ :AD, :AS, :BZ, :CC, :CD, :CO, :DJ, :FM, :IO, :LA, :ME, :MS, :NU, :SC, :SR, :SU, :TV, :TK, :WS
|
755
|
+ ]
|
756
|
+
|
757
|
+ @doc """
|
758
|
+ Returns a list of territory top-level domains that are
|
759
|
+ considered to be generic top level domains.
|
760
|
+
|
761
|
+ See https://developers.google.com/search/docs/advanced/crawling/managing-multi-regional-sites
|
762
|
+ for an explanation of why some valid territory suffixxes
|
763
|
+ are considered as TLDs.
|
764
|
+
|
765
|
+ ## Example
|
766
|
+
|
767
|
+ iex> Cldr.Locale.consider_as_tlds
|
768
|
+ [:AD, :AS, :BZ, :CC, :CD, :CO, :DJ, :FM, :IO, :LA, :ME, :MS, :NU, :SC, :SR, :SU, :TV, :TK, :WS]
|
769
|
+
|
770
|
+ """
|
771
|
+ def consider_as_tlds do
|
772
|
+ @consider_as_tld
|
773
|
+ end
|
774
|
+
|
775
|
+ @doc """
|
776
|
+ Returns a "best fit" locale for a host name.
|
777
|
+
|
778
|
+ ## Arguments
|
779
|
+
|
780
|
+ * `host` is any valid host name
|
781
|
+
|
782
|
+ * `backend` is any module that includes `use Cldr` and therefore
|
783
|
+ is a `Cldr` backend module.
|
784
|
+
|
785
|
+ * `options` is a keyword list of options. The default
|
786
|
+ is `[]`.
|
787
|
+
|
788
|
+ ## Options
|
789
|
+
|
790
|
+ * `:tlds` is a list of territory codes as upper-cased
|
791
|
+ atoms that are to be considered as top-level domains.
|
792
|
+ The default list is `consider_as_tlds/0`.
|
793
|
+
|
794
|
+ ## Returns
|
795
|
+
|
796
|
+ * `{:ok, langauge_tag}` or
|
797
|
+
|
798
|
+ * `{:error, {exception, reason}}`
|
799
|
+
|
800
|
+ ## Notes
|
801
|
+
|
802
|
+ Certain top-level domains have become associated with content
|
803
|
+ underlated to the territory for who the domain is registered.
|
804
|
+ Therefore Google (and perhaps others) do not associate these
|
805
|
+ TLDs as belonging to the territory but rather are considered
|
806
|
+ generic top-level domain names.
|
807
|
+
|
808
|
+ ## Examples
|
809
|
+
|
810
|
+ iex> Cldr.Locale.locale_from_host "a.b.com.au", TestBackend.Cldr
|
811
|
+ Cldr.validate_locale(:"en-AU", TestBackend.Cldr)
|
812
|
+
|
813
|
+ iex> Cldr.Locale.locale_from_host "a.b.com.tv", TestBackend.Cldr
|
814
|
+ {:error,
|
815
|
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \\"tv\\""}}
|
816
|
+
|
817
|
+ iex> Cldr.Locale.locale_from_host "a.b.com", TestBackend.Cldr
|
818
|
+ {:error,
|
819
|
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \\"com\\""}}
|
820
|
+
|
821
|
+ """
|
822
|
+ @doc since: "2.26.0"
|
823
|
+ @spec locale_from_host(String.t(), Cldr.backend(), Keyword.t()) ::
|
824
|
+ {:ok, LanguageTag.t()} | {:error, {module(), String.t()}}
|
825
|
+
|
826
|
+ def locale_from_host(host, backend, options \\ []) do
|
827
|
+ tld_list = Keyword.get(options, :tlds, consider_as_tlds())
|
828
|
+
|
829
|
+ with {:ok, territory} <- territory_from_host(host) do
|
830
|
+ if territory in tld_list do
|
831
|
+ {:error, no_locale_for_territory_error(territory)}
|
832
|
+ else
|
833
|
+ locale_for_territory(territory, backend)
|
834
|
+ end
|
835
|
+ end
|
836
|
+ end
|
837
|
+
|
838
|
+ @doc """
|
839
|
+ Returns the last segment of a host that might
|
840
|
+ be a territory.
|
841
|
+
|
842
|
+ ## Arguments
|
843
|
+
|
844
|
+ * `host` is any valid host name
|
845
|
+
|
846
|
+ ## Returns
|
847
|
+
|
848
|
+ * `{:ok, territory}` or
|
849
|
+
|
850
|
+ * `{:error, {exception, reason}}`
|
851
|
+
|
852
|
+ ## Examples
|
853
|
+
|
854
|
+ iex> Cldr.Locale.territory_from_host("a.b.com.au")
|
855
|
+ {:ok, :AU}
|
856
|
+
|
857
|
+ iex> Cldr.Locale.territory_from_host("a.b.com")
|
858
|
+ {:error,
|
859
|
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \\"com\\""}}
|
860
|
+
|
861
|
+ """
|
862
|
+ @doc since: "2.26.0"
|
863
|
+ @spec territory_from_host(String.t()) ::
|
864
|
+ {:ok, territory_code()} | {:error, {module(), String.t()}}
|
865
|
+
|
866
|
+ def territory_from_host(host) do
|
867
|
+ territory =
|
868
|
+ host
|
869
|
+ |> String.split(".")
|
870
|
+ |> Enum.reverse()
|
871
|
+ |> hd()
|
872
|
+
|
873
|
+ try do
|
874
|
+ territory = String.upcase(territory) |> String.to_existing_atom()
|
875
|
+ Cldr.validate_territory(territory)
|
876
|
+ rescue ArgumentError ->
|
877
|
+ {:error, no_locale_for_territory_error(territory)}
|
878
|
+ end
|
879
|
+ end
|
880
|
+
|
413
881
|
@doc """
|
414
882
|
Returns the effective territory for a locale.
|
415
883
|
|
|
@@ -470,7 +938,7 @@ defmodule Cldr.Locale do
|
470
938
|
however it is correctly parsed to support future use.
|
471
939
|
|
472
940
|
"""
|
473
|
- @spec territory_from_locale(LanguageTag.t() | locale_name()) :: Cldr.Locale.territory()
|
941
|
+ @spec territory_from_locale(LanguageTag.t() | locale_name() | String.t()) :: territory_code()
|
474
942
|
|
475
943
|
@doc since: "2.18.2"
|
476
944
|
|
|
@@ -482,7 +950,7 @@ defmodule Cldr.Locale do
|
482
950
|
language_tag.territory || Cldr.default_territory()
|
483
951
|
end
|
484
952
|
|
485
|
- def territory_from_locale(locale_name) when is_binary(locale_name) do
|
953
|
+ def territory_from_locale(locale_name) do
|
486
954
|
territory_from_locale(locale_name, Cldr.default_backend!())
|
487
955
|
end
|
488
956
|
|
|
@@ -549,12 +1017,12 @@ defmodule Cldr.Locale do
|
549
1017
|
|
550
1018
|
"""
|
551
1019
|
|
552
|
- @spec territory_from_locale(locale_name(), Cldr.backend()) ::
|
553
|
- territory() | {:error, {module(), String.t()}}
|
1020
|
+ @spec territory_from_locale(locale_reference() | String.t(), Cldr.backend()) ::
|
1021
|
+ territory_code() | {:error, {module(), String.t()}}
|
554
1022
|
|
555
1023
|
@doc since: "2.18.2"
|
556
1024
|
|
557
|
- def territory_from_locale(locale, backend) when is_binary(locale) do
|
1025
|
+ def territory_from_locale(locale, backend) do
|
558
1026
|
with {:ok, locale} <- Cldr.validate_locale(locale, backend) do
|
559
1027
|
territory_from_locale(locale)
|
560
1028
|
end
|
|
@@ -586,7 +1054,7 @@ defmodule Cldr.Locale do
|
586
1054
|
|
587
1055
|
"""
|
588
1056
|
|
589
|
- @spec timezone_from_locale(LanguageTag.t() | locale_name()) ::
|
1057
|
+ @spec timezone_from_locale(LanguageTag.t() | locale_name() | String.t()) ::
|
590
1058
|
String.t() | {:error, {module(), String.t()}}
|
591
1059
|
|
592
1060
|
@doc since: "2.19.0"
|
|
@@ -607,7 +1075,7 @@ defmodule Cldr.Locale do
|
607
1075
|
end
|
608
1076
|
end
|
609
1077
|
|
610
|
- def timezone_from_locale(locale_name) when is_binary(locale_name) do
|
1078
|
+ def timezone_from_locale(locale_name) do
|
611
1079
|
timezone_from_locale(locale_name, Cldr.default_backend!())
|
612
1080
|
end
|
613
1081
|
|
|
@@ -630,19 +1098,19 @@ defmodule Cldr.Locale do
|
630
1098
|
iex> Cldr.Locale.timezone_from_locale "en-US-u-tz-ausyd", TestBackend.Cldr
|
631
1099
|
"Australia/Sydney"
|
632
1100
|
|
633
|
- iex> Cldr.Locale.timezone_from_locale "en-AU", TestBackend.Cldr
|
1101
|
+ iex> Cldr.Locale.timezone_from_locale :"en-AU", TestBackend.Cldr
|
634
1102
|
{:error,
|
635
1103
|
{Cldr.AmbiguousTimezoneError,
|
636
1104
|
"Cannot determine the timezone since the territory :AU has 24 timezone IDs"}}
|
637
1105
|
|
638
1106
|
"""
|
639
1107
|
|
640
|
- @spec timezone_from_locale(locale_name(), Cldr.backend()) ::
|
1108
|
+ @spec timezone_from_locale(locale_name() | String.t(), Cldr.backend()) ::
|
641
1109
|
String.t() | {:error, {module(), String.t()}}
|
642
1110
|
|
643
1111
|
@doc since: "2.19.0"
|
644
1112
|
|
645
|
- def timezone_from_locale(locale, backend) when is_binary(locale) do
|
1113
|
+ def timezone_from_locale(locale, backend) do
|
646
1114
|
with {:ok, locale} <- Cldr.validate_locale(locale, backend) do
|
647
1115
|
timezone_from_locale(locale)
|
648
1116
|
end
|
|
@@ -707,13 +1175,13 @@ defmodule Cldr.Locale do
|
707
1175
|
%Cldr.LanguageTag{
|
708
1176
|
backend: TestBackend.Cldr,
|
709
1177
|
canonical_locale_name: "en",
|
710
|
- cldr_locale_name: "en",
|
1178
|
+ cldr_locale_name: :en,
|
711
1179
|
extensions: %{},
|
712
1180
|
gettext_locale_name: "en",
|
713
1181
|
language: "en",
|
714
1182
|
locale: %{},
|
715
1183
|
private_use: [],
|
716
|
- rbnf_locale_name: "en",
|
1184
|
+ rbnf_locale_name: :en,
|
717
1185
|
requested_locale_name: "en",
|
718
1186
|
script: :Latn,
|
719
1187
|
territory: :US,
|
|
@@ -723,7 +1191,7 @@ defmodule Cldr.Locale do
|
723
1191
|
}
|
724
1192
|
|
725
1193
|
"""
|
726
|
- @spec canonical_language_tag(locale_name | Cldr.LanguageTag.t(), Cldr.backend(), Keyword.t()) ::
|
1194
|
+ @spec canonical_language_tag(locale_name | Cldr.LanguageTag.t() | String.t(), Cldr.backend(), Keyword.t()) ::
|
727
1195
|
{:ok, Cldr.LanguageTag.t()} | {:error, {module(), String.t()}}
|
728
1196
|
|
729
1197
|
def canonical_language_tag(locale_name, backend, options \\ [])
|
|
@@ -738,9 +1206,28 @@ defmodule Cldr.Locale do
|
738
1206
|
end
|
739
1207
|
end
|
740
1208
|
|
741
|
- def canonical_language_tag(%LanguageTag{cldr_locale_name: locale} = tag, _backend, _options)
|
742
|
- when is_binary(locale) do
|
743
|
- {:ok, tag}
|
1209
|
+ def canonical_language_tag(locale_name, backend, options) when is_atom(locale_name) do
|
1210
|
+ case Map.fetch(Cldr.Config.all_language_tags(), locale_name) do
|
1211
|
+ {:ok, language_tag} ->
|
1212
|
+ canonical_language_tag(language_tag, backend, options)
|
1213
|
+
|
1214
|
+ :error ->
|
1215
|
+ canonical_language_tag(locale_name, backend, options)
|
1216
|
+ end
|
1217
|
+ end
|
1218
|
+
|
1219
|
+ unvalidated_match = quote do
|
1220
|
+ %LanguageTag{cldr_locale_name: var!(locale_name), canonical_locale_name: var!(canonical_name)}
|
1221
|
+ end
|
1222
|
+
|
1223
|
+ def canonical_language_tag(unquote(unvalidated_match) = language_tag, backend, _options)
|
1224
|
+ when not is_nil(locale_name) and not is_nil(canonical_name) do
|
1225
|
+ language_tag =
|
1226
|
+ language_tag
|
1227
|
+ |> put_backend(backend)
|
1228
|
+ |> put_gettext_locale_name()
|
1229
|
+
|
1230
|
+ {:ok, language_tag}
|
744
1231
|
end
|
745
1232
|
|
746
1233
|
def canonical_language_tag(%LanguageTag{} = language_tag, backend, options) do
|
|
@@ -998,7 +1485,7 @@ defmodule Cldr.Locale do
|
998
1485
|
|
999
1486
|
defp remove_unknown(%LanguageTag{} = language_tag, :script), do: language_tag
|
1000
1487
|
|
1001
|
- defp remove_unknown(%LanguageTag{territory: "ZZ"} = language_tag, :territory) do
|
1488
|
+ defp remove_unknown(%LanguageTag{territory: :ZZ} = language_tag, :territory) do
|
1002
1489
|
%{language_tag | territory: nil}
|
1003
1490
|
end
|
1004
1491
|
|
|
@@ -1055,7 +1542,7 @@ defmodule Cldr.Locale do
|
1055
1542
|
end
|
1056
1543
|
|
1057
1544
|
@spec rbnf_locale_name(Cldr.LanguageTag.t()) :: locale_name | nil
|
1058
|
- defp rbnf_locale_name(%LanguageTag{language: @root_locale}) do
|
1545
|
+ defp rbnf_locale_name(%LanguageTag{language: @root_language}) do
|
1059
1546
|
@root_rbnf_locale_name
|
1060
1547
|
end
|
1061
1548
|
|
|
@@ -1235,7 +1722,7 @@ defmodule Cldr.Locale do
|
1235
1722
|
|
1236
1723
|
## Returns
|
1237
1724
|
|
1238
|
- * The locale name constructed from the non-nil arguments joined
|
1725
|
+ * The atom locale name constructed from the non-nil arguments joined
|
1239
1726
|
by a "-"
|
1240
1727
|
|
1241
1728
|
## Example
|
|
@@ -1247,8 +1734,8 @@ defmodule Cldr.Locale do
|
1247
1734
|
"en-001"
|
1248
1735
|
|
1249
1736
|
"""
|
1250
|
- @spec locale_name_from(language(), script(), territory(), variants(), boolean) ::
|
1251
|
- locale_name()
|
1737
|
+ @spec locale_name_from(language(), script(), territory_reference(), variants(), boolean) ::
|
1738
|
+ String.t()
|
1252
1739
|
|
1253
1740
|
def locale_name_from(language, script, territory, variants, omit_singular_script? \\ true) do
|
1254
1741
|
[language, script, territory, variants]
|
|
@@ -1596,59 +2083,6 @@ defmodule Cldr.Locale do
|
1596
2083
|
end)
|
1597
2084
|
end
|
1598
2085
|
|
1599
|
- @doc """
|
1600
|
- Returns an error tuple for an invalid locale.
|
1601
|
-
|
1602
|
- ## Arguments
|
1603
|
-
|
1604
|
- * `locale_name` is any locale name returned by `Cldr.known_locale_names/1`
|
1605
|
-
|
1606
|
- ## Returns
|
1607
|
-
|
1608
|
- * `{:error, {Cldr.UnknownLocaleError, message}}`
|
1609
|
-
|
1610
|
- ## Examples
|
1611
|
-
|
1612
|
- iex> Cldr.Locale.locale_error :invalid
|
1613
|
- {Cldr.UnknownLocaleError, "The locale :invalid is not known."}
|
1614
|
-
|
1615
|
- """
|
1616
|
- @spec locale_error(locale_name() | LanguageTag.t()) :: {Cldr.UnknownLocaleError, String.t()}
|
1617
|
- def locale_error(%LanguageTag{requested_locale_name: requested_locale_name}) do
|
1618
|
- locale_error(requested_locale_name)
|
1619
|
- end
|
1620
|
-
|
1621
|
- def locale_error(locale_name) do
|
1622
|
- {Cldr.UnknownLocaleError, "The locale #{inspect(locale_name)} is not known."}
|
1623
|
- end
|
1624
|
-
|
1625
|
- @doc """
|
1626
|
- Returns an error tuple for an invalid gettext locale.
|
1627
|
-
|
1628
|
- ## Options
|
1629
|
-
|
1630
|
- * `locale_name` is any locale name returned by `Cldr.known_gettext_locale_names/1`
|
1631
|
-
|
1632
|
- ## Returns
|
1633
|
-
|
1634
|
- * `{:error, {Cldr.UnknownLocaleError, message}}`
|
1635
|
-
|
1636
|
- ## Examples
|
1637
|
-
|
1638
|
- iex> Cldr.Locale.gettext_locale_error :invalid
|
1639
|
- {Cldr.UnknownLocaleError, "The gettext locale :invalid is not known."}
|
1640
|
-
|
1641
|
- """
|
1642
|
- @spec gettext_locale_error(locale_name() | LanguageTag.t()) ::
|
1643
|
- {Cldr.UnknownLocaleError, String.t()}
|
1644
|
- def gettext_locale_error(%LanguageTag{gettext_locale_name: gettext_locale_name}) do
|
1645
|
- gettext_locale_error(gettext_locale_name)
|
1646
|
- end
|
1647
|
-
|
1648
|
- def gettext_locale_error(locale_name) do
|
1649
|
- {Cldr.UnknownLocaleError, "The gettext locale #{inspect(locale_name)} is not known."}
|
1650
|
- end
|
1651
|
-
|
1652
2086
|
@doc """
|
1653
2087
|
Returns the map of likely subtags.
|
1654
2088
|
|
|
@@ -1658,8 +2092,8 @@ defmodule Cldr.Locale do
|
1658
2092
|
## Example
|
1659
2093
|
|
1660
2094
|
Cldr.Locale.likely_subtags
|
1661
|
- %{
|
1662
|
- "bez" => %Cldr.LanguageTag{
|
2095
|
+ => %{
|
2096
|
+ bez; %Cldr.LanguageTag{
|
1663
2097
|
backend: TestBackend.Cldr,
|
1664
2098
|
canonical_locale_name: nil,
|
1665
2099
|
cldr_locale_name: nil,
|
|
@@ -1674,7 +2108,7 @@ defmodule Cldr.Locale do
|
1674
2108
|
transform: %{},
|
1675
2109
|
language_variants: []
|
1676
2110
|
},
|
1677
|
- "fuf" => %Cldr.LanguageTag{
|
2111
|
+ fuf: %Cldr.LanguageTag{
|
1678
2112
|
canonical_locale_name: nil,
|
1679
2113
|
cldr_locale_name: nil,
|
1680
2114
|
extensions: %{},
|
|
@@ -1707,7 +2141,7 @@ defmodule Cldr.Locale do
|
1707
2141
|
|
1708
2142
|
## Examples
|
1709
2143
|
|
1710
|
- iex> Cldr.Locale.likely_subtags "en"
|
2144
|
+ iex> Cldr.Locale.likely_subtags :en
|
1711
2145
|
%Cldr.LanguageTag{
|
1712
2146
|
backend: nil,
|
1713
2147
|
canonical_locale_name: nil,
|
|
@@ -1726,8 +2160,9 @@ defmodule Cldr.Locale do
|
1726
2160
|
}
|
1727
2161
|
|
1728
2162
|
"""
|
1729
|
- @spec likely_subtags(locale_name) :: LanguageTag.t() | nil
|
1730
|
- def likely_subtags(locale_name) when is_binary(locale_name) do
|
2163
|
+ @spec likely_subtags(locale_name | String.t()) :: LanguageTag.t() | nil
|
2164
|
+
|
2165
|
+ def likely_subtags(locale_name) when is_atom(locale_name) do
|
1731
2166
|
Map.get(likely_subtags(), locale_name)
|
1732
2167
|
end
|
1733
2168
|
|
|
@@ -1735,6 +2170,14 @@ defmodule Cldr.Locale do
|
1735
2170
|
likely_subtags(requested_locale_name)
|
1736
2171
|
end
|
1737
2172
|
|
2173
|
+ def likely_subtags(locale_name) when is_binary(locale_name) do
|
2174
|
+ locale_name
|
2175
|
+ |> String.to_existing_atom()
|
2176
|
+ |> likely_subtags()
|
2177
|
+ rescue ArgumentError ->
|
2178
|
+ nil
|
2179
|
+ end
|
2180
|
+
|
1738
2181
|
@doc """
|
1739
2182
|
Return a map of the known aliases for Language, Script and Territory
|
1740
2183
|
"""
|
|
@@ -1755,9 +2198,10 @@ defmodule Cldr.Locale do
|
1755
2198
|
|
1756
2199
|
"""
|
1757
2200
|
@alias_keys Map.keys(@aliases)
|
1758
|
- @spec aliases(locale_name(), atom()) :: String.t() | list(String.t()) | LanguageTag.t() | nil
|
2201
|
+ @spec aliases(locale_name() | String.t(), atom()) ::
|
2202
|
+ String.t() | list(String.t()) | LanguageTag.t() | nil
|
1759
2203
|
|
1760
|
- def aliases(key, :region = type) do
|
2204
|
+ def aliases(key, :region = type) when is_atom(key) do
|
1761
2205
|
aliases()
|
1762
2206
|
|> Map.get(type)
|
1763
2207
|
|> Map.get(to_string(key))
|
|
@@ -1769,6 +2213,14 @@ defmodule Cldr.Locale do
|
1769
2213
|
|> Map.get(key)
|
1770
2214
|
end
|
1771
2215
|
|
2216
|
+ def aliases(key, type) when is_binary(key) do
|
2217
|
+ key
|
2218
|
+ |> String.to_existing_atom()
|
2219
|
+ |> aliases(type)
|
2220
|
+ rescue ArgumentError ->
|
2221
|
+ nil
|
2222
|
+ end
|
2223
|
+
|
1772
2224
|
defp validate_subtags(language_tag) do
|
1773
2225
|
with {:ok, language_tag} <- validate(language_tag, :language),
|
1774
2226
|
{:ok, language_tag} <- validate(language_tag, :script),
|
|
@@ -1806,33 +2258,45 @@ defmodule Cldr.Locale do
|
1806
2258
|
end
|
1807
2259
|
end
|
1808
2260
|
|
2261
|
+ @doc false
|
2262
|
+ def locale_error(%LanguageTag{requested_locale_name: requested_locale_name}) do
|
2263
|
+ locale_error(requested_locale_name)
|
2264
|
+ end
|
2265
|
+
|
2266
|
+ def locale_error(locale_name) do
|
2267
|
+ {Cldr.UnknownLocaleError, "The locale #{inspect(locale_name)} is not known."}
|
2268
|
+ end
|
2269
|
+
|
2270
|
+ @doc false
|
2271
|
+ def gettext_locale_error(%LanguageTag{gettext_locale_name: gettext_locale_name}) do
|
2272
|
+ gettext_locale_error(gettext_locale_name)
|
2273
|
+ end
|
2274
|
+
|
2275
|
+ def gettext_locale_error(locale_name) do
|
2276
|
+ {Cldr.UnknownLocaleError, "The gettext locale #{inspect(locale_name)} is not known."}
|
2277
|
+ end
|
2278
|
+
|
2279
|
+ @doc false
|
1809
2280
|
def invalid_language_error(language) do
|
1810
2281
|
{Cldr.InvalidLanguageError, "The language #{inspect(language)} is invalid"}
|
1811
2282
|
end
|
1812
2283
|
|
2284
|
+ @doc false
|
1813
2285
|
def invalid_script_error(script) do
|
1814
2286
|
{Cldr.InvalidScriptError, "The script #{inspect(script)} is invalid"}
|
1815
2287
|
end
|
1816
2288
|
|
2289
|
+ @doc false
|
1817
2290
|
def invalid_territory_error(territory) do
|
1818
2291
|
{Cldr.InvalidTerritoryError, "The territory #{inspect(territory)} is invalid"}
|
1819
2292
|
end
|
1820
2293
|
|
2294
|
+ @doc false
|
1821
2295
|
def invalid_variant_error(variant) do
|
1822
2296
|
{Cldr.InvalidVariantError, "The variant #{inspect(variant)} is invalid"}
|
1823
2297
|
end
|
1824
2298
|
|
1825
|
- @doc """
|
1826
|
- Returns an error tuple for an invalid locale alias.
|
1827
|
-
|
1828
|
- ## Options
|
1829
|
-
|
1830
|
- * `locale_name` is any locale name returned by `Cldr.known_locale_names/1`
|
1831
|
-
|
1832
|
- """
|
1833
|
- @spec alias_error(locale_name() | LanguageTag.t(), String.t()) ::
|
1834
|
- {Cldr.UnknownLocaleError, String.t()}
|
1835
|
-
|
2299
|
+ @doc false
|
1836
2300
|
def alias_error(locale_name, alias_name) when is_binary(locale_name) do
|
1837
2301
|
{
|
1838
2302
|
Cldr.UnknownLocaleError,
|
|
@@ -1841,7 +2305,20 @@ defmodule Cldr.Locale do
|
1841
2305
|
}
|
1842
2306
|
end
|
1843
2307
|
|
2308
|
+ @doc false
|
1844
2309
|
def alias_error(%LanguageTag{requested_locale_name: requested_locale_name}, alias_name) do
|
1845
2310
|
alias_error(requested_locale_name, alias_name)
|
1846
2311
|
end
|
2312
|
+
|
2313
|
+ @doc false
|
2314
|
+ def no_locale_for_territory_error(territory) when is_binary(territory) do
|
2315
|
+ {Cldr.UnknownLocaleError, "No locale was identified for territory #{inspect territory}"}
|
2316
|
+ end
|
2317
|
+
|
2318
|
+ def no_locale_for_territory_error(territory) when is_atom(territory) do
|
2319
|
+ territory
|
2320
|
+ |> Atom.to_string()
|
2321
|
+ |> String.downcase()
|
2322
|
+ |> no_locale_for_territory_error()
|
2323
|
+ end
|
1847
2324
|
end
|
changed
lib/cldr/locale/cache.ex
|
@@ -37,11 +37,11 @@ defmodule Cldr.Locale.Cache do
|
37
37
|
process_alive?(:cldr_locale_cache)
|
38
38
|
end
|
39
39
|
|
40
|
- defp process_alive?(:can_await_module_compilation?) do
|
41
|
- Code.ensure_loaded?(Code) &&
|
42
|
- function_exported?(Code, :can_await_module_compilation?, 0) &&
|
43
|
- apply(Code, :can_await_module_compilation?, [])
|
44
|
- end
|
40
|
+ defp process_alive?(:can_await_module_compilation?) do
|
41
|
+ Code.ensure_loaded?(Code) &&
|
42
|
+ function_exported?(Code, :can_await_module_compilation?, 0) &&
|
43
|
+ apply(Code, :can_await_module_compilation?, [])
|
44
|
+ end
|
45
45
|
|
46
46
|
defp process_alive?(name) do
|
47
47
|
case Process.get(name) do
|
changed
lib/cldr/locale/loader.ex
|
@@ -22,6 +22,11 @@ defmodule Cldr.Locale.Loader do
|
22
22
|
Returns a list of all locales that are configured and available
|
23
23
|
in the CLDR repository.
|
24
24
|
|
25
|
+ ## Examples
|
26
|
+
|
27
|
+ iex> Cldr.Locale.Loader.known_locale_names %Cldr.Config{locales: ["en", "de"]}
|
28
|
+ [:de, :en, :und]
|
29
|
+
|
25
30
|
"""
|
26
31
|
@spec known_locale_names(Config.t() | Cldr.backend()) :: [Locale.locale_name()]
|
27
32
|
def known_locale_names(backend) when is_atom(backend) do
|
|
@@ -29,13 +34,8 @@ defmodule Cldr.Locale.Loader do
|
29
34
|
|> known_locale_names
|
30
35
|
end
|
31
36
|
|
32
|
- def known_locale_names(%Config{locales: :all}) do
|
33
|
- Cldr.Config.all_locale_names()
|
34
|
- |> Enum.sort()
|
35
|
- end
|
36
|
-
|
37
|
- def known_locale_names(%Config{locales: locales}) do
|
38
|
- locales
|
37
|
+ def known_locale_names(%Config{} = config) do
|
38
|
+ Cldr.Config.configured_locale_names(config)
|
39
39
|
end
|
40
40
|
|
41
41
|
@doc """
|
|
@@ -61,26 +61,26 @@ defmodule Cldr.Locale.Loader do
|
61
61
|
during production run there is no file access or decoding.
|
62
62
|
|
63
63
|
"""
|
64
|
- @spec get_locale(Cldr.Locale.locale_name(), config_or_backend :: Config.t() | Cldr.backend()) ::
|
64
|
+ @spec get_locale(Locale.locale_name(), config_or_backend :: Config.t() | Cldr.backend()) ::
|
65
65
|
map() | no_return()
|
66
66
|
|
67
|
- def get_locale(locale, %{data_dir: _} = config) do
|
67
|
+ def get_locale(locale, %{data_dir: _} = config) when is_atom(locale) do
|
68
68
|
do_get_locale(locale, config)
|
69
69
|
end
|
70
70
|
|
71
|
- def get_locale(locale, backend) when is_atom(backend) do
|
71
|
+ def get_locale(locale, backend) when is_atom(locale) and is_atom(backend) do
|
72
72
|
do_get_locale(locale, backend.__cldr__(:config))
|
73
73
|
end
|
74
74
|
|
75
75
|
@doc false
|
76
|
- def do_get_locale(locale, config) do
|
76
|
+ def do_get_locale(locale, config) when is_atom(locale) do
|
77
77
|
{:ok, path} =
|
78
78
|
case Config.locale_path(locale, config) do
|
79
79
|
{:ok, path} ->
|
80
80
|
{:ok, path}
|
81
81
|
|
82
82
|
{:error, :not_found} ->
|
83
|
- raise RuntimeError, message: "Locale definition was not found for #{locale}"
|
83
|
+ raise RuntimeError, message: "Locale definition was not found for #{inspect locale}"
|
84
84
|
end
|
85
85
|
|
86
86
|
do_get_locale(locale, path, Cldr.Locale.Cache.compiling?())
|
|
@@ -115,7 +115,7 @@ defmodule Cldr.Locale.Loader do
|
115
115
|
end
|
116
116
|
|
117
117
|
@doc false
|
118
|
- def do_get_locale(locale, path, true) do
|
118
|
+ def do_get_locale(locale, path, true) when is_atom(locale) do
|
119
119
|
Cldr.Locale.Cache.get_locale(locale, path)
|
120
120
|
end
|
changed
lib/cldr/plural_rules/plural_rule.ex
|
@@ -93,7 +93,7 @@ defmodule Cldr.Number.PluralRule do
|
93
93
|
"`type: :ordinal` are the only valid options"
|
94
94
|
end
|
95
95
|
|
96
|
- quote location: :keep do
|
96
|
+ quote location: :keep, generated: true do
|
97
97
|
alias Cldr.Math
|
98
98
|
alias Cldr.LanguageTag
|
99
99
|
alias Cldr.Locale
|
|
@@ -233,25 +233,25 @@ defmodule Cldr.Number.PluralRule do
|
233
233
|
|
234
234
|
## Examples
|
235
235
|
|
236
|
- iex> #{inspect(__MODULE__)}.pluralize 1, "en", %{one: "one"}
|
236
|
+ iex> #{inspect(__MODULE__)}.pluralize 1, :en, %{one: "one"}
|
237
237
|
"one"
|
238
238
|
|
239
|
- iex> #{inspect(__MODULE__)}.pluralize 2, "en", %{one: "one"}
|
239
|
+ iex> #{inspect(__MODULE__)}.pluralize 2, :en, %{one: "one"}
|
240
240
|
nil
|
241
241
|
|
242
|
- iex> #{inspect(__MODULE__)}.pluralize 2, "en", %{one: "one", two: "two"}
|
242
|
+ iex> #{inspect(__MODULE__)}.pluralize 2, :en, %{one: "one", two: "two"}
|
243
243
|
"two"
|
244
244
|
|
245
|
- iex> #{inspect(__MODULE__)}.pluralize 22, "en", %{one: "one", two: "two", other: "other"}
|
245
|
+ iex> #{inspect(__MODULE__)}.pluralize 22, :en, %{one: "one", two: "two", other: "other"}
|
246
246
|
"two"
|
247
247
|
|
248
|
- iex> #{inspect(__MODULE__)}.pluralize Decimal.new(1), "en", %{one: "one"}
|
248
|
+ iex> #{inspect(__MODULE__)}.pluralize Decimal.new(1), :en, %{one: "one"}
|
249
249
|
"one"
|
250
250
|
|
251
|
- iex> #{inspect(__MODULE__)}.pluralize Decimal.new(2), "en", %{one: "one"}
|
251
|
+ iex> #{inspect(__MODULE__)}.pluralize Decimal.new(2), :en, %{one: "one"}
|
252
252
|
nil
|
253
253
|
|
254
|
- iex> #{inspect(__MODULE__)}.pluralize Decimal.new(2), "en", %{one: "one", two: "two"}
|
254
|
+ iex> #{inspect(__MODULE__)}.pluralize Decimal.new(2), :en, %{one: "one", two: "two"}
|
255
255
|
"two"
|
256
256
|
|
257
257
|
iex> #{inspect(__MODULE__)}.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
|
|
@@ -264,12 +264,7 @@ defmodule Cldr.Number.PluralRule do
|
264
264
|
end
|
265
265
|
|
266
266
|
@default_substitution :other
|
267
|
- @spec pluralize(
|
268
|
- Math.number_or_decimal() | %Range{},
|
269
|
- LanguageTag.t() | Locale.locale_name(),
|
270
|
- %{}
|
271
|
- ) ::
|
272
|
- any()
|
267
|
+ @spec pluralize(Math.number_or_decimal() | Range.t(), Locale.locale_reference(), %{}) :: any()
|
273
268
|
|
274
269
|
def pluralize(%Range{first: first, last: last}, locale_name, substitutions) do
|
275
270
|
with {:ok, language_tag} <- @backend.validate_locale(locale_name) do
|
|
@@ -283,7 +278,8 @@ defmodule Cldr.Number.PluralRule do
|
283
278
|
end
|
284
279
|
end
|
285
280
|
|
286
|
- def pluralize(number, locale_name, substitutions) when is_binary(locale_name) do
|
281
|
+ def pluralize(number, locale_name, substitutions)
|
282
|
+ when is_atom(locale_name) or is_binary(locale_name) do
|
287
283
|
with {:ok, language_tag} <- @backend.validate_locale(locale_name) do
|
288
284
|
pluralize(number, language_tag, substitutions)
|
289
285
|
end
|
|
@@ -301,18 +297,16 @@ defmodule Cldr.Number.PluralRule do
|
301
297
|
|> do_pluralize(locale, substitutions)
|
302
298
|
end
|
303
299
|
|
304
|
- def pluralize(%Decimal{sign: sign, coef: coef, exp: exp} = number, locale, substitutions)
|
300
|
+ def pluralize(%Decimal{sign: sign, coef: coef, exp: exp}, locale, substitutions)
|
305
301
|
when is_integer(coef) and exp > 0 do
|
306
|
- number
|
307
|
- |> Decimal.to_integer()
|
308
|
- |> do_pluralize(locale, substitutions)
|
302
|
+ number = %Decimal{sign: sign, coef: coef * 10, exp: exp - 1}
|
303
|
+ pluralize(number, locale, substitutions)
|
309
304
|
end
|
310
305
|
|
311
|
- def pluralize(%Decimal{sign: sign, coef: coef, exp: exp} = number, locale, substitutions)
|
306
|
+ def pluralize(%Decimal{sign: sign, coef: coef, exp: exp}, locale, substitutions)
|
312
307
|
when is_integer(coef) and exp < 0 and rem(coef, 10) == 0 do
|
313
|
- number
|
314
|
- |> Decimal.to_integer()
|
315
|
- |> do_pluralize(locale, substitutions)
|
308
|
+ number = %Decimal{sign: sign, coef: Kernel.div(coef, 10), exp: exp + 1}
|
309
|
+ pluralize(number, locale, substitutions)
|
316
310
|
end
|
317
311
|
|
318
312
|
def pluralize(%Decimal{} = number, %LanguageTag{} = locale, %{} = substitutions) do
|
|
@@ -344,7 +338,7 @@ defmodule Cldr.Number.PluralRule do
|
344
338
|
plural_rules()[cldr_locale_name] || plural_rules()[language]
|
345
339
|
end
|
346
340
|
|
347
|
- def plural_rules_for(locale_name) when is_binary(locale_name) do
|
341
|
+ def plural_rules_for(locale_name) do
|
348
342
|
with {:ok, locale} <- @backend.validate_locale(locale_name) do
|
349
343
|
plural_rules_for(locale)
|
350
344
|
end
|
|
@@ -441,18 +435,12 @@ defmodule Cldr.Number.PluralRule do
|
441
435
|
|
442
436
|
def plural_rule(number, locale, rounding \\ Math.default_rounding())
|
443
437
|
|
444
|
- def plural_rule(number, locale_name, rounding) when is_binary(locale_name) do
|
445
|
- with {:ok, locale} <- @backend.validate_locale(locale_name) do
|
446
|
- plural_rule(number, locale, rounding)
|
447
|
- end
|
448
|
- end
|
449
|
-
|
450
|
- def plural_rule(number, locale, rounding) when is_binary(number) do
|
438
|
+ def plural_rule(number, %LanguageTag{} = locale, rounding) when is_binary(number) do
|
451
439
|
plural_rule(Decimal.new(number), locale, rounding)
|
452
440
|
end
|
453
441
|
|
454
442
|
# Plural rule for an integer
|
455
|
- def plural_rule(number, locale, _rounding) when is_integer(number) do
|
443
|
+ def plural_rule(number, %LanguageTag{} = locale, _rounding) when is_integer(number) do
|
456
444
|
n = abs(number)
|
457
445
|
i = n
|
458
446
|
v = 0
|
|
@@ -464,7 +452,7 @@ defmodule Cldr.Number.PluralRule do
|
464
452
|
end
|
465
453
|
|
466
454
|
# For a compact integer
|
467
|
- def plural_rule({number, e}, locale, _rounding) when is_integer(number) do
|
455
|
+ def plural_rule({number, e}, %LanguageTag{} = locale, _rounding) when is_integer(number) do
|
468
456
|
n = abs(number)
|
469
457
|
i = n
|
470
458
|
v = 0
|
|
@@ -475,7 +463,7 @@ defmodule Cldr.Number.PluralRule do
|
475
463
|
end
|
476
464
|
|
477
465
|
# Plural rule for a float
|
478
|
- def plural_rule(number, locale, rounding)
|
466
|
+ def plural_rule(number, %LanguageTag{} = locale, rounding)
|
479
467
|
when is_float(number) and is_integer(rounding) and rounding > 0 do
|
480
468
|
# Testing shows that this is working but just in case we
|
481
469
|
# can go back to casting the number to a decimal and
|
|
@@ -492,7 +480,7 @@ defmodule Cldr.Number.PluralRule do
|
492
480
|
end
|
493
481
|
|
494
482
|
# Plural rule for a compact float
|
495
|
- def plural_rule({number, e}, locale, rounding)
|
483
|
+ def plural_rule({number, e}, %LanguageTag{} = locale, rounding)
|
496
484
|
when is_float(number) and is_integer(rounding) and rounding > 0 do
|
497
485
|
# Testing shows that this is working but just in case we
|
498
486
|
# can go back to casting the number to a decimal and
|
|
@@ -508,7 +496,7 @@ defmodule Cldr.Number.PluralRule do
|
508
496
|
end
|
509
497
|
|
510
498
|
# Plural rule for a %Decimal{}
|
511
|
- def plural_rule(%Decimal{} = number, locale, rounding)
|
499
|
+ def plural_rule(%Decimal{} = number, %LanguageTag{} = locale, rounding)
|
512
500
|
when is_integer(rounding) and rounding > 0 do
|
513
501
|
# n absolute value of the source number (integer and decimals).
|
514
502
|
n = Decimal.abs(number)
|
|
@@ -541,7 +529,7 @@ defmodule Cldr.Number.PluralRule do
|
541
529
|
end
|
542
530
|
|
543
531
|
# Plural rule for a compact %Decimal{}
|
544
|
- def plural_rule({%Decimal{} = number, e}, locale, rounding)
|
532
|
+ def plural_rule({%Decimal{} = number, e}, %LanguageTag{} = locale, rounding)
|
545
533
|
when is_integer(rounding) and rounding > 0 do
|
546
534
|
# n absolute value of the source number (integer and decimals).
|
547
535
|
n = Decimal.abs(number)
|
|
@@ -571,6 +559,12 @@ defmodule Cldr.Number.PluralRule do
|
571
559
|
|
572
560
|
do_plural_rule(locale, n, i, v, w, f, t, e)
|
573
561
|
end
|
562
|
+
|
563
|
+ def plural_rule(number, locale_name, rounding) do
|
564
|
+ with {:ok, locale} <- @backend.validate_locale(locale_name) do
|
565
|
+ plural_rule(number, locale, rounding)
|
566
|
+ end
|
567
|
+ end
|
574
568
|
end
|
575
569
|
end
|
576
570
|
|
|
@@ -718,7 +712,7 @@ defmodule Cldr.Number.PluralRule do
|
718
712
|
}
|
719
713
|
else
|
720
714
|
language_tag
|
721
|
- |> Map.put(:cldr_locale_name, language_tag.language)
|
715
|
+ |> Map.put(:cldr_locale_name, String.to_atom(language_tag.language))
|
722
716
|
|> do_plural_rule(n, i, v, w, f, t, e)
|
723
717
|
end
|
724
718
|
end
|
removed
lib/cldr/sigil.ex
|
@@ -1,87 +0,0 @@
|
1
|
- defmodule Cldr.LanguageTag.Sigil do
|
2
|
- @moduledoc """
|
3
|
- Implements a `sigil_l/2` macro to
|
4
|
- constructing `t:Cldr.LanguageTag` structs.
|
5
|
-
|
6
|
- """
|
7
|
-
|
8
|
- @doc """
|
9
|
- Handles sigil `~l` for language tags.
|
10
|
-
|
11
|
- ## Arguments
|
12
|
-
|
13
|
- * `locale_name` is either a [BCP 47](https://unicode-org.github.io/cldr/ldml/tr35.html#Identifiers)
|
14
|
- locale name as a string or
|
15
|
-
|
16
|
- * `locale_name` | `backend` where backend is a backend module name
|
17
|
-
|
18
|
- ## Options
|
19
|
-
|
20
|
- * `u` Will parse the locale but will not add
|
21
|
- likely subtags and its not guaranteed that this
|
22
|
- language tag is known to the backend module.
|
23
|
-
|
24
|
- ## Returns
|
25
|
-
|
26
|
- * a `t:Cldr.LanguageTag` struct or
|
27
|
-
|
28
|
- * raises an exception
|
29
|
-
|
30
|
- ## Examples
|
31
|
-
|
32
|
- iex> import Cldr.LanguageTag.Sigil
|
33
|
- iex> ~l(en-US-u-ca-gregory)
|
34
|
- #Cldr.LanguageTag<en-US-u-ca-gregory [validated]>
|
35
|
-
|
36
|
- iex> import Cldr.LanguageTag.Sigil
|
37
|
- iex> ~l(en-US-u-ca-gregory|MyApp.Cldr)
|
38
|
- #Cldr.LanguageTag<en-US-u-ca-gregory [validated]>
|
39
|
-
|
40
|
- """
|
41
|
- defmacro sigil_l(locale_name, 'u') do
|
42
|
- {:<<>>, [_], [locale_name]} = locale_name
|
43
|
-
|
44
|
- case parse_locale(String.split(locale_name, "|")) do
|
45
|
- {:ok, locale_name} ->
|
46
|
- quote do
|
47
|
- unquote(Macro.escape(locale_name))
|
48
|
- end
|
49
|
-
|
50
|
- {:error, {exception, reason}} ->
|
51
|
- raise exception, reason
|
52
|
- end
|
53
|
- end
|
54
|
-
|
55
|
- defmacro sigil_l(locale_name, _opts) do
|
56
|
- {:<<>>, [_], [locale_name]} = locale_name
|
57
|
-
|
58
|
- case validate_locale(String.split(locale_name, "|")) do
|
59
|
- {:ok, locale_name} ->
|
60
|
- quote do
|
61
|
- unquote(Macro.escape(locale_name))
|
62
|
- end
|
63
|
-
|
64
|
- {:error, {exception, reason}} ->
|
65
|
- raise exception, reason
|
66
|
- end
|
67
|
- end
|
68
|
-
|
69
|
- defp validate_locale([locale_name, backend]) do
|
70
|
- backend = Module.concat([backend])
|
71
|
- Cldr.validate_locale(locale_name, backend)
|
72
|
- end
|
73
|
-
|
74
|
- defp validate_locale([locale_name]) do
|
75
|
- Cldr.validate_locale(locale_name)
|
76
|
- end
|
77
|
-
|
78
|
- @opts [add_likely_subtags: false]
|
79
|
- defp parse_locale([locale_name, backend]) do
|
80
|
- backend = Module.concat([backend])
|
81
|
- Cldr.Locale.canonical_language_tag(locale_name, backend, @opts)
|
82
|
- end
|
83
|
-
|
84
|
- defp parse_locale([locale_name]) do
|
85
|
- Cldr.Locale.canonical_language_tag(locale_name, Cldr.default_backend!(), @opts)
|
86
|
- end
|
87
|
- end
|
changed
mix.exs
|
@@ -1,7 +1,7 @@
|
1
1
|
defmodule Cldr.Mixfile do
|
2
2
|
use Mix.Project
|
3
3
|
|
4
|
- @version "2.25.0"
|
4
|
+ @version "2.26.0"
|
5
5
|
|
6
6
|
def project do
|
7
7
|
[
|
|
@@ -45,13 +45,14 @@ defmodule Cldr.Mixfile do
|
45
45
|
defp deps do
|
46
46
|
[
|
47
47
|
{:cldr_utils, "~> 2.17"},
|
48
|
+
|
48
49
|
{:decimal, "~> 1.6 or ~> 2.0"},
|
49
50
|
{:castore, "~> 0.1", optional: true},
|
50
51
|
{:certifi, "~> 2.5", optional: true},
|
51
52
|
{:jason, "~> 1.0", optional: true},
|
52
53
|
{:ex_doc, "~> 0.18", only: [:release, :dev]},
|
53
54
|
{:nimble_parsec, "~> 0.5 or ~> 1.0", optional: true},
|
54
|
- {:gettext, "~> 0.13", optional: true},
|
55
|
+ {:gettext, "~> 0.19", optional: true},
|
55
56
|
{:stream_data, "~> 0.4", only: :test},
|
56
57
|
{:dialyxir, "~> 1.0", only: [:dev], runtime: false, optional: true},
|
57
58
|
{:plug, "~> 1.9", optional: true},
|