Cldr.AcceptLanguage (Cldr v2.31.0) View Source

Tokenizer and parser for HTTP Accept-Language header values as defined in rfc2616.

The Accept-Language request-header field is similar to Accept, but restricts the set of natural languages that are preferred as a response to the request. Language tags function are provided in 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 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."

Link to this section Summary

Functions

Parse an Accept-Language string and return the best match for a configured Cldr locale.

Filters the returned results of parse/1 to return only the error tuples.

Parses an Accept-Language header value in its string or tokenized form to return a tuple of the form {:ok, [{quality, %Cldr.LanguageTag{}}, ...]} sorted by quality.

Parses an Accept-Language header value in its string or tokenized form to produce a list of tuples of the form [{quality, %Cldr.LanguageTag{}}, ...] sorted by quality in descending order.

Splits the language ranges for an Accept-Language header value into tuples {quality, language}.

Link to this section Functions

Link to this function

best_match(accept_language, backend)

View Source

Specs

best_match(String.t(), Cldr.backend()) ::
  {:ok, Cldr.LanguageTag.t()}
  | {:error, {Cldr.AcceptLanguageError | Cldr.NoMatchingLocale, String.t()}}

Parse an Accept-Language string and return the best match for a configured Cldr locale.

  • accept_langauge is a string representing an accept language header

Returns:

  • {:ok, language_tag} or

  • {:error, reason}

Examples

iex> 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: %{},
   gettext_locale_name: nil,
   language: "zh",
   locale: %{},
   private_use: [],
   rbnf_locale_name: :"zh-Hant",
   requested_locale_name: "zh-TW",
   script: :Hant,
   territory: :TW,
   transform: %{},
   language_variants: []
 }}

iex> 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: %{},
   gettext_locale_name: nil,
   language: "zh",
   locale: %{},
   private_use: [],
   rbnf_locale_name: :"zh-Hant",
   requested_locale_name: "zh-TW",
   script: :Hant,
   territory: :TW,
   transform: %{},
   language_variants: []
 }}

iex> Cldr.AcceptLanguage.best_match("xx,yy;q=0.3", TestBackend.Cldr)
{:error,
 {Cldr.NoMatchingLocale,
  "No configured locale could be matched to \"xx,yy;q=0.3\""}}

iex> Cldr.AcceptLanguage.best_match("invalid_tag", TestBackend.Cldr)
{:error, {Cldr.LanguageTag.ParseError,
  "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}

Specs

errors([tuple(), ...]) :: [{:error, {Cldr.InvalidLanguageTag, String.t()}}, ...]

Filters the returned results of parse/1 to return only the error tuples.

Example

iex> Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3,invalid_tag", TestBackend.Cldr)
...> |> Cldr.AcceptLanguage.errors
[
  error: {Cldr.LanguageTag.ParseError,
  "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}
]

Specs

parse([{float(), String.t()}, ...] | String.t(), Cldr.backend()) ::
  {:ok,
   [
     {float(), Cldr.LanguageTag.t()}
     | {:error, {Cldr.InvalidLanguageTag, String.t()}},
     ...
   ]}
  | {:error, {Cldr.AcceptLanguageError, String.t()}}

Parses an Accept-Language header value in its string or tokenized form to return a tuple of the form {:ok, [{quality, %Cldr.LanguageTag{}}, ...]} sorted by quality.

Arguments

  • accept-language is any string in the format defined by rfc2616

  • backend is any module that includes use Cldr and therefore is a Cldr backend module

Returns

  • {:ok, [{quality, language_tag}, ...]} or

  • {:error, {Cldr.AcceptLanguageError, String.t}}

If at least one valid language tag is found but errors are also detected on one more more tags, an {ok, list} tuple is returned wuth an error tuple for each invalid tag added at the end of the list.

Example

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: %{},
      gettext_locale_name: nil,
      language: "da",
      locale: %{},
      private_use: [],
      rbnf_locale_name: :da,
      requested_locale_name: "da",
      script: :Latn,
      territory: :DK,
      transform: %{},
      language_variants: []
    }},
   {0.3,
    %Cldr.LanguageTag{
      backend: TestBackend.Cldr,
      canonical_locale_name: "zh-TW",
      cldr_locale_name: :"zh-Hant",
      language_subtags: [],
      extensions: %{},
      gettext_locale_name: nil,
      language: "zh",
      locale: %{},
      private_use: [],
      rbnf_locale_name: :"zh-Hant",
      requested_locale_name: "zh-TW",
      script: :Hant,
      territory: :TW,
      transform: %{},
      language_variants: []
    }}
 ]}

