| Crates.io | globetrotter-rust |
| lib.rs | globetrotter-rust |
| version | 0.0.10 |
| created_at | 2025-04-22 14:41:49.225979+00 |
| updated_at | 2026-01-07 02:42:43.809668+00 |
| description | Polyglot, type-safe internationalization |
| homepage | https://github.com/LuupSystems/globetrotter |
| repository | https://github.com/LuupSystems/globetrotter |
| max_upload_size | |
| id | 1644143 |
| size | 51,603 |
Type-safe internationalization through code generation. Define translations once, use them everywhere with full type safety across multiple programming languages.
Most i18n solutions force you to choose between type safety and runtime flexibility. Globetrotter provides both by separating concerns: translation data is stored as pure JSON and loaded dynamically at runtime, while type definitions are generated at build time and shared across all language files.
This architecture enables:
The key insight: translation keys and their argument signatures are known at build time, even though the actual translated strings are loaded dynamically.
brew install --cask LuupSystems/tap/globetrotter
# Or install from source
cargo install --locked globetrotter-cli
Create a globetrotter.yaml file in your project root:
version: 1
configs:
my-translations:
# Define which languages you support
languages: ["en", "de", "fr"]
# Template engine for interpolation (handlebars or none)
engine: handlebars
# Strict mode: fail on missing translations
strict: true
# Validate templates at build time
check_templates: true
# Input translation files (TOML format)
inputs:
- path: ./translations/common.toml
prefix: "common" # Optional: namespace translations
prepend_filename: true # Optional: use filename as prefix
- path: ./translations/errors.toml
prefix: "errors"
# Output files
outputs:
# JSON files for runtime (one per language)
json:
- ./dist/translations_{{language}}.json
# TypeScript type definitions
typescript:
type: ./src/generated/translations.ts
# Rust type definitions
rust:
- ./src/generated/translations.rs
# Additional language support
golang:
- ./generated/translations.go
python:
- ./generated/translations.py
Create TOML files with your translations:
# translations/common.toml
[greeting]
en = "Hello {{name}}"
de = "Hallo {{name}}"
fr = "Bonjour {{name}}"
arguments = { name = "string" }
[item_count]
en = "You have {{count}} items"
de = "Du hast {{count}} Elemente"
fr = "Vous avez {{count}} éléments"
arguments = { count = "number" }
[welcome]
en = "Welcome to our application"
de = "Willkommen in unserer Anwendung"
fr = "Bienvenue dans notre application"
Run globetrotter to generate type definitions and JSON files:
# Generate from config file in current directory
globetrotter
# Specify config file explicitly
globetrotter --config globetrotter.yaml
# Dry run to preview changes
globetrotter --dry-run
use serde_json;
// Include generated types at compile time
mod translations {
include!(concat!(env!("OUT_DIR"), "/translations.rs"));
}
use translations::Translation;
// Load JSON dynamically at runtime
let json = std::fs::read_to_string("translations_en.json")?;
let translations: globetrotter_model::json::Translations =
serde_json::from_str(&json)?;
// Use with full type safety
let greeting = Translation::CommonGreeting {
name: "Alice"
};
// The key is statically known
let key = greeting.key(); // "common.greeting"
// Render with your template engine
let message = handlebars.render(key, &greeting)?;
// Result: "Hello Alice"
For a complete working example, see examples/example-rust/ in this repository:
cd examples/example-rust
cargo run -- --language en --name "Alice"
# Output: Hello Alice
cargo run -- --language de --name "Alice"
# Output: Hallo Alice
The example demonstrates:
Using a build.rs script to generate types and JSON at compile time
Loading JSON dynamically at runtime
Rendering translations with Handlebars templates
Full type safety with the generated Translation enum
// Import generated types (included at build time)
import type { Translations } from './generated/translations';
// Load JSON dynamically at runtime
async function loadTranslations(lang: string): Promise<Translations> {
const response = await fetch(`/translations_${lang}.json`);
return response.json();
}
// Use with full type safety and autocomplete
const translations = await loadTranslations('en');
// TypeScript knows the exact structure
const greeting = translations['common.greeting'];
// For templates with arguments, types are enforced
type GreetingArgs = { name: string };
const message = renderTemplate(greeting, { name: 'Alice' });
// Result: "Hello Alice"
// TypeScript will error if you use wrong argument types
// renderTemplate(greeting, { name: 123 }); // ❌ Type error
Globetrotter currently generates type-safe bindings for:
Waiting for contributions:
Globetrotter's modular architecture makes it straightforward to add support for new languages. Each language generator is an independent crate that implements a simple interface. See the library documentation to contribute a generator for your language.
All languages share the same JSON format at runtime, ensuring consistency across your stack.
Handlebars - Full Handlebars syntax with custom helpers
Bring your own template engine!
The architecture supports pluggable template engines. Contributions for additional engines are welcome.
Contributions are welcome, especially for new language generators. See the library documentation for implementation details.