| Crates.io | yewi18n |
| lib.rs | yewi18n |
| version | 0.1.0 |
| created_at | 2025-11-25 22:10:58.77996+00 |
| updated_at | 2025-11-25 22:10:58.77996+00 |
| description | A simple i18n library for Yew applications with dynamic JSON loading |
| homepage | |
| repository | https://gitlab.illuminodes.com/illuminodes/yew-i18n |
| max_upload_size | |
| id | 1950520 |
| size | 52,837 |
A simple internationalization (i18n) library for Yew applications that dynamically loads translation JSON files from the browser, similar to how CSS and images are loaded.
Add this to your Cargo.toml:
[dependencies]
yew-i18n = { path = "../yew-i18n" }
# or once published:
# yew-i18n = "0.1"
Create JSON translation files in your static directory:
static/
└── language/
├── en-US.json
└── es-ES.json
Example en-US.json:
{
"welcome_message": "Welcome to our app!",
"login_button": "Login",
"signup_button": "Sign Up"
}
Example es-ES.json:
{
"welcome_message": "¡Bienvenido a nuestra app!",
"login_button": "Iniciar sesión",
"signup_button": "Registrarse"
}
The I18nProvider uses Yew's Suspense, so wrap it with a <Suspense> component to show a fallback while translations are loading.
use yew::prelude::*;
use yew_i18n::I18nProvider;
#[function_component(App)]
fn app() -> Html {
html! {
<Suspense fallback={html! { <p>{"Loading translations..."}</p> }}>
<I18nProvider base_path="/static/language">
<MyComponent />
</I18nProvider>
</Suspense>
}
}
use yew::prelude::*;
use yew_i18n::use_translation;
#[function_component(MyComponent)]
fn my_component() -> Html {
let i18n = use_translation();
html! {
<div>
<h1>{ i18n.t("welcome_message") }</h1>
<button>{ i18n.t("login_button") }</button>
</div>
}
}
use yew::prelude::*;
use yew_i18n::{use_change_locale, Locale};
#[function_component(LanguageSwitcher)]
fn language_switcher() -> Html {
let change_locale = use_change_locale();
let on_english = {
let change_locale = change_locale.clone();
Callback::from(move |_| {
change_locale.emit(Locale::EnglishUS);
})
};
let on_spanish = {
let change_locale = change_locale.clone();
Callback::from(move |_| {
change_locale.emit(Locale::SpanishES);
})
};
html! {
<div>
<button onclick={on_english}>{ "English" }</button>
<button onclick={on_spanish}>{ "Español" }</button>
</div>
}
}
I18nProviderContext provider component that loads and manages translations.
Props:
base_path: &'static str - Base path where translation JSON files are located (e.g., "/static/language")children: Html - Child componentsinitial_locale: Option<Locale> - Optional locale override (defaults to browser detection)use_translation()Hook to access translation context in components.
Returns: UseReducerHandle<TranslationData>
Methods:
.t(key: &str) -> &str - Translate a key (zero-allocation).translate(key: &str) -> &str - Translate a key (same as .t()).current_locale() -> Locale - Get current localeuse_change_locale()Hook to get a callback for changing locale at runtime.
Returns: Callback<Locale> - A callback that accepts a Locale and changes the current locale
Usage:
let change_locale = use_change_locale();
change_locale.emit(Locale::SpanishES);
LocaleEnum representing supported locales.
Variants:
Locale::EnglishUS - English (United States) - "en-US"Locale::SpanishES - Spanish (Spain) - "es-ES"Methods:
.as_ref() -> &str - Get locale code (e.g., "en-US", "es-ES") via AsRef<str> traitLocale::detect_from_browser() -> Locale - Detect from browser settings (with fallback logic)The library automatically detects the browser's language preference on initialization:
// Detects browser language
let locale = Locale::detect_from_browser();
// Override detection
<I18nProvider base_path="/static/language" initial_locale={Some(Locale::EnglishUS)}>
// ...
</I18nProvider>
Unlike other i18n solutions that embed translations at compile-time using include_str!, this library fetches JSON files dynamically using the browser's fetch API. This means:
This crate follows strict linting rules:
#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
If you're migrating from static include_str! translations:
// contexts/language.rs
static ENGLISH_TRANSLATIONS: &str = include_str!("../../../static_resources/language/en.json");
static SPANISH_TRANSLATIONS: &str = include_str!("../../../static_resources/language/es.json");
impl Default for TranslationData {
fn default() -> Self {
// ... manual browser detection and loading
}
}
use yew_i18n::{I18nProvider, use_translation};
// In app.rs
html! {
<I18nProvider base_path="/static/language">
<YourApp />
</I18nProvider>
}
// In components
let i18n = use_translation();
html! { <h1>{ i18n.t("key") }</h1> }