Skip to main content
Version: 4.0 (next)

Locale YAML surface reference

Orientation

This reference lists the canonical surface fields, shared strategy values, date and ordinal blocks, formatter data, and clock notation data. Use the engine catalogues for number parsing and rendering contracts.

Example

surfaces:
ordinal:
date:
pattern: 'MMMM {day}, yyyy'
dayMode: 'Ordinal'
number:
formatting:
decimalSeparator: '.'

Author only values the locale owns; omitted mapped fields can inherit from a same-language parent.

Canonical Surface Sections

The sections below answer two things for every block:

  1. what values are valid
  2. what the block is responsible for in the runtime pipeline

If you need step-by-step authoring guidance, use this document together with Locale YAML how-to.

variantOf

  • Type: scalar locale code
  • Purpose: declares the parent locale whose surfaces and fields should be inherited.
  • Examples in the repo:
    • 'en'
    • 'de'
    • 'fr'
    • 'pt'
    • 'zh-Hans'

list

Purpose:

  • owns list-joining words or delimiters only
  • feeds the collection-humanization registration path
  • should stay small; if the block starts accumulating general grammar, the data belongs elsewhere

Supported mapping engines:

  • engine: 'oxford'
  • engine: 'clitic'
  • engine: 'conjunction'
  • engine: 'delimited'

Fields:

  • engine: 'oxford': uses the built-in Oxford-comma formatter and requires no value.
  • value: the locale-owned conjunction or delimiter token consumed by the selected engine.

The list surface is always a mapping. Scalar shorthand is not accepted.

inflection

Purpose:

  • assigns the locale's Unicode CLDR decimal cardinal rule used by PluralizationForms

Fields:

  • cardinalRule: the checked-in CLDR 48.2 rule used by this locale.
  • regionalRules: optional mapping from a same-language regional culture to a different checked-in CLDR cardinal selector. Use this only when CLDR defines a regional rule that differs from the neutral locale, such as pt-PT.

Regional variants may inherit this surface only when they share the exact primary language subtag. In particular, Nynorsk nn does not inherit Bokmål nb inflection data.

Example:

surfaces:
inflection:
cardinalRule: 'Spanish'

formatter

Purpose:

  • owns formatter-specific grammar and phrase/form selection metadata
  • feeds ProfiledFormatter
  • should contain only information used while humanizing TimeSpan, dates, quantities, or data units through formatter resources

Supported engine:

  • engine: 'profiled'

Fields:

  • resourceKeyDetector
  • exactDateForms
  • exactTimeSpanForms
  • resourceKeySuffixes
  • timeUnitGenders
  • prepositionMode
  • dataUnitDetector
  • dataUnitSuffixes
  • dataUnitFallbackTransform
  • dataUnitNonIntegralForm
  • secondaryPlaceholderMode

Notes:

  • resourceKeyDetector selects the pluralization/resource-shape family.
  • exactDateForms maps exact date counts to a specific grammatical form for selected units and tenses.
  • exactTimeSpanForms maps exact time-span counts to a specific grammatical form for selected units.
  • resourceKeySuffixes supplies suffix fragments appended during resource-key construction.
  • timeUnitGenders carries grammatical gender metadata for time-unit resources.
  • prepositionMode selects locale-specific preposition handling.
  • dataUnitDetector selects file-size/data-size plural behavior.
  • dataUnitSuffixes supplies unit-specific suffix overrides for data units.
  • dataUnitFallbackTransform rewrites fallback data-unit strings when direct resources do not exist.
  • dataUnitNonIntegralForm tells the formatter which grammatical number to use for non-integral values.
  • secondaryPlaceholderMode enables special placeholder behavior for locales with secondary article/consonant rules.

phrases

Purpose:

  • owns locale phrase tables that are not formatter profile metadata
  • feeds the generated phrase-table catalogs used by relative-date, duration, data-unit, and time-unit humanization
  • should contain direct locale phrases, not runtime strategy enums

Members:

  • relativeDate
  • duration
  • dataUnits
  • timeUnits

