From 1eabcb34e67c342af3f1744456710e6abc397179 Mon Sep 17 00:00:00 2001
From: mayel ACLs represent fully populated access control rules that can be reused.
-Can be reused to secure multiple objects, thus exists independently of any object. The table doesn't have any fields of its own:
+Can be reused to secure multiple objects, thus exists independently of any object.has_many(:grants, Grant)
-has_many(:controlled, Controlled)
The table doesn't have any fields of its own:
has_many(:grants, Grant)
+has_many(:controlled, Controlled)
diff --git a/Bonfire.Common.Errors.html b/Bonfire.Common.Errors.html
index 40270aa3f75..3a908448784 100644
--- a/Bonfire.Common.Errors.html
+++ b/Bonfire.Common.Errors.html
@@ -466,12 +466,12 @@ iex> Exception.format_mfa(Foo, :bar, 1)
-{Foo, :bar, "Foo.bar/1"}
-iex> Exception.format_mfa(Foo, :bar, [])
-{Foo, :bar, "Foo.bar()"}
-iex> Exception.format_mfa(nil, :bar, [])
-{nil, :bar, "nil.bar()"}
Anonymous functions are reported as -func/arity-anonfn-count-, +
iex> Exception.format_mfa(Foo, :bar, 1)
+{Foo, :bar, "Foo.bar/1"}
+iex> Exception.format_mfa(Foo, :bar, [])
+{Foo, :bar, "Foo.bar()"}
+iex> Exception.format_mfa(nil, :bar, [])
+{nil, :bar, "nil.bar()"}
Anonymous functions are reported as -func/arity-anonfn-count-, where func is the name of the enclosing function. Convert to "anonymous fn in func/arity"
diff --git a/Bonfire.Common.Localise.Cldr.AcceptLanguage.html b/Bonfire.Common.Localise.Cldr.AcceptLanguage.html index 3a5850d9490..569f1204c1f 100644 --- a/Bonfire.Common.Localise.Cldr.AcceptLanguage.html +++ b/Bonfire.Common.Localise.Cldr.AcceptLanguage.html @@ -119,7 +119,7 @@Cldr.LanguageTag
.The format of an Accept-Language
header is as follows in ABNF
format:
Accept-Language = "Accept-Language" ":"
1#( language-range [ ";" "q" "=" qvalue ] )
- language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
Each language-range MAY be given an associated quality value which represents an + language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
Each language-range MAY be given an associated quality value which represents an estimate of the user's preference for the languages specified by that range. The quality value defaults to "q=1". For example,
Accept-Language: da, en-gb;q=0.8, en;q=0.7
would mean: "I prefer Danish, but will accept British English and other types of English."
@@ -234,54 +234,54 @@iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
-{:ok,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
+{:ok,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }}
+ transform: %{},
+ language_variants: []
+ }}
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
-{:ok,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
+{:ok,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }}
-
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("xx,yy;q=0.3")
-{:error,
- {Cldr.NoMatchingLocale,
- "No configured locale could be matched to \"xx,yy;q=0.3\""}}
-
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("invalid_tag")
-{:error, {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
+ transform: %{},
+ language_variants: []
+ }}
+
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("xx,yy;q=0.3")
+{:error,
+ {Cldr.NoMatchingLocale,
+ "No configured locale could be matched to \"xx,yy;q=0.3\""}}
+
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("invalid_tag")
+{:error, {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
iex> Cldr.AcceptLanguage.parse("da,zh-TW;q=0.3", TestBackend.Cldr)
-{:ok,
- [
- {1.0,
- %Cldr.LanguageTag{
+iex> Cldr.AcceptLanguage.parse("da,zh-TW;q=0.3", TestBackend.Cldr)
+{:ok,
+ [
+ {1.0,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "da",
cldr_locale_name: :da,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "da",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :da,
requested_locale_name: "da",
script: :Latn,
territory: :DK,
- transform: %{},
- language_variants: []
- }},
- {0.3,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }},
+ {0.3,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }}
- ]}
-
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse("invalid_tag")
-{:error,
- {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
-
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse("da,zh-TW;q=0.3,invalid_tag")
-{:ok,
- [
- {1.0,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }}
+ ]}
+
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse("invalid_tag")
+{:error,
+ {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
+
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse("da,zh-TW;q=0.3,invalid_tag")
+{:ok,
+ [
+ {1.0,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "da",
cldr_locale_name: :da,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "da",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :da,
requested_locale_name: "da",
script: :Latn,
territory: :DK,
- transform: %{},
- language_variants: []
- }},
- {0.3,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }},
+ {0.3,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }},
- {:error,
- {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
- ]}
+ transform: %{},
+ language_variants: []
+ }},
+ {:error,
+ {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
+ ]}
iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3")
-[
- {1.0,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3")
+[
+ {1.0,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "da",
cldr_locale_name: :da,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "da",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :da,
requested_locale_name: "da",
script: :Latn,
territory: :DK,
- transform: %{},
- language_variants: []
- }},
- {0.3,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }},
+ {0.3,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }}
-]
+ transform: %{},
+ language_variants: []
+ }}
+]
Bonfire.Common.Localise.Cldr.AcceptLanguage.parse! "invalid_tag"
** (Cldr.AcceptLanguageError) "Expected a BCP47 language tag. Could not parse the remaining "g" starting at position 11
(ex_cldr) lib/cldr/accept_language.ex:304: Cldr.AcceptLanguage.parse!/1
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3,invalid_tag")
-[
- {1.0,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3,invalid_tag")
+[
+ {1.0,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "da",
cldr_locale_name: :da,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "da",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :da,
requested_locale_name: "da",
script: :Latn,
territory: :DK,
- transform: %{},
- language_variants: []
- }},
- {0.3,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }},
+ {0.3,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }},
- {:error,
- {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
-]
+ transform: %{},
+ language_variants: []
+ }},
+ {:error,
+ {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
+]
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_locale "en-GB"
-{:ok, Cldr.Calendar.GB}
+{:ok, Cldr.Calendar.GB}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_locale "en-GB-u-ca-gregory"
-{:ok, Cldr.Calendar.Gregorian}
+{:ok, Cldr.Calendar.Gregorian}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_locale "en"
-{:ok, Cldr.Calendar.US}
+{:ok, Cldr.Calendar.US}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_locale "fa-IR"
-{:ok, Cldr.Calendar.Persian}
+{:ok, Cldr.Calendar.Persian}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_territory :US
-{:ok, Cldr.Calendar.Gregorian}
+{:ok, Cldr.Calendar.Gregorian}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_territory :XX
-{:error, {Cldr.UnknownTerritoryError, "The territory :XX is unknown"}}
notes
@@ -583,19 +583,19 @@iex: MyApp.Cldr.Calendar.strftime_options!
-[
- am_pm_names: #Function<0.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>,
- month_names: #Function<1.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>,
- abbreviated_month_names: #Function<2.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>,
- day_of_week_names: #Function<3.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>,
- abbreviated_day_of_week_names: #Function<4.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>
-]
typical-usage
Typical usageiex: NimbleStrftime.format(Date.today(), MyApp.Cldr.Calendar.strftime_options!())
+iex: NimbleStrftime.format(Date.today(), MyApp.Cldr.Calendar.strftime_options!())
MyApp.Cldr.Currency.currencies_for_locale "en" => {:ok, - %{
FJD: %Cldr.Currency{
+ %{ FJD: %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "FJD",
- count: %{one: "Fijian dollar", other: "Fijian dollars"},
+ count: %{one: "Fijian dollar", other: "Fijian dollars"},
digits: 2,
from: nil,
iso_digits: 2,
@@ -406,12 +406,12 @@ currencies_for_locale(locale, only \\ :all,
symbol: "FJD",
tender: true,
to: nil
- },
- SUR: %Cldr.Currency{
+ },
+ SUR: %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "SUR",
- count: %{one: "Soviet rouble", other: "Soviet roubles"},
+ count: %{one: "Soviet rouble", other: "Soviet roubles"},
digits: 2,
from: nil,
iso_digits: nil,
@@ -421,7 +421,7 @@ currencies_for_locale(locale, only \\ :all,
symbol: "SUR",
tender: true,
to: nil
- },
+ },
...
}}
@@ -472,11 +472,11 @@ currencies_for_locale!(locale, only \\ :all
Example
MyApp.Cldr.Currency.currencies_for_locale! "en"
- => %{
FJD: %Cldr.Currency{
+ => %{FJD: %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "FJD",
- count: %{one: "Fijian dollar", other: "Fijian dollars"},
+ count: %{one: "Fijian dollar", other: "Fijian dollars"},
digits: 2,
from: nil,
iso_digits: 2,
@@ -486,12 +486,12 @@ currencies_for_locale!(locale, only \\ :all
symbol: "FJD",
tender: true,
to: nil
-},
-SUR: %Cldr.Currency{
+},
+SUR: %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "SUR",
- count: %{one: "Soviet rouble", other: "Soviet roubles"},
+ count: %{one: "Soviet rouble", other: "Soviet roubles"},
digits: 2,
from: nil,
iso_digits: nil,
@@ -501,7 +501,7 @@ currencies_for_locale!(locale, only \\ :all
symbol: "SUR",
tender: true,
to: nil
-},
+},
...
}
@@ -559,13 +559,13 @@ currency_for_code(currency_or_currency_code
Examples
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code("AUD")
-{:ok,
- %Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code("AUD")
+{:ok,
+ %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "AUD",
- count: %{one: "Australian dollar", other: "Australian dollars"},
+ count: %{one: "Australian dollar", other: "Australian dollars"},
digits: 2,
iso_digits: 2,
name: "Australian Dollar",
@@ -573,15 +573,15 @@ currency_for_code(currency_or_currency_code
rounding: 0,
symbol: "A$",
tender: true
-}}
+}}
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code("THB")
-{:ok,
- %Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code("THB")
+{:ok,
+ %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "THB",
- count: %{one: "Thai baht", other: "Thai baht"},
+ count: %{one: "Thai baht", other: "Thai baht"},
digits: 2,
iso_digits: 2,
name: "Thai Baht",
@@ -589,7 +589,7 @@ currency_for_code(currency_or_currency_code
rounding: 0,
symbol: "THB",
tender: true
-}}
+}}
@@ -648,12 +648,12 @@ currency_for_code!(currency_or_currency_cod
Examples
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code!("AUD")
-%Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code!("AUD")
+%Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "AUD",
- count: %{one: "Australian dollar", other: "Australian dollars"},
+ count: %{one: "Australian dollar", other: "Australian dollars"},
digits: 2,
iso_digits: 2,
name: "Australian Dollar",
@@ -661,14 +661,14 @@ currency_for_code!(currency_or_currency_cod
rounding: 0,
symbol: "A$",
tender: true
-}
+}
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code!("THB")
-%Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code!("THB")
+%Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "THB",
- count: %{one: "Thai baht", other: "Thai baht"},
+ count: %{one: "Thai baht", other: "Thai baht"},
digits: 2,
iso_digits: 2,
name: "Thai Baht",
@@ -676,7 +676,7 @@ currency_for_code!(currency_or_currency_cod
rounding: 0,
symbol: "THB",
tender: true
-}
+}
@@ -717,11 +717,11 @@ currency_from_locale(locale)
Examples
-iex> {:ok, locale} = Bonfire.Common.Localise.Cldr.validate_locale "en"
+iex> {:ok, locale} = Bonfire.Common.Localise.Cldr.validate_locale "en"
iex> Bonfire.Common.Localise.Cldr.Currency.currency_from_locale locale
:USD
-iex> {:ok, locale} = Bonfire.Common.Localise.Cldr.validate_locale "en-AU"
+iex> {:ok, locale} = Bonfire.Common.Localise.Cldr.validate_locale "en-AU"
iex> Bonfire.Common.Localise.Cldr.Currency.currency_from_locale locale
:AUD
@@ -770,13 +770,13 @@ currency_history_for_locale(language_tag)
Example
iex> MyApp.Cldr.Currency.currency_history_for_locale "en"
-{:ok,
- %{
- USD: %{from: ~D[1792-01-01], to: nil},
- USN: %{tender: false},
- USS: %{from: nil, tender: false, to: ~D[2014-03-01]}
- }
-}
+
{:ok,
+ %{
+ USD: %{from: ~D[1792-01-01], to: nil},
+ USN: %{tender: false},
+ USS: %{from: nil, tender: false, to: ~D[2014-03-01]}
+ }
+}
@@ -836,8 +836,8 @@ currency_strings(locale, only \\ :all, exce
Example
MyApp.Cldr.Currency.currency_strings "en"
-=> {:ok,
- %{
+=> {:ok,
+ %{
"mexican silver pesos" => :MXP,
"sudanese dinar" => :SDD,
"bad" => :BAD,
@@ -847,7 +847,7 @@ currency_strings(locale, only \\ :all, exce
"guyanaese dollars" => :GYD,
"equatorial guinean ekwele" => :GQE,
...
- }}
+
}}
@@ -907,7 +907,7 @@ currency_strings!(locale_name, only \\ :all
Example
MyApp.Cldr.Currency.currency_strings! "en"
-=> %{
+=> %{
"mexican silver pesos" => :MXP,
"sudanese dinar" => :SDD,
"bad" => :BAD,
@@ -917,7 +917,7 @@ currency_strings!(locale_name, only \\ :all
"guyanaese dollars" => :GYD,
"equatorial guinean ekwele" => :GQE,
...
- }
+
}
iex> Bonfire.Common.Localise.Cldr.Currency.current_territory_currencies()
+iex> Bonfire.Common.Localise.Cldr.Currency.current_territory_currencies()
iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code "AUD"
-{:ok, :AUD}
+{:ok, :AUD}
iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code "GGG"
-{:error, {Cldr.UnknownCurrencyError, "The currency \"GGG\" is invalid"}}
+{:error, {Cldr.UnknownCurrencyError, "The currency \"GGG\" is invalid"}}
iex> Bonfire.Common.Localise.Cldr.Currency.new(:XAE, name: "Custom Name", digits: 0)
-{:ok,
- %Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.new(:XAE, name: "Custom Name", digits: 0)
+{:ok,
+ %Cldr.Currency{
alt_code: :XAE,
cash_digits: 0,
cash_rounding: nil,
code: :XAE,
- count: %{other: "Custom Name"},
+ count: %{other: "Custom Name"},
digits: 0,
from: nil,
iso_digits: 0,
@@ -1266,11 +1266,11 @@ new(currency, options \\ [])
symbol: "XAE",
tender: false,
to: nil
- }}
-iex> MyApp.Cldr.Currency.new(:XAH, name: "Custom Name")
-{:error, "Required options are missing. Required options are [:name, :digits]"}
-iex> Bonfire.Common.Localise.Cldr.Currency.new(:XAE, name: "XAE", digits: 0)
-{:error, {Cldr.CurrencyAlreadyDefined, "Currency :XAE is already defined."}}
+ }}
+iex> MyApp.Cldr.Currency.new(:XAH, name: "Custom Name")
+{:error, "Required options are missing. Required options are [:name, :digits]"}
+iex> Bonfire.Common.Localise.Cldr.Currency.new(:XAE, name: "XAE", digits: 0)
+{:error, {Cldr.CurrencyAlreadyDefined, "Currency :XAE is already defined."}}
iex> Bonfire.Common.Localise.Cldr.Currency.pluralize 1, :USD
-{:ok, "US dollar"}
+{:ok, "US dollar"}
iex> Bonfire.Common.Localise.Cldr.Currency.pluralize 3, :USD
-{:ok, "US dollars"}
+{:ok, "US dollars"}
iex> Bonfire.Common.Localise.Cldr.Currency.pluralize 12, :USD, locale: "zh"
-{:ok, "美元"}
+{:ok, "美元"}
iex> Bonfire.Common.Localise.Cldr.Currency.pluralize 12, :USD, locale: "fr"
-{:ok, "dollars des États-Unis"}
+{:ok, "dollars des États-Unis"}
iex> Bonfire.Common.Localise.Cldr.Currency.pluralize 1, :USD, locale: "fr"
-{:ok, "dollar des États-Unis"}
+{:ok, "dollar des États-Unis"}
iex> MyApp.Cldr.Currency.strings_for_currency :AUD, "en"
-["a$", "australian dollars", "aud", "australian dollar"]
+["a$", "australian dollars", "aud", "australian dollar"]
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-12-31]
-{:ok, "Jan 1 – Dec 31, 2020"}
+{:ok, "Jan 1 – Dec 31, 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12]
-{:ok, "Jan 1 – 12, 2020"}
+{:ok, "Jan 1 – 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :long
-{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
+{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-12-01],
...> format: :long, style: :year_and_month
-{:ok, "January – December 2020"}
+{:ok, "January – December 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :short
-{:ok, "1/1/2020 – 1/12/2020"}
+{:ok, "1/1/2020 – 1/12/2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :long, locale: "fr"
-{:ok, "mer. 1 – dim. 12 janv. 2020"}
+{:ok, "mer. 1 – dim. 12 janv. 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :long, locale: "th", number_system: :thai
-{:ok, "พ. ๑ ม.ค. – อา. ๑๒ ม.ค. ๒๐๒๐"}
+{:ok, "พ. ๑ ม.ค. – อา. ๑๒ ม.ค. ๒๐๒๐"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-12-31])
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-12-31])
"Jan 1 – Dec 31, 2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12])
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12])
"Jan 1 – 12, 2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
...> format: :long
"Wed, Jan 1 – Sun, Jan 12, 2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-12-01]),
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-12-01]),
...> format: :long, style: :year_and_month
"January – December 2020"
@@ -391,11 +391,11 @@ to_string!(from, to, options)
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! ~I"2020-01/12"
"Jan 1 – Dec 31, 2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
...> format: :short
"1/1/2020 – 1/12/2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
...> format: :long, locale: "fr"
"mer. 1 – dim. 12 janv. 2020"
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :medium, locale: "en"
-{:ok, "Jul 10, 2017"}
+{:ok, "Jul 10, 2017"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], locale: "en"
-{:ok, "Jul 10, 2017"}
+{:ok, "Jul 10, 2017"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :full, locale: "en"
-{:ok, "Monday, July 10, 2017"}
+{:ok, "Monday, July 10, 2017"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :short, locale: "en"
-{:ok, "7/10/17"}
+{:ok, "7/10/17"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :short, locale: "fr"
-{:ok, "10/07/2017"}
+{:ok, "10/07/2017"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :long, locale: "af"
-{:ok, "10 Julie 2017"}
+{:ok, "10 Julie 2017"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.calendars_for "en"
-{:ok, [:buddhist, :chinese, :coptic, :dangi, :ethiopic, :ethiopic_amete_alem,
+{:ok, [:buddhist, :chinese, :coptic, :dangi, :ethiopic, :ethiopic_amete_alem,
:generic, :gregorian, :hebrew, :indian, :islamic, :islamic_civil,
- :islamic_rgsa, :islamic_tbla, :islamic_umalqura, :japanese, :persian, :roc]}
+ :islamic_rgsa, :islamic_tbla, :islamic_umalqura, :japanese, :persian, :roc]}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_formats "en"
-{:ok, %Cldr.Date.Styles{
+{:ok, %Cldr.Date.Styles{
full: "EEEE, MMMM d, y",
long: "MMMM d, y",
medium: "MMM d, y",
short: "M/d/yy"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_formats "en", :buddhist
-{:ok, %Cldr.Date.Styles{
+{:ok, %Cldr.Date.Styles{
full: "EEEE, MMMM d, y G",
long: "MMMM d, y G",
medium: "MMM d, y G",
short: "M/d/y GGGGG"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_available_formats "en"
-{
+{
:ok,
- %{
+ %{
d: "d",
h: "h a",
hm: "h:mm a",
@@ -535,7 +535,7 @@ date_time_available_formats(locale \\ Bonfi
hmv: "h:mm a v",
ms: "mm:ss",
y: "y",
- yw: %{one: "'week' w 'of' Y", other: "'week' w 'of' Y"},
+ yw: %{one: "'week' w 'of' Y", other: "'week' w 'of' Y"},
Bh: "h B",
Bhm: "h:mm B",
Bhms: "h:mm:ss B",
@@ -561,7 +561,7 @@ date_time_available_formats(locale \\ Bonfi
MEd: "E, M/d",
MMM: "LLL",
MMMEd: "E, MMM d",
- MMMMW: %{one: "'week' W 'of' MMMM", other: "'week' W 'of' MMMM"},
+ MMMMW: %{one: "'week' W 'of' MMMM", other: "'week' W 'of' MMMM"},
MMMMd: "MMMM d",
MMMd: "MMM d",
Md: "M/d",
@@ -574,8 +574,8 @@ date_time_available_formats(locale \\ Bonfi
yMd: "M/d/y",
yQQQ: "QQQ y",
yQQQQ: "QQQQ y"
- }
-}
+ }
+}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_formats "en"
-{:ok, %Cldr.DateTime.Styles{
+{:ok, %Cldr.DateTime.Styles{
full: "{1}, {0}",
long: "{1}, {0}",
medium: "{1}, {0}",
short: "{1}, {0}"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_formats "en", :buddhist
-{:ok, %Cldr.DateTime.Styles{
+{:ok, %Cldr.DateTime.Styles{
full: "{1}, {0}",
long: "{1}, {0}",
medium: "{1}, {0}",
short: "{1}, {0}"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_interval_fallback "en", :gregorian
-[0, " – ", 1]
+[0, " – ", 1]
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.gmt_format "en"
-{:ok, ["GMT", 0]}
+{:ok, ["GMT", 0]}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.gmt_zero_format :en
-{:ok, "GMT"}
+{:ok, "GMT"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.gmt_zero_format "fr"
-{:ok, "UTC"}
+{:ok, "UTC"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.hour_format "en"
-{:ok, {"+HH:mm", "-HH:mm"}}
+{:ok, {"+HH:mm", "-HH:mm"}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.time_formats "en"
-{:ok, %Cldr.Time.Styles{
+{:ok, %Cldr.Time.Styles{
full: "h:mm:ss a zzzz",
long: "h:mm:ss a z",
medium: "h:mm:ss a",
short: "h:mm a"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.time_formats "en", :buddhist
-{:ok, %Cldr.Time.Styles{
+{:ok, %Cldr.Time.Styles{
full: "h:mm:ss a zzzz",
long: "h:mm:ss a z",
medium: "h:mm:ss a",
short: "h:mm a"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Formatter.format ~U[2017-09-03 10:23:00.0Z], "yy/MM/dd hh:MM", "en"
-{:ok, "17/09/03 10:09"}
+{:ok, "17/09/03 10:09"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Interval.to_string ~U[2020-01-01 00:00:00.0Z],
...> ~U[2020-12-31 10:00:00.0Z]
-{:ok, "Jan 1, 2020, 12:00:00 AM – Dec 31, 2020, 10:00:00 AM"}
+{:ok, "Jan 1, 2020, 12:00:00 AM – Dec 31, 2020, 10:00:00 AM"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Interval.to_string ~U[2020-01-01 00:00:00.0Z], nil
-{:ok, "Jan 1, 2020, 12:00:00 AM –"}
+{:ok, "Jan 1, 2020, 12:00:00 AM –"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(-1)
-{:ok, "1 second ago"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(-1)
+{:ok, "1 second ago"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1)
-{:ok, "in 1 second"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1)
+{:ok, "in 1 second"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day)
-{:ok, "tomorrow"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day)
+{:ok, "tomorrow"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day, locale: "fr")
-{:ok, "demain"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day, locale: "fr")
+{:ok, "demain"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day, style: :narrow)
-{:ok, "tomorrow"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day, style: :narrow)
+{:ok, "tomorrow"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1234, unit: :year)
-{:ok, "in 1,234 years"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1234, unit: :year)
+{:ok, "in 1,234 years"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1234, unit: :year, locale: "fr")
-{:ok, "dans 1 234 ans"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1234, unit: :year, locale: "fr")
+{:ok, "dans 1 234 ans"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(31)
-{:ok, "in 31 seconds"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(31)
+{:ok, "in 31 seconds"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(~D[2017-04-29], relative_to: ~D[2017-04-26])
-{:ok, "in 3 days"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(~D[2017-04-29], relative_to: ~D[2017-04-26])
+{:ok, "in 3 days"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(310, style: :short, locale: "fr")
-{:ok, "dans 5 min"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(310, style: :short, locale: "fr")
+{:ok, "dans 5 min"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(310, style: :narrow, locale: "fr")
-{:ok, "+5 min"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(310, style: :narrow, locale: "fr")
+{:ok, "+5 min"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string 2, unit: :wed, style: :short, locale: "en"
-{:ok, "in 2 Wed."}
+{:ok, "in 2 Wed."}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string 1, unit: :wed, style: :short
-{:ok, "next Wed."}
+{:ok, "next Wed."}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string -1, unit: :wed, style: :short
-{:ok, "last Wed."}
+{:ok, "last Wed."}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string -1, unit: :wed
-{:ok, "last Wednesday"}
+{:ok, "last Wednesday"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string -1, unit: :quarter
-{:ok, "last quarter"}
+{:ok, "last quarter"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string -1, unit: :mon, locale: "fr"
-{:ok, "lundi dernier"}
+{:ok, "lundi dernier"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(~D[2017-04-29], unit: :ziggeraut)
-{:error, {Cldr.UnknownTimeUnit,
- "Unknown time unit :ziggeraut. Valid time units are [:day, :hour, :minute, :month, :second, :week, :year, :mon, :tue, :wed, :thu, :fri, :sat, :sun, :quarter]"}}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(~D[2017-04-29], unit: :ziggeraut)
+{:error, {Cldr.UnknownTimeUnit,
+ "Unknown time unit :ziggeraut. Valid time units are [:day, :hour, :minute, :month, :second, :week, :year, :mon, :tue, :wed, :thu, :fri, :sat, :sun, :quarter]"}}
iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
+iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime
-{:ok, "Jan 1, 2000, 11:59:59 PM"}
+{:ok, "Jan 1, 2000, 11:59:59 PM"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, locale: "en"
-{:ok, "Jan 1, 2000, 11:59:59 PM"}
+{:ok, "Jan 1, 2000, 11:59:59 PM"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, format: :long, locale: "en"
-{:ok, "January 1, 2000, 11:59:59 PM UTC"}
+{:ok, "January 1, 2000, 11:59:59 PM UTC"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, format: :hms, locale: "en"
-{:ok, "11:59:59 PM"}
+{:ok, "11:59:59 PM"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, format: :full, locale: "en"
-{:ok, "Saturday, January 1, 2000, 11:59:59 PM GMT"}
+{:ok, "Saturday, January 1, 2000, 11:59:59 PM GMT"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, format: :full, locale: "fr"
-{:ok, "samedi 1 janvier 2000, 23:59:59 UTC"}
+{:ok, "samedi 1 janvier 2000, 23:59:59 UTC"}
iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
+iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string! datetime, locale: "en"
"Jan 1, 2000, 11:59:59 PM"
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string! datetime, format: :long, locale: "en"
diff --git a/Bonfire.Common.Localise.Cldr.Interval.html b/Bonfire.Common.Localise.Cldr.Interval.html
index 5c4288fcc68..8eaf9d82d9f 100644
--- a/Bonfire.Common.Localise.Cldr.Interval.html
+++ b/Bonfire.Common.Localise.Cldr.Interval.html
@@ -284,11 +284,11 @@ to_string(interval, options)
iex> use CalendarInterval
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~I"2020-01-01/12",
...> format: :long
-{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
+{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
-iex> Bonfire.Common.Localise.Cldr.Interval.to_string Date.range(~D[2020-01-01], ~D[2020-12-31]),
+iex> Bonfire.Common.Localise.Cldr.Interval.to_string Date.range(~D[2020-01-01], ~D[2020-12-31]),
...> format: :long
-{:ok, "Wed, Jan 1 – Thu, Dec 31, 2020"}
+{:ok, "Wed, Jan 1 – Thu, Dec 31, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-12-31]
-{:ok, "Jan 1 – Dec 31, 2020"}
+{:ok, "Jan 1 – Dec 31, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-01-12]
-{:ok, "Jan 1 – 12, 2020"}
+{:ok, "Jan 1 – 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :long
-{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
+{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-12-01],
...> format: :long, style: :year_and_month
-{:ok, "January – December 2020"}
+{:ok, "January – December 2020"}
iex> use CalendarInterval
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~I"2020-01-01/12",
...> format: :long
-{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
+{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-12-01 10:05:00.0Z],
...> format: :long
-{:ok, "January 1, 2020, 12:00:00 AM UTC – December 1, 2020, 10:05:00 AM UTC"}
+{:ok, "January 1, 2020, 12:00:00 AM UTC – December 1, 2020, 10:05:00 AM UTC"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-01-01 10:05:00.0Z],
...> format: :long
-{:ok, "January 1, 2020, 12:00:00 AM UTC – 10:05:00 AM UTC"}
+{:ok, "January 1, 2020, 12:00:00 AM UTC – 10:05:00 AM UTC"}
> Bonfire.Common.Localise.Cldr.Language.Language.available_languages(:en)
-["aa", "ab", "ace", "ach", "ada", "ady", "ae", "aeb", "af", "afh", "agq", "ain",
+> Bonfire.Common.Localise.Cldr.Language.Language.available_languages(:en)
+["aa", "ab", "ace", "ach", "ada", "ady", "ae", "aeb", "af", "afh", "agq", "ain",
"ak", "akk", "akz", "ale", "aln", "alt", "am", "an", "ang", "anp", "ar",
"ar-001", "arc", "arn", "aro", "arp", "arq", "ars", "arw", "ary", "arz", "as",
"asa", "ase", "ast", "av", "avk", "awa", "ay", "az", "ba", "bal", "ban", "bar",
-"bas", "bax", "bbc", "bbj", ...]
+"bas", "bax", "bbc", "bbj", ...]
> Bonfire.Common.Localise.Cldr.Language.Language.known_languages(:en)
-%{"bez" => %{standard: "Bena"}, "lo" => %{standard: "Lao"},
-"kha" => %{standard: "Khasi"}, "eo" => %{standard: "Esperanto"},
-"rm" => %{standard: "Romansh"}, "ja" => %{standard: "Japanese"},
-"sw-CD" => %{standard: "Congo Swahili"},
-"pdc" => %{standard: "Pennsylvania German"}, "om" => %{standard: "Oromo"},
-"jut" => %{standard: "Jutish"}, "lij" => %{standard: "Ligurian"},
-"kut" => %{standard: "Kutenai"}, "vep" => %{standard: "Veps"},
-"yao" => %{standard: "Yao"}, "gez" => %{standard: "Geez"},
-"cr" => %{standard: "Cree"}, "ne" => %{standard: "Nepali"},
-"zbl" => %{standard: "Blissymbols"}, "ae" => %{standard: "Avestan"},
-"rof" => %{standard: "Rombo"}, "tkl" => %{standard: "Tokelau"},
-"rgn" => %{standard: "Romagnol"}, "el" => %{standard: "Greek"},
-"myv" => %{standard: "Erzya"}, "smj" => %{standard: "Lule Sami"},
-"fo" => %{standard: "Faroese"}, "ii" => %{standard: "Sichuan Yi"},
-"bum" => %{standard: "Bulu"}, "za" => %{standard: "Zhuang"},
-"raj" => %{standard: "Rajasthani"}, "mrj" => %{standard: "Western Mari"},
-"stq" => %{standard: "Saterland Frisian"}, "hu" => %{standard: "Hungarian"},
-"mga" => %{standard: "Middle Irish"}, "bej" => %{standard: "Beja"},
-"yue" => %{standard: "Cantonese"}, "xog" => %{standard: "Soga"},
-"ttt" => %{standard: "Muslim Tat"}, "uga" => %{standard: "Ugaritic"},
-"rup" => %{standard: "Aromanian"},
-"crs" => %{standard: "Seselwa Creole French"}, "oc" => %{standard: "Occitan"},
-"chp" => %{standard: "Chipewyan"}, "zen" => %{standard: "Zenaga"},
-"kmb" => %{standard: "Kimbundu"}, "nr" => %{standard: "South Ndebele"},
-"tiv" => %{standard: "Tiv"}, "aln" => %{standard: "Gheg Albanian"},
-"sh" => %{standard: "Serbo-Croatian"}, "fil" => %{...}, ...}
+> Bonfire.Common.Localise.Cldr.Language.Language.known_languages(:en)
+%{"bez" => %{standard: "Bena"}, "lo" => %{standard: "Lao"},
+"kha" => %{standard: "Khasi"}, "eo" => %{standard: "Esperanto"},
+"rm" => %{standard: "Romansh"}, "ja" => %{standard: "Japanese"},
+"sw-CD" => %{standard: "Congo Swahili"},
+"pdc" => %{standard: "Pennsylvania German"}, "om" => %{standard: "Oromo"},
+"jut" => %{standard: "Jutish"}, "lij" => %{standard: "Ligurian"},
+"kut" => %{standard: "Kutenai"}, "vep" => %{standard: "Veps"},
+"yao" => %{standard: "Yao"}, "gez" => %{standard: "Geez"},
+"cr" => %{standard: "Cree"}, "ne" => %{standard: "Nepali"},
+"zbl" => %{standard: "Blissymbols"}, "ae" => %{standard: "Avestan"},
+"rof" => %{standard: "Rombo"}, "tkl" => %{standard: "Tokelau"},
+"rgn" => %{standard: "Romagnol"}, "el" => %{standard: "Greek"},
+"myv" => %{standard: "Erzya"}, "smj" => %{standard: "Lule Sami"},
+"fo" => %{standard: "Faroese"}, "ii" => %{standard: "Sichuan Yi"},
+"bum" => %{standard: "Bulu"}, "za" => %{standard: "Zhuang"},
+"raj" => %{standard: "Rajasthani"}, "mrj" => %{standard: "Western Mari"},
+"stq" => %{standard: "Saterland Frisian"}, "hu" => %{standard: "Hungarian"},
+"mga" => %{standard: "Middle Irish"}, "bej" => %{standard: "Beja"},
+"yue" => %{standard: "Cantonese"}, "xog" => %{standard: "Soga"},
+"ttt" => %{standard: "Muslim Tat"}, "uga" => %{standard: "Ugaritic"},
+"rup" => %{standard: "Aromanian"},
+"crs" => %{standard: "Seselwa Creole French"}, "oc" => %{standard: "Occitan"},
+"chp" => %{standard: "Chipewyan"}, "zen" => %{standard: "Zenaga"},
+"kmb" => %{standard: "Kimbundu"}, "nr" => %{standard: "South Ndebele"},
+"tiv" => %{standard: "Tiv"}, "aln" => %{standard: "Gheg Albanian"},
+"sh" => %{standard: "Serbo-Croatian"}, "fil" => %{...}, ...}
iex> Bonfire.Common.Localise.Cldr.Language.Language.to_string("eo")
-{:ok, "Esperanto"}
+iex> Bonfire.Common.Localise.Cldr.Language.Language.to_string("eo")
+{:ok, "Esperanto"}
iex> Bonfire.Common.Localise.Cldr.Locale.fallback_locale_names(:"fr-CA")
-{:ok, [:"fr-CA", :fr, :und]}
+iex> Bonfire.Common.Localise.Cldr.Locale.fallback_locale_names(:"fr-CA")
+{:ok, [:"fr-CA", :fr, :und]}
# Fallbacks are typically formed by progressively
# stripping variant, territory and script from the
# given locale name. But not always - there are
# certain fallbacks that take a different path.
-iex> Bonfire.Common.Localise.Cldr.Locale.fallback_locale_names(:nb)
-{:ok, [:nb, :no, :und]}
+iex> Bonfire.Common.Localise.Cldr.Locale.fallback_locale_names(:nb)
+{:ok, [:nb, :no, :und]}
Bonfire.Common.Localise.Cldr.Locale.fallback_locales(:"fr-CA")
-=> {:ok,
- [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
- #Cldr.LanguageTag<und [validated]>]}
+Bonfire.Common.Localise.Cldr.Locale.fallback_locales(:"fr-CA")
+=> {:ok,
+ [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
+ #Cldr.LanguageTag<und [validated]>]}
# Fallbacks are typically formed by progressively
# stripping variant, territory and script from the
# given locale name. But not always - there are
# certain fallbacks that take a different path.
-Bonfire.Common.Localise.Cldr.Locale.fallback_locales(:nb))
-=> {:ok,
- [#Cldr.LanguageTag<nb [validated]>, #Cldr.LanguageTag<no [validated]>,
- #Cldr.LanguageTag<und [validated]>]}
+Bonfire.Common.Localise.Cldr.Locale.fallback_locales(:nb))
+=> {:ok,
+ [#Cldr.LanguageTag<nb [validated]>, #Cldr.LanguageTag<no [validated]>,
+ #Cldr.LanguageTag<und [validated]>]}
iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host "a.b.com.au"
-Elixir.Bonfire.Common.Localise.Cldr.validate_locale(:"en-AU")
+Elixir.Bonfire.Common.Localise.Cldr.validate_locale(:"en-AU")
-iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host("a.b.com.tv")
-{:error,
- {Cldr.UnknownLocaleError, "No locale was identified for territory \"tv\""}}
+iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host("a.b.com.tv")
+{:error,
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \"tv\""}}
-iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host("a.b.com")
-{:error,
- {Cldr.UnknownLocaleError, "No locale was identified for territory \"com\""}}
+iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host("a.b.com")
+{:error,
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \"com\""}}
iex> Cldr.Locale.territory_from_host("a.b.com.au")
-{:ok, :AU}
+iex> Cldr.Locale.territory_from_host("a.b.com.au")
+{:ok, :AU}
-iex> Cldr.Locale.territory_from_host("a.b.com")
-{:error,
- {Cldr.UnknownLocaleError, "No locale was identified for territory \"com\""}}
+iex> Cldr.Locale.territory_from_host("a.b.com")
+{:error,
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \"com\""}}
iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1, "en", %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1, "en", %{one: "one"}
"one"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 2, "en", %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 2, "en", %{one: "one"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 2, "en", %{one: "one", two: "two", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 2, "en", %{one: "one", two: "two", other: "other"}
"other"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 22, "en", %{one: "one", two: "two", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 22, "en", %{one: "one", two: "two", other: "other"}
"other"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(1), "en", %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(1), "en", %{one: "one"}
"one"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(2), "en", %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(2), "en", %{one: "one"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(2), "en", %{one: "one", two: "two"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(2), "en", %{one: "one", two: "two"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
"few"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1..10, "en", %{one: "one", few: "few", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1..10, "en", %{one: "one", few: "few", other: "other"}
"other"
#=> Bonfire.Common.Localise.Cldr.Number.Format.Format.decimal_format_list
-["#", "#,##,##0%",
+["#", "#,##,##0%",
"#,##,##0.###", "#,##,##0.00¤", "#,##,##0.00¤;(#,##,##0.00¤)",
"#,##,##0 %", "#,##0%", "#,##0.###", "#,##0.00 ¤",
"#,##0.00 ¤;(#,##0.00 ¤)", "#,##0.00¤", "#,##0.00¤;(#,##0.00¤)",
@@ -451,7 +451,7 @@ decimal_format_list()
"000 B ¤", "000 E ¤", "000 K ¤", "000 MRD ¤", "000 Md ¤", "000 Mio'.' ¤",
"000 Mio ¤", "000 Mld ¤", "000 Mln ¤", "000 Mn ¤", "000 Mrd'.' ¤",
"000 Mrd ¤", "000 Mr ¤", "000 M ¤", "000 NT ¤", "000 N ¤", "000 Tn ¤",
-"000 Tr ¤", ...]
+"000 Tr ¤", ...]
iex> Bonfire.Common.Localise.Cldr.Number.Format.decimal_format_list_for(:en)
-{:ok, ["#,##0%", "#,##0.###", "#,##0.00", "#,##0.00;(#,##0.00)","#E0",
+iex> Bonfire.Common.Localise.Cldr.Number.Format.decimal_format_list_for(:en)
+{:ok, ["#,##0%", "#,##0.###", "#,##0.00", "#,##0.00;(#,##0.00)","#E0",
"0 billion", "0 million", "0 thousand",
"0 trillion", "00 billion", "00 million", "00 thousand", "00 trillion",
"000 billion", "000 million", "000 thousand", "000 trillion", "000B", "000K",
@@ -508,7 +508,7 @@ decimal_format_list_for(locale \\ Bonfire.C
"¤#,##0.00", "¤#,##0.00;(¤#,##0.00)", "¤000B", "¤000K", "¤000M",
"¤000T", "¤00B", "¤00K", "¤00M", "¤00T", "¤0B", "¤0K", "¤0M", "¤0T",
"¤ #,##0.00", "¤ #,##0.00;(¤ #,##0.00)", "¤ 000B", "¤ 000K", "¤ 000M",
- "¤ 000T", "¤ 00B", "¤ 00K", "¤ 00M", "¤ 00T", "¤ 0B", "¤ 0K", "¤ 0M", "¤ 0T"]}
+ "¤ 000T", "¤ 00B", "¤ 00K", "¤ 00M", "¤ 00T", "¤ 0B", "¤ 0K", "¤ 0M", "¤ 0T"]}
iex> Bonfire.Common.Localise.Cldr.Number.Format.default_grouping_for(:en)
-{:ok, %{fraction: %{first: 0, rest: 0}, integer: %{first: 3, rest: 3}}}
+iex> Bonfire.Common.Localise.Cldr.Number.Format.default_grouping_for(:en)
+{:ok, %{fraction: %{first: 0, rest: 0}, integer: %{first: 3, rest: 3}}}
iex> Bonfire.Common.Localise.Cldr.Number.Format.default_grouping_for!(:en)
-%{fraction: %{first: 0, rest: 0}, integer: %{first: 3, rest: 3}}
+iex> Bonfire.Common.Localise.Cldr.Number.Format.default_grouping_for!(:en)
+%{fraction: %{first: 0, rest: 0}, integer: %{first: 3, rest: 3}}
iex> Bonfire.Common.Localise.Cldr.Number.Format.minimum_grouping_digits_for("en")
-{:ok, 1}
+iex> Bonfire.Common.Localise.Cldr.Number.Format.minimum_grouping_digits_for("en")
+{:ok, 1}
iex> Bonfire.Common.Localise.Cldr.Number.Format.minimum_grouping_digits_for!("en")
+iex> Bonfire.Common.Localise.Cldr.Number.Format.minimum_grouping_digits_for!("en")
1
iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1, :en, %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1, :en, %{one: "one"}
"one"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 2, :en, %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 2, :en, %{one: "one"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 2, :en, %{one: "one", two: "two"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 2, :en, %{one: "one", two: "two"}
"two"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 22, :en, %{one: "one", two: "two", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 22, :en, %{one: "one", two: "two", other: "other"}
"two"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(1), :en, %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(1), :en, %{one: "one"}
"one"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(2), :en, %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(2), :en, %{one: "one"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(2), :en, %{one: "one", two: "two"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(2), :en, %{one: "one", two: "two"}
"two"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
"other"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1..10, "en", %{one: "one", few: "few", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1..10, "en", %{one: "one", few: "few", other: "other"}
"other"
diff --git a/Bonfire.Common.Localise.Cldr.Number.Symbol.html b/Bonfire.Common.Localise.Cldr.Number.Symbol.html
index f205144e0c8..55a57a9ffd9 100644
--- a/Bonfire.Common.Localise.Cldr.Number.Symbol.html
+++ b/Bonfire.Common.Localise.Cldr.Number.Symbol.html
@@ -351,9 +351,9 @@ number_symbols_for(locale \\ Bonfire.Common
Example:
-iex> Bonfire.Common.Localise.Cldr.Number.Symbol.number_symbols_for(:th)
-{:ok, %{
- latn: %Cldr.Number.Symbol{
+iex> Bonfire.Common.Localise.Cldr.Number.Symbol.number_symbols_for(:th)
+{:ok, %{
+ latn: %Cldr.Number.Symbol{
decimal: ".",
exponential: "E",
group: ",",
@@ -366,8 +366,8 @@ number_symbols_for(locale \\ Bonfire.Common
plus_sign: "+",
superscripting_exponent: "×",
time_separator: ":"
- },
- thai: %Cldr.Number.Symbol{
+ },
+ thai: %Cldr.Number.Symbol{
decimal: ".",
exponential: "E",
group: ",",
@@ -380,8 +380,8 @@ number_symbols_for(locale \\ Bonfire.Common
plus_sign: "+",
superscripting_exponent: "×",
time_separator: ":"
- }
- }}
+ }
+ }}
diff --git a/Bonfire.Common.Localise.Cldr.Number.System.html b/Bonfire.Common.Localise.Cldr.Number.System.html
index 5b83656b9d3..fb92829ee51 100644
--- a/Bonfire.Common.Localise.Cldr.Number.System.html
+++ b/Bonfire.Common.Localise.Cldr.Number.System.html
@@ -290,23 +290,23 @@ number_system_for(locale, system_name)
Examples
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "th", :latn
-{:ok, %{digits: "0123456789", type: :numeric}}
+{:ok, %{digits: "0123456789", type: :numeric}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "en", :default
-{:ok, %{digits: "0123456789", type: :numeric}}
+{:ok, %{digits: "0123456789", type: :numeric}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "he", :traditional
-{:ok, %{rules: "hebrew", type: :algorithmic}}
+{:ok, %{rules: "hebrew", type: :algorithmic}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "en", :native
-{:ok, %{digits: "0123456789", type: :numeric}}
+{:ok, %{digits: "0123456789", type: :numeric}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "en", :finance
-{
+{
:error,
- {Cldr.UnknownNumberSystemError,
- "The number system :finance is unknown for the locale named :en. Valid number systems are %{default: :latn, native: :latn}"}
-}
+
{Cldr.UnknownNumberSystemError,
+ "The number system :finance is unknown for the locale named :en. Valid number systems are %{default: :latn, native: :latn}"}
+}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_names_for "en"
-{:ok, [:latn]}
+{:ok, [:latn]}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_names_for "zz"
-{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
+{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_systems_for "en"
-{:ok, %{default: :latn, native: :latn}}
+{:ok, %{default: :latn, native: :latn}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_systems_for "th"
-{:ok, %{default: :latn, native: :thai}}
+{:ok, %{default: :latn, native: :thai}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_systems_for "zz"
-{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
+{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
ex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:default, "en")
-{:ok, :latn}
+ex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:default, "en")
+{:ok, :latn}
-iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from("latn", "en")
-{:ok, :latn}
+iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from("latn", "en")
+{:ok, :latn}
-iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:native, "en")
-{:ok, :latn}
+iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:native, "en")
+{:ok, :latn}
-iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:nope, "en")
-{
+iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:nope, "en")
+{
:error,
- {Cldr.UnknownNumberSystemError, "The number system :nope is unknown"}
-}
Note that return value is not guaranteed to be a valid
+
{Cldr.UnknownNumberSystemError, "The number system :nope is unknown"}
+}
Note that return value is not guaranteed to be a valid number system for the given locale as demonstrated in the third example.
iex> Bonfire.Common.Localise.Cldr.Number.System.to_system 123456, :hebr
-{:ok, "קכ״ג׳תנ״ו"}
+{:ok, "קכ״ג׳תנ״ו"}
iex> Bonfire.Common.Localise.Cldr.Number.System.to_system 123, :hans
-{:ok, "一百二十三"}
+{:ok, "一百二十三"}
iex> Bonfire.Common.Localise.Cldr.Number.System.to_system 123, :hant
-{:ok, "一百二十三"}
+{:ok, "一百二十三"}
iex> Bonfire.Common.Localise.Cldr.Number.System.to_system 123, :hansfin
-{:ok, "壹佰贰拾叁"}
+{:ok, "壹佰贰拾叁"}
To configure these transliteration pairs, add the to the use Cldr
configuration
-in a backend module:
defmodule MyApp.Cldr do
+in a backend module:defmodule MyApp.Cldr do
use Cldr,
- locale: ["en", "fr", "th"],
+ locale: ["en", "fr", "th"],
default_locale: "en",
- precompile_transliterations: [{:latn, :thai}, {:arab, :thai}]
-end
Where each tuple in the list configures one transliteration map. In this example, two maps are
+
precompile_transliterations: [{:latn, :thai}, {:arab, :thai}]
+end
Where each tuple in the list configures one transliteration map. In this example, two maps are
configured: from :latn
to :thai
and from :arab
to :thai
.
A list of configurable number systems is returned by Cldr.Number.System.systems_with_digits/0
.
If a transliteration is requested between two number pairs that have not been configured for precompilation, a warning is logged.
iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556")
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556")
"123556"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123,556.000", "fr", :default)
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123,556.000", "fr", :default)
"123 556,000"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", :default)
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", :default)
"123556"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", "thai")
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", "thai")
"๑๒๓๕๕๖"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", :native)
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", :native)
"๑๒๓๕๕๖"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("Some number is: 123556", "th", "thai")
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("Some number is: 123556", "th", "thai")
"Some number is: ๑๒๓๕๕๖"
diff --git a/Bonfire.Common.Localise.Cldr.Number.html b/Bonfire.Common.Localise.Cldr.Number.html
index 85ac4cc27e7..1cadf647d6d 100644
--- a/Bonfire.Common.Localise.Cldr.Number.html
+++ b/Bonfire.Common.Localise.Cldr.Number.html
@@ -414,19 +414,19 @@ parse(string, options \\ [])
Examples
-iex> Bonfire.Common.Localise.Cldr.Number.parse("+1.000,34", locale: "de")
-{:ok, 1000.34}
+iex> Bonfire.Common.Localise.Cldr.Number.parse("+1.000,34", locale: "de")
+{:ok, 1000.34}
-iex> Bonfire.Common.Localise.Cldr.Number.parse("-1_000_000.34")
-{:ok, -1000000.34}
+iex> Bonfire.Common.Localise.Cldr.Number.parse("-1_000_000.34")
+{:ok, -1000000.34}
-iex> Bonfire.Common.Localise.Cldr.Number.parse("1.000", locale: "de", number: :integer)
-{:ok, 1000}
+iex> Bonfire.Common.Localise.Cldr.Number.parse("1.000", locale: "de", number: :integer)
+{:ok, 1000}
-iex> Bonfire.Common.Localise.Cldr.Number.parse("+1.000,34", locale: "de", number: :integer)
-{:error,
- {Cldr.Number.ParseError,
- "The string \"+1.000,34\" could not be parsed as a number"}}
+iex> Bonfire.Common.Localise.Cldr.Number.parse("+1.000,34", locale: "de", number: :integer)
+{:error,
+ {Cldr.Number.ParseError,
+ "The string \"+1.000,34\" could not be parsed as a number"}}
@@ -498,17 +498,17 @@ resolve_currencies(list, options \\ [])
Examples
-iex> Bonfire.Common.Localise.Cldr.Number.scan("100 US dollars")
+iex> Bonfire.Common.Localise.Cldr.Number.scan("100 US dollars")
...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies
-[100, :USD]
+[100, :USD]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("100 eurosports")
-...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies(fuzzy: 0.75)
-[100, :EUR]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("100 eurosports")
+...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies(fuzzy: 0.75)
+[100, :EUR]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("100 dollars des États-Unis")
-...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies(locale: "fr")
-[100, :USD]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("100 dollars des États-Unis")
+...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies(locale: "fr")
+[100, :USD]
@@ -585,19 +585,19 @@ resolve_currency(string, options \\ [])
Examples
-iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("US dollars")
-[:USD]
+iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("US dollars")
+[:USD]
-iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("100 eurosports", fuzzy: 0.75)
-[:EUR]
+iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("100 eurosports", fuzzy: 0.75)
+[:EUR]
-iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("dollars des États-Unis", locale: "fr")
-[:USD]
+iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("dollars des États-Unis", locale: "fr")
+[:USD]
-iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("not a known currency", locale: "fr")
-{:error,
- {Cldr.UnknownCurrencyError,
- "The currency \"not a known currency\" is unknown or not supported"}}
+iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("not a known currency", locale: "fr")
+{:error,
+ {Cldr.UnknownCurrencyError,
+ "The currency \"not a known currency\" is unknown or not supported"}}
@@ -661,13 +661,13 @@ resolve_per(string, options \\ [])
Examples
iex> Bonfire.Common.Localise.Cldr.Number.resolve_per "11%"
-["11", :percent]
+["11", :percent]
iex> Bonfire.Common.Localise.Cldr.Number.resolve_per "% of linguists"
-[:percent, " of linguists"]
+[:percent, " of linguists"]
iex> Bonfire.Common.Localise.Cldr.Number.resolve_per "% of linguists %"
-[:percent, " of linguists ", :percent]
+ [:percent, " of linguists ", :percent]
iex> Bonfire.Common.Localise.Cldr.Number.scan("100%")
-...> |> Bonfire.Common.Localise.Cldr.Number.resolve_pers()
-[100, :percent]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("100%")
+...> |> Bonfire.Common.Localise.Cldr.Number.resolve_pers()
+[100, :percent]
iex> Bonfire.Common.Localise.Cldr.Number.scan("£1_000_000.34")
-["£", 1000000.34]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("£1_000_000.34")
+["£", 1000000.34]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("I want £1_000_000 dollars")
-["I want £", 1000000, " dollars"]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("I want £1_000_000 dollars")
+["I want £", 1000000, " dollars"]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("The prize is 23")
-["The prize is ", 23]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("The prize is 23")
+["The prize is ", 23]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("The lottery number is 23 for the next draw")
-["The lottery number is ", 23, " for the next draw"]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("The lottery number is 23 for the next draw")
+["The lottery number is ", 23, " for the next draw"]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("The loss is -1.000 euros", locale: "de", number: :integer)
-["The loss is ", -1000, " euros"]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("The loss is -1.000 euros", locale: "de", number: :integer)
+["The loss is ", -1000, " euros"]
iex> Bonfire.Common.Localise.Cldr.Number.to_approx_string 1234
-{:ok, "~1,234"}
+{:ok, "~1,234"}
iex> Bonfire.Common.Localise.Cldr.Number.to_at_least_string 1234
-{:ok, "1,234+"}
+{:ok, "1,234+"}
iex> Bonfire.Common.Localise.Cldr.Number.to_at_most_string 1234
-{:ok, "≤1,234"}
+{:ok, "≤1,234"}
iex> Bonfire.Common.Localise.Cldr.Number.to_range_string 1234..5678
-{:ok, "1,234–5,678"}
+{:ok, "1,234–5,678"}
Wrapping elements is particularly useful when formatting a number with a currency symbol and the requirement is to have different HTML formatting -applied to the symbol than the number. For example:
iex> Cldr.Number.to_string(100, format: :currency, currency: :USD, wrapper: fn
+applied to the symbol than the number. For example:iex> Cldr.Number.to_string(100, format: :currency, currency: :USD, wrapper: fn
...> string, :currency_symbol -> "<span class=\"symbol\">" <> string <> "</span>"
...> string, :number -> "<span class=\"number\">" <> string <> "</span>"
...> string, :currency_space -> "<span>" <> string <> "</span>"
...> string, _other -> string
-...> end)
-{:ok, "<span class=\"symbol\">$</span><span class=\"number\">100.00</span>"}
It is also possible and recommended to use the Phoenix.HTML.Tag.content_tag/3
+
...> end)
+{:ok, "<span class=\"symbol\">$</span><span class=\"number\">100.00</span>"}
It is also possible and recommended to use the Phoenix.HTML.Tag.content_tag/3
function if wrapping HTML tags since these will ensure HTML entities are
-correctly encoded. For example:
iex> Cldr.Number.to_string(100, format: :currency, currency: :USD, wrapper: fn
-...> string, :currency_symbol -> Phoenix.HTML.Tag.content_tag(:span, string, class: "symbol")
-...> string, :number -> Phoenix.HTML.Tag.content_tag(:span, string, class: "number")
-...> string, :currency_space -> Phoenix.HTML.Tag.content_tag(:span, string)
+correctly encoded. For example:iex> Cldr.Number.to_string(100, format: :currency, currency: :USD, wrapper: fn
+...> string, :currency_symbol -> Phoenix.HTML.Tag.content_tag(:span, string, class: "symbol")
+...> string, :number -> Phoenix.HTML.Tag.content_tag(:span, string, class: "number")
+...> string, :currency_space -> Phoenix.HTML.Tag.content_tag(:span, string)
...> string, _other -> string
-...> end)
-{:ok, "<span class=\"symbol\">$</span><span class=\"number\">100.00</span>"}
When formatting a number the format is parsed into format elements that might include
+
...> end)
+{:ok, "<span class=\"symbol\">$</span><span class=\"number\">100.00</span>"}
When formatting a number the format is parsed into format elements that might include a currency symbol, a literal string, inserted text between a currency symbol and the currency amount, a percent sign, the number itself and several other elements. In some cases it is helpful to be apply specific formatting to each element. @@ -1141,80 +1141,80 @@
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345
-{:ok, "12,345"}
+{:ok, "12,345"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, locale: "fr"
-{:ok, "12 345"}
+{:ok, "12 345"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1345.32, currency: :EUR, locale: "es", minimum_grouping_digits: 1
-{:ok, "1.345,32 €"}
+{:ok, "1.345,32 €"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1345.32, currency: :EUR, locale: "es"
-{:ok, "1345,32 €"}
+{:ok, "1345,32 €"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, locale: "fr", currency: "USD"
-{:ok, "12 345,00 $US"}
+{:ok, "12 345,00 $US"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, format: "#E0"
-{:ok, "1.2345E4"}
+{:ok, "1.2345E4"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, format: :accounting, currency: "THB"
-{:ok, "THB 12,345.00"}
+{:ok, "THB 12,345.00"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string -12345, format: :accounting, currency: "THB"
-{:ok, "(THB 12,345.00)"}
+{:ok, "(THB 12,345.00)"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, format: :accounting, currency: "THB",
...> locale: "th"
-{:ok, "฿12,345.00"}
+{:ok, "฿12,345.00"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, format: :accounting, currency: "THB",
...> locale: "th", number_system: :native
-{:ok, "฿๑๒,๓๔๕.๐๐"}
+{:ok, "฿๑๒,๓๔๕.๐๐"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1244.30, format: :long
-{:ok, "1 thousand"}
+{:ok, "1 thousand"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1244.30, format: :long, currency: "USD"
-{:ok, "1,244 US dollars"}
+{:ok, "1,244 US dollars"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1244.30, format: :short
-{:ok, "1K"}
+{:ok, "1K"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1244.30, format: :short, currency: "EUR"
-{:ok, "€1K"}
+{:ok, "€1K"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1234, format: :spellout
-{:ok, "one thousand two hundred thirty-four"}
+{:ok, "one thousand two hundred thirty-four"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1234, format: :spellout_verbose
-{:ok, "one thousand two hundred and thirty-four"}
+{:ok, "one thousand two hundred and thirty-four"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1989, format: :spellout_year
-{:ok, "nineteen eighty-nine"}
+{:ok, "nineteen eighty-nine"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 123, format: :ordinal
-{:ok, "123rd"}
+{:ok, "123rd"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 123, format: :roman
-{:ok, "CXXIII"}
+{:ok, "CXXIII"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 123, locale: "th-u-nu-thai"
-{:ok, "๑๒๓"}
errors
ErrorsAn error tuple {:error, reason}
will be returned if an error is detected.
-The two most likely causes of an error return are:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(12345, format: "0#")
- {:error, {Cldr.FormatCompileError,
- "Decimal format compiler: syntax error before: \"#\""}}
locale
and
+The two most likely causes of an error return are: iex> Bonfire.Common.Localise.Cldr.Number.to_string(12345, format: "0#")
+ {:error, {Cldr.FormatCompileError,
+ "Decimal format compiler: syntax error before: \"#\""}}
locale
and
number_system
. This happens typically when the number system is
:algorithmic
rather than the more common :numeric
. In this case the error
-return looks like: iex> Bonfire.Common.Localise.Cldr.Number.to_string(1234, locale: "he", number_system: "hebr")
- {:error, {Cldr.UnknownFormatError,
- "The locale :he with number system :hebr does not define a format :standard"}}
+return looks like: iex> Bonfire.Common.Localise.Cldr.Number.to_string(1234, locale: "he", number_system: "hebr")
+ {:error, {Cldr.UnknownFormatError,
+ "The locale :he with number system :hebr does not define a format :standard"}}
iex> Bonfire.Common.Localise.Cldr.Number.validate_number_system "en", :latn
-{:ok, :latn}
+{:ok, :latn}
iex> Bonfire.Common.Localise.Cldr.Number.validate_number_system "en", :default
-{:ok, :latn}
+{:ok, :latn}
iex> Bonfire.Common.Localise.Cldr.Number.validate_number_system "en", :unknown
-{:error,
- {Cldr.UnknownNumberSystemError, "The number system :unknown is unknown"}}
+{:error,
+ {Cldr.UnknownNumberSystemError, "The number system :unknown is unknown"}}
iex> Bonfire.Common.Localise.Cldr.Number.validate_number_system "zz", :default
-{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
+{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
Functions to implement the number system rule-based-number-format rules of CLDR.
These rules are defined only on the "und" locale and represent specialised number formatting.
The standard public API for RBNF is via the Cldr.Number.to_string/2
function.
The functions on this module are defined at compile time based upon the RBNF rules -defined in the Unicode CLDR data repository. Available rules are identified by:
iex> Bonfire.Common.Localise.Cldr.Rbnf.NumberSystem.rule_sets(:und)
-...> |> Enum.sort()
-[
+defined in the Unicode CLDR data repository. Available rules are identified by:iex> Bonfire.Common.Localise.Cldr.Rbnf.NumberSystem.rule_sets(:und)
+...> |> Enum.sort()
+[
:armenian_lower,
:armenian_upper,
:cyrillic_lower,
@@ -132,9 +132,9 @@
:roman_upper,
:tamil,
:zz_default
-]
A rule can then be invoked on an available rule_set. For example
iex> Bonfire.Common.Localise.Cldr.Rbnf.NumberSystem.roman_upper(123, :und)
-"CXXIII"
This particular call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :roman)
-{:ok, "CXXIII"}
+]
A rule can then be invoked on an available rule_set. For example
iex> Bonfire.Common.Localise.Cldr.Rbnf.NumberSystem.roman_upper(123, :und)
+"CXXIII"
This particular call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :roman)
+{:ok, "CXXIII"}
Functions to implement the ordinal rule-based-number-format rules of CLDR.
As CLDR notes, the data is incomplete or non-existent for many languages. It is considered complete for English however.
The standard public API for RBNF is via the Cldr.Number.to_string/2
function.
The functions on this module are defined at compile time based upon the RBNF rules -defined in the Unicode CLDR data repository. Available rules are identified by:
iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.rule_sets(:en)
-[:digits_ordinal]
+defined in the Unicode CLDR data repository. Available rules are identified by:iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.rule_sets(:en)
+[:digits_ordinal]
-iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.rule_sets("fr")
-...> |> Enum.sort()
-[
+iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.rule_sets("fr")
+...> |> Enum.sort()
+[
:digits_ordinal,
:digits_ordinal_feminine,
:digits_ordinal_feminine_plural,
:digits_ordinal_masculine,
:digits_ordinal_masculine_plural
-]
A rule can then be invoked on an available rule_set. For example
iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.digits_ordinal(123, :en)
-"123rd"
This call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :ordinal)
-{:ok, "123rd"}
+]
A rule can then be invoked on an available rule_set. For example
iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.digits_ordinal(123, :en)
+"123rd"
This call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :ordinal)
+{:ok, "123rd"}
Functions to implement the spellout rule-based-number-format rules of CLDR.
As CLDR notes, the data is incomplete or non-existent for many languages. It is considered complete for English however.
The standard public API for RBNF is via the Cldr.Number.to_string/2
function.
The functions on this module are defined at compile time based upon the RBNF rules -defined in the Unicode CLDR data repository. Available rules are identified by:
iex> Bonfire.Common.Localise.Cldr.Rbnf.Spellout.rule_sets("en")
-...> |> Enum.sort()
-[
+defined in the Unicode CLDR data repository. Available rules are identified by:iex> Bonfire.Common.Localise.Cldr.Rbnf.Spellout.rule_sets("en")
+...> |> Enum.sort()
+[
:spellout_cardinal,
:spellout_cardinal_verbose,
:spellout_numbering,
@@ -126,9 +126,9 @@
:spellout_numbering_year,
:spellout_ordinal,
:spellout_ordinal_verbose
-]
A rule can then be invoked on an available rule_set. For example:
iex> Bonfire.Common.Localise.Cldr.Rbnf.Spellout.spellout_ordinal(123, "en")
-"one hundred twenty-third"
This call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :spellout)
-{:ok, "one hundred twenty-three"}
+]
A rule can then be invoked on an available rule_set. For example:
iex> Bonfire.Common.Localise.Cldr.Rbnf.Spellout.spellout_ordinal(123, "en")
+"one hundred twenty-third"
This call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :spellout)
+{:ok, "one hundred twenty-three"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00], format: :short
-{:ok, "10 – 10 AM"}
+{:ok, "10 – 10 AM"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00], format: :medium
-{:ok, "10:00 – 10:03 AM"}
+{:ok, "10:00 – 10:03 AM"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00], format: :long
-{:ok, "10:00 – 10:03 AM"}
+{:ok, "10:00 – 10:03 AM"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00],
...> format: :long, style: :flex
-{:ok, "10:00 – 10:03 in the morning"}
+{:ok, "10:00 – 10:03 in the morning"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-01-01 10:00:00.0Z],
...> format: :long, style: :flex
-{:ok, "12:00 – 10:00 in the morning"}
+{:ok, "12:00 – 10:00 in the morning"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-01-01 10:00:00.0Z],
...> format: :long, style: :zone
-{:ok, "12:00 – 10:00 AM Etc/UTC"}
+{:ok, "12:00 – 10:00 AM Etc/UTC"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00],
...> format: :long, style: :flex, locale: "th"
-{:ok, "10:00 – 10:03 ในตอนเช้า"}
+{:ok, "10:00 – 10:03 ในตอนเช้า"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], nil
-{:ok, "10:00:00 AM –"}
+{:ok, "10:00:00 AM –"}
iex> Cldr.Time.to_string ~T[07:35:13.215217]
-{:ok, "7:35:13 AM"}
+{:ok, "7:35:13 AM"}
iex> Cldr.Time.to_string ~T[07:35:13.215217], format: :short
-{:ok, "7:35 AM"}
+{:ok, "7:35 AM"}
iex> Cldr.Time.to_string ~T[07:35:13.215217], format: :medium, locale: "fr"
-{:ok, "07:35:13"}
+{:ok, "07:35:13"}
iex> Cldr.Time.to_string ~T[07:35:13.215217], format: :medium
-{:ok, "7:35:13 AM"}
+{:ok, "7:35:13 AM"}
-iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
+iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
iex> Cldr.Time.to_string datetime, format: :long
-{:ok, "11:59:59 PM UTC"}
+{:ok, "11:59:59 PM UTC"}
iex> Bonfire.Common.Localise.Cldr.default_locale()
-%Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.default_locale()
+%Cldr.LanguageTag{
backend: Bonfire.Common.Localise.Cldr,
canonical_locale_name: "en-001",
cldr_locale_name: :"en-001",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: "en",
language: "en",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :en,
requested_locale_name: "en-001",
script: :Latn,
territory: :"001",
- transform: %{},
- language_variants: []
-}
+ transform: %{},
+ language_variants: []
+}
iex> Bonfire.Common.Localise.Cldr.default_territory()
+iex> Bonfire.Common.Localise.Cldr.default_territory()
:"001"
iex> Bonfire.Common.Localise.Cldr.ellipsis "And furthermore"
"And furthermore…"
-iex> Bonfire.Common.Localise.Cldr.ellipsis ["And furthermore", "there is much to be done"], locale: :ja
+iex> Bonfire.Common.Localise.Cldr.ellipsis ["And furthermore", "there is much to be done"], locale: :ja
"And furthermore…there is much to be done"
iex> Bonfire.Common.Localise.Cldr.ellipsis "And furthermore", format: :word
"And furthermore …"
-iex> Bonfire.Common.Localise.Cldr.ellipsis ["And furthermore", "there is much to be done"], locale: :ja, format: :word
+iex> Bonfire.Common.Localise.Cldr.ellipsis ["And furthermore", "there is much to be done"], locale: :ja, format: :word
"And furthermore … there is much to be done"
@@ -677,23 +677,23 @@ iex> Bonfire.Common.Localise.Cldr.put_locale("pl")
+iex> Bonfire.Common.Localise.Cldr.put_locale("pl")
iex> Bonfire.Common.Localise.Cldr.get_locale
-%Cldr.LanguageTag{
+%Cldr.LanguageTag{
backend: Elixir.Bonfire.Common.Localise.Cldr,
canonical_locale_name: "pl",
cldr_locale_name: :pl,
- extensions: %{},
+ extensions: %{},
language: "pl",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :pl,
territory: :PL,
requested_locale_name: "pl",
script: :Latn,
- transform: %{},
- language_variants: []
- }
+ transform: %{},
+ language_variants: []
+ }
iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name?("en")
+iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name?("en")
true
-iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name?("!!")
+iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name?("!!")
false
iex> Bonfire.Common.Localise.Cldr.known_locale_name?(:en)
+iex> Bonfire.Common.Localise.Cldr.known_locale_name?(:en)
true
-iex> Bonfire.Common.Localise.Cldr.known_locale_name?(:"!!")
+iex> Bonfire.Common.Localise.Cldr.known_locale_name?(:"!!")
false
@@ -1006,7 +1006,7 @@ known_number_system_types()
Example
iex> Bonfire.Common.Localise.Cldr.known_number_system_types
-[:default, :finance, :native, :traditional]
+[:default, :finance, :native, :traditional]
iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name?(:en)
+iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name?(:en)
true
-iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name?(:"!!")
+iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name?(:"!!")
false
iex> Bonfire.Common.Localise.Cldr.put_locale("en")
-{:ok,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.put_locale("en")
+{:ok,
+ %Cldr.LanguageTag{
backend: Bonfire.Common.Localise.Cldr,
canonical_locale_name: "en",
cldr_locale_name: :en,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: "en",
language: "en",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :en,
requested_locale_name: "en",
script: :Latn,
territory: :US,
- transform: %{},
- language_variants: []
- }}
+ transform: %{},
+ language_variants: []
+ }}
-iex> Bonfire.Common.Localise.Cldr.put_locale("invalid-locale!")
-{:error, {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"!\" starting at position 15"}}
+iex> Bonfire.Common.Localise.Cldr.put_locale("invalid-locale!")
+{:error, {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"!\" starting at position 15"}}
iex> Bonfire.Common.Localise.Cldr.validate_locale(:en)
-{:ok,
-%Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.validate_locale(:en)
+{:ok,
+%Cldr.LanguageTag{
backend: Bonfire.Common.Localise.Cldr,
canonical_locale_name: "en",
cldr_locale_name: :en,
- extensions: %{},
+ extensions: %{},
gettext_locale_name: "en",
language: "en",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :en,
requested_locale_name: "en",
script: :Latn,
territory: :US,
- transform: %{},
- language_variants: []
-}}
+ transform: %{},
+ language_variants: []
+}}
-iex> Bonfire.Common.Localise.Cldr.validate_locale Bonfire.Common.Localise.Cldr.default_locale()
-{:ok,
-%Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.validate_locale Bonfire.Common.Localise.Cldr.default_locale()
+{:ok,
+%Cldr.LanguageTag{
backend: Bonfire.Common.Localise.Cldr,
canonical_locale_name: "en-001",
cldr_locale_name: :"en-001",
- extensions: %{},
+ extensions: %{},
gettext_locale_name: "en",
language: "en",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :en,
requested_locale_name: "en-001",
script: :Latn,
territory: :"001",
- transform: %{},
- language_variants: []
-}}
+ transform: %{},
+ language_variants: []
+}}
-iex> Bonfire.Common.Localise.Cldr.validate_locale("zzz")
-{:error, {Cldr.InvalidLanguageError, "The language \"zzz\" is invalid"}}
+iex> Bonfire.Common.Localise.Cldr.validate_locale("zzz")
+{:error, {Cldr.InvalidLanguageError, "The language \"zzz\" is invalid"}}
iex> Bonfire.Common.Localise.Cldr.validate_number_system_type :default
-{:ok, :default}
+{:ok, :default}
iex> Bonfire.Common.Localise.Cldr.validate_number_system_type :traditional
-{:ok, :traditional}
+{:ok, :traditional}
iex> Bonfire.Common.Localise.Cldr.validate_number_system_type :latn
-{
+{
:error,
- {Cldr.UnknownNumberSystemTypeError, "The number system type :latn is unknown"}
-}
+ {Cldr.UnknownNumberSystemTypeError, "The number system type :latn is unknown"}
+}
iex> Bonfire.Common.Localise.Cldr.validate_number_system_type "bork"
-{
+{
:error,
- {Cldr.UnknownNumberSystemTypeError, "The number system type \"bork\" is invalid"}
-}
+ {Cldr.UnknownNumberSystemTypeError, "The number system type \"bork\" is invalid"}
+}
iex> Bonfire.Common.Localise.Gettext.Plural.nplurals("pl")
+iex> Bonfire.Common.Localise.Gettext.Plural.nplurals("pl")
4
-iex> Bonfire.Common.Localise.Gettext.Plural.nplurals("en")
+iex> Bonfire.Common.Localise.Gettext.Plural.nplurals("en")
2
iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 1)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 1)
0
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 2)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 2)
1
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 5)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 5)
2
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 112)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 112)
2
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 1)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 1)
0
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 2)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 2)
1
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 112)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 112)
1
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("en_GB", 112)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("en_GB", 112)
1
diff --git a/Bonfire.Common.Test.Interactive.html b/Bonfire.Common.Test.Interactive.html
index e9909c76ee1..7b2f49047ee 100644
--- a/Bonfire.Common.Test.Interactive.html
+++ b/Bonfire.Common.Test.Interactive.html
@@ -118,11 +118,11 @@
fcwatch | mix test --stale --listen-on-stdin
to watch for
code changes and run stale tests, but with more control and
without the starting time penalty.
Note that watching requires fswatch on your system.
-Eg on Mac run brew install fswatch
.
To use it, in your project's .iex
file add:
unless GenServer.whereis(Bonfire.Common.Test.Interactive) do
- {:ok, pid} = Bonfire.Common.Test.Interactive.start_link()
+Eg on Mac run brew install fswatch
.To use it, in your project's .iex
file add:
unless GenServer.whereis(Bonfire.Common.Test.Interactive) do
+ {:ok, pid} = Bonfire.Common.Test.Interactive.start_link()
# Process will not exit when the iex goes out
- Process.unlink(pid)
-end
+ Process.unlink(pid)
+end
import Bonfire.Common.Test.Interactive.Helpers
Then to call iex
and run tests just do:
MIX_ENV=test iex -S mix
The Bonfire.Common.Test.Interactive.Helpers
allows to call f
and s
and a
to run failed, stale and all tests respectively.
You can call w
to watch tests and uw
to unwatch.
diff --git a/Bonfire.Data.Assort.Ranked.html b/Bonfire.Data.Assort.Ranked.html
index 5e6ddc17632..9c0ec3837ab 100644
--- a/Bonfire.Data.Assort.Ranked.html
+++ b/Bonfire.Data.Assort.Ranked.html
@@ -114,15 +114,15 @@
-A reusable table to link child or related items and also rank sibling items.
Usage (for global ranking, otherwise you should specify scope):
{:ok, first} = Bonfire.Data.Assort.Ranked.changeset(%{item_id: "01FGTH48ZZD08ADBHQ260KYJHW"}) |> repo().insert
-second = Bonfire.Data.Assort.Ranked.changeset(%{item_id: "01FGTH0N3YPBS5MNNAEAEVV54J"}) |> repo().insert
+A reusable table to link child or related items and also rank sibling items.
Usage (for global ranking, otherwise you should specify scope):
{:ok, first} = Bonfire.Data.Assort.Ranked.changeset(%{item_id: "01FGTH48ZZD08ADBHQ260KYJHW"}) |> repo().insert
+second = Bonfire.Data.Assort.Ranked.changeset(%{item_id: "01FGTH0N3YPBS5MNNAEAEVV54J"}) |> repo().insert
import Ecto.Query
-Bonfire.Data.Assort.Ranked |> order_by(:rank) |> repo().all
+Bonfire.Data.Assort.Ranked |> order_by(:rank) |> repo().all
-first |> Bonfire.Data.Assort.Ranked.changeset(%{rank_set: :last}) |> repo().update
+first |> Bonfire.Data.Assort.Ranked.changeset(%{rank_set: :last}) |> repo().update
-Bonfire.Data.Assort.Ranked |> order_by(:rank) |> repo().all
+Bonfire.Data.Assort.Ranked |> order_by(:rank) |> repo().all
diff --git a/Bonfire.Files.html b/Bonfire.Files.html
index 55a9e54840d..5868b15bb3d 100644
--- a/Bonfire.Files.html
+++ b/Bonfire.Files.html
@@ -118,10 +118,10 @@
your own - a Bonfire.Files.Definition
is an extension of Waffle.Definition
,
however the allowed_media_types/0
callback is added, forcing you to define
what media types are accepted for these types of uploads.
-(You can also return :all
to accept everything).
To use the uploader:
iex> {:ok, media} = Bonfire.Files.upload(MyUploader, context, %{path: "./150.png"})
+(You can also return :all
to accept everything).To use the uploader:
iex> {:ok, media} = Bonfire.Files.upload(MyUploader, context, %{path: "./150.png"})
iex> media.media_type
"image/png"
-iex> Bonfire.Files.remote_url(MyUploader, media)
+iex> Bonfire.Files.remote_url(MyUploader, media)
"/uploads/my/01F3AY6JV30G06BY4DR9BTW5EH"
diff --git a/Bonfire.Me.Accounts.SecondFactors.html b/Bonfire.Me.Accounts.SecondFactors.html
index 8bf898b22bb..c88d519c691 100644
--- a/Bonfire.Me.Accounts.SecondFactors.html
+++ b/Bonfire.Me.Accounts.SecondFactors.html
@@ -280,8 +280,8 @@ changeset(totp \\ %AuthSecondFactor{}, attr
Examples
-iex> changeset(%AuthSecondFactor{secret: <<...>>}, code: "123456")
-%Ecto.Changeset{data: %AuthSecondFactor{}}
+iex> changeset(%AuthSecondFactor{secret: <<...>>}, code: "123456")
+%Ecto.Changeset{data: %AuthSecondFactor{}}
diff --git a/EctoSparkles.SanitiseStrings.html b/EctoSparkles.SanitiseStrings.html
index 49b50b908b4..f0e83988ab1 100644
--- a/EctoSparkles.SanitiseStrings.html
+++ b/EctoSparkles.SanitiseStrings.html
@@ -248,26 +248,26 @@ strip_all_tags(changeset, opts \\ [])
Examples
-iex> attrs = %{string_field: "<script>Bad</script>"}
+iex> attrs = %{string_field: "<script>Bad</script>"}
iex> result_changeset =
...> attrs
-...> |> FakeEctoSchema.changeset()
-...> |> EctoSparkles.SanitiseStrings.strip_all_tags()
+...> |> FakeEctoSchema.changeset()
+...> |> EctoSparkles.SanitiseStrings.strip_all_tags()
iex> result_changeset.changes
-%{string_field: "Bad"}
Fields can be exempted from sanitization via the :except
option.
iex> attrs = %{string_field: "<script>Bad</script>"}
+%{string_field: "Bad"}
Fields can be exempted from sanitization via the :except
option.
iex> attrs = %{string_field: "<script>Bad</script>"}
iex> result_changeset =
...> attrs
-...> |> FakeEctoSchema.changeset()
-...> |> EctoSparkles.SanitiseStrings.strip_all_tags(except: [:string_field])
+...> |> FakeEctoSchema.changeset()
+...> |> EctoSparkles.SanitiseStrings.strip_all_tags(except: [:string_field])
iex> result_changeset.changes
-%{string_field: "<script>Bad</script>"}
+
%{string_field: "<script>Bad</script>"}
you-can-also-specify-a-specific-scrubber-by-passing-a-function-as-reference
You can also specify a specific scrubber (by passing a function as reference):
-ies> attrs
...> |> FakeEctoSchema.changeset()
-...> |> EctoSparkles.SanitiseStrings.sanitise_strings(scrubber: HtmlSanitizeEx.Scrubber.html5/1)
+ies> attrs
...> |> FakeEctoSchema.changeset()
+...> |> EctoSparkles.SanitiseStrings.sanitise_strings(scrubber: HtmlSanitizeEx.Scrubber.html5/1)
diff --git a/EctoSparkles.html b/EctoSparkles.html
index 3fc40306dc4..bdf00abca19 100644
--- a/EctoSparkles.html
+++ b/EctoSparkles.html
@@ -114,14 +114,14 @@
-query_filter
brings convenience and shortens the boilterplate of ecto queries
Common filters available include:
preload
- Preloads fields onto the query resultsstart_date
- Query for items inserted after this dateend_date
- Query for items inserted before this datebefore
- Get items with IDs before this valueafter
- Get items with IDs after this valueids
- Get items with a list of idsfirst
- Gets the first n itemslast
- Gets the last n itemslimit
- Gets the first n itemsoffset
- Offsets limit by n itemssearch
- Warning: This requires schemas using this to have a &by_search(query, val)
function
You are also able to filter on any natural field of a model, as well as use
- gte/gt
- lte/lt
- like/ilike
- is_nil/not(is_nil)
query_filter(User, %{name: %{ilike: "steve"}})
-query_filter(User, %{name: %{ilike: "steve"}}, :last_name, :asc)
-query_filter(User, %{name: %{age: %{gte: 18, lte: 30}}})
-query_filter(User, %{name: %{is_banned: %{!=: nil}}})
-query_filter(User, %{name: %{is_banned: %{==: nil}}})
-
-my_query = query_filter(User, %{name: "Billy"})
-query_filter(my_query, %{last_name: "Joe"})
+query_filter
brings convenience and shortens the boilterplate of ecto queries
Common filters available include:
preload
- Preloads fields onto the query resultsstart_date
- Query for items inserted after this dateend_date
- Query for items inserted before this datebefore
- Get items with IDs before this valueafter
- Get items with IDs after this valueids
- Get items with a list of idsfirst
- Gets the first n itemslast
- Gets the last n itemslimit
- Gets the first n itemsoffset
- Offsets limit by n itemssearch
- Warning: This requires schemas using this to have a &by_search(query, val)
function
You are also able to filter on any natural field of a model, as well as use
- gte/gt
- lte/lt
- like/ilike
- is_nil/not(is_nil)
query_filter(User, %{name: %{ilike: "steve"}})
+query_filter(User, %{name: %{ilike: "steve"}}, :last_name, :asc)
+query_filter(User, %{name: %{age: %{gte: 18, lte: 30}}})
+query_filter(User, %{name: %{is_banned: %{!=: nil}}})
+query_filter(User, %{name: %{is_banned: %{==: nil}}})
+
+my_query = query_filter(User, %{name: "Billy"})
+query_filter(my_query, %{last_name: "Joe"})
@@ -220,11 +220,11 @@ join_preload(query, associations)
import Ecto.Query
Invoice
-|> join(:left, [i], assoc(i, :customer), as: :customer)
-|> join(:left, [i, c], assoc(c, :account), as: :account)
-|> join(:left, [i], assoc(i, :lines), as: :lines)
-|> preload([lines: v, customers: c, account: a], lines: v, customer: {c, [a: account]})
-|> Repo.all()
+
|> join(:left, [i], assoc(i, :customer), as: :customer)
+|> join(:left, [i, c], assoc(c, :account), as: :account)
+|> join(:left, [i], assoc(i, :lines), as: :lines)
+|> preload([lines: v, customers: c, account: a], lines: v, customer: {c, [a: account]})
+|> Repo.all()
example-using-join_preload
@@ -232,9 +232,9 @@ join_preload(query, associations)
import EctoSparkles
Invoice
-|> join_preload([:customer, :account])
-|> join_preload([:lines])
-|> Repo.all()
+|> join_preload([:customer, :account])
+|> join_preload([:lines])
+|> Repo.all()
@@ -260,13 +260,13 @@ proload(query, qual \\ :left, associations)
-AKA join_preload++
. It's more powerful, but it does it with more (and different!) syntax.
e.g.
proload(query, activity: [
+AKA join_preload++
. It's more powerful, but it does it with more (and different!) syntax.
e.g.
proload(query, activity: [
:verb, :boost_count, :like_count, :replied,
# relations under object will have their aliases prefixed with object_, i.e.
# :object_message, :object_post, :object_post_content
# the original names will still be used for the associations.
- object: {"object_", [:message, :post, :post_content]}
-])
+ object: {"object_", [:message, :post, :post_content]}
+])
diff --git a/Flexto.html b/Flexto.html
index fc692b96276..7bcfa7be848 100644
--- a/Flexto.html
+++ b/Flexto.html
@@ -178,35 +178,35 @@ flex_schema(otp_app)
Adds additional associations dynamically from app config.
Reads config for the given OTP application, under the name of the
current module. Each key maps to an Ecto.Schema function:
belongs_to
field
has_many
has_one
many_to_many
Each of these keys should map to a keyword list where the key is the
-name of the field or association and the value is one of:
- A type
- A tuple of type and options (keyword list)
Example Schema:
defmodule My.Schema do
+name of the field or association and the value is one of:- A type
- A tuple of type and options (keyword list)
Example Schema:
defmodule My.Schema do
use Ecto.Schema
- import Flexto, only: [flex_schema: 1]
+ import Flexto, only: [flex_schema: 1]
- schema "my_table" do
+ schema "my_table" do
field :name, :string # just normal schema things
- flex_schema(:my_app) # boom! give me the stuff
- end
-end
Example configuration:
config :my_app, My.Schema,
- belongs_to: [
+ flex_schema(:my_app) # boom! give me the stuff
+ end
+end
Example configuration:
config :my_app, My.Schema,
+ belongs_to: [
foo: Foo, # belongs_to :foo, Foo
- bar: {Bar, type: :integer}, # belongs_to :bar, Bar, type: :integer
- ],
- field: [
+ bar: {Bar, type: :integer}, # belongs_to :bar, Bar, type: :integer
+ ],
+ field: [
foo: :string, # field :foo, :string
- bar: {:integer, default: 4}, # field :foo, :integer, default: 4
- ],
- has_one: [
+ bar: {:integer, default: 4}, # field :foo, :integer, default: 4
+ ],
+ has_one: [
foo: Foo, # has_one :foo, Foo
- bar: {Bar, foreign_key: :the_bar_id}, # has_one :bar, Bar, foreign_key: :the_bar_id
- ]
- has_many: [
+ bar: {Bar, foreign_key: :the_bar_id}, # has_one :bar, Bar, foreign_key: :the_bar_id
+ ]
+ has_many: [
foo: Foo, # has_many :foo, Foo
- bar: {Bar, foreign_key: :the_bar_id}, # has_many :bar, Bar, foreign_key: :the_bar_id
- ]
- many_to_many: [
+ bar: {Bar, foreign_key: :the_bar_id}, # has_many :bar, Bar, foreign_key: :the_bar_id
+ ]
+ many_to_many: [
foo: Foo, # many_to_many :foo, Foo
- bar: {Bar, join_through: FooBar}, # many_to_many :bar, Bar, :join_through: FooBar
- ]
This one won't work very well because we define foo
and bar
5
+
bar: {Bar, join_through: FooBar}, # many_to_many :bar, Bar, :join_through: FooBar
+ ]
This one won't work very well because we define foo
and bar
5
times each, but I think you get the point.
Reading of configuration is done during compile time. The relations
will be baked in during compilation, thus:
- Do not expect this to work in runtime config.
- You will need to rebuild all dependencies which use this macro
when you change their configuration.
diff --git a/Mix.Tasks.Bonfire.Account.New.html b/Mix.Tasks.Bonfire.Account.New.html
index 4e9be4877fb..ef5d4b4d5ff 100644
--- a/Mix.Tasks.Bonfire.Account.New.html
+++ b/Mix.Tasks.Bonfire.Account.New.html
@@ -120,7 +120,7 @@
Usage
-mix bonfire.account.new [email@address]
You will be prompted for a password and an email if it was not provided.
+mix bonfire.account.new [email@address]
You will be prompted for a password and an email if it was not provided.
diff --git a/Mix.Tasks.Bonfire.Localise.Extract.html b/Mix.Tasks.Bonfire.Localise.Extract.html
index e7c9acea2e7..2126d89fead 100644
--- a/Mix.Tasks.Bonfire.Localise.Extract.html
+++ b/Mix.Tasks.Bonfire.Localise.Extract.html
@@ -114,7 +114,7 @@
-Extracts translations by recompiling the Elixir source code.
mix gettext.extract [OPTIONS]
Translations are extracted into POT (Portable Object Template) files (with a
+
Extracts translations by recompiling the Elixir source code.
mix gettext.extract [OPTIONS]
Translations are extracted into POT (Portable Object Template) files (with a
.pot
extension). The location of these files is determined by the :otp_app
and :priv
options given by Gettext modules when they call use Gettext
. One
POT file is generated for each translation domain.
It is possible to give the --merge
option to perform merging
diff --git a/Mix.Tasks.Bonfire.Secrets.html b/Mix.Tasks.Bonfire.Secrets.html
index 34bd4f3c91d..70656376fc0 100644
--- a/Mix.Tasks.Bonfire.Secrets.html
+++ b/Mix.Tasks.Bonfire.Secrets.html
@@ -114,7 +114,7 @@
-Generates secrets and prints to the terminal.
mix bonfire.secrets [length]
By default, it generates keys 64 characters long.
+
Generates secrets and prints to the terminal.
mix bonfire.secrets [length]
By default, it generates keys 64 characters long.
The minimum value for length
is 32.
diff --git a/Paginator.html b/Paginator.html
index fc50d2f43af..4c25b49f63a 100644
--- a/Paginator.html
+++ b/Paginator.html
@@ -121,10 +121,10 @@
Usage
-defmodule MyApp.Repo do
+defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
use Paginator
-end
+
end
options
@@ -137,29 +137,29 @@
Example
-defmodule MyApp.Repo do
+defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
use Paginator,
limit: 10, # sets the default limit to 10
maximum_limit: 100, # sets the maximum limit to 100
include_total_count: true, # include total count by default
total_count_primary_key_field: :uuid # sets the total_count_primary_key_field to uuid for calculate total_count
-end
Note that these values can be still be overriden when paginate/3
is called.
+
end
Note that these values can be still be overriden when paginate/3
is called.
use-without-macros
Use without macros
If you wish to avoid use of macros or you wish to use a different name for
-the pagination function you can define your own function like so:
defmodule MyApp.Repo do
+the pagination function you can define your own function like so:defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
- def my_paginate_function(queryable, opts \ [], repo_opts \ []) do
- defaults = [limit: 10] # Default options of your choice here
- opts = Keyword.merge(defaults, opts)
- Paginator.paginate(queryable, opts, __MODULE__, repo_opts)
- end
-end
+ def my_paginate_function(queryable, opts \ [], repo_opts \ []) do
+ defaults = [limit: 10] # Default options of your choice here
+ opts = Keyword.merge(defaults, opts)
+ Paginator.paginate(queryable, opts, __MODULE__, repo_opts)
+ end
+end
@@ -297,36 +297,36 @@ paginate(queryable, opts, repo_opts)
Simple example
-query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id], select: p)
+query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id], select: p)
-Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
+
Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
example-with-using-custom-sort-directions-per-field
Example with using custom sort directions per field
-query = from(p in Post, order_by: [asc: p.inserted_at, desc: p.id], select: p)
+query = from(p in Post, order_by: [asc: p.inserted_at, desc: p.id], select: p)
-Repo.paginate(query, cursor_fields: [inserted_at: :asc, id: :desc], limit: 50)
+
Repo.paginate(query, cursor_fields: [inserted_at: :asc, id: :desc], limit: 50)
example-with-sorting-on-columns-in-joined-tables
Example with sorting on columns in joined tables
-from(
+from(
p in Post,
as: :posts,
- join: a in assoc(p, :author),
+ join: a in assoc(p, :author),
as: :author,
- preload: [author: a],
+ preload: [author: a],
select: p,
- order_by: [
- {:asc, a.name},
- {:asc, p.id}
- ]
-)
+ order_by: [
+ {:asc, a.name},
+ {:asc, p.id}
+ ]
+)
-Repo.paginate(query, cursor_fields: [{{:author, :name}, :asc}, id: :asc], limit: 50)
When sorting on columns in joined tables it is necessary to use named bindings. In
+
Repo.paginate(query, cursor_fields: [{{:author, :name}, :asc}, id: :asc], limit: 50)
When sorting on columns in joined tables it is necessary to use named bindings. In
this case we name it author
. In the cursor_fields
we refer to this named binding
and its column name.
To build the cursor Paginator uses the returned Ecto.Schema. When using a joined
column the returned Ecto.Schema won't have the value of the joined column
@@ -341,32 +341,32 @@
paginate(queryable, opts, repo_opts)
Example
-from(
+from(
p in Post,
as: :posts,
- join: a in assoc(p, :author),
+ join: a in assoc(p, :author),
as: :author,
- join: c in assoc(a, :company),
+ join: c in assoc(a, :company),
as: :company,
- preload: [author: a],
+ preload: [author: a],
select: p,
- order_by: [
- {:asc, a.name},
- {:asc, p.id}
- ]
-)
-
-Repo.paginate(query,
- cursor_fields: [{{:company, :name}, :asc}, id: :asc],
- fetch_cursor_value_fun: fn
- post, {{:company, name}, _} ->
+ order_by: [
+ {:asc, a.name},
+ {:asc, p.id}
+ ]
+)
+
+Repo.paginate(query,
+ cursor_fields: [{{:company, :name}, :asc}, id: :asc],
+ fetch_cursor_value_fun: fn
+ post, {{:company, name}, _} ->
post.author.company.name
post, field ->
- Paginator.default_fetch_cursor_value(post, field)
- end,
+ Paginator.default_fetch_cursor_value(post, field)
+ end,
limit: 50
-)
+)
@@ -422,10 +422,10 @@ cursor_for_record(record, cursor_fields, fe
Example
-iex> Paginator.cursor_for_record(%Paginator.Customer{id: 1}, [:id])
+iex> Paginator.cursor_for_record(%Paginator.Customer{id: 1}, [:id])
"g3QAAAABZAACaWRhAQ=="
-iex> Paginator.cursor_for_record(%Paginator.Customer{id: 1, name: "Alice"}, [id: :asc, name: :desc])
+iex> Paginator.cursor_for_record(%Paginator.Customer{id: 1, name: "Alice"}, [id: :asc, name: :desc])
"g3QAAAACZAACaWRhAWQABG5hbWVtAAAABUFsaWNl"
@@ -464,10 +464,10 @@ default_fetch_cursor_value(schema, field)
Example
-iex> Paginator.default_fetch_cursor_value(%Paginator.Customer{id: 1}, :id)
+iex> Paginator.default_fetch_cursor_value(%Paginator.Customer{id: 1}, :id)
1
-iex> Paginator.default_fetch_cursor_value(%Paginator.Customer{id: 1, address: %Paginator.Address{city: "London"}}, {:address, :city})
+iex> Paginator.default_fetch_cursor_value(%Paginator.Customer{id: 1, address: %Paginator.Address{city: "London"}}, {:address, :city})
"London"
diff --git a/Pointers.Mixin.html b/Pointers.Mixin.html
index 7bd27c88730..923b25b5c3a 100644
--- a/Pointers.Mixin.html
+++ b/Pointers.Mixin.html
@@ -128,16 +128,16 @@
Declaring a mixin table type
-defmodule My.Mixin do
+defmodule My.Mixin do
use Pointers.Mixin,
otp_app: :my_app,
source: "postgres_table_name"
- mixin_schema do
+ mixin_schema do
field :is_awesome, :boolean
- end
-end
+ end
+end
diff --git a/Pointers.Pointable.html b/Pointers.Pointable.html
index 9970c6b8a26..3a159df7eb0 100644
--- a/Pointers.Pointable.html
+++ b/Pointers.Pointable.html
@@ -125,9 +125,9 @@
source: "my_table", # default name of table in database
table_id: "01EBTVSZJ6X02J01R1XWWPWGZW" # unique ULID to identify table
-pointable_schema do
+pointable_schema do
# ... fields go here, if any
-end
+
end
overriding-with-configuration
diff --git a/Pointers.Virtual.html b/Pointers.Virtual.html
index afc6e6c1465..7f840fa68e1 100644
--- a/Pointers.Virtual.html
+++ b/Pointers.Virtual.html
@@ -128,9 +128,9 @@
source: "my_table", # default name of view in database
table_id: "01EBTVSZJ6X02J01R1XWWPWGZW" # valid ULID to identify virtual
-virtual_schema do
+virtual_schema do
# ... `has_one`, `has_many`, or *virtual* fields ONLY go here.
-end
overriding-with-configuration
diff --git a/Voodoo.html b/Voodoo.html index 46e3415aa69..0a92352a159 100644 --- a/Voodoo.html +++ b/Voodoo.html @@ -185,14 +185,14 @@Generates a reverse router function with the given name based upon a compiled(!) phoenix router module.
Must be used outside of the router module, or else the router won't -be compiled yet and we won't be able to look up the routes.
Generated function wraps the existing phoenix helpers.
defmodule MyAppWeb.Router do
+be compiled yet and we won't be able to look up the routes.Generated function wraps the existing phoenix helpers.
defmodule MyAppWeb.Router do
use MyAppWeb, :router
# ...
-end
-defmodule MyAppWeb.Router.Reverse do
- import Voodoo, only: [def_reverse_router: 2]
+end
+defmodule MyAppWeb.Router.Reverse do
+ import Voodoo, only: [def_reverse_router: 2]
def_reverse_router :path, for: MyAppWeb.Router
-end
+end
The code is broadly composed namespaces such as these, many of which are packaged as "extensions" which live in separate git repositories, which are included in the app by way of mix dependencies:
Bonfire.*
- Core application logic (very little code).Bonfire.*.*
- Bonfire extensions (eg Bonfire.Social.Posts
) containing mostly context modules, APIs, and routesBonfire.Data.*
- Extensions containing database schemas and migrations Bonfire.UI.*
- UI component extensionsBonfire.*.*.LiveHandler
- Backend logic to handle events in the frontendBonfire.Editor.*
(pluggable text editors, eg. CKEditor for WYSIWYG markdown input)Bonfire.GraphQL.*
- Optional GraphQL APIBonfire.Federate.*
- Optional Federation hooksActivityPub
- ActivityPub S2S models, logic and various helper modules ActivityPub.Web
- ActivityPub S2S REST endpoints, activity ingestion and push federation facilities ValueFlows.*
- economic extensions implementing the ValueFlows vocabularyContexts are were we put any core logic. A context often is circumscribed to providing logic for a particular object type (e. g. Bonfire.Social.Posts
implements Bonfire.Data.Social.Post
).
All Bonfire objects use an ULID as their primary key. We use the Pointers
library (with extra logic in Bonfire.Common.Pointers
) to reference any object by its primary key without knowing what type it is beforehand. This is very useful as it allows for example following or liking many different types of objects (as opposed to say only a user or a post) and this approach allows us to store the context of the like/follow by only storing its primary key (see Bonfire.Data.Social.Follow
) for an example.
Context modules usually have one/2
, many/2
, and many_paginated/1
functions for fetching objects, which in turn call a query/2
function. These take a keyword list as filters (and an optional opts
argument) allowing objects to be fetched by arbitrary criteria.
Examples:
Users.one(username: "bob") # Fetching by username
-Posts.many_paginated(by: "01E9TQP93S8XFSV2ZATX1FQ528") # List a page of posts by its author
-EconomicResources.many(deleted: true) # List any deleted resources
Context modules also have functions for creating, updating and deleting objects, as well as hooks for federating or indexing in the search engine.
Here is an incomplete sample of some of current extensions and modules:
Bonfire.Me.Accounts
(for managing and querying local user accounts)Bonfire.Me.Users
(for managing and querying both local and remote user identities and profiles)Bonfire.Boundaries
(for managing and querying circles, ACLs, permissions...)Bonfire.Social.FeedActivities
, Bonfire.Social.Feeds
and Bonfire.Social.Activities
(for managing and querying activities and feeds)Bonfire.Social.Posts
and Bonfire.Social.PostContents
(for managing and querying posts)Bonfire.Social.Threads
(for managing and querying threads and comments)Bonfire.Social.Flags
(for managing and querying flags)Bonfire.Social.Follows
(for managing and querying follows)Bonfire.Classify
(for managing and querying categories, topics, and the like)Bonfire.Tag
(for managing and querying tags and mentions)Bonfire.Geolocate
(for managing and querying locations and geographical coordinates)Bonfire.Quantify
(for managing and querying units and measures)Bonfire.Common
and Bonfire.Common.Utils
(stuff that gets used everywhere)Bonfire.Application
(OTP application)Bonfire.Me.Characters
(a shared abstraction over users, organisations, categories, and other objects that need to have feeds and behave as an actor in ActivityPub land)Bonfire.Federate.ActivityPub
and ActivityPub
(ActivityPub integration)Bonfire.Search
(local search indexing and search API, powered by Meili)Bonfire.Mailer
, Bonfire.Me.Mails
, and Bamboo
(for rendering and sending emails)Bonfire.Files
, Waffle
, TreeMagic
and TwinkleStar
(for managing uploaded content)Bonfire.GraphQL
(GraphQL API abstractions)Queery
and Bonfire.Repo.Query
(Helpers for making queries on the database)Bonfire.Repo
(Ecto repository)Flexto
(to extend DB schemas in config, especially useful for adding associations)AbsintheClient
(for querying the API from within the server)The code is broadly composed namespaces such as these, many of which are packaged as "extensions" which live in separate git repositories, which are included in the app by way of mix dependencies:
Bonfire.*
- Core application logic (very little code).Bonfire.*.*
- Bonfire extensions (eg Bonfire.Social.Posts
) containing mostly context modules, APIs, and routesBonfire.Data.*
- Extensions containing database schemas and migrations Bonfire.UI.*
- UI component extensionsBonfire.*.*.LiveHandler
- Backend logic to handle events in the frontendBonfire.Editor.*
(pluggable text editors, eg. CKEditor for WYSIWYG markdown input)Bonfire.GraphQL.*
- Optional GraphQL APIBonfire.Federate.*
- Optional Federation hooksActivityPub
- ActivityPub S2S models, logic and various helper modules ActivityPub.Web
- ActivityPub S2S REST endpoints, activity ingestion and push federation facilities ValueFlows.*
- economic extensions implementing the ValueFlows vocabularyContexts are were we put any core logic. A context often is circumscribed to providing logic for a particular object type (e. g. Bonfire.Social.Posts
implements Bonfire.Data.Social.Post
).
All Bonfire objects use an ULID as their primary key. We use the Pointers
library (with extra logic in Bonfire.Common.Pointers
) to reference any object by its primary key without knowing what type it is beforehand. This is very useful as it allows for example following or liking many different types of objects (as opposed to say only a user or a post) and this approach allows us to store the context of the like/follow by only storing its primary key (see Bonfire.Data.Social.Follow
) for an example.
Context modules usually have one/2
, many/2
, and many_paginated/1
functions for fetching objects, which in turn call a query/2
function. These take a keyword list as filters (and an optional opts
argument) allowing objects to be fetched by arbitrary criteria.
Examples:
Users.one(username: "bob") # Fetching by username
+Posts.many_paginated(by: "01E9TQP93S8XFSV2ZATX1FQ528") # List a page of posts by its author
+EconomicResources.many(deleted: true) # List any deleted resources
Context modules also have functions for creating, updating and deleting objects, as well as hooks for federating or indexing in the search engine.
Here is an incomplete sample of some of current extensions and modules:
Bonfire.Me.Accounts
(for managing and querying local user accounts)Bonfire.Me.Users
(for managing and querying both local and remote user identities and profiles)Bonfire.Boundaries
(for managing and querying circles, ACLs, permissions...)Bonfire.Social.FeedActivities
, Bonfire.Social.Feeds
and Bonfire.Social.Activities
(for managing and querying activities and feeds)Bonfire.Social.Posts
and Bonfire.Social.PostContents
(for managing and querying posts)Bonfire.Social.Threads
(for managing and querying threads and comments)Bonfire.Social.Flags
(for managing and querying flags)Bonfire.Social.Follows
(for managing and querying follows)Bonfire.Classify
(for managing and querying categories, topics, and the like)Bonfire.Tag
(for managing and querying tags and mentions)Bonfire.Geolocate
(for managing and querying locations and geographical coordinates)Bonfire.Quantify
(for managing and querying units and measures)Bonfire.Common
and Bonfire.Common.Utils
(stuff that gets used everywhere)Bonfire.Application
(OTP application)Bonfire.Me.Characters
(a shared abstraction over users, organisations, categories, and other objects that need to have feeds and behave as an actor in ActivityPub land)Bonfire.Federate.ActivityPub
and ActivityPub
(ActivityPub integration)Bonfire.Search
(local search indexing and search API, powered by Meili)Bonfire.Mailer
, Bonfire.Me.Mails
, and Bamboo
(for rendering and sending emails)Bonfire.Files
, Waffle
, TreeMagic
and TwinkleStar
(for managing uploaded content)Bonfire.GraphQL
(GraphQL API abstractions)Queery
and Bonfire.Repo.Query
(Helpers for making queries on the database)Bonfire.Repo
(Ecto repository)Flexto
(to extend DB schemas in config, especially useful for adding associations)AbsintheClient
(for querying the API from within the server)general-structure
diff --git a/bonfire-flavoured-elixir.html b/bonfire-flavoured-elixir.html index 39aad7bb70f..4610b1c2487 100644 --- a/bonfire-flavoured-elixir.html +++ b/bonfire-flavoured-elixir.html @@ -118,33 +118,33 @@Arrows
The Elixir |> ("pipe") operator is one of the things that seems to get people excited about elixir. Probably in part because you then don't have to keep coming up with function names. Unfortunately it's kind of limiting. -The moment you need to pipe a parameter into a position that isn't the first one, it breaks down and you have to drop out of the pipeline format or write a secondary function to handle it.
Not any more! By simply inserting ...
where you would like the value to be inserted, Arrows
will override where it is placed. This allows you to keep on piping while accommodating that function with the annoying argument order. Arrows
was inspired by an existing library. Here is part of the test suite in lieu of examples:
defmodule ArrowsTest do
+The moment you need to pipe a parameter into a position that isn't the first one, it breaks down and you have to drop out of the pipeline format or write a secondary function to handle it.Not any more! By simply inserting ...
where you would like the value to be inserted, Arrows
will override where it is placed. This allows you to keep on piping while accommodating that function with the annoying argument order. Arrows
was inspired by an existing library. Here is part of the test suite in lieu of examples:
defmodule ArrowsTest do
use ExUnit.Case
use Arrows
- def double(x), do: x * 2
- def double_fst(x, _), do: x * 2
- def double_snd(_, x), do: x * 2
- def add_snd_thd(_, x, y), do: x + y
-
- test "|>" do
- assert 4 == (2 |> double)
- assert 4 == (2 |> double())
- assert 4 == (2 |> double(...))
- assert 8 == (2 |> double(double(...)))
- assert 4 == (2 |> double_fst(1))
- assert 4 == (2 |> double_fst(..., 1))
- assert 8 == (2 |> double_fst(double(...), 1))
- assert 4 == (2 |> double_snd(1, ...))
- assert 8 == (2 |> double_snd(1, double(...)))
- assert 3 == (2 |> add_snd_thd(1, ..., 1))
- assert 4 == (2 |> add_snd_thd(1, ..., ...))
- assert 6 == (2 |> add_snd_thd(1, ..., double(...)))
- for x <- [:yes, 2, nil, false] do
- assert {:ok, x} == (x |> {:ok, ...})
- end
- end
-end
A few little extra features you might notice here:
- You can move the parameter into a subexpression, as in
2 |> double_fst(double(...), 1)
where double will be called before the parameter is passed to double_fst
. - You can use
...
multiple times, substituting it in multiple places. - The right hand side need not even be a function call, you can use any expression with
...
.
+
def double(x), do: x * 2
+ def double_fst(x, _), do: x * 2
+ def double_snd(_, x), do: x * 2
+ def add_snd_thd(_, x, y), do: x + y
+
+ test "|>" do
+ assert 4 == (2 |> double)
+ assert 4 == (2 |> double())
+ assert 4 == (2 |> double(...))
+ assert 8 == (2 |> double(double(...)))
+ assert 4 == (2 |> double_fst(1))
+ assert 4 == (2 |> double_fst(..., 1))
+ assert 8 == (2 |> double_fst(double(...), 1))
+ assert 4 == (2 |> double_snd(1, ...))
+ assert 8 == (2 |> double_snd(1, double(...)))
+ assert 3 == (2 |> add_snd_thd(1, ..., 1))
+ assert 4 == (2 |> add_snd_thd(1, ..., ...))
+ assert 6 == (2 |> add_snd_thd(1, ..., double(...)))
+ for x <- [:yes, 2, nil, false] do
+ assert {:ok, x} == (x |> {:ok, ...})
+ end
+ end
+end
A few little extra features you might notice here:
2 |> double_fst(double(...), 1)
where double will be called before the parameter is passed to double_fst
....
multiple times, substituting it in multiple places....
.ok-pipe
@@ -158,14 +158,14 @@Untangle
provides replacements for the macros in Elixir's Logger
module and the IO.inspect
function to output code location information. The first argument will be inspect
ed and the second (where provided) will be used as a label:
iex(1)> import Untangle
Untangle
-iex(2)> debug(:no, "the answer is") # log at debug
-11:19:09.915 [debug] [iex:2] the answer is: :no
+iex(2)> debug(:no, "the answer is") # log at debug
+11:19:09.915 [debug] [iex:2] the answer is: :no
:no
-iex(3)> dump(%{a: :map}, "it") # inspect something on stdout
-[iex:3] it: %{a: :map}
-%{a: :map}
When used in a code file, the location information becomes slightly more useful, e.g.:
[lib/test_untangle.ex:15@Test.Untangle.example/2] Here's an empty list: []
You may also notice from the iex output that it returns its first argument. This makes it ideal for -inserting into a pipeline for debugging purposes:
do_something()
-|> debug("output of do_something/0")
When you are done debugging something, the location of the debug statement is already in the output so you know where to remove it or comment it out! Bliss!
You will find the codebase uses this a lot, though the debugs are frequently commented out. Just uncomment the ones that would help you with a particular debugging task and you're off.
When used in a code file, the location information becomes slightly more useful, e.g.:
[lib/test_untangle.ex:15@Test.Untangle.example/2] Here's an empty list: []
You may also notice from the iex output that it returns its first argument. This makes it ideal for +inserting into a pipeline for debugging purposes:
do_something()
+|> debug("output of do_something/0")
When you are done debugging something, the location of the debug statement is already in the output so you know where to remove it or comment it out! Bliss!
You will find the codebase uses this a lot, though the debugs are frequently commented out. Just uncomment the ones that would help you with a particular debugging task and you're off.
error-handling
diff --git a/bonfire_umbrella.epub b/bonfire_umbrella.epub index 3369eb8a8ac733c290f831ef922de0431282b3c7..40686e5af077647e05b19ce03bd4bf1d1b2547db 100644 GIT binary patch delta 253032 zcmZ6xQ;;rPuq@cNZQHhY+qP|Mx4yP*+qUiAZQHi3`OmpA5p$)+5w~CCp|pd^l4E%6Nv&h+^ygg*~n&&k_ah7a>c@9sWrki&n0c2N0bS z*gu^8r^EwWiJJH$-jim+8UeM^)w1a}G1|W3N?*69hl~6DJuSbPpG&==SOk>(u#2Ls zC~t;=v6m3657*0l-w*l1l}=?ppmIHtl2`GBCyW!?m70|sTl#fpQ6PWf`p;tl{T2n z65}x#um9*R6Ak1FHB3lmDw&z-h}r%@38ZOA8CW=w{ic?jQFJvBU-ZzAF|shpuMKft zBB@8qZ+9Fiyp#}byfO@=(4p#QR|t$INBHT=ci?$aFt6rWW)Aj4xcRqe1K`cSqX1bn zhhp3-?F`1Vd!TCy# R5S8X@$VP7gs zC&7g(=gs0%C5P@J+z+!T3jijUtaj2h)imdAQ^vj4R_(Ky8J6}Dpb`+2@KA&!`dD_m zag$CtTvN~iWePsCu{gG(^wS!0L^aLB+yAc2b*^eqqG>pM!{0pH)n2?gOLxzc?4e}8 zAXj!?$2onWqf`ACMW@A7dp#?M+J1dKVAaIWb&^zn1iQB8WT)j^4(J dLM``eC8F=ml7*MHj%ro7TZJk{J}N#1``CosF1_FzVrt2{TkNG+8D@CW zf11KDeOGC=--0@7D)2gJN2ktZGnYYkgGrCsI597>Qhd7HY0Cn%!ga;g0kL)e8YeTK zB@!hf__gC=O6HMU31IbR-1$fylSY9ncIZB>lfX6mOqw^{!i}XM?E*Gfpz !q>a|Ch1b zAIqUy7RNh#Z6 6mm znv%mJ6O!L-9oI3i-NK4{2(XD>v2rMtEWS1`g{QE+vs5>Es|ByjWZmhOtBH`VYO?^D zoX_cJZ`Z908Y&XzRC>}KMR2fIYo3)>g>P *3PJ*ZYmRut5u zXExDj$ 637(OJ|xY8b)BZbQyQe0gHxVqe9f7`+(20 zSMFaDAZo5KR_XmAS2aX+_Ji0ybMO`Z?~hWtoyGkJHARC`Tiuubqte%^AELn7D2s3> zwcKhqVN7v-<}B@`7{}Q{RDjo$JPfET>5}Gf<1l|eFPftsHf%&R@i8nL5qmn#BveLJ znf!lg1-es+ SRAya{F}O$Swj&Rds~ML ZppESaPD`QTn1!4~7qaM#@Jv-e#>%J56{c7eW&?kSmK1lV)slww1={bdUOTi}Kw zKqr6qd>|Iq(_Kf(yIbFZz&$Rgq&nYJ25CV=%%}QN{~s)vF4rkC<(Lq9HnhZJ?y^^& z{GD4*K(>x}Lv-Qt!t TTcn+dS!|Zg;b8+Usp6afQ$AlumcW$vBly1xvAHM)aI-2yChVNzUq7l z)g0EGr;d|cVJ2e$b*AUkNpVo%@{ASTqNI&FkJwTsZ^CUrLPgC)x$vNzN#d^PUqQga z(jibHxseSUSN5Ri##cz&(79(Prf!S{;S8gNBYSr{mc04lB6YTb|KpV>hd|yOV9^^( zzIU+f{s=z@j!cRs4A$60Jq*Odd88Os78wwf@DCzY3F|R=Y*@||eG-Y~p#@{64aRLE z#!8+j0Suh6!)!X@39})kB#6k-Ah|;}RY{1W)eIS2@c(!6Wg7RlrhtKf5J7=}@c!e3 z3SuIPDvV~HO$OE%zzF{nH 1m5`P{q@!iZ7Y>v>+J4;P zALF(Dnq oENYT|_4^e(DxwLQ7vG~j)&5ZH(a&p?gX^yFhVUQW* z)ZjSg;N#aa^n)8F2h?mXBO^>+wg}_oWM_92rnZJ590n$CvF08|(tv0Q<47&1Y*#+t zZ9%l{s>-G;Wx })7(#A57?z~5}8UOT|H@sz>hHc1M{_hb4! zk|$<+X1s}xKEr#?wj1T0K(TUMtq9!FqAT*Rda50wX%L!!>>G=j`V?gfJe(?55rh zGl_Kk2gZ$o#p*0h>l6Q)!=3qT<8dH6G@Ggr7A*L`_>NcshO!+Fjc}_QJr20dylZRW zikn5Cj3?`is5~MKOKeDKs|K@x`*Wy;Rr{*lcx_vN8(^{tL0%^bzR^Cs@WGDIc&i@% zu$b 8MJptYOQ3)rKSV7RMMsY@-tAMSsa;w>0H4?NlKPm zh;05JK-@}JMe;4QhSq}GD#Guh;MYgB_oI^83?i1c*hzD3u@%;YeJthX0Jyw4dGK?3 zaC0|y4Avkl{jP#@j`Rp};#aG!H*vdLdt2OC>WT^peu3TI`|@pXR|Rzn`~YI7eqQk2 z4F+tQr!P$lS_KbU_bRNFP=|sr4`at)pL rZ&j^?fe73(>5V+NiBU{w+eoA10#u=@j= z3_6I^-m&QJcB CA)l9XD2Y3?n-tLK#{@$K_M&0xbd>K_HvY&XIn^lEUR$Cirr8` z;t7RbzybDX9Tx?AB!@v%Bbtt^oCd#zxvaqp_>x6fHCXJ_)%mz%0n-ixf?nK*cfu#V z*51+(v5i|LF}JmB?(xzYmLrGrNIlTU1+&LclrCZ!RS&!&@^0~~ABs@B|6ddU0HJIE ztyB2}R`-ek(vh&V?Vbg^S?){g1Lz+9tqJlCZKf2I_RS<0EDC%WI@sfp3a)ewsY$9i zJG3dzF~+Y63(+ZD0(*ZEi_HxY9pcQxWE*_q2*cp}k_l!p40tQ}T-IcVs2tHnP- O#B*0R7*(uGT?U3YriI2>34$5J8fXG3tLPP5?nZCY3!& zk!0e`07zr31ps_s&%fa(^|au4)1JckQ$rdxlx}q063Cj?>2mQ$He?fr9v>f%5?(}` z&kOggozbDu8;*Z@rhXsE7(~_LR?fz&alEC!^>5kcQ({8795Y~Z;lC#)mAPgXvT 8n0aHA+s%6`|C)J0THdZ$ zpdmH5sPrSNEJ>1?wyaPaRD()ECbPzDa!_)9{`!0kcg9=)+v*;qrX
yE6> z!W=viX%BhmKt8OZN?IWg7Scd_P|Cd7jLX|WfB<~4zF1%e+gY0)r?a15BrGN&*4^&> z01l~s;KCV_>aEt!k+dg3Y9|wBPNpus(Ai;JO9JKn*%fCIGp14r8@hoQedHhhVD;eW zKZsj4ri3&&-(zW*Dc`&Pqa37AbAcNicSb4JyBZO(b)k-&8dY9Y%J%W(8T16!1s$OZ z;K1YKWSVld=3gYQGf$A$rHF6D*(sLq12k7BGu36*YfnI49f9N8kRFLPRHT2_6p55A zGPbw}#(vihUm%>YvAPkbPl`d`!;Gqp78mZ)9hz4Lw?NvGHAw3iE3jyltzS2Ca*ama z16Q^0tJ$}sYi&t>M5YANPCj|2utMuOgG0YT>HpzlpAbJAxzg6WLdDKGJ919M1h||u z5Zw+rkM4JJE%^L9aWu(b$r2I&V4DmHP=-(^6<4hOgHv+{DKVKGugO6N$_v^kjjO&N zpG3`w@$d`5&WN=O$E-B)gM)Xn7Ic{z5Ev?LHnk(%hfsHy^@qteSQf`Cc5IIu)F#_= zPaKAm(v`@b;% C&u{ zwV~ZjIUp@O)WdXUGRfM_8~8iv#O( e=4I^|i?wc~$v4SIELNRlFXio7LMz znY(x$QAYj@Ms~A$(crC09eP_my&eaCYAfNWY`T-DSefrys2=#EnoK{36=Qum`Q2Eo zP4%fC@2-CQHAdp{vpr6AoqBeKW!SeL2oPx*>{6g^5wTY~{iH#8zG=Z4qFEASH6VGT zI71NoEyVHDw)6T++PidC_Gk911cS<LH#3Dt^TKf zwr5U#(Y9)C_``~3Ad2RcbZOG->-kQ!+>@fLQN(-f+cU %N&tLo=fF4w_}9?Z!|b$`1PM0csuZCzAAh|xOj zGw5bPcR;%U`Oz**uH?!ysiG5298k)!wh#g_p;CYlMwf-LQOIwbO*RFUO=uhK$)iW~ zp{|&uZpm-9MZZ~L{`6RO2H3$OE|>c3jdpQ%U*Z+uzrlZfv2uI4;!B;W?_T6xQLJgm ziA2Ay^ww`lF6%;9>3yL-)fvAgFA&qoX+7`G@}IwBWF!98;SP&_O&X;f1Z>2it?QiY z+fPAw!+xI(O;2y{J2?EjJ^#7gcDsF^?lb7|26!%BK5w9}Df10tSB3o94$Jx&VvqpL zI!`HNdboE?q;~Zv*f<&GSRta%*21sczujyY^1n1MLyX&Jnt`bL)Ea2FM~wKj;*_cv zaaVn_j<_^pp{x aK_!_{VLTfy+1<|H-qxi^~=wdl9P;G_u%1 z84)G3vZ0oJE4!_Xx+IT=3uThpR6L_taC^QK$pXnS(&8Tfd}#B<1hCR{htKozMQMV# zQrO9-NUC)qSZgQn{IVU4AW$_JwA>5I#F%OW|E4Mz#c)3G!5i>S15g)FSj?_PCsc|M z(>-Oyj(r4Xo9lc*Zw{n7{mGjz(Wv&x;1|>|cJj)zX)5f~BhB7jFL$FerI;g`YBKjL zr-u}mmmyL#uU#JlsfRwL(+5g_fJ*}RvQjj;DH$|bcVTgmt-NUOTe|el66S{zVS2x+ z)4B+6Cl%_HS=HZ^Rmz=E9qx~1GZaa0zfe=ee)%ze)H9x@<~(?~c(L(bXCTUUSy6rv z|JNhG($f1+=b-uiXN9sE+5wL_Hx4@~Yv|1t>jjY0CSvI1foONOwksxidh-LiQ1#>4 z?JEVTp8})i#&^iGXspxGuH#IlXi}`aFCZs^flF5Nwp?A0z>#IOb9jY8OWYKc<3yL{ zdMXmNI>!n%cJ2*5*|@F{A;-KS_3wPL TUEL7Dvyi0e4&N3B&*&VaAbrzY! zbY3^K(}o~GEw91LRKN|>(^mjR5ZfH$Lfv^kGsS=3Z$1tV4u6)rvf5U^Cm(;Zq6B9d z1g{L9KEDs%IcTnC@Fgy{=FgCD#A>b@TtIb%Kwn$VJK@vExg7d=ww)$ys6cJ-zzZi1 z `Ed{^>t7+M&AvywAt6pobepAsz}HeDK#qhfBTf-vvL3pa>E35(Q7M? zpE8bqRHXfFs{1xL*;Xt`*wDx_psvuYvupzvqf_DL(1)tXq|hfIsArHO5rJ0beR7o) z`I`ZsNXm!)^%=yZ-lF6 4%w)}B5b)yn!jAB$V3-9hYRil )KH|=_`Ki!oI>-RklroS6kY5UU77KQ? zrFB^k`sj=ja`BpmvHp_u3msD0zN4vOQ&FjC%I*ha6J_6vPv$KX?`m(WgR+uXzdp{h z=kLE!nto>^6#M#$-W!K4k8{Om8*%0Ss9PJ{aT(7*I0l90vVvF%*zi6gV4D2o*lF6E zF(ER#>5RGdMI- j8R`i)^lXL4*25Dy6?Mmib z1HlxZH2N>o2R-=>^M~)~;EXwJXcOuL%TyR{a QJIh5+^Nl6!aD(4>p&ZFGw zesq^JWEfCwq?~t+;Uw#Fc>HPL&6ht?|A7)z4z+1$;w=GL_?-!rn&@7x6 0@~6rL;Xjzupy!m9ehH#*g-~vL5P#cGX904`epyh z_g@R)`X!s0(gxvWl!&teS!IM*1oBdY{4+U`(C2M2aFp!hJ_P!8g>^2YPR>)~C`IYG z8uAx@h*D+dxiWeGXh_nTK-R*T!Qj6_)MummIoW`ZwYs%il08Fej<|yQFudQ8k+Ba` zf^67JMJX^wgz -PwihR0e+T9{sNLl6@Rv-dBSmk8?LQ#tkt%~m#`<0Z60Q^DocEb# z8YO_AI!?{cE}~QUE#n#ovpd?qqb!*z#$vQg_Sr#BI?d+$DO-l~xRrl!gc}wnn$-OT z=Y(;I01!O`mAFht|F$nVG4~e##9#e`Tjl7+Fujv;cr%+S9`IIjbtG l`)ZrNf3@ z6MX_s4 1Hh^Gyi| zt9wftavr?iqYOJvd^_SjVj1JyC7z7JS2H73l?TJDjav?p!?lgScC5dszo4w0q`tbH zm1x$)dNkIKextsjw)bbFri}Icrs<5Fd6e`2M6bt}yeOpol0F>8e7wKrZvVXfKf#qL zt^ebG-55A6`?r9j@VY-Pm;z$`?Y8~>sOpWj%iNGG&rO{YBvXnH-ga*#H)>(Sl}n1n z0)QgOA8z)yU1ss|(Wo(P-u^fnDV`r!YYtEH_}Tc|NSdih0hby=+!0(GG-_eir@*6K z5d;X6zVTn1kRK@%8^E>?T}S9KuirHW!=pk(li73%k9+18iFiFV2m?lxh9a$|@+)$1 z!J2C3KS^I{$t;sLgeS+x(fraPcNS atLwowO+#$<{cSH-QkcWL#M3O<(BAnp-SRp0C>y7FroqK0xMR zXf~|#MW$7dd00&}_X1+tsXF?p1n73^bY`v^J-JPo)5W3X8ZI|FbP%6}K>~j1OLlj# zR9S4K!3Jou*Z!0}={vMb!5Z3(hHxy(Z@P9SM)ZWCk37i#q2LT;O3}rQe-A)HMFgTz z-yGvx BKjNb%w=|rj##R*1B8q?7qPYAvci0_18t4|ki2*aF%f%Q~ zq2R~hCySFR$+h7++MwoM(;wl<$gE1u$iSwNxa~3J1Us_^y580#;lFymROfki!P{Rm zzw0YPx7-vj`2n=8tFYIG8~011`eE#lt{Q}D;S#1&E;l(h>Yji>b#ixZYkPMv&rlF5 zk-ZsYHY)Pf6EV~&uP>Y_%YCrVAxpN;1DmW3_%)z#D{gF4BObxIGS(}UBL5k=P~V-S zo+&D1kH`&FNb;$(bb*VnKqa%E)yywmU?bU**sptvNCWD)brm=;E+MvCllQccW@ zhxU;KJobt77yfdgoW2CSVaKLkOTLi1R-@OIi`vdB@g4olwbJ?EZ7a1b2Eea|h*iN$ zF}I^3+n##B^x0M@-qIWPftnr$zhiwzu$qt$ljjfH+QA|sU^`|Wf}DW-MKgGdb0kEd z1tQc`TLeHj?9h(H0BY`BF4V6Oqy`#_OK3of(&xxoJ#nF>=vLY19on84qKp^N>$oN} ze4pO~< >@wL#bBC(~uK8-({3u0MrqRv%T zmjcwnD2i-w1Rk#o2%T{Z*&@i 1w-LTK?$%Rg*CbB^W_i>k0F8u9K+TIpjXt zD63Pm4~l)H+Cld_@LbdX!LKN&^kFt%oCK61;n3<{4`Xe>f0Th#rdn;fY@}Zu2}(go z9H a|U;oVnM#let-XVozp0GIw+T>i H=kBqc -3 z@_8zj{Ba4fD&KT3>?SBOTph@E8#6JrLr{MjE4BA~sc}9Xu7%cR@J0$P nxbb!2s`tScg?mAK z9$cW})!-W*-rSN6DGq1lq#$>*%LV{OD3Uae6@VnCB_O3zgiUN=_SV&DSn=A}a>yIw z_rCX+q*&@M;4;3_y`%5KFlvtw*V&NWyL~?v;YZR8XW8v^zm+#yWxH*ossHR%OnKgf zi-`aMBfXbmD`^?|*@yj$XJgfg*ZPDvD-7e&fd_FNupK)niT&}PxAyznq6xTlz~w~w z?gfAsAjW`>E6=P_SY1FlqC%qMaILOcA>koFw8&UtJ59h(q;&s&_h8@D9%;+t8ZZjk zYRMp+j%9Ji;aXc+lmQEh*_%Q!N^H){X3G!d+^&);jZ?*G?65yKFzCnT3JAX6AFU%& zQVJ5}Wk;Kb@HWGrumk|YasgVl54F83lQwQef8fF}mJRq{^NQBz`Ac!D`q(bCH$}F6 zy7q5xIkUb0AFjSJIFqi6HnyFKZQHhO+cutwZQIGjwr$(CCQc^0^UkfhRp0%!s=K;> z_36FN-e<41$%-CUmFT1YxK9dfnY<}@@bP!qu=h~hLb`lCspQ6*fAcrd1kYcI5wz0d zo4yJF!rmnXFdsLT5d$V)Ud- !x`Hy_>)_?Ga z*e39Y2(>=UeZJew>@z!s_cgBX8hJB5Yy51Bk((D&UGRqHJq&(e0yc^%h(1H0>i;y| zaDWkYqbO@Oqc>2xF3rH$CE* LjE^nqr0sj;F(h`^O3hO7niIlRX^lz0P(9@yMzwMqRh*=o^n zVjg*-;>WL5D(vE*?P6N2Suah_sTn*;mc_!Vlo#C1)>0>&iGNlI9uo$&iv(^dt0w9$ zrjiKZb|gxE{zzG7KfE5ti%fj(2Trp|&PNJCumL_hu86a?4`CJOq lR<#mo zq}p}o@K5B$jTu6C0p6a53Fk8~Y{w+poCZfhF?S?x7$JkOdQE*3@1|tYeAE*Bk;IK{ z-;oBp!=jU}L|a%Q)w38@RaQ6`Tv)Vo;ZG_tyZv``)iw!0fQ#4(#>Uwi%1jD;%&nmW zm>{|G(GnRStttFbf#nj4>}sI{Oof;Bu3C$N*9k`6yXt^6S+y>e5@9czR({uw7M^zU zRl#$GHWo9K*MZxv?>j}D7~Oow&!+|^Vez9d77RSIpWfn17XpKLCy)bxYF-qT{u|Nk zgiVZ+Q*=r|bVqs2j2o*R`C#S@IeWk oJeC#G`%E4K*J@gmkzDer zf}{)ykOq70y4aGbff}XBu` yMgeFnI;|U6HG7Y#Ygjz5ps3BFNx!??HV3 z8L!EgYjd$fD(*V{YB}zU@HYt+E}i@wd>08g-rybp*BBgwZdI+)NC393__?rvHInI_ zC-F|7h#N`e#;?0rG9QBBax^mOS7+4`%`nVGt8#mov@j_>x%ZZgd))M|%6Av%;YXE` ziD+}k?v8HfbPZ?n*p`x+N!c*JVscSF@i95i1V_mvyIp6p)r#^?^B>S~KsfO{;5qx^ z9wCr`({~+KoTyQ}=`VO<#@?*Z?``UK>^|x@zZHGoq~>{A=%9-38xsX%IzK-}2hvnN zP4}IN1)hL}3R}i3$X5oapeS+_1Xv3Kv760`z!sxeNfqF$E&&T}Bj%Hc#z8o@Q~y(N z<20Bd1TP@@lA6Mu$r~Ww5QnT`uv2-Sb|+ha+7@>&!eU9kJ FQVqfJiY zv)p?Ow%@ELg>Z!>hNaBZD)Qt25oA8AwT62uR^XbYR~9`=gdH3B?Y1yV*nC~6gshnO zI1-C7+d-4PIfTZxN|AD?jm3Me?3WUTkj|u8rX~Q5iLi%;0X7626h5~ d?^J6 z*>ruD$HWy#RO>B31r*b?N0tO3%4!HuuUyh`z#><;l<(?INZ2s4#UQ|MMl~OE8Z>$( zo*2%$s2&R`nCUA=fl37dbL|@0M)mxFOQR@ni)?e*B92b;9Oion4V19CfN5}eh5&Ua zE613OSmRr3%^~zUGG5ROTL$tj?Kjvh`Dvq;S!MMVKT&d*sr2Pafw0gPM`jP;s%#(t znJ7Y;+euC~GkFN628%wyq pM4{1q@d~}jMy GIA`pvzB*t8tz9Kke!T40Iirk<)}pS!s?#@xJ^FZ34*933JL}H ztDjjw_u*dqk_gP!9ou7gY)J2pp%{a;H{+TgvDK=9N#m%AkJ6-g%Y3)`10SMCaf!`a zK<94Y%x%TEm07yW35uf4=bR;z_l`59?@QQ@QLZk-7aiBAi`5_|uCa@oy?)mq=MCHT z6p1-`oV~);UNY%`o}6Cp-ZowVaiDk@fES%q&P^R+szHY9RpyS{l54#Q6i&ODHY9e5 z6!7i27!)IuxCp~xs{Rbxp0)f}wdso!k;XghYvBsnpDX1lhDC|HhxOwR=WM@hgU|b$ z!IW3e=daK8;pLAH wSk^E_9|LrzMF_~KE z^H{dYum90$zo-xJKCP=D0Rb_}0s#^HJ3s{_AOnnC4qK2vZwvw&7LS-s5)=KN*CU6r zCWo!~+!C{nYI0=D4h4^thoHecfh@HatpGkALdvOlN)}Y|-raZO?9jCCyFIO%eTM?R zpP!el0^RL~Av9*rjHM1&Ey)w|fdlQ %r%6v>YLB}>W?TrLxfi+JKHvSyG zmZ8WFK7!AK9?oH>HC3s0Hrnf;FM}vPx-v(~k)SZ5Zf_=rFSDfQ#u=TSY9>QtFhZFU z3?NbgmT7j*cbtyetaX!ikDVzx^{|mCH~~!2(PSU*tqhkp0}rxM1h~mSw*WcnJ%$AM zqL>bJq!U63Md}z0RC);L<>Y?7wvNqS!)-2wPcYdmJW(;o`+I&qU(}Ay`wUs)as(v? zfd n2R|elG%V&Xw__X5m0#v{srPt%GJl3w2h0 )7mm}fd+@ni<1X(9rmP2!hCA9t1 z2Dp`#x?+M2EOegG8^2Z=)hmMRP}O3tMB^1bkmoth#QS>HxUh;eIo)s)pIA``N)K2v z3eH|cYqq~k=v?uXE0R`nVMEhyfT}gVeuZKxj3c{ff}YoBojtS(ENtmKoj>phL||OF z2>^>A6u3}H6`KO-@9mWQ(XH7d+JK)>-3pFni2JS6CiE%YvL`c{-7{!Jhd_>YSjGH@ z&wHe80&Adts7XrwH%>msihy{GW~vZ4HLCT9 I2QEn#vJ4AQ}RhbDTF*8%3YHn_(*eN2|oc2lp*$E|4&e+2_HI1+x} z(;Nc&RiSP(N&NF^^jAUAJn|9dumN{Cj?GH1bj#$8RYpMaZfMaumZI~9Ij)AbLpxNY zL6yj=@slFtV-M!4 0^BAM*t+T zSTcj@xp^@nQcp+9-kvT)W`xf*cY3m9|6#ONr#0atIcvYU@D?u0;VMTsmxw-) I>Tiyq*aJ~#sI)P?7{2)=Q DxxMj}ecmg;bH65lUW)pU3n-s26GQT{ug4LTa0? zqCNgsD*7shCh<6?MZCj^OVmZ|^J}V}U6*TKk#NcKl{{rwdN)}Dq--OX`C0FG`6P)M z6ex#XvrP$MK>9Wl^m1gDIzU=Vulm@`#tm9l8SgMg>E1;>+P9x#;=p`!45{ePmQe{c z4JrD_@lm4S@sxVJa_;8=vJJ{m8l*IjEAqC4BOQ4d?EypWjxKXU&R@wdv+Z`Wqvo(m zQHgGCJ8Zh~dPrv^Ebb+mS;fAHhOYb0B|cZ(x)=AhfIa%V(1CpDI^clW_AaiQQzYcm zSd!Au_ERGL>}9Hj&pq-zh3worNu|7e6F+w(= GS|Xc!OS~Y*5_-i6i#&2khqO zL|v#<3~>~$Gzj{FD?D{62BACbRnA=&Wk9g`p%xvp kS zkwWaC?~T24C+RqVgU40niMLKd?)bN$PJ-^q(4HO`KY;EbvV3i|Xyx3sw`2lScA-iD z@x%w$tG(QFl~FC9ZESv+XTGa$VUBjY+Sc|{sY84HOHZ*%dGa>dUS-uOah12DkaU?E z;8(I|LurwR%P=H08DsE ^Z)(qg#o4v#08H@&ZqIjX5Wahy-<@<-?QBu)WD1qBF;prXab zxbgEOF2Qet?0kWBlE+)`(4DA2KQ*K4T8vv;7l6)(jL UGrwlC^QlXV4VUcm@!LguUOdKg-!B@elW4&7&(-!4x;@!7k!dXh)(xTT9X`TB3 z(YwxKeU#*`=Bw@z@xkt{Gee(C&;@hrE(%|M^iXa-TPZPbE1H|z)DPGA<%x$41=)fF zaGTgvT1Py*=ZS+Scm6citVKyV5CuB;K3-&iYaq-N-dN~Q+GZ+`jGk&^85`jeX~n0o z60Mf!4Yez96?efijyzP^(WtfEG(Q~xdS~vNuB9qO62Fe7`1jx3BS+;;zwA#dUxBS{ zG6d=-SyuiW+Jx{py6{8_JJPj?y^Yp;v|4S0h_J!uV-6fS3GH^}$a=7?8a;MY)!Hd> zN)&Z=UAN uxF-!{&S*C4r(-PNy$YSZlfs?8AddK8phDd z2ReSGCV(~pQ>)@O?~dsOT!pIAMBcK=pe)iFIQMg0f~60qZYlpqUzK8Zwz1 =_0Sj0ZUsYJGQ`q6u^U`E&U;59gp3ho#$Qr! z)0oETaafs`;&Ahk;Q>(qP8yUeh0V%ayV{8|t0ZI9JKgnyC)~AyX89{5HFL<-L;`O$ zoQB^$j %Zj9FADA{PGNp z%#g377ssC`luHv*7s8~`1MLjvVASM4%#0ncmN3mv0={SJa{&6{#b!nt)+|!lw-0aj zr)v-0DQre-Ne5M&yxuR*N1oqjubthW4pA4iX6Fz!m1bQH;!dYCFdC``yWoety#};6 zBv1lDF&bn}OcmPhkjrdr{nEW=r{X+RW6lgtt+e$mxD{rsT^=;eiJ6fXpz!8Qzf+dB zRJ>TdEo{os9soIPHV~Az*VK>2pCQd7%&QssU`e^q_e-y@;C6Mbr_IDC E5tj!RHMsW!zbEKO4Mda`e>-t>Cf2?^6hmQ-en8ZZG zbi1F!+5@1i;=PC4vSNm9$f)+kUBi}#Ltlb~y&QXG`Cgm&`M!e&`Xt9=n!q1YZOZD- zwF>0wH`k{9mAZ|&xF_A&qd4W)M^(y|P!tYQi%83qKiJs_FAFo}x@W(3VG{~%W0cMD zNJMO$S0>eRV^4YIJC?*!TwbHmeMTtFe68&$(*b*5RAjigIk?xiw|TgESHRzwnAk>) zGo5 `F-{kUk$qf(554^8q0Ad=5iUx*{)2yd;ly&1*ovb$X0sLS{iOg~Ng zTR0R(rWW+#F^Yyz(Kqz1&%11~wAWcog!-e__Ek(mLtFDnoADrPVy0jkJrRGrj|64- zE&@u *uU_^9+bwNsj4F@y+B{-8KxE-cQN4aC?=tPM{sif@?i>pY_%;9* zQ87O_qYdb;Ze_9{90*?IR;HVD%?{@=mWiz|+ZJDxa`ul;3Sugf6h6she+4qIi3D8} z5|oW)fXG8Z?GjpR0PeTbnl4g}W@Tdz!U6nBXv1`hrSK4#R&~yTzd_~&^It?p$`3t5 zMD2Qz)Gh=+jURK<{=^PyZjjWQEO9Q%hchK9B_xRsr=$>SiLi4k3KZP rZc|bjOD?*;OL6uhPptM-__$|%>N^mNaiE1R7#rHSwlTMCyl9zO&$Pz z29keIE`;}zWkD9P5$iv}oX~iwxJ>?>knd%SC0t*WPH~ql+ZY|4iU?bOO(-aLk
4D&3b(KhVEH2y9smL6+Iz9PJ zjJIk|r7M`ABnCwmSak`fgc2Dzd^!MrA%@f=(^r7P@MqQ1 VXlFS19mEF*I{j^AvXKkgxhTPrWXV$;qeb6sKli&|ulJPBsQF!Z 6-&<@LKM>gnYge7O2K3D~UWc`)L3(|wF!#?^RjAzH*@gHCLO+wl_5yY^@- zUpf45`!*Y=-`G6_5YQ$z5D?zK>H|U{0YGYT%?<1*(ROytcA+|nE^@dazodRjomeZe z!Wh>b@Qy%5!_b+iQg*$6KU_bS;dPRMseE{sloWM1=~1g-Wb{CL5xotm`&UdJ)<2-l zcJVaP05`d Yw&FbE_D#PRLc_w9vFqB?w)i=X?eeU 1z_-4 z%q%1datPi)dY^cROBdwX-z4ONh33A)2bJHd-Lz$n)x99bKZ(@Am}ES|)>C%-qcOVw z)SnYB&*Lx}d+_ikIynULP@l|W^rs;gJ_Hra(v&owAZ>`45Qajng6Y*GT K7m zoMBpIF|GclzO5{f=>sF9dq#m4Az)+UC1m8yDBjV;C-x`3`A6pE&H8d@ wWlE|TcGu4GFu2y$u^_?ua% k_|u zP~LW};!&ELisc>SFyWd)63&d=eqC!#rU5aST2_@PgV{ZmfXpK77gbh$I6z^!SqmeH z<5FUvkm$VwGE9&m<`xhpAuK#b3|k* >+Zw}WD1&k34qrSH{wYFC2{7*&=B50$SonuYiXn8u {1%OPBW-n#l 12zw!y0v`wBa+^>Ojeg#YN`pe>^%3v7M=UW5bpn>D*1jtOQ7 X941DTx2P)#uDT2%=X#ZvYR3(Vr8kjtsxC$NVi*S &R2A~_Tjx~^`*Ki%-cv=3cKTlBjRM>;@G zL`4se<0FK5t&V3pizF&PUG4cotG{j6KvyBWW|(Ap0P!z6fdJh>8@ay(Y~sRzFZt#c z9c`a@!^B&=IOY21GlTziH+9jXlp~Z=S3?%jM7P%KA(7kDRO*u;d08GH*CbIbv~$&R zq}uM0CQ)Ex>h8BJpt>G|tiO7Se<5qb$bV92H~f+=GjMX= Fv!m4-mU{<`?0iIg8l7J$ZF8Lf3w&ptjb?AE}==A zxsA$w(6E&sE_SPfw|%}o>BE?7+P8zPhX4n`mXAn*_vgHjZ<-j# j{G}O-iUX z?srmZJL nBE4r9VM%$OkLm?%LO#3t1em#ugOo{V-gb8Bd~u(%S&hme z+&&$M3Ud+_#~CEKd|cw=Y&X#)``je2i_R9MMGbQQL~NFu6+aEFFk7*c@QD;(FLzCv z-)y;LC%{j=QPo(S?dRstJf*&{KuIz>#?w{HJ~_uoR<}W-4FkC_RoC-U1L;XbEFDe8 zg}>s~dAXDkTQ*eQ9!`OF?jE=YQo^Dk2(ifMPOas(QR4Ij4*Te1+?%a@VxQ4ON2Ca% zt{UB3A}D;+Iq?0%z%A2yg3XjIdR_w#Hr$<#8bE4h8SLe$nguC6+>Wy%1AkPj;T*wZ zL2lzntDt?Co)m>zUw1#ru<;+wYTH4FWGH(O4ygCvQ+B^jxGSG7CRb$gl(}^N^zTfg zIn8{wk&7RndL8{WK0%$?-{?)rt$VO95uBkd>W+4=G}8mE)a$!y<+R!+?R?T-xomDq zX#mi2WScQ69ES=kx8fDr^)*Chk90a!V&$w^Bpoh3oLfa{ww` !JXQx$MS4!@ewkIdvW+TNI0}H3P^M*ey6!@doVFAvUbpRgsl9k4HN*-WFKxpo zrv_I~^cPXdmM-`Ht}Qw@?b!C>Y5#Z`UIvhL@p(U-oP9VubB9E6>{WO;bG37pISBO6 zzwx|!Ir|Iq1$LfDo>zP )wq0x#-mJc*LqE{)N z+FM@vBuH{&&w4HYo)W-&cxwBj*Y}CLH 6z9qD^-&4%UKAPe|7`aA8|UN z__Xl %GQmNR&12X^s){8!mg53)dB3mMD>-_11uIzabEBsSG|hE?)u&nK zAO;!MYraOg7+^H+*)n2*$*_#FB!y;&udfvi1ic$j7z(Hl$Df!r6@`(#Em>cdp`XE(7vMpwZ3OIEvp>QKfF`0qqBx|WE&OigU z+&%+#Z-=rehY#d~J3cOz6eH};F-eO|9K^xt!c#*a>(Me{SUnqk=}n5tIDRwW!?}>3 z y5ov=r% zY%^?!P#fAL*7(Gn)!+VdzUdtXiU|Z*D| 8C>vPGIUfLva#>F~@Mf%pyNt8Xl_ z7><7u^4AD!z(bs4lk*}GPHfwO{dA1BESZL#LkxU=#*#6uitdlec_Lu}pb_?bB6*a6Or- NT}%|7u8V~Xz5I_(D%YS^}*CCU@Gi1^`z-&ImLz^s(o_NC8Y<+=3t76FvG+n z8Twk5Rt&z?jFMPWxxn6yq*^mnT}>c^F#bXw1*WF*leiTfzXdTxDdkyLQW=%hxsbEU zABJF2xu;E)omq`T-6?3hke&g2nDv-n9rrZ2a$u+Uq@qbPRq HWn Hv3%vXHqFPw zp8*eVW;Pp>#Rcrl=OuMKgcSPpbT;Iugp=LAO=T;jhB2t!Dgd|G-#slOZpCosoPp>5 zi~K3$HtB5K{F}%_xTvzZf?=o~Fmq&oe!eSL4!dq1LNYdbjW-vUdHarXtCd#^0bf%^ zPR&a{JZzF4m91`>TRFg1{Tb57AVyeX1#TeRIpSEr={X!xceV2~%KsLIWtA;rv$JM( zeyZlJ0o}F*hg*%yz$jNvA2Mkoo#EU9DsHO!5T4Z zerG3)E#WF_?QX2EbA 9^QZZsq(PR_$Q_NA$P2yFLhAxC srA-|QX!6mT;Zri?{(dhjdfV90prP|E>a zxr&`jj0`~DRTu!H_n5)`k9V;IJ;-NfWr%l!g{W_FWd@z6h5`1boT31r!vK)t+H0S4 zqt-%@a;qV6w+%FWIC|*l|69yyM-O;Y=<|aMu;Pci(3>JF>l%qlJ5C1GVf!IR%owq6TQ-eyyumum6s%P<4Zwjy;h)Q zX?MFRILTXy9WMDiThFFFeO`o_X{HKH=Hv~dRK9QFL&qPMLTe=6+>JTIM89Fs+Xdz+ zBo!E@AHTT0sV<0!awx2vDZ+$c&ULty`Fmc-TAyh%0|uTU{Rx(sxeS`Ip2n;!r|?Nx ztrkxPKNg)6Hctjg8C36tm3?onI907lakv+#F|Fq9|H}LK!a(!dVSs=nS^vrVo9fU3 zc5y#AkiPtTjXP2{c>dOmj`#BGl(VvzDprf-7Sxs0h)m!vc^Y@tc0iY&dp)`sz?9wH z=BAG`8U8vgy=G{{`4!FP_WC}bTq~?1WtKqAh(8NxGKdwA%3I3vK6WizAJ_P5RD`VJ z!$It9OmM1OQc5;q@z6ROzMsP_0H}rl@x$Y;h+(q_UXe>y&3|&En^E%zC{0cOntB(J zv4B}hCYzgIk(%#xIrmLs!gB $mj)+HZd}TW1 s69% B? z24B?%y`M`-k7`#*in=ZyEy|*c?rZ+Q^{$P1Yg2-B5B8`1qy{}*vyFGK%i95DvgE?? zCC)cN{V`}A1BM`8RSIm<6&h87Lr{vSG z>mjEpqJ$;4m6le#N6%1WnxaR?fpj^^I#bDTG;S3tOFocRS`U RLiilq#j zwjz&UwYlSkqEjH_8q9tM(|?0aJ^2Ryw|&Jcl>~d1^VJ=cg`FaTF~&9sSNc{;q_7$j z+A ?~Wfe8!G}A zb>q%;A)c(jz0_OI-ci$cXj4%eASIVj^MLwNJ!84+;|@N&Skg5*Xrqz^Gp~e*Z?gnE zg<5KYSaJ_zfV19;>bF~GXQJyY^p|fimYVZf+R?2Fv~4eI-E!>bd-DD6bD8m)yhR!( z-pDSZWHOY|X?D=V`K&v&(;{|d)*x#I>EhzZLzEJG_ehG&Y4!Bw(LKHIDBAmi{&z97 z)77LzlMy?yfAV+~cmK &a^iPqC*%-(@Lx$hJy$l6=eQJb6iyb)~JWch^QmdV6ebbq9G^l1=3cR wCw2{#m3OGEdK5jdd3duN5YM8S#an zY{?M?;5U2_ n_MOs6mVg5TWua=Cj2`X!RrhjTvI z?Z-f#EG>G%4TgIEaSL=FRTYh;3H07%ld=`(DdBmwx<0PN*SdM*_F1!w<0{PnlOk=_ z=;zJ3{Mq5W >{z?Dxf2EGsn*WJf5RtzAs#@m43W0HH>hTz)k|tXSfT@!%TS#H! zEEdOInR##s@FkLdwBiAhE}^Q-7og0YkfqScToC8!^~9hBqr6{2rV5WBy(&FJ^=ilM z=j 3jL@84}=-xCli`Lh#OrNJsy$?#fcFas=ld~;mG}Q`r zAfNUoPx<}BJNHng`Q!6~IL+2(H7oJEl;SjH!*ihJyjlMwD=7fF$uJ?Xilw<(f)T0X zWNKeO!y!xzV;ADJa*>1BUVpId!39!xFtKtEDhI6M+k!GP!gTSa$?RcJQ_$9e2Ogsr zpi2kQA;VQ7LCKh9KdYcfn+sC!2?Jq(o3F%oxG^(~ju*9t-m0EZC$kIAm^jEtBPGb9 zHUSUP&|`V!cf0|*CaQjX9x2vJ;In_(aPz)dfbs_~X&I9f4GSVYydOc(*iZ62f?42T zxZP`OX{$5CN+-7XEA= r71_HIGMsxPmJj%@8MZI&@klg{CA&it@>3Jovl{-` zr^6%dOH;O*l5ixV#BlC(ip1U&T}*9Kh$QPgo;W80pNO}XPGpulZ%!LsO20FP7v;zw ztPtgL9Fbtd!jw1P*-za~0Z8Vdi0N@6uMBE)#Y+k!AB3WtnHhFbbDgJh(>upWeXvqE z55>D8W3a`K(n9gzHsv~CJEWRUL~M-)>HDL>Pq6j^8bi|$-jnd!DF9MgN&ITcsoQ 5t6WM8NP#5zwL=*!ERI7ZuKwH@r2Z2M77ub$8 z84qCj%Y<0)JtYOJrPA$OHT@+x5UutCNP7y06b~>&U|y^4kXO^oBP-|~u-KdqN~^i8 zXdAkuxVOBUecs?RivdJL%qztp!?wq>u#tdYRCzo?=zm_jedVih`q|Ac5#ix3wiH69 zjaa1gt&4?=qiqq>#nHKC$-k>(3Vet-mpp9v_RaimZGERonDOFf tqY{S?qzW4wW!}doyt&u5P2tg3f^)A`TDtM>FkM<6 z-P-eRZ8P}K*O@=PTYUL+z8oxMIuzF3XERuhx>cXFAIz+>ye1<|>DwGIS{e4d+<^{@ z?wEWlP4{)KaRCliH^mWs!7Vh;5Paeizh&Ul#+p8s77kfnl` ER7q6o zY``F*aB(>*(`?DWfL&o Op7&BgFGnq(YmTRxS>eeG@9i-*i&*MVD10Ui%$xx}?Y=0eH{hYjng=KV{5`Uts z4rO (cqMRNvE(;YOO z(sNJW $vpT5mPB4+ z#EEX5t9Ciqzo_MJM($|&!$pUyQ-~+xIr-(2Vh`8NB3Bv9XcP_G7DG`AQb0pm^X%lC zfAcPCeSD2aNmuA3J%5q|KAf6)dAnY*9qM_EX`*d$>&1D)aPfQ%bm@DqMmc_|XS#~p zvfdAn@f @pvYSvkj?PuY{8oU1VVF!mnLV z2F7{LN!R!mEH53YfSh&vB3P|7wdL1^IbOtTq$S!W#+6|dG2-0-6AL3iG9fcYr#90L z1$L5Uuw*liW;8d7IwefHn~u#aYJvPpMM$2H3x;yo=bH|c<4hx#X0Dr}`oTr#^ZSo~ zTR{B JL|6=i7E@X{FxvM#jGsjH-Gs~&?#m}7Z8y#& zOF7`=g$Y_wY#eBS2}@S69$GWU56liWkb&)~ASQz5a!_!1xG?5Ta}L753m_%=Fp!D5 zGi2aW1bA`G?=?E# F0q$lnjkYATa8b2 zAuXcH)p7{mK$`8)6BLbt@? )kLDb J-4E3_Mx=MHH438_zzN6y9v&%LtZhvE^+_a!0|KH4O2GnV z25kQ~;|nlrP;hP)v@W0BVij2(R)QC8R#kPKuOO0otXWNmEoGnh^~A#^CD4ce%eJnI z^YzBVqxXG+%**4;&&kinD?nOD!!)@Ka$_llm5RRFZl=((TR-g5>enN6=G5tf<)Lex z3U}o%-I8>f=-i$d#g}v0?7Pxw{dHt7fQoDC!JQ{Y`G_IN&*CFi3OwfW_LA@vRUCVj ztqo$%Vag5I>N<3ayky$olYOpc)-DjW++D01rJoHsM;ba7nHuO~h=-2&_>fhFBTyKo zhP=FTg*iEx2xQe>ks7+ra@7l1Ok{LvNd3bnx=a=nxnUBs397<7B%O9ZW^W_nfGMo# zK8whhZS}3>>`f7R>FFr6(}A@yGSa=2H7Gn<2m3S%3Jrll1RqA*bc`4=@y4|H^}D#? zr~6CRuApeLdHINFaeA+LA|I*Jd%BCZQcnd!Bot1eRF9QOXq2}kBz?pq=Q6w$)KwHF ztzYJq!xc^86S#EXhYOBKqoh`>019XoE& 5zly5E${slJ zKKHk=US00N>If1wk7=K2vHZk~3GG`g!2*Hj?ozHccYtDf8Sz!`cpfl307yZiE}DB} zdo| +Lg^kn{oxAr)MW9;Jk|Hn^nLCH zpI!NkZ3jHsV~uCKrxbUPp@-~Yl9!fut>)VVM~|K_r>cCFlM+etm}l+grDd~}_eE$& z#B(5Z#|lSR;}bPNim0NO#S&gIP-pqiGfGNNb+Q(9m(YTTmhvulXHb&@m k z)xP?7wbLXyE#V~Het@URfdb 9Q+l6HVK7M g@u&vAOD`e -A6U82|m?>)-{&>&7wGi5GO93;R>bfr+I{kLXf<7xpTI9IuAFeEk-RmcoP z6h*g-S?g(oulS$RN!LUxmtL2N-5yq@4{Ym}IdeHbC8?K!@g3HqfD`_+CT!(y=gUF^ zl?}_(ivppxAJ@eh2$_p =Hj(yy))Ck{3%HbYiD90L|>cVT?amR9$K!^wUTH?9lEt+R9o)h~*2aR1bv*inz$u zz;Gv$r(Gs(?q?|=-A~*c9z#1VUB4FAS7po)vc}B>EI2F!(uChi1zh_F BsVXlxdF4x+3z(?)Fb7w$ZM_4Dy0EdzpIwXRGz1UO*Uuj1BhJ;Ilbt?t?Tf z8Uh#>aK6CaKfjiUFv6_8Q8iaawCP+mk{V6QG4B5vdqpbO|6kPaX* IEQ=DVu=&WHbS=60tGUrWa7o{92fjbuv@FMJY05VBI>3 z_Dv=J+c)B3{p(xGrX22GajEO8DpInZx9qI^HtsV4^HkLa-v=4%nPD)$-swPgE>P|+ z61wzP0!)!6%pjO&@5YRo?KRx!SJ)|~GyTfgm9!vs3!6|CoA{nfWb^v5tVMJNC}IYg z@i`iWZdPC7etot>`#pvLKE~;($BTaqAJ$6!L5Yy|a9MoReA*-=Z~!n)nj93cJfH{5 zuMIaRZU!Q42Pmo4jxa##sI;JN~)}Vjn%| )KC$p~Si5mvZnKx5M5uq{I7&5zmPi8>UY!7ct6If{u_ z7~S_NrUcQsR5XV!H(nq5p3RE>e(NWs#Bc8BE!8eGm61uqjQFEr3BTH0q(!+z;}jZ9 zan8mgGFP32PnBgRyX%voin^EL2Zk@U!jUNOMj_+MRi$@Pdja-9$H#wd0=cC3rl8&Y z^`tbU&tHs_)n~|?6lW-e5+v2FOKe#`omlv|JN{rh)V=q~Yc6{pRC&U1@qhTc^L^ga z_kfN!n07|MLkM-7G8m+08OyQjQn*SGD*xaNnA$u$4*zvvgslG((Y~FVOhOqM+8 G(DhfOe7U|836*Lsh{0F9hTjm8W!#ze?g^3baKT;V;fIsT~>`@5#AA;qjY!$ zWpzz?f=|OTek7A@bjKw _Uyy%p z%g;dMwZ?z{9TDjyC2Nc{01FCS+5{djEMRf2wL0}9aY)`8c5DF%XQO&J6@fC8D8Hm} zSc{k|G19hb(_vSs;UQ3a=ctXYfz9AbvLno6mQRBJ{&&=At^Dk64}Z{*xm6p7D*@xI zvXQvHaWywWU?Js4;i(KCJhy~|ME@4wVS8At3VA6BVhE(h?sNVJ4N zEv9^XdVn5fWCLfbkZCkz)5#c%J0PJ@3hBDyQS{LCXn1R_Z+UkhdA8lY+xOx5cz<6( z;N9#BW=%Ac23A~xL*x&nKktMWH5L)>g42AqaDmO5@?@;zf7JV*|i-Pb7F s7DUKJ0c6d;R@Zhwx+#TB(Hh@2E|9T`&Bl9&QW3o)`YHE{Fsk9
lSEf}^I^Kpk&2Choj7bl?(hl8^mJX2J5LYzef5)H4%Q z6>OTK=5>rob5XL>QZmLxlTp9jz&nrnZGqi!)NiZ5Zq(^eB?ppcbY8!A%$}9Q4MVo{ z7^_AnIFDsye3b>&{0A>k3ru}~=hVJ@&_8|9I}50Qcjf;1xFS?>h1ItwAXR0Ah5-wK z8;}Cs0c>eao6zZP=!20 ?NBS%DE6gUa3T0r5 e=gXF|wrWe<> z5rA`FL?pMB%~IhH($Xq_3o1k77x2vj49`@_r9o|L&6Mx^D<@SXs4K1unWr)FGs7~u zOP1zk)|E>mIE f1 zV;{~F`iK0YGxeoDmU +k#J&&MWm2S(pb4`Wy7v`EEVH_Dr7>)g}cx6w45Sp zK#U~G4_hR24%H~yV@uP!X|aq=Ne>o-@0VYeOVQqebF#iJ`IOUUsuvF1hi^;DOf^WW zu|$%m$(^of#8QsAyMuE^N Hn(TbmQO7V_fxZmq{jt&Ox!)^S+On4z} zIZcy4o4*k>i>IuAHgvb^oz!}XqI!>8yVjN#PUhqF?ObDXugRyQ
Yk@r`KrnD8TZ0&LoMB Wk&t#+3E&tmytVqtOYlyYH{=4v_kbZTjTjI-FLy8ExXuXjPy2ERff zwxJ!o`VF9bYpwqgU@JR$xY p)TQ;V`enV5 zP_}fO{hFcrueE1zKihLullDIa)ohfT3Ho0Mq0_#fO6YXz-y6ywq_)6ot`f)I$CJt6 z6UwCSReVc-nfwg^0RR8wnBPv@Fcik`d5WW4Adp&06Z!{eE$s<*vzuv}kZDdEtF9Bp z4lUaD?mH q97bR41(T1iz{?75w$6sS^X9Jya#b)IzEF{-@9&7^!RiCSX#c6Rb zvFc_PK+FyAuky6W`XZhO(IlD-uSe6%aeo*E?5yE`kXQDQ7Z(>^@y@*x^B5IcMp5NY zfc`9b(L3hGWyv-oU{@{!(tyq9E(7Wl9a$Es)D=4F`gyuCe!Si-b!FA+wU2AG552;9 zkTUuxq)d*Ol&ME6Vm;T@@nCN1#oVM#=B6DocYVCfg_n(=sNt~L6Sa(Ip|1`2%L;kG zfBiv!8g3ZA5BRl;-L>27WDO~9$oV4gWe3An?O=xuH?(>7V_>e%$~MKEZ|AmIRbPy~ zylQCkst1{95B{h__`7zvJdR89?@Z!Bzs=&d(s5g{3tnD1Y}G4wX&1Wo%Kt-eWHZa} zkY3N09eKIkuvND^?hfC`_S@zt@U64z?+;&pPZJZ>JR|nn5nf(AvU%}?cscK*b- Mr78$RgKa*U^kDbn>xQMx1=+Rl)n %>@WYBix^AeMRPugM*sl&x8k^1c*u2gMO}(;dD=X&JtEZMVJ6LLe zkFI-Qdtvp%fv1?x5y!Owox=_P3O87!G16O>(`&{)!4kJ1g)tHVcP8ib0XIdC8XnUE zHe!_+P^l3MgamWEp`mP6NH&v#eWh Y$~J{GA|q8sY*6>g?6nc5FhZ?B zm@@Z2U&$n2pnjd_3rWuR)lRsIK?|BmA!(-K13sWCv!vB2)WT3L_X+p*YxJToj;lv_ zEjCrgB!?6~Pd_NvGl|&ebw3js9awZtaLhO)IWFfxVoauQ27?55@oxaP? @V5Q c7hDU(|%OZt_TsNpy$Dq3aW{fI)GFPO9e_D%r9l?_;h;V z(MRc=iF>dMe}z<*&TW($69CFQ4~$)KYH~_#ZGW!m T_a zyWc}kTQfGPX3B!m=_<+d ^+5#_!(V{tClu zxVe4%>UMB<_Y6jZyV3Ca6}%i=4sI_-!?)M)Za8`km&2DY2e*Uk5e(nlTn*mfC;#>i zhIjDWH6DI<@g6O#_ 8i}59!?WBli-8A;W&;I4g}`S1Af|PfNA5J^-tUFsKfO zUr3CIQAE^7@3SDz=tQ9r`1J9+SrEgz=VIb$l-Y&mK7fo^(w=Hrs ;yjtC1YJ|oLa9%CV`=Nv!V z#qW;kl-Uie&URuI#6SL3O8c{eMT5AAeDg91Q&~hyENcsDXHwsrXw{Ao4_1^-S%lRi z(!5cluw)ZXx2d^3r2p(9HN}ko7gSb2iqD_w@C*>Ys*f3cpj@izi^nyaQ^1onV`2(4 zf1A=x>A6oSA`;bPHPm>7ksMG#jco=C!ok@KO%YT8Ig^YiOEnZSD>)5eB&(xngg{jC z=Q1F+wHDYA4WnW)CQ3z1Mu>Au*-)@)Zh=dAkEnT1n}xkf-<_~84dOS83#Gz~O4Tm| z!Glic@U(N%>mKX_f`SC`FO?0MO!rFrf7QPzWoZ;lN|CzuWw14II`!e3Xj%Bo`(vfu z{!#Z^B!0?qlR4Y$NoY 7!?L1P_>yMTaP)~VeP)3?4%4OrQSr6Jdayac#Lr6V z+Pm`?CK~2>w!W*^_Ua|CXE5;j3p2(!%!n3lMDR>oj+v%^m58+2#}N6kqpT*3f3+eK zVsOgTJUVzZJ8U{WrFM+)E%i8Aj9C^P?oL%2s@;^j1MNg|E@xDaxl9R1xn^f#1jD_k z(VOVe)OsI%9$8LA#_723a-T_6kVQhr6|}0<)#^*-rG>Q8_dDSSEj>(w|9Ms>}(k z+*8Ty>_WIj+sNgfLYF*H5Yobe5L!qm6~GF`X@R3Vbz`qAr {fcZ={b(Ytw(kRFH;UWvnx_u;dBB#~6 zFX*~Bf7hILoA )Z7zuDpM#X~I%{=&jY5 |kX@L_3@jdf_@Fv#O zr`zXA=k&PKJ?wv+blph0_PXO!L~AcKzQkZ*CbO?@?WW6}PZ2d}twS$uzgc{{`&is< z)MApRR5fyov{mV&eJnj{*3t(Qq`z5gkN2_oxKWD};%?o)nZ+mjSbVbO3U=)d|D81% z=6(_oX@f1s4e@TpZuAm#xwg2yW3LO_E&49E6`Ypp1r~pEt{P9){*cgU&OP7sgTUr% zqnn#r%YCFZSe`46!>KjRNy4~GPs<95L*6(ei$)w+upoZkyxL-I1@5Yx8zQYP8>}Bq zXPV*itRya8i?5!6r~9DZ>Hj(Ex!a89BBr#QFWeoSJMdos00960&6aO(+At8t-}5O> zsnotHq=0|uS_+n?y_z&_lQwCZrYSPcK`b2GwH;c%{m#kOZc~6#rPFx9p9_BO@%j9- zxn?tOxdx%Q_w&RiY&uJ0 z37+0oCfs~Al>=@qXkKCy>dv!AooC$|k97^M!tQ@e@|@d%t_yQEft&~4UpZ6RzRc&z z<>+cM8V^U8 t*8k@GoOPR3Y@x6Xvp%8MTPfy0zHvxQQt#JW9zxxE6;b06~Y@OZV zMWJQ(|E5caJGwNwm fm(b&7AprCut)JZ+ YOtUg~R1MDMGM*nx+Nb=SKK}EmK2d(mJhDJVJU jpQczx zH)y%d=xWeKzek3~QgpR @6aWAK z2moq?w_G# =tJ0&0Y}NmT(66bNdB_f{S>`Q4XdX#p_- zWS5j_0f8KT8|lIX0}%96!IOcb?B~LA7N@*4!tMo?o%Vj0F=_!aX8g4uc?KOxisxc4 zm ;sI0iNQEW`WAagG;c998_3Sk>3 zq@|ed1&K5^B2V;0Chug~JGuIN^2;ydkD;S&7@N41g=MCUyCiS7$!Y=c2MhJ*?YCRM zY;W(p?YG2o0Tvg3?@uE)5dF?yVWm|I6=Z>OZ3Q6`KXNS+;t ILdNv;Vk{nC@}F7bNCGjHB|-WZ|PQ&O6&E~t% +=r)sH4y7Y8l<7lViK@29K`umCG%HgQ{piTv z$P!>Ep9fTbYODy&OFow#>qQ|l6CTBcF_9XHnW=%H_5nmQe=0IH8j%GI#cWrMhzc>X zM7+sTX(kk_uB7$Cj6&X&Q5hpGj-IHLTzk uO7vO>++Ge>6}vpvEua)5+3y zZZB+&IYex1j`5cuEYD<~;g)QvoKr?~p3hC><=NnW?EI|X6RT&>6Q5mQi`%=aU$3rv zKll1gTAmu`eg4#p@VS$uCZldAsVx4@54(L&l{gZ6;;z=61Ph(2dp-k0N3t&b?#mFE zdWCWxB?_ZOWq{?;{{Ft$9$eh+> U?g&X3vxI$)|835+Kv3;;FTb#lhZ4Wgd7KXD*Zx75HFO5p*SBo zH)f!0JZp%~9(WwY=iYo6^p3^VqA%!8D?LVkav?*>R;3=*ENNS~I?aW2;;fW^0*AZH z{!*oyup6h+6Q#9BHwFkXi{)5y#i6!^KxxFzRI0H>cg!%J7>YO+9cG3|3+dcxOX&g# zx4IX1y|Y12^nM@oZu(arZp77lfgZ4M)gSalsysdUlLf2rce&yGC=%=)2zHib+~_ZV zgTZYdOgmyY20@BtiLN9F231brZrn3FC0mPJiV8+KgI(|nqcwrlNL1E5%|Olv5;tR| zp9I1#5I19O!&$Z&fkJwWgo!fE72xDlwayBFCs(Z@V`H>j7JC>B!q?T#oHxsPxnhF| zE8;@LGMAiHz@>>H=1Q>-S;A+SV{9dVCF|7){PHlC6}Cm=Z`c*4JGkyA{r>f841=S& z-Q5@A6~;W^U>`Za8-fi6pIy UQ96n$ zpf9XJK^Y7=^~MH>P}y27-E-m$&TF#7QZc`olR^#WpZE6L2krg6@32Wt62OZhm&FBt z9#~VOZ&YKLQFG7k^T-=1;qs_|!H{s7GE~wkj3cWpV;kQ+g0BPuGtBjPj1dPrVAjBf zOflijXtRs}L9f42^U}c3YV;cdG}>pU9pZM#Ic7-sFZ)uTbH%T*zVq1oJTOelO!XJ~ z-lq1r9WmdD1A&R Q)3@?*|j4J z!UbT8!c4iN)!k4865~pgHhLPU=)#$9p6NJ}kniMW=9Kb*;22b>CuLj0Td5t4j80qH zw7MNvLG;a54gKN@ U#^9+jh3_u%ly z_WlO2+M9x)_4RmkkJpB%R+rz6HpHB~2Gd5YQUDx&nmAfztqT%e@D@akI$Q{bMFKHx zg7}~3!(iXD#@|TVfcQr6UIpUSdT`6!=lJnO_D!rwTiuTp-lwurwQ|`MhL_b=_v=?^ zcwcW$`aiXK@nVs0iG+0G?~$gV_~or_{TJ(ao(C=e>e=ESvUp83*^IO1zAU<1e*sWS z0|XQR000O8YJ~SzIv8ml- D1G7n!6 IQ!nn# z>6f@}YU9sFRS50rY_?vnv-RW5y4CFX 0K9=(Lt*bv9CFB(|^a3I2b_CQen` z<$HE?*)G}AqlXWFnAz5k7I AfzdIkw22&u7uvU|S;_ zbv9Zlqnr%ZjYMHhPzHXyx_*CY3$pX*Bzv;+r`G0DgiVX5g1Qc~!uyfHo@XN;HnsAV zQlUqra%y=tDzy(Yf@P{|eXZT}_4^O6pFMl~d&bZ9hJE358-#bo@R1*${`bdsuYY-* zeFSdvSzNTZcaI>P^%%}`TW$o$dNxV{OtnEwz&cv5j)g9_AL8w=A{u|6nN`OqkG2P2 zbY6K8Dkao)0gz!wys )uJgvec?BVb};Iiz *RKEk_QEghlMOoYyWj3iGA3q%X@h2l?^*E&=~ zV@RJzX;7e81aMWL7mm;*FJPo=j2~y>r|3(8j8e`ec4lah8;XB=shl!}qIe`dPM%3) z5rvCeWg_AAuF{mL4msP1MoB{@AOjxbaC__I($H`vIk~wS;8n(WB*m`u%7{y~5v@hG z=xKJv18Tk0MKXSbM$-jvEn!GE(rxIeiKsPIjS=TBQ_y2ESIvUL*cstS<} s& z>!z)#h9&=A+YWyl za_t7D9e<`%fvU BsMsQ62Y@;6F2-<0`L#T$x(@BYIUu1T@$|{H3_m| zPi-C9^`n0@o84cGUBo66FissNZ0CgE_yCff%QU)ZjC;)SN?n(>@LAi;xL=j?vxnKU z?BVQ9`ZHsNus8^0zb1h>pUFiwWS3P(+|PWRgY}nj29;f8Lxi~9M4SUo@4E(h^R}T` z)0whoa4JF2_e!0z^{!rETGK8sBs74)O4tbC$;5x36?ktj0D9K gk9T|gt`*G>k0N!%6TP)u7ARus zb}4^oY|~KQq{n6ydT-!nh+nbd5l70{ZdK9VOH0E)$q1$cKaSP#g*Aem>}>POlabo> zEA@$*wzF6GFI6PHq>9@O^;+kS;6I8JpHT(-IEGd5sM3t^c;^;}TRmEwml))Fx#92< z8&27$_pd>QM0=1;kC^q)Q-?Z^1p+;hnk|3zZ)Y^{B}P3O)W;Z=Vc|0wrdl}|{R-64 z {f#H(Nm2_(i0Ri}7ohP0es2|8eBSYtSsCw(tP=ph- zJ;ge7;i#x7iKz*AA3vUmmA;~VJ4!&S94SJ{TwPv4vr4LWvsJ>@p|$#M^a^MY Eq7Xg^XKO|h2Da+S5)k&6?| z2NH#NgDMfdByc*RA5Etg>c)Ru6%vIO$0j^2>ExEGDGD#rtcsHid8F2&g_A^0Asvev zqL)2Jp<#gukasK2ta1+akgyik8VQ(5GAPYrIM;?c;Y!vWw qFZ*m_5j?C^Wq*Gjiu38+&AN9_ zuJv<@2r#B2=K__Ev=@;P@>i$Buo#|p<1yj8)MR?`Evm9#I~Z%}EWg#%NpvvDvn1OW zh=;7}a?3bWyW=$FdlsAWbwwI@I@TS19!LCS$dkJYIJgnRc5z@k9i@g&M-* n;?D{3uk{Q-@g`9slfa=e#!0m>1Z&Yp|E6EhttE=XS%xXc^oLLD`f^T zi!~T5nctt#uh2i6epQ^&K9T!pf{WQCsV-;(4A!`S 7y{luK&aepBsa~s(xxp#j%abNN|5@P|b$5nrC9@&3$%*RP&2pW|UJGF-< zmEHl=BEJHoZ|cwN^Ge@8pz07o0XhAOGlL;r-D4U@E#s3kbWdVwDRF#%WyaSw{hgP( z#)L)MB1`h+8i|5R*2}#+kXLjBPvP=#s4UBFdoRVxIE7uk> __e9}o-FUAD&r=(% ~!kT}s$>}<3kU$pbyAf47eFfr3 z6X;9sWbu^LA7YGpffCO>kL`8_I9u940`y%wC^~MNRC&SL`+}w_t7oS^b=s+h;*1Bk z%~x-?h6-tTK@jWtPcr?V8>bmZRe}?0+eX~u35Rlp*p^Q5v4>RB8tg&jk$5sOAV j>Ob!8J0!k1}0l`%I>5eCkA|OmhbW_;{OO2Q=iOX^)0=N3(P`K>; zMbrsB> 651?kEh4*&)#4yel2ytpyBK5yN0u^N$$8qtJ=|Ga+5FdJFG81 z^M16jp}ml8dxOc-yEsbbPW$g43AT%P8~<0j>uu+XgYezi+tK15pE?` ~i{I5+$Iz413m_-FT1PFx460pUU9xDtT>125f0`$*$>S!%-+H6hujFp&>yV*)@M> zg@NU(sBo^bSHoce51CGFT$RI03+2Gr;V3?jN5l8cWBg7$2o)Eulu^ *!^tQIqm89a_?h@{3`K*;@ z@AiP9 3GVu4`5jK~Z3XUw09A~h?3ag*02C})YRD_*SC zp-2l?o>eWAYbo0OqFpuTRn^d3F^58bo4sfFjwxOO$t4l@1t=yp&&X5R8jnQEQmvLE zuZ=IS0fRV?J%hA129;*;;6PbCW7>F*Ck8&$!a(-?dPo{|X=Qb7QrJ_fRvCX7xhClu4?~N@FxIuSLntnyp}cJ;VbvK%_;ukM4CGiBY%K0E=vsrKy&6 zsTh_zTCdWlHl60f7qy+{!{a`HA&|gPd98qH46b2*;52qMNhBqDT6}*5xn>K>O7WqF zjVE6#3@9%v%+4JLqGvIWGPXoNSM@>)TacCL8XT%6d3_0x*-)##OYdr5@)gt-1Btv$ z#GK*EQo7 fNj@oWqH*bQ7nS<=j67z_0B)0 zx|?=-1Z|__rw_GuKeuQ+r!<~786IvuA BIh`c$O$=S