Skip to content

Locale metadata

Translate language, country, script, calendar, and currency codes into their localised display names — and reach a handful of related lookups (text direction, flag emoji, the runtime's supported values, likely-subtags expansion). Every display method falls back to the instance locale's own subtags when called without an argument, which makes "describe this locale" a no-argument call.

Method Returns Default argument
language(code?) localised language name the instance language
country(code?) localised region/country name the instance region
script(code?) localised script name the instance script
calendar(code) localised calendar name —
currency(code?, symbol?, strict?) currency name or symbol the currency modifier
displayName(type, code) any of the above, by type —
direction(language?) "ltr" / "rtl" the instance locale
flag(region?) country flag emoji the instance region
supportedValues(key) values the runtime's ICU supports —
addLikelySubtags() / removeLikelySubtags() a new Cosmo with subtags expanded/collapsed —

Language, country, script, calendar

Each takes a code and returns its name in the instance locale's language — so a fa instance describes everything in Persian.

const fa = new Cosmo("fa");
fa.language("en");           // "انگلیسی"
fa.country("AU");            // "استرالیا"

const en = new Cosmo("en");
en.script("Latn");           // "Latin"
en.calendar("buddhist");     // "Buddhist Calendar"
$fa = new Cosmo('fa');
$fa->language('en');          // "انگلیسی"
$fa->country('AU');           // "استرالیا"

$en = new Cosmo('en');
$en->script('Latn');          // "Latin"
$en->calendar('buddhist');    // "Buddhist Calendar"
fa = Cosmo("fa")
fa.language("en")            # "انگلیسی"
fa.country("AU")             # "استرالیا"

en = Cosmo("en")
en.script("Latn")            # "Latin"
en.calendar("buddhist")      # "Buddhist Calendar"
Cosmo fa = new Cosmo("fa");
fa.language("en");           // "انگلیسی"
fa.country("AU");            // "استرالیا"

Cosmo en = new Cosmo("en");
en.script("Latn");           // "Latin"
en.calendar("buddhist");     // "Buddhist Calendar"
var fa = new Cosmo("fa");
fa.Language("en");           // "انگلیسی"
fa.Country("AU");            // "استرالیا"

var en = new Cosmo("en");
en.Script("Latn");           // "Latin"
en.Calendar("buddhist");     // "Buddhist Calendar"

Called with no argument, each uses the instance locale: new Cosmo('en_AU')'s country() returns "Australia", language() returns "English". language() and country() also accept a full locale and pull the right subtag out of it, so language("pt-BR") → "Portuguese" and country("pt-BR") → "Brazil".

Generic dispatcher: displayName()

When the category is itself a variable (say, you're rendering a settings row by type), displayName(type, code) is the single entry point over all of the above:

const c = new Cosmo("en");
c.displayName("language", "fr");   // "French"
c.displayName("region", "JP");     // "Japan"
c.displayName("currency", "EUR");  // "Euro"
$c = new Cosmo('en');
$c->displayName('language', 'fr');  // "French"
$c->displayName('region', 'JP');    // "Japan"
$c->displayName('currency', 'EUR'); // "Euro"
c = Cosmo("en")
c.display_name("language", "fr")    # "French"
c.display_name("region", "JP")      # "Japan"
c.display_name("currency", "EUR")   # "Euro"
Cosmo c = new Cosmo("en");
c.displayName("language", "fr");   // "French"
c.displayName("region", "JP");     // "Japan"
c.displayName("currency", "EUR");  // "Euro"
var c = new Cosmo("en");
c.DisplayName("language", "fr");   // "French"
c.DisplayName("region", "JP");     // "Japan"
c.DisplayName("currency", "EUR");  // "Euro"

type is one of language, region, script, calendar, currency. An unknown type throws.

Currency name & symbol

currency() is the metadata view of a currency — its localised name (default) or symbol — independent of any amount (for amounts, see Money).

Argument Default Meaning
code the currency modifier ISO 4217 code
symbol false true → the disambiguated symbol, not the name
strict false throw on an unknown code instead of echoing it back
const c = new Cosmo("en-US");
c.currency("AUD");              // "Australian Dollar"
c.currency("AUD", true);        // "A$"
c.currency("ZZZ", false, true); // throws — unknown currency, strict
$c = new Cosmo('en_US');
$c->currency('AUD');            // "Australian Dollar"  (localised name)
$c->currency('AUD', true);      // "A$"                 (disambiguated symbol)
c = Cosmo("en_US")
c.currency("AUD")               # "Australian Dollar"
c.currency("AUD", True)         # "A$"
Cosmo c = new Cosmo("en_US");
c.currency("AUD");                  // "Australian Dollar"
c.currency("AUD", true, false);     // "A$"   (symbol, non-strict)
var c = new Cosmo("en-US");
c.Currency("AUD");                  // "Australian Dollar"
c.Currency("AUD", symbol: true);    // "A$"

The symbol form returns the standard, disambiguated symbol ("A$" for AUD in en_US), not the ambiguous narrow "$" — so a price list mixing AUD, USD, and CAD stays unambiguous. Without strict, an unrecognised code is echoed back uppercased (handy for graceful UIs); with strict, it throws so you catch bad data early.

Direction & flag

new Cosmo("fa").direction();    // "rtl"
new Cosmo("en").direction();    // "ltr"
new Cosmo("en-AU").flag();      // "🇦🇺"
new Cosmo('fa')->direction();   // "rtl"
new Cosmo('en')->direction();   // "ltr"
new Cosmo('en_AU')->flag();     // "🇦🇺"
Cosmo("fa").direction()         # "rtl"
Cosmo("en").direction()         # "ltr"
Cosmo("en_AU").flag()           # "🇦🇺"
new Cosmo("fa").direction();    // "rtl"
new Cosmo("en").direction();    // "ltr"
new Cosmo("en_AU").flag();      // "🇦🇺"
new Cosmo("fa").Direction();    // "rtl"
new Cosmo("en").Direction();    // "ltr"
new Cosmo("en-AU").Flag();      // "🇦🇺"

direction() is what you bind to an HTML dir attribute. It resolves likely subtags first, so even a script-only or minority RTL language (ku, ckb) is detected correctly; pass a language/locale to test one other than the instance. flag() is pure Unicode codepoint math (region letters → regional-indicator symbols), so no data table is involved — it returns "" for anything that isn't a two-letter region.

Supported values

supportedValues(key) lists everything the runtime's ICU can handle for a given category — useful to populate a dropdown without hardcoding a list that drifts from the engine:

key Yields
calendar gregory, persian, buddhist, …
collation standard, phonebook, pinyin, …
currency every ISO 4217 code
numberingSystem latn, arab, deva, …
timeZone every IANA zone
unit every formattable unit
new Cosmo("en").supportedValues("currency").length;  // e.g. 300+
new Cosmo("en").supportedValues("calendar");         // ["buddhist", "chinese", …]
count(new Cosmo('en')->supportedValues('currency'));  // e.g. 300+
new Cosmo('en')->supportedValues('calendar');         // ['buddhist', 'chinese', …]
len(Cosmo("en").supported_values("currency"))         # e.g. 300+
Cosmo("en").supported_values("calendar")              # ["buddhist", "chinese", …]
new Cosmo("en").SupportedValues("currency").Count;    // e.g. 300+
new Cosmo("en").SupportedValues("calendar");          // ["buddhist", "chinese", …]
// "unit" throws CosmoUnsupportedException — not exposed in the ICU C API

PHP/Python/Java/C# also accept transliterator here (see Transliteration). An unknown key throws; in JS the method needs Intl.supportedValuesOf (Node 18+). C# does not support the "unit" key (the ICU C API exposes no unit enumeration).

Likely subtags

ICU can expand a terse locale to its most likely full form and back — addLikelySubtags() returns a new Cosmo with the script/region filled in, removeLikelySubtags() strips the redundant ones:

new Cosmo("en").addLikelySubtags().locale;          // "en-Latn-US"
new Cosmo("en-Latn-US").removeLikelySubtags().locale; // "en"
Cosmo("en").add_likely_subtags().locale             # "en-Latn-US"
Cosmo("en-Latn-US").remove_likely_subtags().locale  # "en"
new Cosmo("en").addLikelySubtags().locale;          // "en_Latn_US"
new Cosmo("en_Latn_US").removeLikelySubtags().locale; // "en"
new Cosmo("en").AddLikelySubtags().Locale;          // "en_Latn_US"
new Cosmo("en_Latn_US").RemoveLikelySubtags().Locale; // "en"

Likely subtags are JS, Python, Java & C#

PHP's intl extension does not expose the likely-subtags algorithm, so it is the one port without addLikelySubtags() / removeLikelySubtags(). See Platform notes.

Practical examples

A language switcher. Render each supported locale's endonym (its name in its own language) alongside its flag and direction:

const supported = ["en-US", "fr-FR", "ar-EG", "ja-JP"];
const menu = supported.map((tag) => {
  const c = new Cosmo(tag);
  return { tag, label: c.language(), flag: c.flag(), dir: c.direction() };
});
// { tag: "ar-EG", label: "العربية", flag: "🇪🇬", dir: "rtl" }, …
$supported = ['en-US', 'fr-FR', 'ar-EG', 'ja-JP'];
$menu = array_map(function ($tag) {
  $c = new Cosmo($tag);
  return ['tag' => $tag, 'label' => $c->language(), 'flag' => $c->flag(), 'dir' => $c->direction()];
}, $supported);
supported = ["en-US", "fr-FR", "ar-EG", "ja-JP"]
menu = [
    {"tag": t, "label": (c := Cosmo(t)).language(), "flag": c.flag(), "dir": c.direction()}
    for t in supported
]
var supported = new[] { "en-US", "fr-FR", "ar-EG", "ja-JP" };
var menu = supported.Select(tag => {
    var c = new Cosmo(tag);
    return new { tag, label = c.Language(), flag = c.Flag(), dir = c.Direction() };
}).ToList();
// { tag: "ar-EG", label: "العربية", flag: "🇪🇬", dir: "rtl" }, …

A native-name picker, sorted for the user. Build names in the user's locale, then sort() them with that locale's collator so the list reads naturally.