Notes:

  • relativeDate owns phrases such as "yesterday", "tomorrow", and tense-sensitive relative-date templates.

  • duration owns phrase tables used by duration humanization outside formatter profile selection metadata.

  • dataUnits owns localized data-unit phrases.

  • Explicit SI and IEC formatting requires these entries and canonical symbols:

    KeySymbol
    decimalKilobytekB
    decimalMegabyteMB
    decimalGigabyteGB
    decimalTerabyteTB
    decimalPetabytePB
    decimalExabyteEB
    binaryKibibyteKiB
    binaryMebibyteMiB
    binaryGibibyteGiB
    binaryTebibyteTiB
    binaryPebibytePiB

    Every non-variant locale must author localized forms for all 11 entries. The current catalog has 90 authoring roots and 12 regional variants. Variants may inherit the entries only through their existing same-language variantOf chain. A supported locale must never obtain these words from the default English formatter fallback.

  • timeUnits owns localized time-unit phrases.

  • phrases is a distinct canonical surface from formatter. Do not hide phrase-table ownership under formatter just because both influence humanized output.

ordinal

Purpose:

  • owns numeric ordinalization plus date-specific ordinal day rendering
  • feeds the numeric ordinalizer and generated date-to-ordinal converters
  • keeps all ordinal behavior under one conceptual surface

Members:

  • numeric
  • date
  • dateOnly

numeric owns numeric ordinalization rules when the runtime output stays in numeric form. date and dateOnly own date-specific day placement and day rendering mode.

Supported engines:

  • modulo-suffix
  • number-word-suffix
  • suffix
  • template
  • word-form-template

Date-specific fields:

  • date.pattern: output format string using {day} for the day component.
  • date.dayMode: day rendering strategy.
  • dateOnly.pattern
  • dateOnly.dayMode

number.words

Purpose:

  • owns render-side number composition data
  • feeds the generated number-to-words profile catalog
  • should contain words, lexical tables, scale rows, and structural strategy choices used while producing text from numbers

For locale parity work, number.words is the writer half of the number contract and should be planned together with number.parse.

Supported engines in current checked-in YAML:

  • agglutinative-ordinal-scale
  • appended-group
  • billion-strategy
  • conjoined-gendered-scale
  • conjunctional-scale
  • construct-state-scale
  • contextual-decimal
  • contracted-one-scale
  • east-asian-grouped
  • east-slavic
  • gendered-scale-ordinal
  • harmony-ordinal
  • hyphenated-scale
  • hyphenated-ordinal
  • indian-grouping
  • indian-grouping-gendered
  • indian-scale-forms
  • inverted-tens
  • joined-scale
  • linking-scale
  • linked-vigesimal
  • long-scale-stem-ordinal
  • dual-form-scale
  • ordinal-prefix-scale
  • pluralized-scale
  • scale-leading-compound
  • stemmed-scale
  • scale-strategy
  • segmented-scale
  • south-slavic-cardinal
  • terminal-ordinal-scale
  • triad-scale
  • unit-leading-compound
  • variant-decade
  • west-slavic-gendered

For joined-scale profiles, scale rows may include nameWithRemainder when the singular scale noun changes before a following lower-order remainder. Scale rows may also include pluralName and pluralNameWithRemainder for languages whose scale nouns change when the scale count is not one. Runtime selection precedence is: plural remainder form, plural exact form, singular remainder form, then singular exact name. Profiles that use an authored hundredsMap may also include hundredsMapWithRemainder, a parallel table used for exact-vs-remainder hundreds forms.

number.parse

Purpose:

  • owns parse-side number lexicons and normalization settings
  • feeds the generated words-to-number profile catalog or token-map lexicon generator
  • should contain only input-facing tokens and parser behavior, not render-only vocabulary that users never type or speak

For locale parity work, number.parse is the parser half of the same number contract and should accept the same natural forms that number.words emits.

Supported engines in current checked-in YAML:

  • compound-scale
  • contracted-scale
  • east-asian-positional
  • greedy-compound
  • inverted-tens
  • linking-affix
  • linked-vigesimal
  • scale-leading-compound
  • prefixed-tens-scale
  • stemmed-scale
  • suffix-scale
  • token-map
  • vigesimal-compound

clock

