i18n-timezones

March 8, 2026 · View on GitHub

Crates.io License: MIT

Localized timezone names for Rust -- 36 locales, 152 timezones, zero runtime I/O.

Building a timezone picker? Displaying meeting times across regions? Your users expect to see "Eastern Time (US & Canada)" -- in their own language, not as a raw IANA identifier.

i18n-timezones provides human-friendly, localized timezone display names sourced from CLDR, the same data that powers ICU, Chrome, and Android. All translation data is embedded at compile time via include_str! -- no external files, no filesystem access, no network calls. Your binary is fully self-contained.

Why i18n-timezones?

  • 36 locales covering 4+ billion speakers -- from Arabic to Vietnamese
  • Compile-time embedded -- all data baked into the binary, zero runtime I/O
  • Two APIs -- owned Registry struct for testability, or global convenience functions for simplicity
  • Thread-safe globals -- global API is protected by Mutex, safe for concurrent use
  • No panic -- all lookups return Option, never panics on missing data
  • Minimal dependencies -- only serde_json and once_cell

Install

[dependencies]
i18n-timezones = "0.1"

Quick Start

use i18n_timezones::Registry;

let mut reg = Registry::new();
reg.register_locale("ja").unwrap();
reg.set_default_locale("ja").unwrap();

assert_eq!(reg.get_translation("Tokyo"), Some("東京"));

Usage

The Registry struct gives you an owned, testable translation store:

use i18n_timezones::Registry;

let mut reg = Registry::new();
reg.register_locale("de").unwrap();
reg.register_locale("fr").unwrap();
reg.set_default_locale("de").unwrap();

// Lookup with default locale
let name = reg.get_translation("Tokyo");
assert_eq!(name, Some("Tokio"));

// Lookup with explicit locale
let name = reg.get_translation_for_locale("fr", "Tokyo");
assert_eq!(name, Some("Tokyo"));

// List what's loaded
let locales = reg.registered_locales(); // ["de", "fr"]

Register all locales at once

let mut reg = Registry::new();
reg.register_all_locales().unwrap();
// All 36 locales now available

Global convenience API

For simpler use cases where you don't want to pass a Registry around:

i18n_timezones::register_locale("de").unwrap();
i18n_timezones::set_default_locale("de").unwrap();

let name = i18n_timezones::get_translation("Tokyo");
assert_eq!(name, Some("Tokio".to_string()));

// Explicit locale
let name = i18n_timezones::get_translation_for_locale("de", "Berlin");
assert_eq!(name, Some("Berlin".to_string()));

List available locales

// All locales in the embedded data (no registration needed)
let available = i18n_timezones::available_locales();
assert!(available.len() >= 36);
assert!(available.contains(&"ja"));

API Reference

Registry (struct-based)

MethodDescription
Registry::new()Create a new empty registry.
register_locale(&mut self, locale)Load translations for a single locale. No-op if already registered.
register_all_locales(&mut self)Load all 36 available locales.
set_default_locale(&mut self, locale)Set the default locale. Returns Err if not registered.
default_locale(&self)Get the current default locale.
get_translation(&self, key)Get the localized name using the default locale.
get_translation_for_locale(&self, locale, key)Get the localized name for a specific locale.
available_locales()List all locales in the embedded data (static).
registered_locales(&self)List all currently loaded locales.

Global functions

FunctionDescription
register_locale(locale)Register a locale in the global registry.
register_all_locales()Register all locales in the global registry.
set_default_locale(locale)Set the global default locale.
get_translation(key)Translate using the global default locale. Returns Option<String>.
get_translation_for_locale(locale, key)Translate for a specific locale. Returns Option<String>.
available_locales()List all available locales.

All lookups return None when a timezone or locale is not found -- no panics.

Supported Locales

36 locales covering major world languages:

arbncacsdadeel
eneseufifrhehi
hrhuiditjakoms
nlnoplptpt-BRroru
sqsvthtrukvizh-CN
zh-TW

Data Source

All translations come from the Unicode CLDR (Common Locale Data Repository) -- the industry-standard source used by every major platform including iOS, Android, Chrome, and Java. This ensures translations are accurate, consistent, and maintained by native speakers through Unicode's established review process.

Also Available For

  • Ruby -- Rails gem with automatic time_zone_select integration
  • JavaScript/TypeScript -- NPM package with tree-shaking and dropdown helpers
  • Go -- Go module with embedded data via go:embed

License

MIT