g18n

Types

Formatting styles for date and time display.

Provides different levels of detail and formats for displaying dates and times, from compact short formats to verbose full formats with day names.

Examples

let date = calendar.Date(2024, calendar.January, 15)

g18n.format_date(translator, date, g18n.Short)
// "1/15/24"

g18n.format_date(translator, date, g18n.Full)
// "Monday, January 15, 2024"

g18n.format_date(translator, date, g18n.Custom("YYYY-MM-DD"))
// "2024-01-15"
pub type DateTimeFormat {
  Short
  Medium
  Long
  Full
  Custom(String)
}

Constructors

  • Short

    Compact format: 12/25/23, 3:45 PM

  • Medium

    Medium format: Dec 25, 2023, 3:45:30 PM

  • Long

    Long format: December 25, 2023, 3:45:30 PM GMT

  • Full

    Full format: Monday, December 25, 2023, 3:45:30 PM GMT

  • Custom(String)

    Custom format string: “YYYY-MM-DD HH:mm:ss”

Parameters for string formatting and interpolation.

A dictionary mapping parameter names to their string values for use in translation templates like “Hello {name}!” or “You have {count} items”.

Examples

let params = g18n.new_format_params()
  |> g18n.add_param("name", "Alice")
  |> g18n.add_param("count", "5")
pub type FormatParams =
  dict.Dict(String, String)

Number formatting styles for locale-aware number display.

Supports various number formats including decimals, currency, percentages, scientific notation, and compact notation for large numbers.

Examples

g18n.format_number(translator, 1234.56, g18n.Decimal(2))
// "1,234.56" (English) or "1.234,56" (German)

g18n.format_number(translator, 1234.56, g18n.Currency("USD", 2))
// "$1,234.56"

g18n.format_number(translator, 0.75, g18n.Percentage(1))
// "75.0%"

g18n.format_number(translator, 1000000.0, g18n.Compact)
// "1.0M"
pub type NumberFormat {
  Decimal(precision: Int)
  Currency(currency_code: String, precision: Int)
  Percentage(precision: Int)
  Scientific(precision: Int)
  Compact
}

Constructors

  • Decimal(precision: Int)

    Decimal format with specified precision

  • Currency(currency_code: String, precision: Int)

    Currency format with currency code and precision

  • Percentage(precision: Int)

    Percentage format with precision

  • Scientific(precision: Int)

    Scientific notation with precision

  • Compact

    Compact format: 1.2K, 3.4M, 1.2B

Duration units for relative time formatting.

Used to express time differences in human-readable formats like “2 hours ago” or “in 3 days”.

Examples

g18n.format_relative_time(translator, g18n.Hours(2), g18n.Past)
// "2 hours ago"

g18n.format_relative_time(translator, g18n.Days(3), g18n.Future)
// "in 3 days"
pub type RelativeDuration {
  Seconds(Int)
  Minutes(Int)
  Hours(Int)
  Days(Int)
  Weeks(Int)
  Months(Int)
  Years(Int)
}

Constructors

  • Seconds(Int)
  • Minutes(Int)
  • Hours(Int)
  • Days(Int)
  • Weeks(Int)
  • Months(Int)
  • Years(Int)

Direction for relative time formatting.

Indicates whether the time is in the past or future relative to now.

Examples

g18n.format_relative_time(translator, g18n.Hours(2), g18n.Past)
// "2 hours ago"

g18n.format_relative_time(translator, g18n.Hours(2), g18n.Future)
// "in 2 hours"
pub type TimeRelative {
  Past
  Future
}

Constructors

  • Past

    Time in the past (e.g., “2 hours ago”)

  • Future

    Time in the future (e.g., “in 2 hours”)

Context for disambiguating translations with multiple meanings.

Used to distinguish between different meanings of the same word or phrase. For example, “bank” could refer to a financial institution or a riverbank.

Examples

g18n.translate_with_context(translator, "bank", g18n.Context("financial"))
// Returns "financial institution"

g18n.translate_with_context(translator, "bank", g18n.Context("river"))
// Returns "riverbank"

g18n.translate_with_context(translator, "bank", g18n.NoContext)
// Returns default "bank" translation
pub type TranslationContext {
  NoContext
  Context(String)
}

Constructors

  • NoContext

    No specific context - use the default translation

  • Context(String)

    Specific context to disambiguate meaning

Container for translation key-value pairs with hierarchical organization.

Uses an efficient trie data structure for fast lookups and supports hierarchical keys with dot notation like “ui.button.save”. This is an opaque type - use the provided functions to interact with it.

Examples

let translations = g18n.new_translations()
  |> g18n.add_translation("ui.button.save", "Save")
  |> g18n.add_translation("ui.button.cancel", "Cancel")
  |> g18n.add_context_translation("bank", "financial", "Bank")
pub opaque type Translations

A translator that combines a locale with translations and optional fallback support.

This is the core type for performing translations. It holds the primary locale and translations, plus optional fallback locale and translations for when keys are missing in the primary set.

Examples

let assert Ok(en_locale) = locale.new("en")
let translations = g18n.new_translations()
  |> g18n.add_translation("hello", "Hello")
let translator = g18n.new_translator(en_locale, translations)

