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 separatorsCurrency(currency_code, precision)
: Currency with appropriate symbols and placementPercentage(precision)
: Percentage formatting with locale conventionsScientific(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 fileshelp
: 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 filesgenerate_nested
: Generate Gleam modules from nested JSON fileshelp
: 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)