Getting Started

Cldr is an Elixir library for the Unicode Consortium’s Common Locale Data Repository (CLDR). The intentions of CLDR, and this library, it to simplify the locale specific formatting of numbers, lists, currencies, calendars, units of measure and dates/times. As of September 6th 2016, Cldr is based upon CLDR version 29. Version 30 of CLDR is expected to be released in the third week of September (as is usual each year) and this library will be updated with that CLDR version’s data before the end of September.

Installation

Add cldr as a dependency to your mix project:

defp deps do
  [
    {:ex_cldr, "~> 0.0.4"}
  ]
end

then retrieve ex_cldr from hex:

mix deps.get
mix deps.compile

Although Cldr is purely a library application, it should be added to your application list so that it gets bundled correctly for release:

def application do
  [applications: [:ex_cldr]]
end

Quick Configuration

Without any specific configuration Cldr will support the “en” locale only. To support additional locales update your config.exs file (or the relevant environment version).

A more complete configuration can include the key :default_locale, :locales, :gettext and :dataset. For example:

config :ex_cldr,
  default_locale: "en",
  locales: ["fr-*", "pt-BR", "en", "pl", "ru", "th", "he"],
  gettext: MyApp.Gettext

Configures a default locale of "en" (which is itself the Cldr default). Additional locales are configured with the :locales key. In this example, all locales starting with “fr-“ will be configured along with Brazilian Portugues, English, Polish, Russian, Thai and Hebrew.

If you are also using Gettext then you can tell Cldr to use that module to inform Cldr about which locales you wish to configure. By default Cldr will use the :full dataset of Cldr. If you prefer you can configure the :modern set instead.

Defaults

Although a locale is required for all formatting functions, and a number system is often required, Cldr attempts to use sensible defaults. if not supplied Cldr will default to a locale of Cldr.get_locale() and a number_system of :default. There are two functions that set and get the current locale:

  • Cldr.get_locale() retrieves the current locale, or the default locale if none is set.

  • Cldr.put_locale(locale) sets the current locale to locale. The locale is kept in the process directory via Process.put/2 which means that Cldr.locale() is ephemeral and needs to be set in any process that intends to use it. For a Phoenix application, for example, Cldr.put_locale/2 would need to be called for all requests in a plug or in your controller.

Formatting Numbers

The Cldr.Number module provides number formatting. The public API for number formatting is Cldr.Number.to_string/2. Some examples:

iex> Cldr.Number.to_string 12345
  "12,345"

  iex> Cldr.Number.to_string 12345, locale: "fr"
  "12 345"

  iex> Cldr.Number.to_string 12345, locale: "fr", currency: "USD"
  "12 345,00 $US"

  iex(4)> Cldr.Number.to_string 12345, format: "#E0"
  "1.2345E4"

See h Cldr.Number and h Cldr.Number.to_string in iex for further information.

Formatting Lists

The Cldr.List module provides list formatting. The public API for list formating is Cldr.List.to_string/2. Some examples:

iex> Cldr.List.to_string(["a", "b", "c"], locale: "en")
  "a, b, and c"

  iex> Cldr.List.to_string(["a", "b", "c"], locale: "en", format: :unit_narrow)
  "a b c"

  iex> Cldr.List.to_string(["a", "b", "c"], locale: "fr")
  "a, b et c"

Seer h Cldr.List and h Cldr.List.to_string in iex for further information.

Formatting Dates, Times, Units and Other Stuff

Not currently supported, but they’re next on the development priority list.

Gettext Integration

There is an experimental plurals module for Gettext called Cldr.Gettext.Plural. Its not yet fully tested. It is configured in Gettext by

defmodule MyApp.Gettext do
  use Gettext, plural_forms: Cldr.Gettext.Plural
end

Cldr.Gettext.Plural will fall back to Gettext pluralisation if the locale is not known to Cldr. This module is only compiled if Gettext is configured as a dependency in your project.

Phoenix Integration

There is an imcomplete (ie development not finished) implemenation of a Plug intended to parse the HTTP accept-language header into Cldr compatible locale and number system. Since it’s not development complete it definitely won’t work yet. Comments and ideas (and pull requests) are, however, welcome.

About Locale strings

Note that Cldr defines locale string according to the Unicode standard:

  • Language codes are two lowercase letters (ie “en”, not “EN”)
  • Potentially one or more modifiers separated by “-“ (dash), not a ““ (underscore). If you configure a Gettext module then Cldr will transliterate Gettext’s “” into “-“ for compatibility.
  • Typically the modifier is a territory code. This is commonly a two-letter uppercase combination. For example “pt-BR” is the locale referring to Brazilian Portugese.
  • In Cldr a locale is always a binary and never an atom. Locale strings are often passed around in HTTP headers and converting to atoms creates an attack vector we can do without.
  • The locales known to Cldr can be retrieved by Cldr.known_locales to get the locales known to this configuration of Cldr and Cldr.all_locales to get the locales available in the CLDR data repository.

There are other configuration options that are available, including configuring Cldr to use locales defined in Gettext. For further information see the configuration guide.