// With fallback
let translator_with_fallback = translator
  |> g18n.with_fallback(fallback_locale, fallback_translations)
pub opaque type Translator

Errors found during translation validation.

Represents different types of issues that can be found when validating translations between different locales, such as missing keys, parameter mismatches, or incomplete plural forms.

Examples

let report = g18n.validate_translations(primary, target, es_locale)
list.each(report.errors, fn(error) {
  case error {
    g18n.MissingTranslation(key, locale) -> 
      io.println("Missing: " <> key <> " for " <> locale.to_string(locale))
    g18n.MissingParameter(key, param, locale) ->
      io.println("Missing param {" <> param <> "} in " <> key)
    _ -> Nil
  }
})
pub type ValidationError {
  MissingTranslation(key: String, locale: locale.Locale)
  MissingParameter(
    key: String,
    param: String,
    locale: locale.Locale,
  )
  UnusedParameter(
    key: String,
    param: String,
    locale: locale.Locale,
  )
  InvalidPluralForm(
    key: String,
    missing_forms: List(String),
    locale: locale.Locale,
  )
  EmptyTranslation(key: String, locale: locale.Locale)
}

Constructors

  • MissingTranslation(key: String, locale: locale.Locale)

    Translation key exists in primary but missing in target locale

  • MissingParameter(
      key: String,
      param: String,
      locale: locale.Locale,
    )

    Required parameter is missing from translation template

  • UnusedParameter(
      key: String,
      param: String,
      locale: locale.Locale,
    )

    Parameter exists in translation but not expected

  • InvalidPluralForm(
      key: String,
      missing_forms: List(String),
      locale: locale.Locale,
    )

    Plural form is incomplete (missing required plural variants)

  • EmptyTranslation(key: String, locale: locale.Locale)

    Translation key exists but has empty/blank value

Complete validation report with errors, warnings, and coverage statistics.

Provides comprehensive analysis of translation completeness and quality between a primary locale (e.g., English) and target locales.

Examples

let report = g18n.validate_translations(primary, target, es_locale)

io.println("Coverage: " <> float.to_string(report.coverage * 100.0) <> "%")
io.println("Errors: " <> int.to_string(list.length(report.errors)))
io.println("Translated: " <> int.to_string(report.translated_keys) 
  <> "/" <> int.to_string(report.total_keys))
pub type ValidationReport {
  ValidationReport(
    errors: List(ValidationError),
    warnings: List(ValidationError),
    total_keys: Int,
    translated_keys: Int,
    coverage: Float,
  )
}

Constructors

  • ValidationReport(
      errors: List(ValidationError),
      warnings: List(ValidationError),
      total_keys: Int,
      translated_keys: Int,
      coverage: Float,
    )

    Arguments

    errors

    List of validation errors found

    warnings

    List of validation warnings (non-critical issues)

    total_keys

    Total number of keys in primary translations

    translated_keys

    Number of keys successfully translated in target

    coverage

    Translation coverage as decimal (0.0 to 1.0)

Values

pub fn add_context_translation(
  translations: Translations,
  key: String,
  context: String,
  value: String,
) -> Translations

Add a context-sensitive translation to a translations container.

Helper function to add translations with context using the key@context format.

Examples

let translations = g18n.translations()
  |> g18n.add_context_translation("bank", "financial", "financial institution")
  |> g18n.add_context_translation("bank", "river", "riverbank")
  |> g18n.add_context_translation("bank", "turn", "lean to one side")
pub fn add_param(
  params: dict.Dict(String, String),
  key: String,
  value: String,
) -> dict.Dict(String, String)

Add a parameter key-value pair to a format parameters container.

Used for template substitution in translations.

Examples

let params = g18n.format_params()
  |> g18n.add_param("user", "Alice")
  |> g18n.add_param("item_count", "3")
pub fn add_translation(
  translations: Translations,
  key: String,
  value: String,
) -> Translations

Add a translation key-value pair to a translations container.

Supports hierarchical keys using dot notation for organization.

Examples

let translations = g18n.new()
  |> g18n.add_translation("ui.button.save", "Save")
  |> g18n.add_translation("ui.button.cancel", "Cancel")
  |> g18n.add_translation("user.name", "Name")
