MishkaCmsCore.Localized (Mishka CMS Core v0.0.1)

Copy Markdown View Source

Dates, times, "how long ago", numbers, lists and language names written the way the reader's language writes them — its month and weekday names, digits, separators, word order and plural forms — from Unicode CLDR, through Localize. Nothing here is translated by hand.

The language is the calling process's Gettext locale (MishkaCmsCore.Gettext): the admin's on a dashboard, the page's on a site. :locale names another.

Localized.date(~D[2025-07-03])                          #=> "Jul 3, 2025"
Localized.date(~D[2025-07-03], :MMMd, locale: "de")     #=> "3. Juli"
Localized.ago(DateTime.add(DateTime.utc_now(), -150))   #=> "3 minutes ago"
Localized.number(1284, locale: "fa")                    #=> "۱٬۲۸۴"
Localized.compact(8429)                                 #=> "8.4K"
Localized.list(["French", "Persian"])                   #=> "French and Persian"

A format is a CLDR one: :short, :medium, :long or :full, or a skeleton such as :yMMMd (Jul 3, 2025), :MMMd (Jul 3), :yMMMM (July 2025), :MMMEd (Thu, Jul 3), :MMMdHm (Jul 3, 18:04) or :Hm (18:04), which each language writes in its own order.

A language's data

English ships with Localize. Another language is read from the cache directory the host configures (config :localize, otp_app: ...), downloaded there the first time it is asked for where the host allows it (allow_runtime_locale_download), and kept in :persistent_term from then on. A language whose data is not there writes in English, never in CLDR's bare root forms.

Nothing here raises: a value none of these functions can write reads as "".

Summary

Functions

How long ago value was, or how long until it is — now, 5 seconds ago, 3 hours ago, yesterday, last month, in 2 days — in the largest unit that says it.

The CLDR locale locale/1 is written in: its own when its data is there — loaded once, downloaded first where the host allows it — else English. An unknown language is English too.

A number shortened as the language shortens it: 8.4K, 1.2M in English, 1,2 Mio. in German.

A date — of a Date, DateTime or NaiveDateTime — in format, :medium by default.

A date and time — of a DateTime or NaiveDateTime — in format, :medium by default.

The name of the language code names, in the reader's language: language("fa") is Persian in English and فارسی in Persian. A region is the language's own name where CLDR has one — pt-BR is Brazilian Portuguese — and in brackets where it has none, fa-IR is Persian (Iran). nil for a code CLDR does not know.

Phrases joined as the language joins a list: a, b, and c in English, a, b und c in German. list_style: :or joins with "or".

The language the reader reads in: :locale when given, else the Gettext locale of the calling process.

A number with the language's digits and separators: 1,284 in English, 1.284 in German, ۱٬۲۸۴ in Persian. Other options are Localize.Number.to_string/2's, such as format: :percent or fractional_digits: 1.

strings in the language's alphabetical order — accents, case and its own letters where it puts them (CLDR collation).

A time of day — of a Time, DateTime or NaiveDateTime — in format, :short by default: 6:04 PM in English, 18:04 in German.

Functions

ago(value, opts \\ [])

@spec ago(term(), keyword()) :: String.t()

How long ago value was, or how long until it is — now, 5 seconds ago, 3 hours ago, yesterday, last month, in 2 days — in the largest unit that says it.

Options: :format — :standard (default), :short (3 hr. ago) or :narrow (3h ago); :relative_to — the moment it is measured from, now by default.

cldr_locale(opts \\ [])

@spec cldr_locale(keyword()) :: atom()

The CLDR locale locale/1 is written in: its own when its data is there — loaded once, downloaded first where the host allows it — else English. An unknown language is English too.

cldr_locale(locale: "pt_BR") #=> :pt
cldr_locale(locale: "xx")    #=> :en

compact(value, opts \\ [])

@spec compact(term(), keyword()) :: String.t()

A number shortened as the language shortens it: 8.4K, 1.2M in English, 1,2 Mio. in German.

date(value, format \\ :medium, opts \\ [])

@spec date(term(), atom() | String.t(), keyword()) :: String.t()

A date — of a Date, DateTime or NaiveDateTime — in format, :medium by default.

date(~D[2025-07-03])         #=> "Jul 3, 2025"
date(~D[2025-07-03], :full)  #=> "Thursday, July 3, 2025"

datetime(value, format \\ :medium, opts \\ [])

@spec datetime(term(), atom() | String.t(), keyword()) :: String.t()

A date and time — of a DateTime or NaiveDateTime — in format, :medium by default.

datetime(~U[2025-07-03 18:04:00Z], :MMMdHm) #=> "Jul 3, 18:04"

language(code, opts \\ [])

@spec language(String.t(), keyword()) :: String.t() | nil

The name of the language code names, in the reader's language: language("fa") is Persian in English and فارسی in Persian. A region is the language's own name where CLDR has one — pt-BR is Brazilian Portuguese — and in brackets where it has none, fa-IR is Persian (Iran). nil for a code CLDR does not know.

list(items, opts \\ [])

@spec list([String.t()], keyword()) :: String.t()

Phrases joined as the language joins a list: a, b, and c in English, a, b und c in German. list_style: :or joins with "or".

locale(opts \\ [])

@spec locale(keyword()) :: String.t() | atom()

The language the reader reads in: :locale when given, else the Gettext locale of the calling process.

number(value, opts \\ [])

@spec number(term(), keyword()) :: String.t()

A number with the language's digits and separators: 1,284 in English, 1.284 in German, ۱٬۲۸۴ in Persian. Other options are Localize.Number.to_string/2's, such as format: :percent or fractional_digits: 1.

sort(strings, opts \\ [])

@spec sort([String.t()], keyword()) :: [String.t()]

strings in the language's alphabetical order — accents, case and its own letters where it puts them (CLDR collation).

time(value, format \\ :short, opts \\ [])

@spec time(term(), atom() | String.t(), keyword()) :: String.t()

A time of day — of a Time, DateTime or NaiveDateTime — in format, :short by default: 6:04 PM in English, 18:04 in German.