Internationalization
Translation support lives in the optional waterui_i18n crate. It installs as a plugin, reroutes
Text content through a translation map, and exposes helpers for locale-aware formatting.
Installing the Plugin
#![allow(unused)]
fn main() {
use waterui::prelude::*;
use waterui_i18n::I18n;
use waterui::text::locale::Locale;
fn env_with_i18n() -> Environment {
let mut i18n = I18n::new();
i18n.insert("en", "greeting", "Hello");
i18n.insert("fr", "greeting", "Bonjour");
let mut env = Environment::new();
i18n.install(&mut env);
env.insert(Locale("fr".into()));
env
}
}
Every text!("greeting") now resolves through the i18n map and emits the French string.
Dynamic Locales
Locales are reactive—store a Binding<Locale> in the environment and update it when the user picks
a new language. Because the plugin uses computed signals, existing text views update automatically.
#![allow(unused)]
fn main() {
use waterui::prelude::*;
use waterui::text::locale::Locale;
pub fn switch_locale(env: &mut Environment) {
let locale = binding(Locale("en".into()));
env.insert(locale.clone());
button("Switch to French").action_with(&locale, |loc| loc.set(Locale("fr".into())));
}
}
Parameterized Strings
Translations can include placeholders; format values client-side before passing them to text!, or
store template keys in the map and handle interpolation in your code:
#![allow(unused)]
fn main() {
use waterui::prelude::*;
use waterui_i18n::I18n;
use waterui::text::locale::Locale;
pub fn formatted_count() -> impl View {
let mut i18n = I18n::new();
i18n.insert("en", "items_label", "items");
let locale = Locale("en".into());
let item_count = 3;
// In a real app, you would fetch the translation dynamically
let label = i18n.get(&locale.0, "items_label");
text!("{count} {text}", count = item_count, text = label)
}
}
Future releases will expand the formatter API so you can define ICU-style templates directly in the translation map.
Pluralization and Formatting
For locale-aware numbers and dates, reach for waterui::text::locale:
#![allow(unused)]
fn main() {
use waterui::prelude::*;
use waterui::text::locale::{DateFormatter, Locale};
use time::Date;
pub fn formatted_date() -> impl View {
let date = binding(Date::from_calendar_date(2025, 1, 1).unwrap());
let formatter = DateFormatter { locale: Locale("en-US".into()) };
Text::format(date, formatter)
}
}
Pair these with I18n so both phrasing and formatting respect the user’s locale.
Internationalization is just an environment plugin—install it once, keep translations in sync with your keys, and the rest of WaterUI’s text pipeline stays reactive and type-safe.