iex> Cldr.AcceptLanguage.parse("invalid_tag", TestBackend.Cldr)
{: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,invalid_tag", TestBackend.Cldr)
{:ok,
 [
   {1.0,
    %Cldr.LanguageTag{
      backend: TestBackend.Cldr,
      canonical_locale_name: "da",
      cldr_locale_name: :da,
      language_subtags: [],
      extensions: %{},
      gettext_locale_name: nil,
      language: "da",
      locale: %{},
      private_use: [],
      rbnf_locale_name: :da,
      requested_locale_name: "da",
      script: :Latn,
      territory: :DK,
      transform: %{},
      language_variants: []
    }},
   {0.3,
    %Cldr.LanguageTag{
      backend: TestBackend.Cldr,
      canonical_locale_name: "zh-TW",
      cldr_locale_name: :"zh-Hant",
      language_subtags: [],
      extensions: %{},
      gettext_locale_name: nil,
      language: "zh",
      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"}}
 ]}
Link to this function

parse!(accept_language, backend)

View Source

Parses an Accept-Language header value in its string or tokenized form to produce a list of tuples of the form [{quality, %Cldr.LanguageTag{}}, ...] sorted by quality in descending order.

  • accept-language is any string in the format defined by rfc2616

Returns:

If at least one valid language tag is found but errors are also detected on one more more tags, an {ok, list} tuple is returned wuth an error tuple for each invalid tag added at the end of the list.

Example

iex> Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3", TestBackend.Cldr)
[
  {1.0,
   %Cldr.LanguageTag{
     backend: TestBackend.Cldr,
     canonical_locale_name: "da",
     cldr_locale_name: :da,
     language_subtags: [],
     extensions: %{},
     gettext_locale_name: nil,
     language: "da",
     locale: %{},
     private_use: [],
     rbnf_locale_name: :da,
     requested_locale_name: "da",
     script: :Latn,
     territory: :DK,
     transform: %{},
     language_variants: []
   }},
  {0.3,
   %Cldr.LanguageTag{
     backend: TestBackend.Cldr,
     canonical_locale_name: "zh-TW",
     cldr_locale_name: :"zh-Hant",
     language_subtags: [],
     extensions: %{},
     gettext_locale_name: nil,
     language: "zh",
     locale: %{},
     private_use: [],
     rbnf_locale_name: :"zh-Hant",
     requested_locale_name: "zh-TW",
     script: :Hant,
     territory: :TW,
     transform: %{},
     language_variants: []
   }}
]

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> Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3,invalid_tag", TestBackend.Cldr)
[
  {1.0,
   %Cldr.LanguageTag{
     backend: TestBackend.Cldr,
     canonical_locale_name: "da",
     cldr_locale_name: :da,
     language_subtags: [],
     extensions: %{},
     gettext_locale_name: nil,
     language: "da",
     locale: %{},
     private_use: [],
     rbnf_locale_name: :da,
     requested_locale_name: "da",
     script: :Latn,
     territory: :DK,
     transform: %{},
     language_variants: []
   }},
  {0.3,
   %Cldr.LanguageTag{
     backend: TestBackend.Cldr,
     canonical_locale_name: "zh-TW",
     cldr_locale_name: :"zh-Hant",
     language_subtags: [],
     extensions: %{},
     gettext_locale_name: nil,
     language: "zh",
     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"}}
]
Link to this function

tokenize(accept_language)

View Source

Specs

tokenize(String.t()) :: [{float(), String.t()}, ...]

Splits the language ranges for an Accept-Language header value into tuples {quality, language}.

  • accept-language is any string in the format defined by rfc2616

Example

iex> Cldr.AcceptLanguage.tokenize "da,zh-TW;q=0.3"
[{1.0, "da"}, {0.3, "zh-tw"}]