moonlocale

Application-focused internationalization and localization toolkit for MoonBit

i18n
l10n
locale
message-format
plural
moon add zlhahaha/moonlocale@0.1.0
Download zip
Author
Version
0.1.0
License
Apache-2.0
Last updated
19 days ago
Downloads
3
README

#MoonLocale

MoonLocale is a dependency-free internationalization and localization toolkit for MoonBit applications. It covers the routines that product code needs every day: locale negotiation, translated message catalogs, plurals, numbers, currencies, dates, lists, relative time, units, byte sizes, durations, and pseudo-localization.

The package is deterministic and does not depend on an operating-system locale database, so the same input produces the same text on native and WebAssembly targets.

#Install

moon add zlhahaha/moonlocale

Then import the package in moon.pkg:

import {
"zlhahaha/moonlocale",
}

#Quick start

fn main {
let en = @moonlocale.Locale::parse("en").unwrap()
let catalog = @moonlocale.MessageCatalog::compile(en, [
@moonlocale.message_resource(
"inbox",
"{count, plural, one {Hello {name}, one message} other {Hello {name}, # messages}}",
),
]).unwrap()
let bundle = @moonlocale.MessageBundle::new(en, [catalog]).unwrap()
let text = bundle.format(
@moonlocale.Locale::parse("en-GB").unwrap(),
"inbox",
[
@moonlocale.string_argument("name", "Mina"),
@moonlocale.int_argument("count", 2500),
],
).unwrap()
println(text) // Hello Mina, 2,500 messages
}

See examples/basic for a runnable example:

moon run examples/basic

#What it provides

  • Practical BCP 47 locale parsing, normalization, fallback chains, and matching.
  • Cardinal and ordinal plural rules for commonly used language families.
  • ICU-inspired messages with variables, select, plural, selectordinal, exact selectors, offsets, nesting, and apostrophe escaping.
  • Compiled catalogs, per-message locale fallback, and contextual errors.
  • Integer, decimal, percentage, and currency formatting without floating-point rounding surprises.
  • Validated civil dates and times with localized date and time styles.
  • Conjunction, disjunction, relative-time, measurement-unit, byte-size, and duration formatting.
  • Pseudo-localization and catalog audits for missing, extra, or incompatible translations.

#Locale behavior

Locale::parse accepts common tags such as en-US, zh_Hans_CN, and sl-Latn-SI-rozaj, then emits a normalized tag. best_locale first attempts an exact match and progressively falls back through script, region, and language. Message bundles also fall back per key, so a regional catalog can contain only the strings it overrides.

MoonLocale intentionally ships a compact, application-oriented ruleset rather than the full Unicode CLDR dataset. Unknown locales use stable English-like defaults. This keeps binaries and behavior predictable while leaving room for additional locale data in future releases.

#Message syntax