Purpose:

  • owns clock-phrase templates and phrase-family choices for TimeOnly clock notation
  • feeds the single generated phrase-clock engine
  • should stay separate from general time humanization and formatter resource behavior

Notes:

  • clock is the canonical YAML authoring surface.
  • The generator emits this surface into the runtime timeOnlyToClockNotation feature slot.
  • All shipped locales resolve clock notation through the unified phrase-clock engine, either directly or through locale inheritance. There are no residual handwritten clock leaves.

Supported engine:

  • engine: 'phrase-clock'

compass

Purpose:

  • owns localized 16-point compass heading tables
  • feeds the generated heading-table catalog used by HeadingExtensions
  • should contain only the heading strings for each style, not extra navigation logic

Fields:

  • full
  • short

Notes:

  • Both full and short must contain exactly 16 entries.
  • compass is the canonical YAML authoring surface.
  • The generator currently emits this surface into the runtime headings feature slot.

calendar

Purpose:

  • owns locale-specific temporal data that overrides CultureInfo.DateTimeFormat when platform globalization data (ICU or NLS) differs across platforms, target frameworks, or globalization sources, or is incorrect
  • feeds the generated OrdinalDatePattern profiles with month-name arrays
  • should contain only data that differs from the platform-supplied CultureInfo; omit the block entirely when CultureInfo is correct

Members:

  • months
  • monthsGenitive
  • hijriMonths

Fields:

  • months: array of exactly 12 strings, indexed by Gregorian month (index 0 = January). Overrides DateTimeFormatInfo.MonthNames in DateToOrdinalWords and DateOnlyToOrdinalWords output.
  • monthsGenitive: optional parallel array of 12 strings for locales that distinguish nominative and genitive month forms (e.g., Czech, Polish, Russian). When present, the genitive form is used in date patterns where the month follows a day number. When absent, months is used in all positions.
  • hijriMonths: optional array of exactly 12 strings, indexed by Islamic (Hijri) calendar month (index 0 = Muharram). When present and the culture's active calendar is HijriCalendar or UmAlQuraCalendar, the runtime uses these month names instead of the Gregorian months array. Requires ordinal.date.calendarMode: 'Native' (or ordinal.dateOnly.calendarMode: 'Native') to activate.

Notes:

  • All month arrays must contain exactly 12 entries if present. The generator validates this at build time.
  • Empty or absent = no override; the runtime falls through to CultureInfo.DateTimeFormat.
  • Inherits via variantOf: a child locale inherits the parent's calendar arrays (months, monthsGenitive, and hijriMonths) unless it authors its own overrides.
  • Only MMMM (full month name) substitution is supported. If an ordinal-date pattern uses MMM (abbreviated month) while calendar.months is active, the generator emits a diagnostic error.
  • hijriMonths items must not contain Unicode directionality controls (U+200E, U+200F, U+061C). The generator validates this at build time.

Example:

surfaces:
calendar:
months:
- 'জানুয়ারি'
- 'ফেব্রুয়ারি'
- 'মার্চ'
- 'এপ্রিল'
- 'মে'
- 'জুন'
- 'জুলাই'
- 'আগস্ট'
- 'সেপ্টেম্বর'
- 'অক্টোবর'
- 'নভেম্বর'
- 'ডিসেম্বর'

Example (Hijri month names):

surfaces:
calendar:
months:
- 'جنوری'
- 'فروری'
# ... (12 Gregorian month names)
hijriMonths:
- 'محرم'
- 'صفر'
- 'ربیع الاول'
- 'ربیع الثانی'
- 'جمادی الاول'
- 'جمادی الثانی'
- 'رجب'
- 'شعبان'
- 'رمضان'
- 'شوال'
- 'ذوالقعدہ'
- 'ذوالحجہ'

When the runtime encounters a HijriCalendar or UmAlQuraCalendar and calendarMode is Native, the OrdinalDatePattern indexes into hijriMonths instead of months for month name substitution. Existing locales without hijriMonths are unaffected.

Future fields: monthsAbbreviated, days, daysAbbreviated, dayPeriods, amDesignator, pmDesignator, eraNames. These are reserved but not yet implemented.

number.formatting