pub fn context_variants(
  translations: Translations,
  base_key: String,
) -> List(#(String, String))

Get all context variants for a given base key.

Returns all translations that match the base key with different contexts. Useful for discovering available contexts for a particular key.

Examples

let translations = g18n.translations()
  |> g18n.add_translation("bank", "bank")
  |> g18n.add_context_translation("bank", "financial", "financial institution")
  |> g18n.add_context_translation("bank", "river", "riverbank")

g18n.get_context_variants(translations, "bank")
// [#("bank", "bank"), #("bank@financial", "financial institution"), #("bank@river", "riverbank")]
pub fn export_validation_report(
  report: ValidationReport,
) -> String

Export a validation report to a formatted string.

Converts a ValidationReport into a human-readable text format suitable for display in console output, log files, or CI/CD reports. Includes coverage statistics, error counts, and detailed error descriptions.

Examples

let assert Ok(en) = g18n.locale("en")
let assert Ok(es) = g18n.locale("es")

let primary = g18n.translations()
  |> g18n.add_translation("hello", "Hello {name}!")
  |> g18n.add_translation("goodbye", "Goodbye")

let target = g18n.translations()
  |> g18n.add_translation("hello", "Hola {nombre}!")  // Parameter mismatch
  // Missing "goodbye" translation

let report = g18n.validate_translations(primary, target, es)
let formatted = g18n.export_validation_report(report)

// formatted contains:
// "Translation Validation Report"
// "================================"
// "Coverage: 50.0%"
// "Total Keys: 2"
// "Translated: 1" 
// "Errors: 2"
// "Warnings: 0"
// 
// "ERRORS:"
// "Missing translation: 'goodbye' for locale es"
// "Missing parameter: 'name' in 'hello' for locale es"
pub fn extract_placeholders(template: String) -> List(String)

Extract all parameter placeholders from a template string.

Returns a list of parameter names found within {braces}.

Examples

g18n.extract_placeholders("Hello {name}, you have {count} new {type}")
// ["name", "count", "type"]
pub fn fallback_locale(
  translator: Translator,
) -> option.Option(locale.Locale)

Get the fallback locale from a translator, if set.

Examples

let assert Ok(en) = g18n.locale("en")
let assert Ok(es) = g18n.locale("es")
let translator = g18n.translator(es, g18n.translations())
  |> g18n.with_fallback(en, g18n.translations())
g18n.get_fallback_locale(translator) // Some(Locale(language: "en", region: None))
pub fn fallback_translations(
  translator: Translator,
) -> option.Option(Translations)

Get the fallback translations from a translator, if set.

Examples

let en_translations = g18n.translations()
  |> g18n.add_translation("hello", "Hello")
let translator = g18n.translator(g18n.locale("es"), g18n.translations())
  |> g18n.with_fallback(g18n.locale("en"), en_translations)
g18n.get_fallback_translations(translator) // Some(translations)
pub fn find_unused_translations(
  translations: Translations,
  used_keys: List(String),
) -> List(String)

Find translation keys that are not being used in the application.

Compares all available translation keys against a list of keys actually used in the application code. Returns keys that exist in translations but are not referenced, helping identify obsolete translations that can be removed.

Examples

let translations = g18n.translations()
  |> g18n.add_translation("common.save", "Save")
  |> g18n.add_translation("common.cancel", "Cancel")
  |> g18n.add_translation("old.feature", "Old Feature")
  |> g18n.add_translation("user.profile", "Profile")

// Keys actually used in application code
let used_keys = ["common.save", "common.cancel", "user.profile"]

let unused = g18n.find_unused_translations(translations, used_keys)
// unused == ["old.feature"] - this key exists but is not used

// If all keys are used
let all_used = ["common.save", "common.cancel", "old.feature", "user.profile"]
let no_unused = g18n.find_unused_translations(translations, all_used)
// no_unused == [] - all translation keys are being used
pub fn format_date(
  translator: Translator,
  date: calendar.Date,
  format: DateTimeFormat,
) -> String

Format a date according to the translator’s locale and specified format.

Supports multiple format levels from short numeric formats to full text with day-of-week names. Automatically uses locale-appropriate formatting including proper date separators, month names, and cultural conventions.

Supported Languages

English, Spanish, Portuguese, French, German, Italian, Russian, Chinese, Japanese, Korean, Arabic, Hindi (with fallback for others)

Format Types

  • Short: Compact numeric format (e.g., “12/25/23”, “25/12/23”)
  • Medium: Month abbreviation (e.g., “Dec 25, 2023”, “25 dez 2023”)
  • Long: Full month names with GMT (e.g., “December 25, 2023 GMT”)
  • Full: Complete with day-of-week (e.g., “Monday, December 25, 2023 GMT”)
  • Custom(pattern): Custom pattern with YYYY, MM, DD placeholders

Examples

import gleam/time/calendar

let assert Ok(en_locale) = g18n.locale("en")
let assert Ok(pt_locale) = g18n.locale("pt") 
let translations = g18n.translations()
let en_translator = g18n.translator(en_locale, translations)
let pt_translator = g18n.translator(pt_locale, translations)

let date = calendar.Date(2024, calendar.January, 15)

g18n.format_date(en_translator, date, g18n.Short)
// "01/15/24"

g18n.format_date(pt_translator, date, g18n.Short) 
// "15/01/24"

g18n.format_date(en_translator, date, g18n.Medium)
// "Jan 15, 2024"

g18n.format_date(en_translator, date, g18n.Full)
// "Monday, January 15, 2024 GMT"

g18n.format_date(en_translator, date, g18n.Custom("YYYY-MM-DD"))
// "2024-01-15"
pub fn format_datetime(
  translator: Translator,
  date: calendar.Date,
  time: calendar.TimeOfDay,
  format: DateTimeFormat,
) -> String

Format a date and time together according to the translator’s locale and specified format.

Combines date and time formatting into a single localized string, using appropriate separators and conventions for each language. Supports all format levels from compact numeric formats to full descriptive text.

Format Types

  • Short: Compact format (e.g., “12/25/23, 3:45 PM”, “25/12/23, 15:45”)
  • Medium: Readable format (e.g., “Dec 25, 2023, 3:45:30 PM”, “25 dez 2023, 15:45:30”)
  • Long: Full format with timezone (e.g., “December 25, 2023, 3:45:30 PM GMT”)
  • Full: Complete descriptive format (e.g., “Monday, December 25, 2023, 3:45:30 PM GMT”)
  • Custom(pattern): Custom pattern combining date and time placeholders

Examples

let assert Ok(en_locale) = g18n.locale("en")
let assert Ok(pt_locale) = g18n.locale("pt")
let en_translator = g18n.translator(en_locale, g18n.translations())
let pt_translator = g18n.translator(pt_locale, g18n.translations())
let date = calendar.Date(year: 2023, month: calendar.December, day: 25)
let time = calendar.TimeOfDay(hours: 15, minutes: 30, seconds: 0)

// English formatting
g18n.format_datetime(en_translator, date, time, g18n.Short)
// "12/25/23, 3:30 PM"

g18n.format_datetime(en_translator, date, time, g18n.Medium)
// "Dec 25, 2023, 3:30:00 PM"

g18n.format_datetime(en_translator, date, time, g18n.Long)
// "December 25, 2023, 3:30:00 PM GMT"

// Portuguese formatting
g18n.format_datetime(pt_translator, date, time, g18n.Short)
// "25/12/23, 15:30"

g18n.format_datetime(pt_translator, date, time, g18n.Medium) 
// "25 dez 2023, 15:30:00"

// Custom formatting
g18n.format_datetime(en_translator, date, time, g18n.Custom("YYYY-MM-DD HH:mm"))
// "2023-12-25 15:30"
pub fn format_number(
  translator: Translator,
  number: Float,
  format: NumberFormat,
) -> String

Format numbers according to locale-specific conventions and format type.

Provides comprehensive number formatting including decimal separators, thousands separators, currency symbols, percentage formatting, and compact notation. Uses proper locale conventions for each language.

Format Types

  • Decimal(precision): Standard decimal formatting with locale separators
  • Currency(currency_code, precision): Currency with appropriate symbols and placement
  • Percentage(precision): Percentage formatting with locale conventions
  • Scientific(precision): Scientific notation (simplified)
  • Compact: Compact notation (1.5K, 2.3M, 1.2B)

Examples

let assert Ok(en_locale) = g18n.locale("en")
let assert Ok(de_locale) = g18n.locale("de")
let translations = g18n.translations()
let en_translator = g18n.translator(en_locale, translations)
let de_translator = g18n.translator(de_locale, translations)

// Decimal formatting (locale-aware separators)
g18n.format_number(en_translator, 1234.56, g18n.Decimal(2))
// "1234.56" (English uses . for decimal)
g18n.format_number(de_translator, 1234.56, g18n.Decimal(2))
// "1234,56" (German uses , for decimal)

// Currency formatting  
g18n.format_number(en_translator, 29.99, g18n.Currency("USD", 2))
// "$29.99"
g18n.format_number(de_translator, 29.99, g18n.Currency("EUR", 2))
// "29.99 €" (German places currency after)

// Percentage
g18n.format_number(en_translator, 0.75, g18n.Percentage(1))
// "75.0%"

// Compact notation
g18n.format_number(en_translator, 1500000.0, g18n.Compact)
// "1.5M"
g18n.format_number(en_translator, 2500.0, g18n.Compact)  
// "2.5K"
pub fn format_relative_time(
  translator: Translator,
  duration: RelativeDuration,
  relative: TimeRelative,
) -> String

Format relative time expressions like “2 hours ago” or “in 5 minutes”.

Generates culturally appropriate relative time expressions using proper pluralization rules and language-specific constructions. Supports past and future expressions in 12 languages.

Supported Languages & Expressions

  • English: “2 hours ago”, “in 5 minutes”
  • Spanish: “hace 2 horas”, “en 5 minutos”
  • Portuguese: “há 2 horas”, “em 5 minutos”
  • French: “il y a 2 heures”, “dans 5 minutes”
  • German: “vor 2 Stunden”, “in 5 Minuten”
  • Russian: “2 часа назад”, “через 5 минут” (with complex pluralization)
  • Chinese: “2小时前”, “5分钟后” (no pluralization)
  • Japanese: “2時間前”, “5分後”
  • Korean: “2시간 전”, “5분 후”
  • Arabic: “منذ ساعتان”, “خلال 5 دقائق” (dual/plural forms)
  • Hindi: “2 घंटे पहले”, “5 मिनट में”
  • Italian: “2 ore fa”, “tra 5 minuti”

Examples

let assert Ok(en_locale) = g18n.locale("en")
let assert Ok(es_locale) = g18n.locale("es")
let assert Ok(ru_locale) = g18n.locale("ru")
let translations = g18n.translations()
let en_translator = g18n.translator(en_locale, translations)
let es_translator = g18n.translator(es_locale, translations) 
let ru_translator = g18n.translator(ru_locale, translations)

// English
g18n.format_relative_time(en_translator, g18n.Hours(2), g18n.Past)
// "2 hours ago"
g18n.format_relative_time(en_translator, g18n.Minutes(30), g18n.Future)
// "in 30 minutes"

// Spanish  
g18n.format_relative_time(es_translator, g18n.Days(3), g18n.Past)
// "hace 3 días"

// Russian (complex pluralization)
g18n.format_relative_time(ru_translator, g18n.Hours(1), g18n.Past) 
// "1 час назад"
g18n.format_relative_time(ru_translator, g18n.Hours(2), g18n.Past)
// "2 часа назад"  
g18n.format_relative_time(ru_translator, g18n.Hours(5), g18n.Past)
// "5 часов назад"
pub fn format_time(
  translator: Translator,
  time: calendar.TimeOfDay,
  format: DateTimeFormat,
) -> String

Format a time according to the translator’s locale and specified format.

Supports multiple format levels from compact numeric formats to full text with timezone information. Automatically uses locale-appropriate time formatting including 12-hour vs 24-hour notation based on cultural conventions.

Format Types

  • Short: Compact time format (e.g., “3:45 PM”, “15:45”)
  • Medium: Time with seconds (e.g., “3:45:30 PM”, “15:45:30”)
  • Long: Time with timezone (e.g., “3:45:30 PM GMT”, “15:45:30 GMT”)
  • Full: Complete time format (e.g., “3:45:30 PM GMT”, “15:45:30 GMT”)
  • Custom(pattern): Custom pattern with HH, mm, ss placeholders

Examples

let assert Ok(en_locale) = g18n.locale("en")
let assert Ok(pt_locale) = g18n.locale("pt")
let en_translator = g18n.translator(en_locale, g18n.translations())
let pt_translator = g18n.translator(pt_locale, g18n.translations())
let time = calendar.TimeOfDay(hours: 15, minutes: 30, seconds: 45)

// English uses 12-hour format
g18n.format_time(en_translator, time, g18n.Short)  // "3:30 PM"
g18n.format_time(en_translator, time, g18n.Medium) // "3:30:45 PM"
g18n.format_time(en_translator, time, g18n.Long)   // "3:30:45 PM GMT"

// Portuguese uses 24-hour format  
g18n.format_time(pt_translator, time, g18n.Short)  // "15:30"
g18n.format_time(pt_translator, time, g18n.Medium) // "15:30:45"

// Custom formatting
g18n.format_time(en_translator, time, g18n.Custom("HH:mm")) // "15:30"
pub fn get_keys_with_prefix(
  translations: Translations,
  prefix: String,
) -> List(String)

Get all translation keys that start with a given prefix.

Useful for finding all keys within a specific namespace.

Examples

let translations = g18n.new()
  |> g18n.add_translation("ui.button.save", "Save")
  |> g18n.add_translation("ui.button.cancel", "Cancel")
  |> g18n.add_translation("user.name", "Name")

g18n.get_keys_with_prefix(translations, "ui.button")
// ["ui.button.save", "ui.button.cancel"]
pub fn locale(translator: Translator) -> locale.Locale

Get the locale from a translator.

Examples

let assert Ok(locale) = g18n.locale("en-US")
let translator = g18n.translator(locale, g18n.translations())
g18n.get_locale(translator) // Locale(language: "en", region: Some("US"))
pub fn main() -> Nil

Main entry point for the g18n CLI tool.

Handles command-line arguments and dispatches to appropriate command handlers. Currently supports ‘generate’ command to create Gleam translation modules and ‘help’ command to display usage information.

Supported Commands

  • generate: Generate Gleam modules from translation JSON files
  • help: Display help information
  • No arguments: Display help information

Examples

Run via command line:

gleam run generate  # Generate translation modules
gleam run help      # Show help
gleam run           # Show help (default)

Main entry point for the g18n CLI tool.

Handles command-line arguments and dispatches to appropriate command handlers. Supports ‘generate’ for flat JSON, ‘generate_nested’ for nested JSON, and ‘help’ for usage information.

Supported Commands

  • generate: Generate Gleam modules from flat JSON files
  • generate_nested: Generate Gleam modules from nested JSON files
  • help: Display help information
  • No arguments: Display help information

Examples

Run via command line:

gleam run generate        # Generate from flat JSON files
gleam run generate_nested # Generate from nested JSON files  
gleam run help           # Show help
gleam run                # Show help (default)
pub fn namespace(
  translator: Translator,
  namespace: String,
) -> List(#(String, String))

Get all key-value pairs from translations within a specific namespace.

Returns tuples of (key, translation) for all keys that start with the namespace prefix.

Examples

let translations = g18n.translations()
  |> g18n.add_translation("ui.button.save", "Save")
  |> g18n.add_translation("ui.button.cancel", "Cancel")
  |> g18n.add_translation("user.name", "Name")
let translator = g18n.translator(g18n.locale("en"), translations)

g18n.get_namespace(translator, "ui.button")
// [#("ui.button.save", "Save"), #("ui.button.cancel", "Cancel")]
pub fn new_format_params() -> dict.Dict(String, String)

Create a new empty parameter container for string formatting.

Examples

let params = g18n.new()
  |> g18n.add_param("name", "Alice")
  |> g18n.add_param("count", "5")
pub fn new_translations() -> Translations

Create a new empty translations container.

Examples

let translations = g18n.new()
  |> g18n.add_translation("hello", "Hello")
  |> g18n.add_translation("goodbye", "Goodbye")
pub fn new_translator(
  locale: locale.Locale,
  translations: Translations,
) -> Translator

Create a new translator with the specified locale and translations.

A translator combines a locale with a set of translations to provide localized text output. This is the main interface for translation operations.

Examples

let assert Ok(locale) = g18n.locale("en-US")
let translations = g18n.translations()
  |> g18n.add_translation("hello", "Hello")
  |> g18n.add_translation("welcome", "Welcome {name}!")

let translator = g18n.translator(locale, translations)

g18n.translate(translator, "hello")
// "Hello"
pub fn translate(translator: Translator, key: String) -> String

Translate a key to localized text using the translator.

Looks up the translation for the given key in the translator’s translations. If not found, tries the fallback translations. If still not found, returns the original key as fallback.

Supports hierarchical keys using dot notation for organization.

Examples

let assert Ok(locale) = g18n.locale("en")
let translations = g18n.translations()
  |> g18n.add_translation("ui.button.save", "Save")
  |> g18n.add_translation("user.greeting", "Hello")

let translator = g18n.translator(locale, translations)

g18n.t(translator, "ui.button.save")
// "Save"

g18n.t(translator, "user.greeting") 
// "Hello"

g18n.t(translator, "missing.key")
// "missing.key" (fallback to key)
pub fn translate_cardinal(
  translator: Translator,
  key: String,
  count: Int,
) -> String

Translate with cardinal pluralization rules.

Alias for translate_plural that explicitly indicates the use of cardinal number rules (used for counting: 1 item, 2 items, etc.). This is the standard pluralization used for most counting scenarios.

Examples

g18n.translate_cardinal(en_translator, "book", 1)   // "book.one" 
g18n.translate_cardinal(en_translator, "book", 3)   // "book.other"
g18n.translate_cardinal(pt_translator, "livro", 0)  // "livro.zero" 
pub fn translate_ordinal(
  translator: Translator,
  key: String,
  position: Int,
) -> String

Translate with ordinal number rules.

Uses ordinal pluralization rules for position-based numbers (1st, 2nd, 3rd, etc.). Different languages have different rules for ordinal endings, and this function applies the appropriate ordinal key suffix based on the position and locale.

Examples

g18n.translate_ordinal(en_translator, "place", 1)   // "place.one" → "1st place"
g18n.translate_ordinal(en_translator, "place", 2)   // "place.two" → "2nd place"  
g18n.translate_ordinal(en_translator, "place", 3)   // "place.few" → "3rd place"
g18n.translate_ordinal(en_translator, "place", 11)  // "place.other" → "11th place"
pub fn translate_ordinal_with_params(
  translator: Translator,
  key: String,
  position: Int,
  params: dict.Dict(String, String),
) -> String

Translate ordinal numbers with parameter substitution.

Combines ordinal number translation with parameter substitution. Automatically adds position and ordinal parameters to the provided parameters for convenient template formatting.

Examples

let params = dict.from_list([("name", "Alice")])

g18n.translate_ordinal_with_params(en_translator, "winner", 1, params)
// Template: "{name} finished in {position}{ordinal} place" 
// Result: "Alice finished in 1st place"

g18n.translate_ordinal_with_params(en_translator, "winner", 3, params)
// Result: "Alice finished in 3rd place"
pub fn translate_plural(
  translator: Translator,
  key: String,
  count: Int,
) -> String

Translate with automatic pluralization based on count and locale rules.

Automatically selects the appropriate plural form based on the count and the language’s pluralization rules. Supports multiple plural forms including zero, one, two, few, many, and other.

Supported Plural Rules

  • English: 1 → .one, others → .other
  • Portuguese: 0 → .zero, 1 → .one, others → .other
  • Russian: Complex Slavic rules → .one/.few/.many

Examples

let assert Ok(en_locale) = g18n.locale("en")
let assert Ok(pt_locale) = g18n.locale("pt")
let translations = g18n.translations()
  |> g18n.add_translation("item.one", "1 item")
  |> g18n.add_translation("item.other", "{count} items")
  |> g18n.add_translation("item.zero", "no items")

let en_translator = g18n.translator(en_locale, translations)
let pt_translator = g18n.translator(pt_locale, translations)

// English pluralization (1 → one, others → other)
g18n.translate_plural(en_translator, "item", 1)  // "1 item"
g18n.translate_plural(en_translator, "item", 5)  // "{count} items"

// Portuguese pluralization (0 → zero, 1 → one, others → other)  
g18n.translate_plural(pt_translator, "item", 0)  // "no items"
g18n.translate_plural(pt_translator, "item", 1)  // "1 item"
g18n.translate_plural(pt_translator, "item", 3)  // "{count} items"
pub fn translate_plural_with_params(
  translator: Translator,
  key: String,
  count: Int,
  params: dict.Dict(String, String),
) -> String

Translate with pluralization and parameter substitution.

Combines pluralization and parameter substitution in a single function. First determines the appropriate plural form based on count and locale, then performs parameter substitution on the resulting template.

Examples

let params = dict.from_list([("name", "Alice"), ("count", "3")])

g18n.translate_plural_with_params(en_translator, "user.items", 3, params)
// "Alice has 3 items"

g18n.translate_plural_with_params(en_translator, "user.items", 1, params) 
// "Alice has 1 item"
pub fn translate_range(
  translator: Translator,
  key: String,
  from: Int,
  to: Int,
) -> String

Translate for numeric ranges.

Handles translations for numeric ranges, choosing between single value and range translations. Uses “.single” key suffix when from equals to, and “.range” suffix for actual ranges.

Examples

g18n.translate_range(en_translator, "pages", 5, 5)   // "pages.single" → "Page 5"
g18n.translate_range(en_translator, "pages", 1, 10)  // "pages.range" → "Pages 1-10"
g18n.translate_range(en_translator, "items", 3, 7)   // "items.range" → "Items 3 through 7"
pub fn translate_range_with_params(
  translator: Translator,
  key: String,
  from: Int,
  to: Int,
  params: dict.Dict(String, String),
) -> String

Translate numeric ranges with parameter substitution.

Combines range translation with parameter substitution. Automatically adds from, to, and total parameters to the provided parameters for convenient template formatting.

Examples

let params = dict.from_list([("type", "chapters")])

g18n.t_range_with_params(en_translator, "content", 1, 5, params)
// Template: "Reading {type} {from} to {to} ({total} total)"
// Result: "Reading chapters 1 to 5 (5 total)"

g18n.t_range_with_params(en_translator, "content", 3, 3, params) 
// Uses .single key, Result: "Reading chapter 3"
pub fn translate_with_context(
  translator: Translator,
  key: String,
  context: TranslationContext,
) -> String

Translate a key with context for disambiguation.

Context-sensitive translations allow the same key to have different translations based on the context in which it’s used. This is essential for words that have multiple meanings or grammatical forms in different situations.

Context keys are stored as key@context in the translation files.

Examples

let assert Ok(locale) = g18n.locale("en")
let translations = g18n.translations()
  |> g18n.add_translation("may", "may")                    // auxiliary verb
  |> g18n.add_translation("may@month", "May")              // month name
  |> g18n.add_translation("may@permission", "allowed to")  // permission

let translator = g18n.translator(locale, translations)

g18n.t_with_context(translator, "may", NoContext)         // "may"
g18n.t_with_context(translator, "may", Context("month"))  // "May"  
g18n.t_with_context(translator, "may", Context("permission")) // "allowed to"
pub fn translate_with_context_and_params(
  translator: Translator,
  key: String,
  context: TranslationContext,
  params: dict.Dict(String, String),
) -> String

Translate a key with context and parameter substitution.

Combines context-sensitive translation with parameter formatting. Useful for complex translations that need both disambiguation and dynamic values.

Examples

let assert Ok(locale) = g18n.locale("en")
let translations = g18n.translations()
  |> g18n.add_translation("close", "close")
  |> g18n.add_translation("close@door", "Close the {item}")
  |> g18n.add_translation("close@application", "Close {app_name}")

let translator = g18n.translator(locale, translations)
let params = g18n.format_params() |> g18n.add_param("item", "door")

g18n.translate_with_context_and_params(
  translator, 
  "close", 
  Context("door"), 
  params
) // "Close the door"
pub fn translate_with_params(
  translator: Translator,
  key: String,
  params params: dict.Dict(String, String),
) -> String

Translate a key with parameter substitution.

Performs translation lookup and then substitutes parameters in the resulting template. Parameters are specified using {param} syntax in the translation template.

Examples

let assert Ok(locale) = g18n.locale("en")
let translations = g18n.translations()
  |> g18n.add_translation("user.welcome", "Welcome {name}!")
  |> g18n.add_translation("user.messages", "You have {count} new messages")

let translator = g18n.translator(locale, translations)
let params = g18n.format_params()
  |> g18n.add_param("name", "Alice")
  |> g18n.add_param("count", "5")

g18n.t_with_params(translator, "user.welcome", params)
// "Welcome Alice!"

g18n.t_with_params(translator, "user.messages", params)
// "You have 5 new messages"
pub fn translation_coverage(
  primary_translations: Translations,
  target_translations: Translations,
) -> Float

Calculate translation coverage percentage.

Computes the percentage of primary translation keys that have been translated in the target translations. Returns a float between 0.0 and 1.0 where 1.0 indicates complete coverage (100%).

Examples

let primary = g18n.translations()
  |> g18n.add_translation("hello", "Hello")
  |> g18n.add_translation("goodbye", "Goodbye")
  |> g18n.add_translation("welcome", "Welcome")

let partial_target = g18n.translations()
  |> g18n.add_translation("hello", "Hola")
  |> g18n.add_translation("goodbye", "Adiós")
  // Missing "welcome" translation

let coverage = g18n.get_translation_coverage(primary, partial_target)
// coverage == 0.67 (67% - 2 out of 3 keys translated)

let complete_target = partial_target
  |> g18n.add_translation("welcome", "Bienvenido")

let full_coverage = g18n.get_translation_coverage(primary, complete_target)
// full_coverage == 1.0 (100% coverage)
pub fn translations(translator: Translator) -> Translations

Get the translations from a translator.

Examples

let translations = g18n.translations()
  |> g18n.add_translation("hello", "Hello")
let translator = g18n.translator(g18n.locale("en"), translations)
g18n.get_translations(translator) // Returns the translations container
pub fn translations_from_json(
  json_string: String,
) -> Result(Translations, Nil)

Parse a JSON string into a Translations structure.

Converts a JSON object with dotted keys into an internal trie structure for efficient translation lookups. The JSON should contain key-value pairs where keys use dot notation (e.g., “user.name”, “welcome.message”) and values are the translation strings.

Examples

let json = "{\"user.name\": \"Name\", \"user.email\": \"Email\"}"
let assert Ok(translations) = g18n.translations_from_json(json)
pub fn translations_from_nested_json(
  json_string: String,
) -> Result(Translations, String)

Import translations from nested JSON format.

Converts nested JSON objects to the internal flat trie structure. This is the industry-standard format used by most i18n libraries like react-i18next, Vue i18n, and Angular i18n.

Parameters

  • json_string: JSON string with nested structure

Returns

Result(Translations, String) - Success with translations or error message

Examples

let nested_json = "
{
  \"ui\": {
    \"button\": {
      \"save\": \"Save\",
      \"cancel\": \"Cancel\"
    }
  },
  \"user\": {
    \"name\": \"Name\",
    \"email\": \"Email\"
  }
}"

