I18n Functions
Internationalization with translations, pluralization, and locale-aware formatting.
Locale Management
I18n.locale()
Get the current locale.
Returns
String - The current locale code (e.g., "en", "fr", "de")
println(I18n.locale()) # "en"
I18n.set_locale(locale)
Set the current locale.
Parameters
locale : String - The locale code to set
I18n.set_locale("fr")
I18n.set_locale("de")
Translations
I18n.translate(key, locale_or_values?, values?)
Translate a key against the auto-loaded locale tree (see Locale Files). Placeholders use {name} syntax; unknown placeholders are left intact so missing data is visible.
Parameters
key : String — dotted lookup path (e.g. "app.welcome")String for an explicit locale, or Hash of interpolation values (current locale used)Hash? of interpolation values when an explicit locale was passedI18n.translate("app.welcome") # "Welcome"
I18n.translate("app.welcome", "fr") # "Bienvenue"
I18n.translate("app.greeting", { name: "Alice" }) # "Hello, Alice!"
I18n.translate("app.greeting", "fr", { name: "Alice" }) # "Bonjour, Alice !"
I18n.plural(key, count, locale_or_values?, values?)
Resolves <key>_zero (count == 0), <key>_one (count == 1), or <key>_other. Same locale-or-values disambiguation as translate. {count} is auto-injected into the interpolation values.
en:
items_zero: No items
items_one: One item
items_other: "{count} items"
I18n.plural("items", 0) # "No items"
I18n.plural("items", 1) # "One item"
I18n.plural("items", 5) # "5 items"
Locale Files
Soli auto-loads every *.yml (and *.yaml) file under config/locales/ at server boot. The top-level YAML key is the locale name; nested keys form the dotted lookup path used by I18n.translate.
- Resolution falls back to
enwhen the active locale has no entry. - If no locale resolves the key, the literal key is returned (e.g.
"app.welcome") — typos surface during development. - A single file may declare multiple locales, and several files may extend the same locale (e.g.
en.yml+accounts.en.yml).
en:
app:
welcome: Welcome
greeting: "Hello, {name}!"
errors:
not_found: Not found
fr:
app:
welcome: Bienvenue
greeting: "Bonjour, {name} !"
errors:
not_found: Introuvable
Locale-Aware Formatting
I18n.format_number(number, locale?)
Format a number according to locale conventions.
I18n.format_number(1234.56, "en") # "1,234.56"
I18n.format_number(1234.56, "fr") # "1 234,56"
I18n.format_number(1234.56, "de") # "1.234,56"
I18n.format_currency(amount, currency, locale?)
Format a currency amount.
Parameters
amount : Float - The amountcurrency : String - Currency code (USD, EUR, etc.)locale : String? - Optional localeI18n.format_currency(1234.56, "USD", "en") # "$1,234.56"
I18n.format_currency(1234.56, "EUR", "de") # "1.234,56 €"
I18n.format_currency(1234.56, "GBP", "en") # "£1,234.56"
I18n.format_date(timestamp, locale?)
Format a date according to locale conventions.
ts = __datetime_parse("2024-01-15T10:30:00Z")
I18n.format_date(ts, "en") # "01/15/2024"
I18n.format_date(ts, "fr") # "15/01/2024"
I18n.format_date(ts, "de") # "15.01.2024"
DateTime.format(pattern, locale?)
Format a DateTime instance with a custom strftime pattern and optional locale for localized month/day names. See DateTime.format() for full details.
Parameters
pattern : String - strftime format pattern (e.g. "%A %d %B %Y")locale : String? - Optional locale code: "en", "fr", "es", "de", "it", "pt"dt = DateTime.parse("2024-03-06T14:30:00Z")
dt.format("%A %d %B %Y", "fr") # "mercredi 06 mars 2024"
dt.format("%A %d %B %Y", "es") # "miércoles 06 marzo 2024"
dt.format("%d %b %Y", "fr") # "06 mars 2024"
Complete Example
en:
welcome: "Welcome!"
cart_items_zero: "Your cart is empty"
cart_items_one: "You have 1 item in your cart"
cart_items_other: "You have {count} items in your cart"
total: "Total: {amount}"
fr:
welcome: "Bienvenue !"
cart_items_zero: "Votre panier est vide"
cart_items_one: "Vous avez 1 article"
cart_items_other: "Vous avez {count} articles"
total: "Total : {amount}"
# Set locale based on user preference
I18n.set_locale(user["preferred_locale"] ?? "en")
welcome = I18n.translate("welcome")
cart_msg = I18n.plural("cart_items", cart_count)
total = I18n.translate("total", { amount: I18n.format_currency(cart_total, "USD") })