A comprehensive, strongly-typed Rust library for managing Unicode locales, built directly on the CLDR (Common Locale Data Repository) dataset.
This workspace contains two crates:
- locale-rs The production library for locale management and formatting.
- locale-dev The code generation tool for updating locale data.
Locale is designed to be the foundational "source of truth" for locale identifiers in the Rust ecosystem. Rather than relying on hardcoded strings, this project leverages automated generation to stay perfectly in sync with the latest Unicode releases.
- Authenticity: Data is sourced directly from the official Unicode CLDR-JSON repository.
- Safety: Every locale identifier is a first-class citizen in a Rust
enum, preventing typos and invalid locale errors at compile-time. - Efficiency: Zero-cost abstractions for locale identification and string conversion.
- Automation: Automated code generation ensures the library stays in sync with Unicode standards.
- Inspiration: Heavily inspired by the architectural patterns of the
num-formatcrate.
Add to your Cargo.toml:
[dependencies]
# Standard installation
locale-rs = "0.3"
# Or opt into specific features
locale-rs = { version = "0.3", features = ["nums"] }
locale-rs = { version = "0.3", features = ["all"] }
Basic usage:
use locale_rs::Locale;
let locale = Locale::en_GB;
println!("{}", locale); // "en-GB"
// Number formatting
use locale_rs::num_formats::ToFormattedString;
let num = 1234567;
println!("{}", num.to_formatted_string(&Locale::en)); // 1,234,567
println!("{}", num.to_formatted_string(&Locale::de)); // 1.234.567To update to the latest CLDR release:
# In the workspace root
cargo run -p locale-dev
# This will:
# 1. Check GitHub for the latest CLDR-JSON release
# 2. Download or use cached data
# 3. Generate updated locale-rs code
# 4. Format and lint the generated code
locale/
βββ locale-rs/ # Production library
β βββ src/
β β βββ lib.rs # Public API
β β βββ locale.rs # Auto-generated: Locale enum
β β βββ error.rs # Error types
β β βββ num_formats.rs # Auto-generated: Number formatting
β β βββ currency_formats.rs# Auto-generated: Currency patterns
β β βββ datetime_formats.rs# Auto-generated: DateTime data
β βββ examples/ # Usage examples
β βββ benches/ # Benchmarks
β βββ Cargo.toml
βββ locale-dev/ # Code generation tool
β βββ src/
β β βββ main.rs # Entry point
β β βββ download_latest.rs # GitHub API & caching
β β βββ generate_locales.rs# Locale enum generation
β β βββ ...
βββ ...
| Feature | Description |
|---|---|
| 766 Unicode Locales | Complete CLDR 48.1.0 coverage out of the box. |
| Type-Safe Locales | Compile-time validated enum variants. |
| Number Formatting | Locale-aware formatting using native digits. |
| Currency Formatting | ICU-compatible currency patterns. |
| DateTime Formatting | Localized month and weekday names. |
| Flexible Parsing | Parse seamlessly with hyphens, underscores, or mixed cases. |
| Locale Negotiation | Find the best matching locale from available options using fallback chains. |
| Fuzzy Suggestions | Intelligently suggest corrections for typos or unknown locales. |
- Latin (0-9)
- Arabic-Indic (Ω -Ω©)
- Extended Arabic-Indic (Ϋ°-ΫΉ)
- Devanagari (ΰ₯¦-ΰ₯―)
- Bengali (০-৯)
- Gujarati (૦-૯)
- Gurmukhi (੦-੯)
- Kannada (೦-೯)
- Malayalam (ࡦ-࡯)
- Oriya (ΰ¦-ΰ―)
- Tamil (ΰ―¦-ΰ――)
- Telugu (౦-౯)
- Thai (ΰΉ-ΰΉ)
- Tibetan (ΰΌ -ΰΌ©)
- And many more...
use locale_rs::Locale;
use std::str::FromStr;
// Direct enum access
let locale = Locale::en_GB;
assert_eq!(locale.as_str(), "en-GB");
// Parse from string & flexible alternatives
let locale = Locale::from_str("en-GB")?;
let locale = Locale::from_flexible("en_gb")?;
// Extract subtags & fallback chain
assert_eq!(locale.language_code(), "en");
assert_eq!(locale.region_code(), Some("GB"));
assert_eq!(locale.fallback(), Some(Locale::en));use locale_rs::Locale;
// 1. Negotiation
let user_preference = Locale::en_GB;
let available = vec![Locale::en, Locale::de, Locale::fr];
if let Some(best) = user_preference.negotiate(&available) {
println!("Using: {}", best); // Falls back to "en"
}
// 2. Fuzzy Suggestions
let suggestions = Locale::suggest("en-gbb");
for locale in suggestions {
println!("{}", locale); // Suggests: en-GB, en, etc.
}- Runtime: Zero-cost abstractions; all data mapping operations are compile-time validated.
- Memory: Locale enum variants are completely zero-sized types.
This project respects and adheres to the licensing requirements of its source data:
- Data Source: All locale data is derived from the Unicode CLDR project and is subject to the Unicode License V3.
- Code Inspiration: Architectural patterns inspired by
num-format, dual-licensed under Apache-2.0 or MIT. - This Project: Dual-licensed under MIT License or Apache-2.0 License.
Contributions are welcome! Since the core code is generated, most improvements should be directed toward:
locale-devβ Improving code generation logic and CLDR data extraction.locale-rsβ Adding new helper methods, testing runtime scenarios, or extending examples.