moon_l10n

    A cross-target ICU MessageFormat subset runtime and catalog linter for MoonBit.

    moonbit
    i18n
    l10n
    icu
    localization
    Download zip
    Author
    Version
    0.2.0
    License
    MIT
    Last updated
    2 months ago
    Downloads
    82

    #MoonL10n

    CI

    MoonL10n is a cross-target MoonBit internationalization library and CLI. It implements the practical core of ICU MessageFormat: variables, select, cardinal plural, selectordinal, nested branches, locale-aware fallback, JSON catalogs, static linting, and deterministic validation reports.

    The runtime has no file-system dependency and supports native, JavaScript, WebAssembly, and wasm-gc. File access is isolated in the CLI package.

    #Installation

    Add the latest Mooncakes release:

    moon add Zhouz-z/moon_l10n

    To reproduce this release after version 0.2.0 is published:

    moon add Zhouz-z/moon_l10n@0.2.0

    Import the package from moon.pkg:

    ///|
    import {
    "Zhouz-z/moon_l10n",
    }

    The default package alias is @moon_l10n. Run moon update after changing dependencies if the local package index is stale.

    #Minimal library example

    ///|
    test {
    let message = @moon_l10n.parse_message(
    "{count, plural, one {# file} other {# files}}",
    )
    let values : Map[String, @moon_l10n.Argument] = {
    "count": @moon_l10n.Number(2),
    }
    inspect(@moon_l10n.format(message, values, "en"), content="2 files")
    }

    Load catalogs and use locale fallback:

    ///|
    test {
    let english = @moon_l10n.Catalog::from_json(
    "en", "{\"files\":\"{count, plural, one {# file} other {# files}}\"}",
    )
    let translator = @moon_l10n.Translator::new("zh-CN", "en")
    translator.add_catalog(english)
    let result = translator.translate_detailed(
    "files",
    { "count": @moon_l10n.Number(1) },
    locale="zh-Hans-CN",
    )
    inspect(result.value(), content="1 file")
    inspect(result.resolved_locale(), content="en")
    }

    Fallback formatting uses the locale of the catalog that supplied the message. For example, an English fallback selected from a Chinese request still applies English plural rules.

    #Message syntax

    Variables:

    Hello {name}

    Text selection:

    {gender, select, female {She} male {He} other {They}}

    Cardinal plural:

    {count, plural, =0 {No files} one {# file} other {# files}}

    Ordinal selection:

    {position, selectordinal, one {#st} two {#nd} few {#rd} other {#th}}

    Choices may contain other choices. Within a plural or ordinal branch, # renders the active numeric argument. An inner plural temporarily replaces the outer # value; an inner select preserves it.

    The standard formatter name is selectordinal. The parser rejects the common misspelling selectorordinal and reports a correction.

    #Catalogs and fallback

    A catalog is a JSON object whose values are MessageFormat templates:

    { "greeting": "Hello {name}", "files": "{count, plural, one {# file} other {# files}}" }

    Catalog::from_json is strict and rejects malformed templates. Catalog::from_json_lenient preserves malformed templates so validators and translation editors can report all problems in one run.

    Requested locales are canonicalized and expanded into parents. A request for zh-Hans-CN tries:

    zh-Hans-CN -> zh-Hans -> zh -> configured default -> configured fallback

    Translator::resolve and translate_detailed expose the requested locale, resolved catalog locale, template provenance, and whether fallback occurred.

    #Linting

    lint_catalogs(reference, translation) reports:

    • missing and extra keys;
    • malformed reference or translation templates with line and column;
    • missing and extra arguments;
    • text-versus-number argument usage changes;
    • select, plural, and selectordinal kind changes;
    • missing or unexpected selectors;
    • missing exact selectors such as =0;
    • plural categories expected by the target locale.

    Reports have stable issue codes, severity, text output, JSON output, summary counts, and exit-code semantics. Catalog utilities also provide key diffs, coverage percentages, builders, deterministic JSON serialization, statistics, and multi-locale coverage matrices.

    #CLI

    Validate templates and semantic signatures:

    moon run cmd/main -- validate examples/locales/en.json examples/locales/en.json en moon run cmd/main -- validate examples/locales/en.json examples/locales/ru.json ru --json

    Compare catalog key sets:

    moon run cmd/main -- diff examples/locales/en.json examples/locales/zh-CN.json zh-CN

    Render one message:

    moon run cmd/main -- render examples/locales/en.json en files count=3 moon run cmd/main -- render examples/locales/en.json en files count=1 --json

    Exit code 0 means clean, 1 means warnings or extra-only differences, and 2 means errors or missing required content. render returns 0 on success.

    #Locale coverage

    Version 0.2.0 explicitly implements integer plural behavior for:

    • Chinese (zh, including zh-CN) and Japanese (ja): other;
    • English (en): cardinal one/other, ordinal one/two/few/other;
    • Russian (ru): one/few/many/other;
    • Arabic (ar): zero/one/two/few/many/other.

    The locale layer also provides canonicalization, language/script/region parsing, parent fallback chains, text direction, negotiation, supported category metadata, and representative plural examples.

    #ICU and CLDR scope

    MoonL10n is an original MoonBit implementation informed by public internationalization specifications. It does not copy ICU or CLDR source code or data files.

    References:

    Version 0.2.0 intentionally does not implement:

    • date, time, number, or currency formatting;
    • gettext PO/POT catalogs;
    • plural offset;
    • decimal plural operands;
    • complete generated CLDR locale data;
    • ICU apostrophe quoting;
    • remote translation services.

    Backslash escaping is used for literal {, }, #, and \ in this subset. These boundaries keep the runtime compact, deterministic, and cross-target.

    #Validation

    python scripts/count_effective_moonbit.py --minimum 4000 moon fmt --check moon check --target all --deny-warn moon build --target all --deny-warn moon test --target all --deny-warn moon info moon package

    The effective-line check counts code-bearing lines in production MoonBit library packages. Tests, examples, the CLI executable, generated interfaces, comments, and build output are excluded.

    GitHub Actions runs the same gates plus CLI smoke tests and uploads the Mooncakes zip artifact.

    #License

    MIT. See LICENSE.

    MessageError

    pub(all) suberror MessageError {
    ParseError(position~ : Int, message~ : String)
    InvalidCatalog(String)
    InvalidLocale(String)
    InvalidCommand(String)
    EvaluationLimit(Int)
    MissingArgument(String)
    WrongArgumentType(String)
    MissingChoice(String)
    } derive(Eq,
    Debug
    )

    Argument

    pub(all) enum Argument {
    Text(String)
    Number(Int)
    } derive(Eq,
    Debug
    )

    Argument::as_number

    fn Argument::as_number(self : Argument) -> Int raise MessageError

    Argument::as_text

    fn Argument::as_text(self : Argument) -> String

    Argument::is_number

    fn Argument::is_number(self : Argument) -> Bool

    Argument::is_text

    fn Argument::is_text(self : Argument) -> Bool

    Argument::kind

    fn Argument::kind(self : Argument) -> String

    ArgumentRole

    pub(all) enum ArgumentRole {
    Interpolation
    SelectSelector
    CardinalSelector
    OrdinalSelector
    } derive(Eq,
    Debug
    )

    Describes how an argument is consumed by a message.

    ArgumentRole::expects_number

    fn ArgumentRole::expects_number(self : ArgumentRole) -> Bool

    ArgumentRole::name

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

    ArgumentUse

    pub(all) struct ArgumentUse {
    name : String
    roles : Array[ArgumentRole]
    occurrences : Int
    } derive(Eq,
    Debug
    )

    A single use of an argument in a parsed message.

    ArgumentUse::expects_number

    fn ArgumentUse::expects_number(self : ArgumentUse) -> Bool

    ArgumentUse::name

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

    ArgumentUse::occurrences

    fn ArgumentUse::occurrences(self : ArgumentUse) -> Int

    ArgumentUse::roles

    ArgumentUse::uses_role

    fn ArgumentUse::uses_role(self : ArgumentUse, role : ArgumentRole) -> Bool

    Catalog

    pub struct Catalog {
    locale : String
    entries : Map[String, String]
    } derive(
    Debug
    )

    Catalog::analyses

    fn Catalog::analyses(self : Catalog) -> Array[CatalogEntryAnalysis]

    Catalog::contains

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

    Catalog::entries

    fn Catalog::entries(self : Catalog) -> Map[String, String]

    Catalog::entry_analysis

    fn Catalog::entry_analysis(self : Catalog, key : String) -> CatalogEntryAnalysis?

    Catalog::from_json

    fn Catalog::from_json(locale : String, source : String) -> Catalog raise MessageError

    Catalog::from_json_lenient

    fn Catalog::from_json_lenient(locale : String, source : String) -> Catalog raise MessageError

    Load a catalog without rejecting invalid message templates.

    This is intended for validators and editors that need to report every malformed entry in one pass. Applications should normally use from_json.

    Catalog::get

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

    Catalog::invalid_keys

    fn Catalog::invalid_keys(self : Catalog) -> Array[String]

    Catalog::is_empty

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

    Catalog::keys

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

    Catalog::length

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

    Catalog::locale

    fn Catalog::locale(self : Catalog) -> String

    Catalog::merge

    fn Catalog::merge(self : Catalog, other : Catalog, policy? : CatalogMergePolicy) -> Catalog raise MessageError

    Catalog::parsed

    fn Catalog::parsed(self : Catalog, key : String) -> Message?

    Catalog::stats

    fn Catalog::stats(self : Catalog) -> CatalogStats

    Compute aggregate catalog statistics.

    Catalog::subset

    fn Catalog::subset(self : Catalog, prefix : String) -> Catalog

    Catalog::to_json

    fn Catalog::to_json(self : Catalog, pretty? : Bool) -> String

    Serialize a catalog deterministically with keys in lexical order.

    Catalog::valid_keys

    fn Catalog::valid_keys(self : Catalog) -> Array[String]

    Catalog::values

    fn Catalog::values(self : Catalog) -> Array[String]

    Catalog::with_entry

    fn Catalog::with_entry(self : Catalog, key : String, template : String) -> Catalog raise MessageError

    Catalog::without_entry

    fn Catalog::without_entry(self : Catalog, key : String) -> Catalog

    CatalogBuilder

    pub struct CatalogBuilder {
    locale : String
    entries : Map[String, String]
    }

    A builder for constructing catalogs without exposing mutable internals.

    CatalogBuilder::build

    fn CatalogBuilder::build(self : CatalogBuilder, validate? : Bool) -> Catalog raise MessageError

    CatalogBuilder::clear

    CatalogBuilder::contains

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

    CatalogBuilder::from_catalog

    fn CatalogBuilder::from_catalog(catalog : Catalog) -> CatalogBuilder

    CatalogBuilder::length

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

    CatalogBuilder::locale

    fn CatalogBuilder::locale(self : CatalogBuilder) -> String

    CatalogBuilder::new

    fn CatalogBuilder::new(locale : String) -> CatalogBuilder

    CatalogBuilder::remove

    fn CatalogBuilder::remove(self : CatalogBuilder, key : String) -> CatalogBuilder

    CatalogBuilder::set

    fn CatalogBuilder::set(self : CatalogBuilder, key : String, template : String) -> CatalogBuilder

    CatalogCoverage

    pub(all) struct CatalogCoverage {
    reference_keys : Int
    translated_keys : Int
    missing_keys : Int
    extra_keys : Int
    coverage_percent : Int
    } derive(Eq,
    Debug
    )

    Result of a catalog coverage calculation.

    CatalogCoverage::coverage_percent

    fn CatalogCoverage::coverage_percent(self : CatalogCoverage) -> Int

    CatalogCoverage::extra_keys

    fn CatalogCoverage::extra_keys(self : CatalogCoverage) -> Int

    CatalogCoverage::missing_keys

    fn CatalogCoverage::missing_keys(self : CatalogCoverage) -> Int

    CatalogCoverage::reference_keys

    fn CatalogCoverage::reference_keys(self : CatalogCoverage) -> Int

    CatalogCoverage::summary

    fn CatalogCoverage::summary(self : CatalogCoverage) -> String

    CatalogCoverage::translated_keys

    fn CatalogCoverage::translated_keys(self : CatalogCoverage) -> Int

    CatalogDiff

    pub(all) struct CatalogDiff {
    reference_locale : String
    translation_locale : String
    shared_keys : Array[String]
    missing_keys : Array[String]
    extra_keys : Array[String]
    } derive(Eq,
    Debug
    )

    Key-level difference between two catalogs.

    CatalogDiff::coverage

    fn CatalogDiff::coverage(self : CatalogDiff) -> CatalogCoverage

    CatalogDiff::extra_keys

    fn CatalogDiff::extra_keys(self : CatalogDiff) -> Array[String]

    CatalogDiff::is_equal

    fn CatalogDiff::is_equal(self : CatalogDiff) -> Bool

    CatalogDiff::missing_keys

    fn CatalogDiff::missing_keys(self : CatalogDiff) -> Array[String]

    CatalogDiff::reference_locale

    fn CatalogDiff::reference_locale(self : CatalogDiff) -> String

    CatalogDiff::shared_keys

    fn CatalogDiff::shared_keys(self : CatalogDiff) -> Array[String]

    CatalogDiff::translation_locale

    fn CatalogDiff::translation_locale(self : CatalogDiff) -> String

    CatalogEntryAnalysis

    pub(all) struct CatalogEntryAnalysis {
    key : String
    template : String
    valid : Bool
    diagnostic : MessageDiagnostic?
    message : MessageAnalysis?
    } derive(
    Debug
    )

    Analysis for a single catalog entry.

    CatalogEntryAnalysis::diagnostic

    CatalogEntryAnalysis::key

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

    CatalogEntryAnalysis::message

    CatalogEntryAnalysis::template

    fn CatalogEntryAnalysis::template(self : CatalogEntryAnalysis) -> String

    CatalogEntryAnalysis::valid

    fn CatalogEntryAnalysis::valid(self : CatalogEntryAnalysis) -> Bool

    CatalogMatrix

    pub(all) struct CatalogMatrix {
    reference_locale : String
    locales : Array[String]
    rows : Array[CatalogMatrixRow]
    } derive(Eq,
    Debug
    )

    Cross-locale catalog coverage matrix.

    CatalogMatrix::complete

    fn CatalogMatrix::complete(self : CatalogMatrix) -> Bool

    CatalogMatrix::complete_rows

    fn CatalogMatrix::complete_rows(self : CatalogMatrix) -> Array[CatalogMatrixRow]

    CatalogMatrix::coverage_for

    fn CatalogMatrix::coverage_for(self : CatalogMatrix, locale : String) -> CatalogCoverage?

    CatalogMatrix::has_locale

    fn CatalogMatrix::has_locale(self : CatalogMatrix, locale : String) -> Bool

    CatalogMatrix::incomplete_rows

    fn CatalogMatrix::incomplete_rows(self : CatalogMatrix) -> Array[CatalogMatrixRow]

    CatalogMatrix::key_count

    fn CatalogMatrix::key_count(self : CatalogMatrix) -> Int

    CatalogMatrix::locale_count

    fn CatalogMatrix::locale_count(self : CatalogMatrix) -> Int

    CatalogMatrix::locales

    fn CatalogMatrix::locales(self : CatalogMatrix) -> Array[String]

    CatalogMatrix::missing_count

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

    CatalogMatrix::missing_keys_for

    fn CatalogMatrix::missing_keys_for(self : CatalogMatrix, locale : String) -> Array[String]

    CatalogMatrix::present_keys_for

    fn CatalogMatrix::present_keys_for(self : CatalogMatrix, locale : String) -> Array[String]

    CatalogMatrix::reference_locale

    fn CatalogMatrix::reference_locale(self : CatalogMatrix) -> String

    CatalogMatrix::row

    fn CatalogMatrix::row(self : CatalogMatrix, key : String) -> CatalogMatrixRow?

    CatalogMatrix::rows

    CatalogMatrix::to_json

    fn CatalogMatrix::to_json(self : CatalogMatrix) -> String

    CatalogMatrix::to_text

    fn CatalogMatrix::to_text(self : CatalogMatrix) -> String

    CatalogMatrixRow

    pub(all) struct CatalogMatrixRow {
    key : String
    present_locales : Array[String]
    missing_locales : Array[String]
    } derive(Eq,
    Debug
    )

    Presence information for one key across a catalog set.

    CatalogMatrixRow::complete

    fn CatalogMatrixRow::complete(self : CatalogMatrixRow) -> Bool

    CatalogMatrixRow::coverage_percent

    fn CatalogMatrixRow::coverage_percent(self : CatalogMatrixRow) -> Int

    CatalogMatrixRow::key

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

    CatalogMatrixRow::missing_locales

    fn CatalogMatrixRow::missing_locales(self : CatalogMatrixRow) -> Array[String]

    CatalogMatrixRow::present_locales

    fn CatalogMatrixRow::present_locales(self : CatalogMatrixRow) -> Array[String]

    CatalogMergePolicy

    pub(all) enum CatalogMergePolicy {
    KeepExisting
    ReplaceExisting
    RejectDuplicate
    } derive(Eq,
    Debug
    )

    How duplicate keys should be handled while combining catalogs.

    CatalogStats

    pub(all) struct CatalogStats {
    locale : String
    key_count : Int
    template_count : Int
    valid_template_count : Int
    invalid_template_count : Int
    argument_count : Int
    choice_count : Int
    } derive(Eq,
    Debug
    )

    Summary information for one catalog.

    CatalogStats::argument_count

    fn CatalogStats::argument_count(self : CatalogStats) -> Int

    CatalogStats::choice_count

    fn CatalogStats::choice_count(self : CatalogStats) -> Int

    CatalogStats::invalid_template_count

    fn CatalogStats::invalid_template_count(self : CatalogStats) -> Int

    CatalogStats::key_count

    fn CatalogStats::key_count(self : CatalogStats) -> Int

    CatalogStats::locale

    fn CatalogStats::locale(self : CatalogStats) -> String

    CatalogStats::summary

    fn CatalogStats::summary(self : CatalogStats) -> String

    CatalogStats::template_count

    fn CatalogStats::template_count(self : CatalogStats) -> Int

    CatalogStats::valid_template_count

    fn CatalogStats::valid_template_count(self : CatalogStats) -> Int

    ChoiceKind

    pub(all) enum ChoiceKind {
    Select
    Plural
    SelectOrdinal
    } derive(Eq,
    Debug
    )

    The kind of selector represented by a choice expression.

    ChoiceKind::from_name

    fn ChoiceKind::from_name(name : String) -> ChoiceKind?

    ChoiceKind::is_numeric

    fn ChoiceKind::is_numeric(self : ChoiceKind) -> Bool

    ChoiceKind::name

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

    ChoiceUse

    pub(all) struct ChoiceUse {
    argument : String
    kind : ChoiceKind
    selectors : Array[String]
    depth : Int
    ordinal : Int
    } derive(Eq,
    Debug
    )

    One choice expression found in a message.

    ChoiceUse::argument

    fn ChoiceUse::argument(self : ChoiceUse) -> String

    ChoiceUse::category_selectors

    fn ChoiceUse::category_selectors(self : ChoiceUse) -> Array[String]

    ChoiceUse::depth

    fn ChoiceUse::depth(self : ChoiceUse) -> Int

    ChoiceUse::exact_selectors

    fn ChoiceUse::exact_selectors(self : ChoiceUse) -> Array[String]

    ChoiceUse::has_selector

    fn ChoiceUse::has_selector(self : ChoiceUse, selector : String) -> Bool

    ChoiceUse::identifier

    fn ChoiceUse::identifier(self : ChoiceUse) -> String

    ChoiceUse::kind

    fn ChoiceUse::kind(self : ChoiceUse) -> ChoiceKind

    ChoiceUse::ordinal

    fn ChoiceUse::ordinal(self : ChoiceUse) -> Int

    ChoiceUse::selectors

    fn ChoiceUse::selectors(self : ChoiceUse) -> Array[String]

    CliCommandKind

    pub(all) enum CliCommandKind {
    Validate
    Diff
    Render
    Help
    } derive(Eq,
    Debug
    )

    Stable command names understood by the pure CLI parser.

    CliCommandKind::name

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

    CliOutput

    pub(all) struct CliOutput {
    exit_code : Int
    stdout : String
    stderr : String
    } derive(Eq,
    Debug
    )

    Result returned by the pure CLI execution layer.

    CliOutput::display

    fn CliOutput::display(self : CliOutput) -> String

    CliOutput::exit_code

    fn CliOutput::exit_code(self : CliOutput) -> Int

    CliOutput::failed

    fn CliOutput::failed(self : CliOutput) -> Bool

    CliOutput::stderr

    fn CliOutput::stderr(self : CliOutput) -> String

    CliOutput::stdout

    fn CliOutput::stdout(self : CliOutput) -> String

    CliOutput::succeeded

    fn CliOutput::succeeded(self : CliOutput) -> Bool

    CliRequest

    pub(all) struct CliRequest {
    kind : CliCommandKind
    paths : Array[String]
    locale : String?
    key : String?
    arguments : Map[String, Argument]
    json : Bool
    } derive(Eq,
    Debug
    )

    Parsed CLI request independent of file-system access.

    CliRequest::arguments

    fn CliRequest::arguments(self : CliRequest) -> Map[String, Argument]

    CliRequest::json

    fn CliRequest::json(self : CliRequest) -> Bool

    CliRequest::key

    fn CliRequest::key(self : CliRequest) -> String?

    CliRequest::kind

    CliRequest::locale

    fn CliRequest::locale(self : CliRequest) -> String?

    CliRequest::path

    fn CliRequest::path(self : CliRequest, index : Int) -> String?

    CliRequest::paths

    fn CliRequest::paths(self : CliRequest) -> Array[String]

    FormatEvent

    pub(all) struct FormatEvent {
    kind : FormatEventKind
    depth : Int
    path : String
    argument : String?
    selector : String?
    output : String
    } derive(Eq,
    Debug
    )

    One deterministic event from message evaluation.

    FormatEvent::argument

    fn FormatEvent::argument(self : FormatEvent) -> String?

    FormatEvent::depth

    fn FormatEvent::depth(self : FormatEvent) -> Int

    FormatEvent::display

    fn FormatEvent::display(self : FormatEvent) -> String

    FormatEvent::emits_output

    fn FormatEvent::emits_output(self : FormatEvent) -> Bool

    FormatEvent::has_argument

    fn FormatEvent::has_argument(self : FormatEvent) -> Bool

    FormatEvent::has_selector

    fn FormatEvent::has_selector(self : FormatEvent) -> Bool

    FormatEvent::is_choice

    fn FormatEvent::is_choice(self : FormatEvent) -> Bool

    FormatEvent::kind

    FormatEvent::output

    fn FormatEvent::output(self : FormatEvent) -> String

    FormatEvent::path

    fn FormatEvent::path(self : FormatEvent) -> String

    FormatEvent::selector

    fn FormatEvent::selector(self : FormatEvent) -> String?

    FormatEventKind

    pub(all) enum FormatEventKind {
    EmitText
    EmitArgument
    EmitPound
    SelectBranch
    } derive(Eq,
    Debug
    )

    Kind of evaluation event emitted by format_with_trace.

    FormatEventKind::name

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

    FormatOptions

    pub(all) struct FormatOptions {
    missing_argument : MissingArgumentBehavior
    maximum_depth : Int
    } derive(Eq,
    Debug
    )

    Runtime options for message evaluation.

    FormatOptions::default

    fn FormatOptions::default() -> FormatOptions

    FormatOptions::maximum_depth

    fn FormatOptions::maximum_depth(self : FormatOptions) -> Int

    FormatOptions::missing_argument

    fn FormatOptions::missing_argument(self : FormatOptions) -> MissingArgumentBehavior

    FormatOptions::permissive

    fn FormatOptions::permissive() -> FormatOptions

    FormattedMessage

    pub(all) struct FormattedMessage {
    value : String
    events : Array[FormatEvent]
    } derive(Eq,
    Debug
    )

    Formatted value plus a deterministic evaluation trace.

    FormattedMessage::choice_events

    fn FormattedMessage::choice_events(self : FormattedMessage) -> Array[FormatEvent]

    FormattedMessage::event_count

    fn FormattedMessage::event_count(self : FormattedMessage) -> Int

    FormattedMessage::events

    FormattedMessage::events_for_argument

    fn FormattedMessage::events_for_argument(self : FormattedMessage, argument : String) -> Array[FormatEvent]

    FormattedMessage::maximum_depth

    fn FormattedMessage::maximum_depth(self : FormattedMessage) -> Int

    FormattedMessage::trace_text

    fn FormattedMessage::trace_text(self : FormattedMessage) -> String

    FormattedMessage::value

    fn FormattedMessage::value(self : FormattedMessage) -> String

    LintIssue

    pub struct LintIssue {
    severity : LintSeverity
    code : String
    key : String
    message : String
    argument : String?
    selector : String?
    } derive(Eq,
    Debug
    )

    LintIssue::argument

    fn LintIssue::argument(self : LintIssue) -> String?

    LintIssue::code

    fn LintIssue::code(self : LintIssue) -> String

    LintIssue::display

    fn LintIssue::display(self : LintIssue) -> String

    LintIssue::key

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

    LintIssue::message

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

    LintIssue::selector

    fn LintIssue::selector(self : LintIssue) -> String?

    LintIssue::severity

    fn LintIssue::severity(self : LintIssue) -> LintSeverity

    LintOptions

    pub(all) struct LintOptions {
    report_extra_keys : Bool
    report_extra_arguments : Bool
    report_extra_selectors : Bool
    require_locale_categories : Bool
    } derive(Eq,
    Debug
    )

    Policy switches for catalog linting.

    LintOptions::default

    fn LintOptions::default() -> LintOptions

    LintOptions::minimal

    fn LintOptions::minimal() -> LintOptions

    LintOptions::report_extra_arguments

    fn LintOptions::report_extra_arguments(self : LintOptions) -> Bool

    LintOptions::report_extra_keys

    fn LintOptions::report_extra_keys(self : LintOptions) -> Bool

    LintOptions::report_extra_selectors

    fn LintOptions::report_extra_selectors(self : LintOptions) -> Bool

    LintOptions::require_locale_categories

    fn LintOptions::require_locale_categories(self : LintOptions) -> Bool

    LintReport

    pub struct LintReport {
    reference_locale : String
    locale : String
    issues : Array[LintIssue]
    } derive(
    Debug
    )

    LintReport::contains_code

    fn LintReport::contains_code(self : LintReport, code : String) -> Bool

    LintReport::exit_code

    fn LintReport::exit_code(self : LintReport) -> Int

    LintReport::has_errors

    fn LintReport::has_errors(self : LintReport) -> Bool

    LintReport::issues

    fn LintReport::issues(self : LintReport) -> Array[LintIssue]

    LintReport::issues_with_code

    fn LintReport::issues_with_code(self : LintReport, code : String) -> Array[LintIssue]

    LintReport::issues_with_severity

    fn LintReport::issues_with_severity(self : LintReport, severity : LintSeverity) -> Array[LintIssue]

    LintReport::locale

    fn LintReport::locale(self : LintReport) -> String

    LintReport::ok

    fn LintReport::ok(self : LintReport) -> Bool

    LintReport::reference_locale

    fn LintReport::reference_locale(self : LintReport) -> String

    LintReport::summary

    fn LintReport::summary(self : LintReport) -> LintSummary

    LintReport::to_json

    fn LintReport::to_json(self : LintReport) -> String

    LintReport::to_text

    fn LintReport::to_text(self : LintReport) -> String

    LintSeverity

    pub(all) enum LintSeverity {
    Error
    Warning
    Information
    } derive(Eq,
    Debug
    )

    Severity assigned to a catalog lint issue.

    LintSeverity::name

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

    LintSeverity::rank

    fn LintSeverity::rank(self : LintSeverity) -> Int

    LintSummary

    pub(all) struct LintSummary {
    errors : Int
    warnings : Int
    information : Int
    total : Int
    } derive(Eq,
    Debug
    )

    Aggregate lint counts.

    LintSummary::display

    fn LintSummary::display(self : LintSummary) -> String

    LintSummary::errors

    fn LintSummary::errors(self : LintSummary) -> Int

    LintSummary::information

    fn LintSummary::information(self : LintSummary) -> Int

    LintSummary::total

    fn LintSummary::total(self : LintSummary) -> Int

    LintSummary::warnings

    fn LintSummary::warnings(self : LintSummary) -> Int

    LocaleId

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

    Parsed and normalized locale identifier.

    LocaleId::canonical

    fn LocaleId::canonical(self : LocaleId) -> String

    LocaleId::fallback_chain

    fn LocaleId::fallback_chain(self : LocaleId) -> Array[String]

    Return the exact locale followed by progressively broader parent locales.

    LocaleId::has_region

    fn LocaleId::has_region(self : LocaleId) -> Bool

    LocaleId::has_script

    fn LocaleId::has_script(self : LocaleId) -> Bool

    LocaleId::is_language

    fn LocaleId::is_language(self : LocaleId, language : String) -> Bool

    LocaleId::language

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

    LocaleId::original

    fn LocaleId::original(self : LocaleId) -> String

    LocaleId::parse

    fn LocaleId::parse(value : String) -> LocaleId raise MessageError

    Parse and canonicalize a compact BCP-47-style locale identifier.

    LocaleId::region

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

    LocaleId::script

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

    LocaleId::variants

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

    LocaleNegotiation

    pub(all) struct LocaleNegotiation {
    requested : String
    candidates : Array[String]
    available : Array[String]
    matched : String?
    used_default : Bool
    } derive(Eq,
    Debug
    )

    Result of negotiating requested and available locales.

    LocaleNegotiation::available

    fn LocaleNegotiation::available(self : LocaleNegotiation) -> Array[String]

    LocaleNegotiation::candidates

    fn LocaleNegotiation::candidates(self : LocaleNegotiation) -> Array[String]

    LocaleNegotiation::matched

    fn LocaleNegotiation::matched(self : LocaleNegotiation) -> String?

    LocaleNegotiation::requested

    fn LocaleNegotiation::requested(self : LocaleNegotiation) -> String

    LocaleNegotiation::succeeded

    fn LocaleNegotiation::succeeded(self : LocaleNegotiation) -> Bool

    LocaleNegotiation::summary

    fn LocaleNegotiation::summary(self : LocaleNegotiation) -> String

    LocaleNegotiation::used_default

    fn LocaleNegotiation::used_default(self : LocaleNegotiation) -> Bool

    LocaleProfile

    pub(all) struct LocaleProfile {
    locale : LocaleId
    direction : TextDirection
    cardinal_family : PluralRuleFamily
    ordinal_family : PluralRuleFamily
    cardinal_categories : Array[String]
    ordinal_categories : Array[String]
    } derive(Eq,
    Debug
    )

    Metadata used by the runtime and linter for a supported locale.

    LocaleProfile::cardinal_categories

    fn LocaleProfile::cardinal_categories(self : LocaleProfile) -> Array[String]

    LocaleProfile::cardinal_family

    fn LocaleProfile::cardinal_family(self : LocaleProfile) -> PluralRuleFamily

    LocaleProfile::direction

    fn LocaleProfile::direction(self : LocaleProfile) -> TextDirection

    LocaleProfile::locale

    fn LocaleProfile::locale(self : LocaleProfile) -> LocaleId

    LocaleProfile::ordinal_categories

    fn LocaleProfile::ordinal_categories(self : LocaleProfile) -> Array[String]

    LocaleProfile::ordinal_family

    fn LocaleProfile::ordinal_family(self : LocaleProfile) -> PluralRuleFamily

    LocaleSupport

    pub(all) struct LocaleSupport {
    language : String
    english_name : String
    native_name : String
    direction : TextDirection
    cardinal_categories : Array[String]
    ordinal_categories : Array[String]
    } derive(Eq,
    Debug
    )

    Human-facing metadata for one explicitly supported base locale.

    LocaleSupport::cardinal_categories

    fn LocaleSupport::cardinal_categories(self : LocaleSupport) -> Array[String]

    LocaleSupport::direction

    fn LocaleSupport::direction(self : LocaleSupport) -> TextDirection

    LocaleSupport::english_name

    fn LocaleSupport::english_name(self : LocaleSupport) -> String

    LocaleSupport::language

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

    LocaleSupport::native_name

    fn LocaleSupport::native_name(self : LocaleSupport) -> String

    LocaleSupport::ordinal_categories

    fn LocaleSupport::ordinal_categories(self : LocaleSupport) -> Array[String]

    LocaleSupport::summary

    fn LocaleSupport::summary(self : LocaleSupport) -> String

    Message

    pub struct Message {
    nodes : Array[MessageNode]
    } derive(
    Debug
    )

    Message::analyze

    fn Message::analyze(self : Message) -> MessageAnalysis

    Analyze the argument signature and structural complexity of a message.

    Message::argument_uses

    fn Message::argument_uses(self : Message) -> Array[ArgumentUse]

    Message::ast_text

    fn Message::ast_text(self : Message) -> String

    Render a deterministic, human-readable AST tree.

    Message::choice_uses

    fn Message::choice_uses(self : Message) -> Array[ChoiceUse]

    Message::from_nodes

    fn Message::from_nodes(nodes : Array[MessageNode]) -> Message

    Construct a message from AST nodes.

    Message::maximum_depth

    fn Message::maximum_depth(self : Message) -> Int

    Message::node_count

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

    Message::nodes

    fn Message::nodes(self : Message) -> Array[MessageNode]

    Message::signature

    fn Message::signature(self : Message) -> MessageSignature

    Return a semantic signature for linting and tooling.

    Message::to_template

    fn Message::to_template(self : Message) -> String

    Serialize an AST using MoonL10n's canonical spacing and escaping.

    MessageAnalysis

    pub(all) struct MessageAnalysis {
    arguments : Array[ArgumentUse]
    node_count : Int
    text_node_count : Int
    argument_node_count : Int
    choice_node_count : Int
    pound_node_count : Int
    maximum_depth : Int
    } derive(Eq,
    Debug
    )

    Structural information collected from a parsed message.

    MessageAnalysis::argument_node_count

    fn MessageAnalysis::argument_node_count(self : MessageAnalysis) -> Int

    MessageAnalysis::arguments

    MessageAnalysis::choice_node_count

    fn MessageAnalysis::choice_node_count(self : MessageAnalysis) -> Int

    MessageAnalysis::maximum_depth

    fn MessageAnalysis::maximum_depth(self : MessageAnalysis) -> Int

    MessageAnalysis::node_count

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

    MessageAnalysis::pound_node_count

    fn MessageAnalysis::pound_node_count(self : MessageAnalysis) -> Int

    MessageAnalysis::text_node_count

    fn MessageAnalysis::text_node_count(self : MessageAnalysis) -> Int

    MessageDiagnostic

    pub(all) struct MessageDiagnostic {
    code : String
    message : String
    position : SourcePosition
    } derive(Eq,
    Debug
    )

    A stable, serializable parser diagnostic.

    MessageDiagnostic::code

    fn MessageDiagnostic::code(self : MessageDiagnostic) -> String

    MessageDiagnostic::display

    fn MessageDiagnostic::display(self : MessageDiagnostic) -> String

    MessageDiagnostic::message

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

    MessageDiagnostic::position

    MessageNode

    pub(all) enum MessageNode {
    TextNode(String)
    ArgumentNode(String)
    PoundNode
    ChoiceNode(String, String, Map[String, Array[MessageNode]])
    } derive(
    Debug
    )

    MessageSignature

    pub(all) struct MessageSignature {
    arguments : Array[ArgumentUse]
    choices : Array[ChoiceUse]
    } derive(Eq,
    Debug
    )

    Full semantic signature used by catalog linting.

    MessageSignature::argument

    fn MessageSignature::argument(self : MessageSignature, name : String) -> ArgumentUse?

    MessageSignature::argument_count

    fn MessageSignature::argument_count(self : MessageSignature) -> Int

    MessageSignature::argument_names

    fn MessageSignature::argument_names(self : MessageSignature) -> Array[String]

    Return sorted argument names used by a message.

    MessageSignature::arguments

    MessageSignature::choice_count

    fn MessageSignature::choice_count(self : MessageSignature) -> Int

    MessageSignature::choices

    MessageSignature::choices_for_argument

    fn MessageSignature::choices_for_argument(self : MessageSignature, name : String) -> Array[ChoiceUse]

    MessageSignature::choices_of_kind

    fn MessageSignature::choices_of_kind(self : MessageSignature, kind : ChoiceKind) -> Array[ChoiceUse]

    MessageSignature::compatible_with

    fn MessageSignature::compatible_with(self : MessageSignature, other : MessageSignature) -> Bool

    Compare argument names and roles while ignoring occurrence counts.

    MessageSignature::has_argument

    fn MessageSignature::has_argument(self : MessageSignature, name : String) -> Bool

    MessageSignature::summary

    fn MessageSignature::summary(self : MessageSignature) -> String

    Render a compact signature suitable for CLI diagnostics.

    MissingArgumentBehavior

    pub(all) enum MissingArgumentBehavior {
    RaiseError
    KeepPlaceholder
    ReplaceWithEmpty
    } derive(Eq,
    Debug
    )

    Behavior used by the configurable formatter when an argument is absent.

    MissingArgumentBehavior::name

    PluralExamples

    pub(all) struct PluralExamples {
    category : String
    values : Array[Int]
    } derive(Eq,
    Debug
    )

    Example values discovered for one plural category.

    PluralExamples::category

    fn PluralExamples::category(self : PluralExamples) -> String

    PluralExamples::is_empty

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

    PluralExamples::summary

    fn PluralExamples::summary(self : PluralExamples) -> String

    PluralExamples::values

    fn PluralExamples::values(self : PluralExamples) -> Array[Int]

    PluralRuleFamily

    pub(all) enum PluralRuleFamily {
    OtherOnly
    English
    Russian
    Arabic
    } derive(Eq,
    Debug
    )

    Plural rule set selected for a locale.

    PluralRuleFamily::name

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

    PluralSelection

    pub(all) struct PluralSelection {
    locale : String
    value : Int
    ordinal : Bool
    category : String
    exact_selector : String
    selected_selector : String
    used_exact : Bool
    used_other : Bool
    } derive(Eq,
    Debug
    )

    Explanation of plural branch selection.

    PluralSelection::category

    fn PluralSelection::category(self : PluralSelection) -> String

    PluralSelection::exact_selector

    fn PluralSelection::exact_selector(self : PluralSelection) -> String

    PluralSelection::locale

    fn PluralSelection::locale(self : PluralSelection) -> String

    PluralSelection::ordinal

    fn PluralSelection::ordinal(self : PluralSelection) -> Bool

    PluralSelection::selected_selector

    fn PluralSelection::selected_selector(self : PluralSelection) -> String

    PluralSelection::summary

    fn PluralSelection::summary(self : PluralSelection) -> String

    PluralSelection::used_exact

    fn PluralSelection::used_exact(self : PluralSelection) -> Bool

    PluralSelection::used_other

    fn PluralSelection::used_other(self : PluralSelection) -> Bool

    PluralSelection::value

    fn PluralSelection::value(self : PluralSelection) -> Int

    ResolvedMessage

    pub(all) struct ResolvedMessage {
    key : String
    requested_locale : String
    resolved_locale : String
    template : String
    used_fallback : Bool
    } derive(Eq,
    Debug
    )

    A message template together with the catalog that supplied it.

    ResolvedMessage::key

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

    ResolvedMessage::requested_locale

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

    ResolvedMessage::resolved_locale

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

    ResolvedMessage::template

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

    ResolvedMessage::used_fallback

    fn ResolvedMessage::used_fallback(self : ResolvedMessage) -> Bool

    SourcePosition

    pub(all) struct SourcePosition {
    offset : Int
    line : Int
    column : Int
    } derive(Eq,
    Debug
    )

    A one-based source location together with its zero-based character offset.

    SourcePosition::column

    fn SourcePosition::column(self : SourcePosition) -> Int

    SourcePosition::display

    fn SourcePosition::display(self : SourcePosition) -> String

    SourcePosition::line

    fn SourcePosition::line(self : SourcePosition) -> Int

    SourcePosition::offset

    fn SourcePosition::offset(self : SourcePosition) -> Int

    SourceSpan

    pub(all) struct SourceSpan {
    start : SourcePosition
    end : SourcePosition
    } derive(Eq,
    Debug
    )

    A half-open range in a message template.

    SourceSpan::end

    SourceSpan::length

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

    SourceSpan::start

    fn SourceSpan::start(self : SourceSpan) -> SourcePosition

    TextDirection

    pub(all) enum TextDirection {
    LeftToRight
    RightToLeft
    } derive(Eq,
    Debug
    )

    Text direction associated with a locale.

    TextDirection::name

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

    TranslationResult

    pub(all) struct TranslationResult {
    key : String
    requested_locale : String
    resolved_locale : String
    value : String
    used_fallback : Bool
    } derive(Eq,
    Debug
    )

    Detailed result returned after translation and formatting.

    TranslationResult::key

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

    TranslationResult::requested_locale

    fn TranslationResult::requested_locale(self : TranslationResult) -> String

    TranslationResult::resolved_locale

    fn TranslationResult::resolved_locale(self : TranslationResult) -> String

    TranslationResult::used_fallback

    fn TranslationResult::used_fallback(self : TranslationResult) -> Bool

    TranslationResult::value

    fn TranslationResult::value(self : TranslationResult) -> String

    Translator

    pub struct Translator {
    default_locale : String
    fallback_locale : String
    catalogs : Map[String, Catalog]
    } derive(
    Debug
    )

    Translator::add_catalog

    fn Translator::add_catalog(self : Translator, catalog : Catalog) -> Unit

    Translator::available_locales

    fn Translator::available_locales(self : Translator) -> Array[String]

    Translator::catalog_count

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

    Translator::default_locale

    fn Translator::default_locale(self : Translator) -> String

    Translator::fallback_locale

    fn Translator::fallback_locale(self : Translator) -> String

    Translator::has_catalog

    fn Translator::has_catalog(self : Translator, locale : String) -> Bool

    Translator::new

    fn Translator::new(default_locale : String, fallback_locale : String) -> Translator

    Translator::resolve

    fn Translator::resolve(self : Translator, key : String, locale? : String) -> ResolvedMessage raise MessageError

    Resolve a key and preserve the locale of the catalog that supplied it.

    Translator::translate

    fn Translator::translate(self : Translator, key : String, arguments : Map[String, Argument], locale? : String) -> String raise MessageError

    Look up and format a key, trying requested, default, then fallback locale.

    Translator::translate_detailed

    fn Translator::translate_detailed(self : Translator, key : String, arguments : Map[String, Argument], locale? : String) -> TranslationResult raise MessageError

    Resolve, format, and return locale provenance for a translation.

    canonicalize_locale

    fn canonicalize_locale(value : String) -> String raise MessageError

    Canonicalize a locale identifier.

    catalog_matrix

    fn catalog_matrix(reference : Catalog, translations : Array[Catalog]) -> CatalogMatrix

    Build a key-presence matrix for a reference and multiple translations.

    cli_diff_sources

    fn cli_diff_sources(reference_source : String, translation_source : String, locale : String, json? : Bool) -> CliOutput raise MessageError

    Compare the key sets of two in-memory catalog sources.

    cli_render_source

    fn cli_render_source(source : String, locale : String, key : String, arguments : Map[String, Argument], json? : Bool) -> CliOutput raise MessageError

    Render one key from an in-memory catalog source.

    cli_usage

    fn cli_usage() -> String

    Return the stable command-line help text.

    cli_validate_sources

    fn cli_validate_sources(reference_source : String, translation_source : String, locale : String, json? : Bool) -> CliOutput raise MessageError

    Validate two in-memory catalog sources.

    diagnose_message

    fn diagnose_message(template : String) -> MessageDiagnostic?

    Parse a message and return a diagnostic instead of raising on failure.

    diagnostic_from_error

    fn diagnostic_from_error(source : String, error : MessageError) -> MessageDiagnostic

    Convert a parser error into a stable diagnostic with line and column.

    diff_catalogs

    fn diff_catalogs(reference : Catalog, translation : Catalog) -> CatalogDiff

    Compare the key sets of two catalogs.

    format

    fn format(message : Message, arguments : Map[String, Argument], locale : String) -> String raise MessageError

    Format a parsed message with text and integer arguments.

    format_with_options

    fn format_with_options(message : Message, arguments : Map[String, Argument], locale : String, options : FormatOptions) -> String raise MessageError

    Format a message using explicit runtime options.

    format_with_trace

    fn format_with_trace(message : Message, arguments : Map[String, Argument], locale : String, options? : FormatOptions) -> FormattedMessage raise MessageError

    Format a message and retain a deterministic evaluation trace.

    is_supported_locale

    fn is_supported_locale(locale : String) -> Bool

    Return whether MoonL10n has an explicit plural rule for the locale.

    lint_catalog_set

    fn lint_catalog_set(reference : Catalog, translations : Array[Catalog]) -> Array[LintReport]

    Lint multiple translations using one reference catalog.

    lint_catalogs

    fn lint_catalogs(reference : Catalog, translation : Catalog) -> LintReport

    Compare a translation against the reference catalog.

    lint_catalogs_with_options

    fn lint_catalogs_with_options(reference : Catalog, translation : Catalog, options : LintOptions) -> LintReport

    Compare a translation against the reference catalog with explicit policy.

    locale_fallback_chain

    fn locale_fallback_chain(locale : String) -> Array[String]

    Build a fallback chain for a locale, tolerating non-canonical input.

    locale_profile

    fn locale_profile(locale : String) -> LocaleProfile raise MessageError

    Return plural metadata for a locale.

    locale_support

    fn locale_support(locale : String) -> LocaleSupport?

    locale_support_table

    fn locale_support_table() -> Array[LocaleSupport]

    Return human-facing metadata for every explicitly supported language.

    missing_plural_categories

    fn missing_plural_categories(locale : String, selectors : Array[String], ordinal? : Bool) -> Array[String]

    Check whether selectors cover all categories declared for a locale.

    negotiate_locale

    fn negotiate_locale(requested : String, available : Array[String], default_locale? : String) -> LocaleNegotiation

    Negotiate a requested locale against an available locale list.

    observed_plural_categories

    fn observed_plural_categories(locale : String, start : Int, end : Int, ordinal? : Bool) -> Array[String]

    Return every category observed over an inclusive integer range.

    ordinal_category

    fn ordinal_category(locale : String, value : Int) -> String

    parse_cli_argument

    fn parse_cli_argument(value : String) -> (String, Argument) raise MessageError

    Parse one name=value CLI argument.

    parse_cli_request

    fn parse_cli_request(args : Array[String]) -> CliRequest raise MessageError

    Parse command arguments without accessing the file system.

    The first element must be the command itself, not the executable path.

    parse_message

    fn parse_message(template : String) -> Message raise MessageError

    Parse a message template using the supported ICU MessageFormat subset.

    plural_category

    fn plural_category(locale : String, value : Int) -> String

    plural_examples

    fn plural_examples(locale : String, start : Int, end : Int, ordinal? : Bool, limit_per_category? : Int) -> Array[PluralExamples]

    Collect representative integer values for each plural category.

    required_cardinal_categories

    fn required_cardinal_categories(locale : String) -> Array[String]

    Return the cardinal categories expected by the linter.

    required_ordinal_categories

    fn required_ordinal_categories(locale : String) -> Array[String]

    Return the ordinal categories expected by the linter.

    select_plural_branch

    fn select_plural_branch(locale : String, value : Int, ordinal : Bool, selectors : Array[String]) -> PluralSelection raise MessageError

    Explain how a numeric choice selects a branch.

    source_position

    fn source_position(source : String, offset : Int) -> SourcePosition

    Convert a zero-based character offset into a one-based line and column.

    source_span

    fn source_span(source : String, start : Int, end : Int) -> SourceSpan

    Create a half-open source span from two offsets.

    supported_languages

    fn supported_languages() -> Array[String]

    Return all canonical base languages with explicit plural support.

    supported_locales

    fn supported_locales() -> Array[String]

    Return all locale identifiers with explicit v0.2 plural support.