Purpose:

  • owns locale-specific number formatting data that overrides NumberFormatInfo when platform globalization data (ICU or NLS) differs across platforms, target frameworks, or globalization sources, or is incorrect
  • feeds culture-aware Ordinalize overloads, byte-size string formatting (ByteSize.ToString / ToFullWords), and MetricNumeralExtensions with stable decimal separator, negative sign, and group separator values
  • symmetric with number.words (output as words) and number.parse (input); number.formatting is "output as digits"

Fields:

  • decimalSeparator: single character (or multi-character string for locales like Persian). Overrides NumberFormatInfo.NumberDecimalSeparator in Humanizer formatting call sites. Caller-supplied custom NumberFormatInfo / IFormatProvider is never overridden.
  • negativeSign: single character (or multi-character string). Overrides NumberFormatInfo.NegativeSign in Humanizer formatting call sites. Used when the platform's NLS data returns U+002D (hyphen-minus) but the locale-correct character is U+2212 (minus sign), as is the case for several Nordic and European locales. Caller-supplied custom NumberFormatInfo / IFormatProvider is never overridden.
  • groupSeparator: single character (or multi-character string). Overrides NumberFormatInfo.NumberGroupSeparator in Humanizer formatting call sites. Used when the platform's NLS data returns a different thousands separator than the locale-correct one (e.g., lb-LU where NLS returns a space but CLDR specifies a period). Caller-supplied custom NumberFormatInfo / IFormatProvider is never overridden.

Notes:

  • Empty or absent = no override; the runtime uses the platform's NumberFormatInfo value for each respective property.
  • Inherits via variantOf: a child locale inherits the parent's number.formatting fields unless it authors its own. For example, nn.yml uses variantOf: 'nb' and inherits nb's negativeSign override automatically.
  • The generated LocaleNumberFormattingOverrides registry walks CultureInfo.Parent at runtime (same fallback semantics as LocaliserRegistry.FindLocaliser), so unlisted child cultures fall back to the parent override.
  • Override fields are consumed by culture-aware Ordinalize int and long overloads (formatting only), byte-size string formatting (ByteSize.ToString and ByteSize.ToFullWords), and MetricNumeralExtensions. String Ordinalize overloads parse with the culture's native NumberFormatInfo (no overrides). ByteSize.TryParse applies only the decimal separator override, and only when an explicit CultureInfo is passed as the format provider; it does not use negativeSign or groupSeparator overrides.

Example (decimal separator):

surfaces:
number:
formatting:
decimalSeparator: '.'

Example (negative sign for Nordic/European locales):

surfaces:
number:
formatting:
negativeSign: '−' # U+2212 minus sign

Example (group separator):

surfaces:
number:
formatting:
groupSeparator: '.'

Future fields: digitSubstitution, percentSymbol. These are reserved but not yet implemented.

Shared Strategy Values

These are the non-lexical option values that currently appear in checked-in locale YAML.

Clock Hour Modes

  • h12 — 12-hour clock with words via ToWords() (default)
  • h24 — 24-hour clock with words via ToWords()
  • numeric — digits instead of words (e.g., Japanese "3時")

Clock Day Period Positions

  • prefix — day period appears before the clock phrase
  • suffix — day period appears after the clock phrase (default)

Ordinal Date Calendar Modes

  • Gregorian — forces the Gregorian calendar regardless of the culture's default calendar (default)
  • Native — uses the culture's default calendar (e.g., Thai Buddhist year + 543, Hebrew calendar)

Date Day Modes

  • DotSuffix
  • MasculineOrdinalWhenDayIsOne
  • Numeric
  • Ordinal
  • OrdinalWhenDayIsOne

Formatter Strategy Values

resourceKeyDetector

  • arabic-like
  • between2-and4-paucal
  • lithuanian
  • russian
  • slovenian
  • south-slavic

dataUnitDetector

  • arabic-like
  • between2-and4-paucal
  • lithuanian
  • russian
  • singular-plural
  • slovenian
  • south-slavic

dataUnitFallbackTransform

  • latvian
  • trim-trailing-s

dataUnitNonIntegralForm

  • plural

prepositionMode

  • romanian-de