Welcome, {name} {role, select, admin {Administrator} other {Member}} {count, plural, =0 {Empty} one {# item} other {# items}} {rank, selectordinal, one {#st} two {#nd} few {#rd} other {#th}} {count, plural, offset:1 =0 {Nobody came} one {{name} came} other {{name} and # others came}}

Templates are parsed when a catalog is compiled. Invalid syntax, duplicate keys, missing arguments, and incompatible argument types are returned as typed errors instead of being silently ignored.

#Quality checks

let audit = @moonlocale.audit_catalogs(reference, translations)
if !audit.is_complete() {
for issue in audit.issues() {
println(issue.message())
}
}

let preview = reference.pseudo_localized(
@moonlocale.Locale::parse("en-XA").unwrap(),
)

Pseudo-localization preserves placeholders and message branches while accenting and expanding visible text, which makes clipped UI and untranslated strings easier to find.

#Development

moon fmt moon check --deny-warn moon build moon test --deny-warn moon run examples/basic

#License

Apache-2.0. See LICENSE.

#
BundleBuildError

pub(all) enum BundleBuildError {
EmptyBundle
DuplicateCatalog(String)
MissingDefaultCatalog(String)
} derive(Eq,
Debug
)

Errors found while combining locale catalogs into one bundle.

#
BundleBuildError::message

fn BundleBuildError::message(self : BundleBuildError) -> String

#
BundleFormatError

pub(all) enum BundleFormatError {
MissingMessage(String, Array[String])
MessageFormattingFailed(String, String, MessageFormatError)
} derive(Eq,
Debug
)

Failures produced while resolving and formatting a bundled message.

#
BundleFormatError::message

fn BundleFormatError::message(self : BundleFormatError) -> String

#
ByteSizeStyle

pub(all) enum ByteSizeStyle {
DecimalBytes
BinaryBytes
} derive(Eq,
Debug
)

Controls the base used when automatically scaling byte quantities.

#
CatalogAudit

pub struct CatalogAudit {
reference_locale : Locale
checked_catalogs : Int
issues : Array[CatalogAuditIssue]
} derive(Eq,
Debug
)

Summary of a reference-to-translations catalog comparison.

#
CatalogAudit::argument_mismatch_count

fn CatalogAudit::argument_mismatch_count(self : CatalogAudit) -> Int

#
CatalogAudit::checked_catalogs

fn CatalogAudit::checked_catalogs(self : CatalogAudit) -> Int

#
CatalogAudit::is_complete

fn CatalogAudit::is_complete(self : CatalogAudit) -> Bool

#
CatalogAudit::issues

#
CatalogAudit::missing_count

fn CatalogAudit::missing_count(self : CatalogAudit) -> Int

#
CatalogAudit::reference_locale

fn CatalogAudit::reference_locale(self : CatalogAudit) -> Locale

#
CatalogAudit::unexpected_count

fn CatalogAudit::unexpected_count(self : CatalogAudit) -> Int

#
CatalogAuditIssue

pub(all) enum CatalogAuditIssue {
MissingKey(String, String)
UnexpectedKey(String, String)
ArgumentSetMismatch(String, String, Array[String], Array[String])
} derive(Eq,
Debug
)

A concrete difference between a reference catalog and a translation.

#
CatalogAuditIssue::key

fn CatalogAuditIssue::key(self : CatalogAuditIssue) -> String

#
CatalogAuditIssue::locale_tag

fn CatalogAuditIssue::locale_tag(self : CatalogAuditIssue) -> String

#
CatalogAuditIssue::message

fn CatalogAuditIssue::message(self : CatalogAuditIssue) -> String

#
CatalogCompileError

pub(all) enum CatalogCompileError {
EmptyMessageKey(Int)
DuplicateMessageKey(String)
InvalidMessage(String, MessageParseError)
} derive(Eq,
Debug
)

Errors found while compiling one locale's message resources.

#
CatalogCompileError::message

fn CatalogCompileError::message(self : CatalogCompileError) -> String

#
CatalogMessage

pub struct CatalogMessage {
key : String
template : MessageTemplate
} derive(Eq,
Debug
)

A parsed message associated with its stable application key.

#
CatalogMessage::key

fn CatalogMessage::key(self : CatalogMessage) -> String

#
CatalogMessage::template

#
CivilDate

pub struct CivilDate {
year : Int
month : Int
day : Int
} derive(Compare, Eq,
Debug
)

A Gregorian calendar date without a time zone.

#
CivilDate::day

fn CivilDate::day(self : CivilDate) -> Int

#
CivilDate::month

fn CivilDate::month(self : CivilDate) -> Int

#
CivilDate::new

fn CivilDate::new(year : Int, month : Int, day : Int) -> Result[CivilDate, DateTimeError]

#
CivilDate::to_iso_string

fn CivilDate::to_iso_string(self : CivilDate) -> String

#
CivilDate::weekday

fn CivilDate::weekday(self : CivilDate) -> Weekday

#
CivilDate::year

fn CivilDate::year(self : CivilDate) -> Int

#
CivilTime

pub struct CivilTime {
hour : Int
minute : Int
second : Int
} derive(Compare, Eq,
Debug
)

A wall-clock time without a date or time zone.

#
CivilTime::hour

fn CivilTime::hour(self : CivilTime) -> Int

#
CivilTime::minute

fn CivilTime::minute(self : CivilTime) -> Int

#
CivilTime::new

fn CivilTime::new(hour : Int, minute : Int, second : Int) -> Result[CivilTime, DateTimeError]

#
CivilTime::second

fn CivilTime::second(self : CivilTime) -> Int

#
CivilTime::to_iso_string

fn CivilTime::to_iso_string(self : CivilTime) -> String

#
CurrencyDisplay

pub(all) enum CurrencyDisplay {
Symbol
NarrowSymbol
Code
Name
} derive(Eq,
Debug
)

Controls how a currency identifier is displayed.

#
DateStyle

pub(all) enum DateStyle {
Numeric
Short
Medium
Long
Full
} derive(Eq,
Debug
)

#
DateTimeError

pub(all) enum DateTimeError {
InvalidYear(Int)
InvalidMonth(Int)
InvalidDay(Int)
InvalidHour(Int)
InvalidMinute(Int)
InvalidSecond(Int)
} derive(Eq,
Debug
)

Reports invalid civil date and clock values.

#
DateTimeError::message

fn DateTimeError::message(self : DateTimeError) -> String

#
DateTimeFormatter

pub struct DateTimeFormatter {
locale : Locale
date_style : DateStyle
hour_cycle : HourCycle
include_seconds : Bool
} derive(Eq,
Debug
)

#
DateTimeFormatter::format_date

fn DateTimeFormatter::format_date(self : DateTimeFormatter, date : CivilDate) -> String

#
DateTimeFormatter::format_datetime

fn DateTimeFormatter::format_datetime(self : DateTimeFormatter, date : CivilDate, time : CivilTime) -> String

#
DateTimeFormatter::format_time

fn DateTimeFormatter::format_time(self : DateTimeFormatter, time : CivilTime) -> String

#
DateTimeFormatter::new

#
DateTimeFormatter::with_date_style

fn DateTimeFormatter::with_date_style(self : DateTimeFormatter, style : DateStyle) -> DateTimeFormatter

#
DateTimeFormatter::with_hour_cycle

fn DateTimeFormatter::with_hour_cycle(self : DateTimeFormatter, cycle : HourCycle) -> DateTimeFormatter

#
DateTimeFormatter::with_seconds

fn DateTimeFormatter::with_seconds(self : DateTimeFormatter, enabled : Bool) -> DateTimeFormatter

#
Decimal

pub struct Decimal {
coefficient : Int
scale : Int
} derive(Eq,
Debug
)

A base-10 value represented without binary floating-point rounding.

Decimal::new(12345, 2) represents 123.45. Trailing fractional zeroes are normalized so equality is based on the numeric value.

#
Decimal::coefficient

fn Decimal::coefficient(self : Decimal) -> Int

#
Decimal::from_int

fn Decimal::from_int(value : Int) -> Decimal

#
Decimal::is_zero

fn Decimal::is_zero(self : Decimal) -> Bool

#
Decimal::new

fn Decimal::new(coefficient : Int, scale : Int) -> Decimal

#
Decimal::round

fn Decimal::round(self : Decimal, fraction_digits : Int) -> Decimal

Rounds to a fixed number of fractional digits, with halfway values rounded away from zero.

#
Decimal::scale

fn Decimal::scale(self : Decimal) -> Int

#
Decimal::times_int

fn Decimal::times_int(self : Decimal, factor : Int) -> Decimal

Multiplies a decimal by an integer factor.

#
DecimalFormatter

pub struct DecimalFormatter {
locale : Locale
grouping : Bool
minimum_fraction_digits : Int
maximum_fraction_digits : Int
sign_display : SignDisplay
} derive(Eq,
Debug
)

Locale-aware options for decimal, percentage, and currency output.

#
DecimalFormatter::format

fn DecimalFormatter::format(self : DecimalFormatter, value : Decimal) -> String

Formats a decimal with deterministic base-10 rounding.

#
DecimalFormatter::format_percent

fn DecimalFormatter::format_percent(self : DecimalFormatter, value : Decimal, spacing : PercentSpacing) -> String

Formats a ratio as a percentage. Decimal::new(125, 3) becomes 12.5%.

#
DecimalFormatter::locale

#
DecimalFormatter::new

#
DecimalFormatter::with_grouping

fn DecimalFormatter::with_grouping(self : DecimalFormatter, enabled : Bool) -> DecimalFormatter

#
DecimalFormatter::with_maximum_fraction_digits

fn DecimalFormatter::with_maximum_fraction_digits(self : DecimalFormatter, digits : Int) -> DecimalFormatter

Sets the maximum fraction digits, clamped to 0 through 12.

#
DecimalFormatter::with_minimum_fraction_digits

fn DecimalFormatter::with_minimum_fraction_digits(self : DecimalFormatter, digits : Int) -> DecimalFormatter

Sets the minimum fraction digits, clamped to 0 through 12.

#
DecimalFormatter::with_sign_display

fn DecimalFormatter::with_sign_display(self : DecimalFormatter, display : SignDisplay) -> DecimalFormatter

#
HourCycle

pub(all) enum HourCycle {
LocaleDefault
Hour12
Hour24
} derive(Eq,
Debug
)

#
ListFormatter

pub struct ListFormatter {
locale : Locale
list_type : ListType
width : ListWidth
} derive(Eq,
Debug
)

#
ListFormatter::format

fn ListFormatter::format(self : ListFormatter, values : Array[String]) -> String

Joins already-rendered values using locale punctuation and conjunctions.

#
ListFormatter::new

fn ListFormatter::new(locale : Locale) -> ListFormatter

#
ListFormatter::with_type

fn ListFormatter::with_type(self : ListFormatter, list_type : ListType) -> ListFormatter

#
ListFormatter::with_width

fn ListFormatter::with_width(self : ListFormatter, width : ListWidth) -> ListFormatter

#
ListType

pub(all) enum ListType {
And
Or
Unit
} derive(Eq,
Debug
)

#
ListWidth

pub(all) enum ListWidth {
Long
Short
Narrow
} derive(Eq,
Debug
)

#
Locale

pub struct Locale {
language : String
script : String?
region : String?
variants : Array[String]
} derive(Eq,
Debug
)

A normalized, practical subset of a BCP 47 language tag.

MoonLocale keeps the language, optional script, optional region, and any remaining variants separately. This is sufficient for application locale negotiation without coupling callers to a large standards database.

#
Locale::fallback_chain

fn Locale::fallback_chain(self : Locale) -> Array[Locale]

Produces a most-specific-to-least-specific fallback chain.

For zh-Hans-CN-posix, this returns zh-Hans-CN-posix, zh-Hans-CN, zh-Hans, and zh.

#
Locale::from_string

fn Locale::from_string(tag : String) -> Locale?

Creates a locale and returns None for an invalid tag.

#
Locale::language

fn Locale::language(self : Locale) -> String

#
Locale::language_only

fn Locale::language_only(self : Locale) -> Locale

Returns only the language component.

#
Locale::match_score

fn Locale::match_score(self : Locale, candidate : Locale) -> Int

Measures how closely two locales match.

A negative score means the languages differ. Higher scores prefer exact tags, then matching scripts, regions, and variants.

#
Locale::parse

fn Locale::parse(tag : String) -> Result[Locale, LocaleError]

Parses a locale tag such as en, pt-BR, or zh-Hans-CN.

Underscores are accepted as a convenience for operating-system locale values. The returned locale always renders with hyphens and conventional casing.

#
Locale::region

fn Locale::region(self : Locale) -> String?

#
Locale::script

fn Locale::script(self : Locale) -> String?

#
Locale::tag

fn Locale::tag(self : Locale) -> String

#
Locale::variants

fn Locale::variants(self : Locale) -> Array[String]

#
Locale::without_region

fn Locale::without_region(self : Locale) -> Locale

Returns the locale with its region removed.

#
Locale::without_variants

fn Locale::without_variants(self : Locale) -> Locale

Returns the locale with all variants removed.

#
LocaleError

pub enum LocaleError {
EmptyTag
EmptySubtag(Int)
InvalidLanguage(String)
InvalidVariant(String)
DuplicateScript(String)
DuplicateRegion(String)
} derive(Eq,
Debug
)

Reports why a locale tag could not be parsed.

#
LocaleError::message

fn LocaleError::message(self : LocaleError) -> String

#
MeasurementUnit

pub(all) enum MeasurementUnit {
Meter
Kilometer
Centimeter
Millimeter
SquareMeter
Hectare
Liter
Milliliter
Gram
Kilogram
MeterPerSecond
KilometerPerHour
BitPerSecond
KilobitPerSecond
MegabitPerSecond
Celsius
Fahrenheit
Byte
Kilobyte
Megabyte
Gigabyte
Terabyte
Kibibyte
Mebibyte
Gibibyte
Tebibyte
Millisecond
Second
Minute
Hour
Day
} derive(Eq,
Debug
)

Units commonly displayed by consumer, business, and system applications.

#
MessageArgument

pub struct MessageArgument {
name : String
value : MessageValue
} derive(Eq,
Debug
)

A named value passed to MessageTemplate::format.

#
MessageArgument::name

fn MessageArgument::name(self : MessageArgument) -> String

#
MessageArgument::new

fn MessageArgument::new(name : String, value : MessageValue) -> MessageArgument

#
MessageArgument::value

#
MessageBundle

pub struct MessageBundle {
default_locale : Locale
catalogs : Array[MessageCatalog]
} derive(Eq,
Debug
)

A set of locale catalogs with deterministic per-message fallback.

Resolution tries the request's exact fallback chain first, then the closest catalog in the same language, and finally the default locale. If a catalog exists but lacks the requested key, resolution continues to the next candidate. This allows regional catalogs to override only selected strings.

#
MessageBundle::catalog_count

fn MessageBundle::catalog_count(self : MessageBundle) -> Int

#
MessageBundle::default_locale

fn MessageBundle::default_locale(self : MessageBundle) -> Locale

#
MessageBundle::format

fn MessageBundle::format(self : MessageBundle, requested : Locale, key : String, arguments : Array[MessageArgument]) -> Result[String, BundleFormatError]

Resolves and formats one localized message.

#
MessageBundle::new

fn MessageBundle::new(default_locale : Locale, catalogs : Array[MessageCatalog]) -> Result[MessageBundle, BundleBuildError]

#
MessageBundle::resolve

fn MessageBundle::resolve(self : MessageBundle, requested : Locale, key : String) -> Result[ResolvedMessage, BundleFormatError]

Resolves a key and reports which locale supplied the message.

#
MessageBundle::supported_locales

fn MessageBundle::supported_locales(self : MessageBundle) -> Array[Locale]

#
MessageCase

pub struct MessageCase {
selector : String
nodes : Array[MessageNode]
} derive(Eq,
Debug
)

A branch in a select, plural, or selectordinal message argument.

#
MessageCase::new

fn MessageCase::new(selector : String, nodes : Array[MessageNode]) -> MessageCase

#
MessageCase::nodes

#
MessageCase::selector

fn MessageCase::selector(self : MessageCase) -> String

#
MessageCatalog

pub struct MessageCatalog {
locale : Locale
messages : Array[CatalogMessage]
} derive(Eq,
Debug
)

An immutable collection of compiled messages for one locale.

#
MessageCatalog::compile

fn MessageCatalog::compile(locale : Locale, resources : Array[MessageResource]) -> Result[MessageCatalog, CatalogCompileError]

Parses and validates all messages for a locale.

#
MessageCatalog::contains

fn MessageCatalog::contains(self : MessageCatalog, key : String) -> Bool

#
MessageCatalog::get

fn MessageCatalog::get(self : MessageCatalog, key : String) -> MessageTemplate?

#
MessageCatalog::is_empty

fn MessageCatalog::is_empty(self : MessageCatalog) -> Bool

#
MessageCatalog::keys

fn MessageCatalog::keys(self : MessageCatalog) -> Array[String]

#
MessageCatalog::length

fn MessageCatalog::length(self : MessageCatalog) -> Int

#
MessageCatalog::locale

fn MessageCatalog::locale(self : MessageCatalog) -> Locale

#
MessageCatalog::pseudo_localized

fn MessageCatalog::pseudo_localized(self : MessageCatalog, locale : Locale, options? : PseudoOptions) -> MessageCatalog

Creates a pseudo-locale catalog without reparsing or modifying arguments.

#
MessageFormatError

pub(all) enum MessageFormatError {
MissingArgument(String)
DuplicateArgument(String)
ExpectedNumber(String)
ExpectedSelector(String)
NoMatchingCase(String)
} derive(Eq,
Debug
)

Errors produced while rendering an otherwise valid message template.

#
MessageFormatError::message

fn MessageFormatError::message(self : MessageFormatError) -> String

#
MessageNode

pub(all) enum MessageNode {
Text(String)
Argument(String)
Select(String, Array[MessageCase])
Plural(String, Int, PluralKind, Array[MessageCase])
} derive(Eq,
Debug
)

The parsed representation of a localized message template.

Keeping the syntax tree public lets applications cache compiled templates, inspect their arguments, and build tooling without reparsing source text.

#
MessageParseError

pub enum MessageParseError {
UnexpectedEnd(Int, String)
UnexpectedCharacter(Int, Char)
ExpectedToken(Int, String)
EmptyArgument(Int)
UnknownArgumentType(Int, String)
MissingOtherCase(Int)
DuplicateCase(Int, String)
InvalidOffset(Int, String)
TrailingContent(Int)
} derive(Eq,
Debug
)

Describes an invalid message template and its character offset.

#
MessageParseError::message

fn MessageParseError::message(self : MessageParseError) -> String

#
MessageParseError::position

fn MessageParseError::position(self : MessageParseError) -> Int

#
MessageResource

pub struct MessageResource {
key : String
source : String
} derive(Eq,
Debug
)

An uncompiled message resource supplied by an application.

Catalog compilation parses every source string up front, so syntax errors are reported during application initialization rather than during a request.

#
MessageResource::key

fn MessageResource::key(self : MessageResource) -> String

#
MessageResource::new

fn MessageResource::new(key : String, source : String) -> MessageResource

#
MessageResource::source

fn MessageResource::source(self : MessageResource) -> String

#
MessageTemplate

pub struct MessageTemplate {
source : String
nodes : Array[MessageNode]
} derive(Eq,
Debug
)

A reusable parsed message template.

#
MessageTemplate::arguments

fn MessageTemplate::arguments(self : MessageTemplate) -> Array[String]

Collects argument names in first-use order without duplicates.

#
MessageTemplate::format

fn MessageTemplate::format(self : MessageTemplate, locale : Locale, arguments : Array[MessageArgument]) -> Result[String, MessageFormatError]

Renders this template using locale-aware plural rules and numbers.

#
MessageTemplate::node_count

fn MessageTemplate::node_count(self : MessageTemplate) -> Int

Returns the number of syntax-tree nodes, including nested branch content.

#
MessageTemplate::nodes

#
MessageTemplate::parse

fn MessageTemplate::parse(source : String) -> Result[MessageTemplate, MessageParseError]

Parses an ICU-inspired message template.

Supported arguments are simple variables, select, plural, and selectordinal. Plural branches accept exact selectors such as =0 and optional non-negative offsets. Apostrophes quote syntax characters.

#
MessageTemplate::pseudo_localized

fn MessageTemplate::pseudo_localized(self : MessageTemplate, options? : PseudoOptions) -> MessageTemplate

Pseudo-localizes literal text while preserving arguments, selectors, plural rules, and the template's original source for diagnostics.

#
MessageTemplate::source

fn MessageTemplate::source(self : MessageTemplate) -> String

#
MessageValue

pub(all) enum MessageValue {
StringValue(String)
IntValue(Int)
DecimalValue(Decimal)
BoolValue(Bool)
} derive(Eq,
Debug
)

A runtime value supplied to a localized message.

#
MessageValue::from_bool

fn MessageValue::from_bool(value : Bool) -> MessageValue

#
MessageValue::from_decimal

fn MessageValue::from_decimal(value : Decimal) -> MessageValue

#
MessageValue::from_int

fn MessageValue::from_int(value : Int) -> MessageValue

#
MessageValue::from_string

fn MessageValue::from_string(value : String) -> MessageValue

#
NumberFormatter

pub struct NumberFormatter {
locale : Locale
grouping : Bool
minimum_integer_digits : Int
sign_display : SignDisplay
} derive(Eq,
Debug
)

Immutable configuration for localized number output.

#
NumberFormatter::format_int

fn NumberFormatter::format_int(self : NumberFormatter, value : Int) -> String

Formats an integer using locale punctuation and grouping.

#
NumberFormatter::locale

fn NumberFormatter::locale(self : NumberFormatter) -> Locale

#
NumberFormatter::new

#
NumberFormatter::with_grouping

fn NumberFormatter::with_grouping(self : NumberFormatter, enabled : Bool) -> NumberFormatter

#
NumberFormatter::with_minimum_integer_digits

fn NumberFormatter::with_minimum_integer_digits(self : NumberFormatter, digits : Int) -> NumberFormatter

Sets the minimum number of integer digits, clamped to the range 1–21.

#
NumberFormatter::with_sign_display

fn NumberFormatter::with_sign_display(self : NumberFormatter, display : SignDisplay) -> NumberFormatter

#
NumberSymbols

pub struct NumberSymbols {
decimal : String
group : String
minus : String
plus : String
primary_group : Int
secondary_group : Int
} derive(Eq,
Debug
)

Symbols and grouping rules used by a numbering system.

#
NumberSymbols::decimal

fn NumberSymbols::decimal(self : NumberSymbols) -> String

#
NumberSymbols::group

fn NumberSymbols::group(self : NumberSymbols) -> String

#
NumberSymbols::minus

fn NumberSymbols::minus(self : NumberSymbols) -> String

#
NumberSymbols::plus

fn NumberSymbols::plus(self : NumberSymbols) -> String

#
NumberSymbols::primary_group

fn NumberSymbols::primary_group(self : NumberSymbols) -> Int

#
NumberSymbols::secondary_group

fn NumberSymbols::secondary_group(self : NumberSymbols) -> Int

#
PercentSpacing

pub(all) enum PercentSpacing {
LocaleDefault
Compact
Spaced
} derive(Eq,
Debug
)

Controls whether a percentage suffix is separated from the value.

#
PluralCategory

pub(all) enum PluralCategory {
Zero
One
Two
Few
Many
Other
} derive(Eq,
Debug
)

CLDR-compatible plural categories used by message selection.

#
PluralCategory::name

fn PluralCategory::name(self : PluralCategory) -> String

#
PluralKind

pub(all) enum PluralKind {
Cardinal
Ordinal
} derive(Eq,
Debug
)

The kind of plural rule requested by an application.

#
PluralRules

pub struct PluralRules {
locale : Locale
kind : PluralKind
} derive(Eq,
Debug
)

Reusable plural selector bound to a locale.

#
PluralRules::kind

fn PluralRules::kind(self : PluralRules) -> PluralKind

#
PluralRules::locale

fn PluralRules::locale(self : PluralRules) -> Locale

#
PluralRules::new

fn PluralRules::new(locale : Locale, kind? : PluralKind) -> PluralRules

#
PluralRules::ordinal

fn PluralRules::ordinal(locale : Locale) -> PluralRules

Creates rules for ordinal values such as 1st and 23rd.

#
PluralRules::select

fn PluralRules::select(self : PluralRules, value : Int) -> PluralCategory

#
PseudoOptions

pub struct PseudoOptions {
accents : Bool
expand : Bool
wrap : Bool
} derive(Eq,
Debug
)

Controls how application text is transformed for localization testing.

#
PseudoOptions::accents

fn PseudoOptions::accents(self : PseudoOptions) -> Bool

#
PseudoOptions::expands

fn PseudoOptions::expands(self : PseudoOptions) -> Bool

#
PseudoOptions::new

fn PseudoOptions::new(accents? : Bool, expand? : Bool, wrap? : Bool) -> PseudoOptions

#
PseudoOptions::wraps

fn PseudoOptions::wraps(self : PseudoOptions) -> Bool

#
RelativeNumeric

pub(all) enum RelativeNumeric {
Always
Auto
} derive(Eq,
Debug
)

#
RelativeTimeFormatter

pub struct RelativeTimeFormatter {
locale : Locale
numeric : RelativeNumeric
width : ListWidth
} derive(Eq,
Debug
)

#
RelativeTimeFormatter::format

fn RelativeTimeFormatter::format(self : RelativeTimeFormatter, value : Int, unit : RelativeUnit) -> String

Formats a signed offset, where negative values are in the past.

#
RelativeTimeFormatter::new

#
RelativeTimeFormatter::with_numeric

#
RelativeTimeFormatter::with_width

#
RelativeUnit

pub(all) enum RelativeUnit {
Second
Minute
Hour
Day
Week
Month
Quarter
Year
} derive(Eq,
Debug
)

#
ResolvedMessage

pub struct ResolvedMessage {
requested : Locale
resolved : Locale
key : String
template : MessageTemplate
} derive(Eq,
Debug
)

A message together with the locale that ultimately supplied it.

#
ResolvedMessage::key

fn ResolvedMessage::key(self : ResolvedMessage) -> String

#
ResolvedMessage::requested_locale

fn ResolvedMessage::requested_locale(self : ResolvedMessage) -> Locale

#
ResolvedMessage::resolved_locale

fn ResolvedMessage::resolved_locale(self : ResolvedMessage) -> Locale

#
ResolvedMessage::template

#
SignDisplay

pub(all) enum SignDisplay {
Auto
Always
Never
ExceptZero
} derive(Eq,
Debug
)

Controls when a localized number includes a sign.

#
UnitFormatter

pub struct UnitFormatter {
locale : Locale
width : UnitWidth
number : DecimalFormatter
} derive(Eq,
Debug
)

Locale-aware formatter for measurements and application-facing quantities.

#
UnitFormatter::format

fn UnitFormatter::format(self : UnitFormatter, value : Decimal, unit : MeasurementUnit) -> String

Formats a decimal quantity with a localized unit label.

#
UnitFormatter::format_int

fn UnitFormatter::format_int(self : UnitFormatter, value : Int, unit : MeasurementUnit) -> String

#
UnitFormatter::locale

fn UnitFormatter::locale(self : UnitFormatter) -> Locale

#
UnitFormatter::new

fn UnitFormatter::new(locale : Locale) -> UnitFormatter

#
UnitFormatter::with_fraction_digits

fn UnitFormatter::with_fraction_digits(self : UnitFormatter, minimum : Int, maximum : Int) -> UnitFormatter

#
UnitFormatter::with_width

fn UnitFormatter::with_width(self : UnitFormatter, width : UnitWidth) -> UnitFormatter

#
UnitWidth

pub(all) enum UnitWidth {
UnitLong
UnitShort
UnitNarrow
} derive(Eq,
Debug
)

Controls whether a unit is written as a word, abbreviation, or symbol.

#
Weekday

pub(all) enum Weekday {
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
} derive(Compare, Eq,
Debug
)

#
Weekday::iso_number

fn Weekday::iso_number(self : Weekday) -> Int

#
audit_catalogs

fn audit_catalogs(reference : MessageCatalog, translations : Array[MessageCatalog]) -> CatalogAudit

Compares every translation with a source-of-truth catalog.

Argument order may differ between languages, but names must form the same set so messages cannot fail only after reaching production.

#
best_locale

fn best_locale(requested : Locale, supported : Array[Locale], default? : Locale?) -> Locale?

Selects the best supported locale for a requested locale.

#
bool_argument

fn bool_argument(name : String, value : Bool) -> MessageArgument

#
cardinal_plural

fn cardinal_plural(locale : Locale, value : Int) -> PluralCategory

Selects a cardinal category for an integer.

The implementation covers the major CLDR integer rule families. Languages without grammatical integer plurals safely return other.

#
currency_fraction_digits

fn currency_fraction_digits(code : String) -> Int

Returns the conventional number of minor-unit digits for a currency.

#
days_in_month

fn days_in_month(year : Int, month : Int) -> Int

#
decimal_argument

fn decimal_argument(name : String, coefficient : Int, scale : Int) -> MessageArgument

#
format_byte_size

fn format_byte_size(bytes : Int, locale : Locale, style? : ByteSizeStyle, fraction_digits? : Int) -> String

Automatically selects a byte unit using SI (1000) or IEC (1024) scaling.

#
format_currency

fn format_currency(locale : Locale, value : Decimal, code : String, display : CurrencyDisplay) -> String

Formats a monetary value using common currency digits and locale placement.

#
format_duration

fn format_duration(total_seconds : Int, locale : Locale, width? : UnitWidth, max_parts? : Int) -> String

Formats seconds as a localized compound duration such as 1 hour, 2 minutes or 1小时2分钟.

#
format_int

fn format_int(locale : Locale, value : Int) -> String

Convenience entry point with default options.

#
format_list

fn format_list(locale : Locale, values : Array[String]) -> String

#
format_message

fn format_message(locale : Locale, source : String, arguments : Array[MessageArgument]) -> Result[String, String]

Parses and formats a one-off template.

Applications that reuse a message should parse it once and retain the MessageTemplate instead.

#
int_argument

fn int_argument(name : String, value : Int) -> MessageArgument

#
is_leap_year

fn is_leap_year(year : Int) -> Bool

#
message_resource

fn message_resource(key : String, source : String) -> MessageResource

#
number_symbols

fn number_symbols(locale : Locale) -> NumberSymbols

Returns practical decimal symbols for a locale.

MoonLocale intentionally keeps Latin digits as its portable default while selecting punctuation and grouping conventions from the locale.

#
ordinal_plural

fn ordinal_plural(locale : Locale, value : Int) -> PluralCategory

Selects an ordinal category for an integer.

#
pseudo_localize

fn pseudo_localize(text : String, options? : PseudoOptions) -> String

Transforms plain UI text so untranslated strings and cramped layouts stand out during testing.

#
string_argument

fn string_argument(name : String, value : String) -> MessageArgument

#
valid_locales

fn valid_locales(tags : Array[String]) -> Array[Locale]

Parses a list of supported tags and ignores invalid entries.