ESC
Type to search...
S
Soli Docs

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")
2nd arg : String for an explicit locale, or Hash of interpolation values (current locale used)
3rd arg : Hash? of interpolation values when an explicit locale was passed
I18n.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 en when 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 amount
currency : String - Currency code (USD, EUR, etc.)
locale : String? - Optional locale
I18n.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") })