secondaryPlaceholderMode

  • luxembourgish-eifeler-n

Ordinalizer Strategy Values

negativeNumberMode

  • absolute-culture
  • absolute-invariant

Number-To-Words Strategy Values

addAndMode

  • always-default
  • use-caller-flag

andStrategy

  • within-group-and-after-scale-sub-hundred-remainder
  • within-group-only

ordinalMode

  • cardinal
  • english
  • lithuanian
  • numeric-culture
  • numeric-string
  • suffix

ordinalLeadingOneStrategy

  • keep-leading-one
  • omit-leading-one

hundredStrategy

  • allow-explicit-one-in-composite
  • omit-one-when-singular

ordinalSuffixStrategy

  • final-character-membership
  • last-vowel-map

cardinalStrategy

  • norwegian-bokmal
  • swedish

ordinalStrategy

  • norwegian-bokmal
  • swedish

formDetector

  • lithuanian
  • polish

unitVariantStrategy

  • lithuanian
  • polish

seventyStrategy

  • regular
  • sixty-plus-teens

ninetyStrategy

  • eighty-plus-teens
  • regular

tensJoinerTransform

  • eifeler

scaleFormDetector

  • slovenian

numberComposition

  • inverted-tens-with-linker

defaultGender

  • feminine
  • masculine
  • neuter

hundredTailPrefixMode

  • low-or-exact-tens
  • none

scaleTailPrefixMode

  • low-or-exact-tens
  • none
  • sub-hundred

Words-To-Number Strategy Values

normalizationProfile

  • collapse-whitespace
  • CollapseWhitespace
  • LowercaseRemovePeriods
  • LowercaseRemovePeriodsAndDiacritics
  • LowercaseReplacePeriodsWithSpaces
  • Persian
  • punctuation-to-spaces-remove-diacritics

ordinalGenderVariant

  • all
  • masculine-and-feminine
  • none

Date And Ordinal Blocks

ordinal.date and ordinal.dateOnly

Fields:

  • pattern
  • dayMode
  • calendarMode