let assert Ok(translations) = g18n.translations_from_nested_json(nested_json)
// Converts to flat keys: "ui.button.save", "ui.button.cancel", etc.
pub fn translations_to_json(translations: Translations) -> String

Convert a Translations structure to a JSON string.

Converts the internal trie structure back to a JSON object with dotted keys. This is useful for exporting translations or debugging the current state of loaded translations.

Examples

let assert Ok(translations) = g18n.translations_from_json("{\"user.name\": \"Name\"}")
let json_output = g18n.translations_to_json(translations)
// Returns: {"user.name": "Name"}
pub fn translations_to_nested_json(
  translations: Translations,
) -> String

Export translations to nested JSON format.

Converts the internal flat trie structure to nested JSON objects. This produces the industry-standard format expected by most i18n tools.

Parameters

  • translations: The translations to export

Returns

String - Nested JSON representation of the translations

Examples

let translations = g18n.translations()
  |> g18n.add_translation("ui.button.save", "Save")
  |> g18n.add_translation("ui.button.cancel", "Cancel")
  |> g18n.add_translation("user.name", "Name")

let nested_json = g18n.translations_to_nested_json(translations)
// Returns: {"ui":{"button":{"save":"Save","cancel":"Cancel"}},"user":{"name":"Name"}}
pub fn validate_translation_parameters(
  translations: Translations,
  key: String,
  required_params: List(String),
  locale: locale.Locale,
) -> List(ValidationError)

