-
Hello there. I am in the process of converting my existing Nuxt.js website to yew+wasm. In Nuxt.js, I could add multiple translations using their i18n module. Yew doesn't have its own module, but there are several rust crates that do this, such as gettext-rs and fluent. The principle of both seems great, because of the simplicity I am leaning towards gettext-rs. However, there is basically 0 documentation out there (which makes it quite challenging for me as a Rust beginner), and like no examples, especially in websites. Does anyone have experience with i18n in Yew, and would like to share me some suggestions, tips, and perhaps some code? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
A cursory glance favors fluent. I don't think gettext-rs supports the wasm target. The important thing is that you can't read files! Fluent seems to allow one to define translations from other sources, and even strings, so you should get by without needing any file access. On the yew side of things, you most likely want to use contexts to pass down the choice of language/localization to your components. |
Beta Was this translation helpful? Give feedback.
-
By the way, I kinda solved this for my use case, using Context Providers: # localization.rs
use core::fmt::Display;
use stylist::yew::styled_component;
use yew::html::ImplicitClone;
use yew::prelude::*;
use std::default::Default;
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum Localization {
DE,
EN,
}
impl Default for Localization {
fn default() -> Self {
Localization::EN
}
}
impl Display for Localization {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Localization::DE => write!(f, "Deutsch"),
Localization::EN => write!(f, "English"),
}
}
}
impl ImplicitClone for Localization {}
#[derive(Debug, Clone)]
pub(crate) struct LocalizationContext {
inner: UseStateHandle<Localization>,
}
impl LocalizationContext {
pub fn new(inner: UseStateHandle<Localization>) -> Self {
Self { inner }
}
pub fn set(&self, localization: Localization) {
self.inner.set(localization);
}
pub fn get(&self) -> Localization {
(*self.inner).clone()
}
}
impl PartialEq for LocalizationContext {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
#[derive(Debug, PartialEq, Properties)]
pub(crate) struct LocalizationProviderProps {
pub children: Children,
}
#[styled_component]
pub(crate) fn LocalizationProvider(props: &LocalizationProviderProps) -> Html {
let localization = use_state(|| Localization::default());
let localization_ctx = LocalizationContext::new(localization);
html! {
<ContextProvider<LocalizationContext> context={localization_ctx}>
{props.children.clone()}
</ContextProvider<LocalizationContext>>
}
}
#[hook]
pub(crate) fn use_localization() -> LocalizationContext {
use_context::<LocalizationContext>().unwrap()
} If people like this, I might polish it and then add it to the examples. |
Beta Was this translation helpful? Give feedback.
By the way, I kinda solved this for my use case, using Context Providers: