intl
internationalization (i18n)
use intlIn two phases. Phase 1 (now): the useful minimum, with a message catalog, CLDR plural, and hooks for locale-aware formatting reusing the
localethat already exists in the core. Phase 2 (sketched): full ICU, with collation, segmentation (grapheme/word/line break), bidi, non-Gregorian calendars, transliteration, formatted ranges/lists. Tier 1.
Phase 1: catalog, plural, formatting
Section titled “Phase 1: catalog, plural, formatting”decl Locale { ... } // "pt-BR", "en-US" (BCP 47); extends the core localefn locale_of(tag: string) -> Result[Locale, error{Malformed}]fn (l: Locale) language() -> string // "pt"fn (l: Locale) region() -> Optional[string] // "BR"
// message catalog: lookup by key + localedecl Catalog { ... }fn (Catalog) load(messages: Map[string, string], locale: Locale) -> Catalogfn (c: Catalog) get(key: string) -> Optional[string]fn (c: Catalog) format(key: string, args: Map[string, string]) -> string // interpolates {{name}} (§16)
// plural rules (CLDR): chooses the right category for the number in the localedecl PluralCategory { Zero; One; Two; Few; Many; Other }fn (l: Locale) plural(n: i64) -> PluralCategory // pt: 1 to One, rest to Other; ru/ar: rich rulesfn (c: Catalog) plural(key: string, n: i64) -> string // chooses the variant and interpolates
// locale-aware formatting (hooks over the core locale)fn (l: Locale) format_int(n: i64) -> string // locale thousands/decimal separatorsfn (l: Locale) format_float(x: f64, frac_digits: u32) -> stringfn (l: Locale) format_currency(amount: i64, currency: string) -> string // "R$ 1.234,56" / "$1,234.56"fn (l: Locale) format_date(t: DateTime, style: DateStyle) -> string // named styles (no magic layout)decl DateStyle { Short; Medium; Long; Full }use intl
cat := intl.Catalog.load(mensagens_pt, intl.locale_of("pt-BR").or_panic())msg := cat.plural("itens_no_carrinho", n) // "1 item" / "3 items", correct category per CLDRpreco := intl.locale_of("pt-BR").or_panic().format_currency(123456, "BRL") // "R$ 1.234,56"Phase 2: full ICU (sketch)
Section titled “Phase 2: full ICU (sketch)”Surface foreseen, implementation deferred (each one pulls heavy Unicode/CLDR tables, pure opt-in):
fn (l: Locale) collator() -> Collator // localized alphabetical ordering (collation)fn (c: Collator) compare(a: string, b: string) -> Orderfn graphemes(s: string) -> Iterator[string] // segmentation by grapheme clusterfn words(s: string, l: Locale) -> Iterator[string] // segmentation by word (locale-aware)fn line_breaks(s: string) -> Iterator[usize] // line break points (UAX 14)fn (s: string) to_bidi(l: Locale) -> string // bidirectional reordering (UAX 9)fn transliterate(s: string, scheme: string) -> string // "Greek-Latin", etc.// + non-Gregorian calendars, range/list formatting, etc.Curation
Section titled “Curation”- Two phases, opt-in: phase 1 covers 90% (catalog + plural + format) reusing the core
locale; phase 2 (ICU) is the heavy universe, written as surface now, implemented when needed. The Unicode/CLDR tables only weigh on whoever imports them. - Reuses the core
locale/unicode:intlis the layer of locale-aware policies; the data and the Unicode mechanism come from below (tier 0), coherent with the mechanism-vs-data split of the tiers (§1). - No magic format string: named styles (
DateStyle) + interpolation (§16), liketime.