Notes:

  • pattern is a normal output template that must include {day} where the formatted day should appear.
  • dayMode controls whether the day is numeric, ordinal, or conditionally ordinal.
  • calendarMode controls how the calendar is resolved when formatting ordinal dates. Values are Gregorian (default, forces the Gregorian calendar regardless of culture) and Native (uses the culture's default calendar, e.g., Thai Buddhist, Hebrew, Persian). When omitted, Gregorian is used.
  • pattern is the owning block's complete output template; the generator does not infer extra punctuation or month placement for you.
  • if a locale has both ordinal.date and ordinal.dateOnly, document the reason in the locale file comments because most locales either share the same pattern family or omit one of the two blocks.

ordinalizer: modulo-suffix

Fields:

  • defaultSuffix
  • useAbsoluteValue
  • absoluteAtLeast
  • exactSuffixes
  • lastTwoDigitsRange
  • lastTwoDigitSuffixes
  • lastDigitSuffixes

Notes:

  • This engine computes suffixes from the numeric value.
  • defaultSuffix is the fallback suffix when no special rule matches.
  • exactSuffixes overrides exact numeric values.
  • lastTwoDigitsRange handles ranges like 11 through 20.
  • lastTwoDigitSuffixes handles repeating two-digit endings such as every value ending in 20.
  • lastDigitSuffixes handles trailing-digit special cases such as 1, 2, and 3.
  • absoluteAtLeast and useAbsoluteValue control whether negative numbers are normalized before suffix selection.

ordinalizer: suffix

Fields:

  • masculineSuffix
  • feminineSuffix
  • neuterSuffix
  • zeroAsPlainNumber

Notes:

  • This engine appends one of a small set of suffixes to the numeric form.
  • zeroAsPlainNumber leaves zero unmodified instead of suffixing it.

ordinalizer: template

Fields:

  • masculine
  • feminine
  • neuter
  • negativeNumberMode
  • minValueAsPlainNumber
  • zeroAsPlainNumber

Notes:

  • The gendered template fields are numeric-string templates.
  • negativeNumberMode supports None and AbsoluteInvariant.
  • For compatibility, minValueAsPlainNumber emits 0 only when the input is exactly Int32.MinValue; other negative values, including Int64.MinValue, follow negativeNumberMode.
  • Both template engines accept long inputs. Exact replacement and exact suffix dictionaries remain int-keyed; values outside that range use the last-digit or default suffix rule.

ordinalizer: word-form-template

Fields:

  • masculine
  • feminine
  • neuter
  • negativeNumberMode
  • minValueAsPlainNumber
  • zeroAsPlainNumber
  • useCulture

Notes:

  • This is the same general family as template, but the runtime kernel also receives the current culture and adds AbsoluteCulture to the supported negativeNumberMode values.

ordinalizer: number-word-suffix

Fields:

  • useCulture: must be true when present. The number-word-suffix engine is intrinsically culture-bound because it resolves the locale's INumberToWordsConverter; the generator passes the resolving CultureInfo to the runtime ordinalizer. The field is required in YAML but the binding is structural to the engine, not an arbitrary author choice.
  • masculine: gender block for masculine ordinals.
    • defaultSuffix: suffix appended to the cardinal word form for productive ordinals.
    • exactReplacements: mapping of number to irregular ordinal word (bypasses the cardinal-plus-suffix path).
  • feminine: gender block for feminine ordinals, same shape as masculine.
    • defaultSuffix
    • exactReplacements
  • neuter: optional gender block for real neuter ordinals, same shape as masculine.
    • defaultSuffix
    • exactReplacements
  • neuterFallback: the gender to fall back to when GrammaticalGender.Neuter is requested and no neuter block is authored. Must be 'masculine' or 'feminine'.

Notes:

  • This engine produces full word ordinals (e.g., پانچواں for 5th masculine) rather than numeric-suffix ordinals (e.g., 5واں). It does this by calling the locale's INumberToWordsConverter.Convert to get the cardinal word form, then appending the gendered suffix.
  • Exact replacements handle irregular low ordinals where the ordinal stem differs from the cardinal (e.g., Urdu 4th چوتھا vs cardinal چار).
  • Neuter gender uses an authored neuter block when present. Otherwise it falls back to the gender specified by neuterFallback (typically masculine for two-gender languages).
  • The engine requires useCulture: true because it internally resolves the number-to-words converter for the locale.

Example:

surfaces:
ordinal:
numeric:
engine: 'number-word-suffix'
useCulture: true
masculine:
defaultSuffix: 'واں'
exactReplacements:
1: 'پہلا'
2: 'دوسرا'
3: 'تیسرا'
4: 'چوتھا'
feminine:
defaultSuffix: 'ویں'
exactReplacements:
1: 'پہلی'
2: 'دوسری'
3: 'تیسری'
4: 'چوتھی'
neuterFallback: 'masculine'

Locales with real neuter ordinal forms may author neuter alongside masculine and feminine:

neuter:
defaultSuffix: 'वे'
exactReplacements:
1: 'पहिले'
2: 'दुसरे'

Formatter Block

formatter: profiled

Fields:

  • resourceKeyDetector
  • exactDateForms
  • exactTimeSpanForms
  • resourceKeySuffixes
  • timeUnitGenders
  • prepositionMode
  • dataUnitDetector
  • dataUnitSuffixes
  • dataUnitFallbackTransform
  • dataUnitNonIntegralForm
  • secondaryPlaceholderMode

Authoring notes:

  • resourceKeyDetector and dataUnitDetector choose the plural/resource family; these are structural strategy values, not locale display strings.
  • exactDateForms, exactTimeSpanForms, and resourceKeySuffixes are the escape hatches for locales that need exact-count or unit-specific form selection beyond the default detector.
  • timeUnitGenders belongs here because formatter resources often inflect by unit gender even when number.words does not.
  • secondaryPlaceholderMode is rare; if you add it, leave a YAML comment in the locale file explaining the grammatical rule being modeled.

Time-Only Clock Notation

clock: phrase-clock

The unified phrase-clock engine handles all clock notation patterns through YAML configuration. It replaces the former phrase-hour, relative-hour, and residual leaf engines (French, German, Luxembourgish, Japanese).

Core fields:

  • hourMode: hour display strategy (see Shared Strategy Values below)
  • hourGender: grammatical gender for ToWords() hour rendering (masculine, feminine, neuter; default masculine)
  • minuteGender: grammatical gender for ToWords() minute rendering (masculine, feminine, neuter; default masculine)
  • midnight: display string for 00:00
  • midday: display string for 12:00

Minute-bucket templates:

Explicit templates for each 5-minute increment. Templates use placeholders {hour}, {nextHour}, {minutes}, {minutesReverse} (60 minus minutes), {minutesFromHalf} (minutes minus 30), {nextArticle}, and {dayPeriod} (inline day-period placement).

  • min0 through min55: templates for minutes 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55
  • defaultTemplate: catch-all fallback for non-bucketed minutes

Range-based default templates (fill gaps between 5-minute bucket positions):

  • pastHourTemplate: minutes 1-24 (excluding any explicit bucket templates at 5, 10, 15, 20)
  • beforeHalfTemplate: minutes 26-29
  • afterHalfTemplate: minutes 31-34
  • beforeNextTemplate: minutes 36-59 (excluding any explicit bucket templates at 40, 45, 50, 55)

Zero filler:

  • zeroFiller: zero-pad word for minutes less than 10 (e.g., "noll", "零")

Day-period support:

  • earlyMorning: display string for the early morning period
  • morning: display string for the morning period
  • afternoon: display string for the afternoon period
  • night: display string for the night period
  • dayPeriodPosition: prefix or suffix (default suffix)

The {dayPeriod} placeholder allows inline day-period placement within bucket templates. When a template contains {dayPeriod}, the engine expands it inline and does not append or prepend the day period again. This is useful for languages like Kurdish where the day period appears mid-phrase.

Hour and minute word overrides:

  • hourZeroWord: override word for hour zero
  • hourOneWord: override word for hour one
  • hourTwelveWord: override word for hour twelve
  • hourWordsMap: optional dense sequence of locale-specific hour words indexed by the resolved hour value, used instead of ToWords() when the locale needs pre-declined or article-attached forms (e.g., Arabic). The required length depends on hourMode: 13 entries (indices 0-12) for h12, or 24 entries (indices 0-23) for h24/numeric.
  • minuteWordsMap: optional dense sequence of locale-specific minute words

Hour suffixes:

  • hourSuffixSingular: singular hour suffix (e.g., French "heure")
  • hourSuffixPlural: plural hour suffix (e.g., French "heures")
  • hourSuffixPaucal: paucal hour suffix (for Slavic-family locales)

Minute suffixes:

  • minuteSuffixSingular: singular minute suffix (e.g., Luxembourgish "Minutt")
  • minuteSuffixPlural: plural minute suffix (e.g., Luxembourgish "Minutten")
  • minuteSuffixPaucal: paucal minute suffix (for Slavic-family locales)

Articles:

  • singularArticle: article for singular hours
  • pluralArticle: article for plural hours

Compact mode:

  • compactMinuteWords: boolean (default false) — when true, minute words use a compact conjunction form
  • compactConjunction: conjunction word used in compact mode (e.g., Arabic "و")

Paucal control:

  • paucalLowOnly: boolean (default false) — restricts paucal suffixes to low values only

Eifeler Rule support (Luxembourgish morphology):

  • applyEifelerRule: boolean (default false) — applies EifelerRule.DoesApply() post-processing to trim trailing 'n' from number words when the following word blocks it

Notes:

  • All shipped locales resolve clock notation through phrase-clock, either directly or through locale inheritance. There are no residual handwritten clock leaves.
  • Non-bucketed minutes fall to range-based defaults or defaultTemplate.
  • Day-period hour resolution is template-aware: templates that reference {nextHour} or {nextArticle} base the day period on hour+1 (since the phrasing is relative to the next hour), while templates using {hour} base the period on the current hour.

Pitfall

Keep formatter separate from phrases, and keep number.words separate from number.parse. Calendar and number-formatting overrides are optional compatibility contracts, not placeholders for platform defaults.

Version notes

These fields and strategy values describe main/preview. Verify the schema on a historical branch before applying them there.