Internationalization Nodes
Voce IR supports two i18n compilation modes. In static mode (default), the compiler resolves all LocalizedStrings against the target locale’s MessageCatalog and emits fully resolved HTML per locale with zero runtime i18n code. In runtime mode, a single output is emitted with locale switching and on-demand translation loading (~1KB runtime).
LocalizedString
A reference to a translated message, used in TextNode content, FormField labels, PageMetadata, and anywhere user-visible text appears. The validator checks that every message_key exists in all declared locale catalogs.
| Field | Type | Required | Description |
|---|---|---|---|
| message_key | string | yes | Message key (e.g., “hero.title”, “form.email.label”) |
| default_value | string | no | Fallback value in the primary language |
| parameters | [MessageParameter] | no | Typed parameters for interpolation |
| description | string | no | Context for translators |
MessageParameter
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Parameter name (e.g., “count”, “name”) |
| param_type | MessageParamType | no | StringParam (default), NumberParam, DateParam, CurrencyParam, PluralParam, SelectParam |
| format_options | FormatOptions | no | Formatting configuration |
{
"message_key": "cart.item_count",
"default_value": "{count, plural, one {# item} other {# items}} in your cart",
"parameters": [
{ "name": "count", "param_type": "PluralParam" }
],
"description": "Shopping cart item count displayed in the header"
}
MessageCatalog
A collection of translated messages for a single locale. Stored as a companion file alongside the IR, not embedded in the main binary.
| Field | Type | Required | Description |
|---|---|---|---|
| locale | string | yes | BCP 47 locale tag (e.g., “en-US”, “fr-FR”) |
| messages | [Message] | yes | All translated messages for this locale |
| fallback_locale | string | no | Fallback locale (e.g., “en” for “en-US”) |
Message
| Field | Type | Required | Description |
|---|---|---|---|
| key | string | yes | Message key matching LocalizedString.message_key |
| value | string | yes | ICU MessageFormat translated string |
ICU MessageFormat supports plurals, select, and nested expressions:
- Simple:
"Hello {name}" - Plural:
"{count, plural, one {# item} other {# items}}" - Select:
"{gender, select, female {She} male {He} other {They}} commented"
{
"locale": "fr-FR",
"messages": [
{ "key": "hero.title", "value": "Bienvenue sur Voce" },
{ "key": "hero.subtitle", "value": "Representation intermediaire pour l'IA" },
{ "key": "cart.item_count", "value": "{count, plural, one {# article} other {# articles}} dans votre panier" }
],
"fallback_locale": "en"
}
FormatOptions
Locale-aware formatting configuration for number, date, and currency parameters.
| Field | Type | Required | Description |
|---|---|---|---|
| number_style | NumberStyle | no | Decimal (default), Currency, Percent, Unit |
| currency_code | string | no | ISO 4217 code (e.g., “USD”, “EUR”) for Currency style |
| date_style | DateStyle | no | Short, Medium (default), Long, Full, Custom |
| custom_date_pattern | string | no | ICU date pattern for Custom style (e.g., “yyyy-MM-dd”) |
| min_fraction_digits | int32 | no | Minimum fractional digits for numbers |
| max_fraction_digits | int32 | no | Maximum fractional digits for numbers |
{
"number_style": "Currency",
"currency_code": "EUR",
"min_fraction_digits": 2,
"max_fraction_digits": 2
}
I18nConfig
Application-level internationalization configuration. Added to VoceDocument.i18n.
| Field | Type | Required | Description |
|---|---|---|---|
| default_locale | string | yes | Default/primary locale (e.g., “en-US”) |
| supported_locales | [string] | yes | All supported locale tags |
| mode | string | no | “static” (default) or “runtime” |
Compilation modes:
- static – one output per locale. All LocalizedStrings resolved at compile time. Zero runtime cost. Best for SEO and performance.
- runtime – single output with locale switching. Translations loaded on demand. Adds ~1KB of i18n runtime. Best for SPAs with in-app language switching.
{
"default_locale": "en-US",
"supported_locales": ["en-US", "fr-FR", "de-DE", "ja-JP"],
"mode": "static"
}