Validate that a translation key has the correct parameters.

Checks if a specific translation contains all required parameters and identifies any unused parameters. This ensures parameter consistency between different language versions of the same translation.

Examples

let assert Ok(locale) = g18n.locale("es")
let translations = g18n.translations()
  |> g18n.add_translation("user.greeting", "Hola {nombre}!")
  |> g18n.add_translation("user.stats", "Tienes {points} puntos")

// Check if Spanish translation has required English parameters
let errors1 = g18n.validate_translation_parameters(
  translations, "user.greeting", ["name"], locale
)
// Returns [MissingParameter("user.greeting", "name", locale)] - "name" missing, "nombre" unused

let errors2 = g18n.validate_translation_parameters(
  translations, "user.stats", ["points"], locale  
)
// Returns [] - parameters match correctly
pub fn validate_translations(
  primary_translations: Translations,
  target_translations: Translations,
  target_locale: locale.Locale,
) -> ValidationReport

Validate target translations against primary translations.

Compares a primary set of translations (e.g., English) with target translations (e.g., Spanish) to identify missing translations, parameter mismatches, invalid plural forms, and empty translations. Returns a comprehensive validation report with error details and translation coverage statistics.

Examples

let assert Ok(en) = g18n.locale("en")
let assert Ok(es) = g18n.locale("es")

let primary = g18n.new()
  |> g18n.add_translation("welcome", "Welcome {name}!")
  |> g18n.add_translation("items.one", "1 item")
  |> g18n.add_translation("items.other", "{count} items")

let target = g18n.new()
  |> g18n.add_translation("welcome", "¡Bienvenido {nombre}!")  // Parameter mismatch
  |> g18n.add_translation("items.one", "1 artículo")
  // Missing "items.other" translation

let report = g18n.validate_translations(primary, target, es)
// report.errors will contain MissingParameter and MissingTranslation errors
// report.coverage will be 0.67 (2 out of 3 keys translated)
pub fn with_fallback(
  translator: Translator,
  fallback_locale: locale.Locale,
  fallback_translations: Translations,
) -> Translator

Add fallback locale and translations to an existing translator.

When a translation key is not found in the primary translations, the translator will fall back to the fallback translations before returning the original key.

Examples

let assert Ok(en) = g18n.locale("en")
let assert Ok(es) = g18n.locale("es")

let en_translations = g18n.translations()
  |> g18n.add_translation("hello", "Hello")

let es_translations = g18n.translations()
  |> g18n.add_translation("goodbye", "Adiós")

let translator = g18n.translator(es, es_translations)
  |> g18n.with_fallback(en, en_translations)

g18n.translate(translator, "goodbye") // "Adiós"
g18n.translate(translator, "hello")   // "Hello" (from fallback)
Search Document