Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

I18n RS

Edit Component

Y i18nrs Yew Usage

i18nrs’ Yew integration targets Yew 0.22.0 and later.

Adding i18nrs to your Yew project is simple:

  1. Make sure your project is set up with Yew. Follow their Getting Started Guide for setup instructions.

  2. Add the i18nrs library to your dependencies by including it in your Cargo.toml file:

    cargo add i18nrs --features=yew
    
  3. Import the I18nProvider component into your Yew application and wrap it around your app’s main component to provide translations.

🛠️ Usage

There exists two ways to integrate i18n-rs into your Yew application:

A. Function Based

Follow these steps to integrate i18nrs into your Yew application:

Step 1: Import the Required Components

Import the I18nProvider and any related types into your Yew project:

use yew::prelude::*;
use i18nrs::yew::I18nProvider;
use i18nrs::yew::I18nProviderConfig;
use std::collections::HashMap;

Step 2: Define Translations

Define your translations in a HashMap where keys are language codes (e.g., en, fr), and values are the translation strings in JSON format:

use yew::prelude::*;
use std::collections::HashMap;

#[function_component(App)]
pub fn app() -> Html {
    let translations = HashMap::from([
        ("en", r#"{"greeting": "Hello", "farewell": "Goodbye"}"#),
        ("fr", r#"{"greeting": "Bonjour", "farewell": "Au revoir"}"#),
    ]);
    html! {
    }
}

Step 3: Wrap Your App with the I18nProvider

Wrap your main app component inside the I18nProvider to give it access to the internationalization context:

use yew::prelude::*;
use i18nrs::yew::I18nProvider;
use i18nrs::yew::I18nProviderConfig;
use std::collections::HashMap;

#[function_component(App)]
pub fn app() -> Html {
    let translations = HashMap::from([
        ("en", r#"{"greeting": "Hello", "farewell": "Goodbye"}"#),
        ("fr", r#"{"greeting": "Bonjour", "farewell": "Au revoir"}"#),
    ]);

    let config = I18nProviderConfig {
        translations: translations,
        default_language: "en".to_string(),
        ..Default::default()
    };

    html! {
        <I18nProvider ..config>
            <MainApp />
        </I18nProvider>
    }
}

#[function_component(MainApp)]
pub fn main_app() -> Html {
    html! {
        <h1>{ "Welcome to i18nrs Example!" }</h1>
    }
}

fn main() {
    // yew::Renderer::<App>::new().render();
}

Step 4: Access Translations with the use_translation Hook

Use the use_translation hook to access translation functions within your components:

use yew::prelude::*;
use i18nrs::yew::use_translation;

#[function_component(MainApp)]
pub fn main_app() -> Html {
    let (i18n, set_language) = use_translation();

    let greeting = i18n.t("greeting"); // Retrieves translation for key "greeting"

    html! {
        <div>
            <h1>{ greeting }</h1>
            <button onclick={Callback::from(move |_| set_language.emit("fr".to_string()))}>
                { "Switch to French" }
            </button>
        </div>
    }
}

fn main() {
    // yew::Renderer::<MainApp>::new().render();
}

B. Component Based

See the complete example in struct_components.rs. Follow these steps to integrate i18nrs into your Yew component-based application:

Step 1: Define main struct-component

Use a struct-component for the entry-point of the application. Configure some languages via I18nProviderConfig and use a I18nProvider:

use i18nrs::yew::use_translation;
use i18nrs::yew::I18nProvider;
use i18nrs::yew::I18nProviderConfig;
use std::collections::HashMap;
use web_sys::wasm_bindgen::JsCast;
use web_sys::HtmlInputElement;
use yew::prelude::*;

pub struct StructComponents {}

pub struct StructComponentsMsg {}
#[derive(Properties, PartialEq, Default)]
pub struct StructComponentsProps {}

impl Component for StructComponents {
    type Message = StructComponentsMsg;
    type Properties = StructComponentsProps;

    fn create(_ctx: &Context<Self>) -> Self {
        Self {}
    }

    fn view(&self, _ctx: &Context<Self>) -> Html {
        let translations = HashMap::from([
            ("en", r#"{"greeting": "Hello", "farewell": "Goodbye"}"#),
            ("fr", r#"{"greeting": "Bonjour", "farewell": "Au revoir"}"#),
        ]);

        let config = I18nProviderConfig {
            translations,
            default_language: "en".to_string(),
            ..Default::default()
        };

        html! {
            <I18nProvider ..config>
                <FMainStructComponents />
            </I18nProvider>
        }
    }
}

fn main() {
    yew::Renderer::<StructComponents>::new().render();
}

Step 2: Define a wrapper function-component

Define a function-component to wrap your final struct-component. This is needed because you cannot call use_translation from a struct-component directly:

#[function_component(FMainStructComponents)]
pub fn f_main_struct_components() -> Html {
    let (i18n, set_language) = use_translation();
    html! {<MainStructComponents i18n={i18n} set_language={set_language} />}
}

Step 3: Define the final struct-component

Define the final struct-component. Use MainProps to propagate the i18n and set_language properties from the function-component to the struct-component:

pub struct MainStructComponents {}

pub struct MainMsg {}
#[derive(Properties, PartialEq)]
pub struct MainProps {
    i18n: i18nrs::I18n,
    set_language: Callback<String>,
}

impl Component for MainStructComponents {
    type Message = MainMsg;
    type Properties = MainProps;

    fn create(_ctx: &Context<Self>) -> Self {
        Self {}
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let greeting = ctx.props().i18n.t("greeting"); // Retrieves translation for key "greeting"
        let language = (&ctx.props().set_language).clone();
        let callback = Callback::from(move |e: MouseEvent| {
            let id = JsCast::unchecked_into::<HtmlInputElement>(e.target().unwrap()).id();
            language.emit(id.to_string())
        });

        html! {
            <div>
                <h1>{ greeting }</h1>
                <button id={"fr"} onclick={&callback}>
                    { "Switch to French" }
                </button>
                <button id={"en"} onclick={&callback}>
                    { "Switch to English" }
                </button>
            </div>
        }
    }
}

The following is a complete example based on the previous steps:

use i18nrs::yew::use_translation;
use i18nrs::yew::I18nProvider;
use i18nrs::yew::I18nProviderConfig;
use std::collections::HashMap;
use web_sys::wasm_bindgen::JsCast;
use web_sys::HtmlInputElement;
use yew::prelude::*;

pub struct StructComponents {}

pub struct StructComponentsMsg {}
#[derive(Properties, PartialEq, Default)]
pub struct StructComponentsProps {}
pub struct MainStructComponents {}

pub struct MainMsg {}
#[derive(Properties, PartialEq)]
pub struct MainProps {
    i18n: i18nrs::I18n,
    set_language: Callback<String>,
}

impl Component for MainStructComponents {
    type Message = MainMsg;
    type Properties = MainProps;

    fn create(_ctx: &Context<Self>) -> Self {
        Self {}
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let greeting = ctx.props().i18n.t("greeting"); // Retrieves translation for key "greeting"
        let language = (&ctx.props().set_language).clone();
        let callback = Callback::from(move |e: MouseEvent| {
            let id = JsCast::unchecked_into::<HtmlInputElement>(e.target().unwrap()).id();
            language.emit(id.to_string())
        });

        html! {
            <div>
                <h1>{ greeting }</h1>
                <button id={"fr"} onclick={&callback}>
                    { "Switch to French" }
                </button>
                <button id={"en"} onclick={&callback}>
                    { "Switch to English" }
                </button>
            </div>
        }
    }
}

#[function_component(FMainStructComponents)]
pub fn f_main_struct_components() -> Html {
    let (i18n, set_language) = use_translation();
    html! {<MainStructComponents i18n={i18n} set_language={set_language} />}
}

impl Component for StructComponents {
    type Message = StructComponentsMsg;
    type Properties = StructComponentsProps;

    fn create(_ctx: &Context<Self>) -> Self {
        Self {}
    }

    fn view(&self, _ctx: &Context<Self>) -> Html {
        let translations = HashMap::from([
            ("en", r#"{"greeting": "Hello", "farewell": "Goodbye"}"#),
            ("fr", r#"{"greeting": "Bonjour", "farewell": "Au revoir"}"#),
        ]);

        let config = I18nProviderConfig {
            translations,
            default_language: "en".to_string(),
            ..Default::default()
        };

        html! {
            <I18nProvider ..config>
                <FMainStructComponents />
            </I18nProvider>
        }
    }
}

fn main() {
    // yew::Renderer::<StructComponents>::new().render();
}

🔧 Props

I18nProviderConfig Props

Main Props

PropertyTypeDescriptionDefault
languagesVec<&'static str>List of supported languages.["en", "fr"]
translationsHashMap<&'static str, &'static str>Mapping of language codes to translation JSON content. Defaults to an empty map.{}
childrenHtmlChild components that will have access to the i18n context.Required
storage_typeStorageTypeType of browser storage for persisting the selected language (LocalStorage or SessionStorage).LocalStorage
storage_nameStringKey name in browser storage for saving the selected language."i18nrs"
default_languageStringLanguage to fall back to if none is found in storage."en"

Behavioral Props

PropertyTypeDescriptionDefault
onchangeCallback<String>Callback triggered when the language is changed. Receives the new language code as a String.No-op
onerrorCallback<String>Callback triggered when an error occurs in the i18n process. Receives the error message.No-op

💡 Notes

  1. Translation Keys: Use dot-separated keys to organize translations hierarchically, e.g., menu.file.open. Translation files use a JSON format and can include nested keys for better organization.

    • Example:

      {
        "menu": {
          "file": {
            "open": "Open",
            "save": "Save"
          },
          "edit": "Edit"
        }
      }
      
  2. Language Switching: The set_language callback dynamically updates the language and persists it using the specified storage type.

  3. Fallback Mechanism: If a translation is not found for the current language, the default language is used.

Usage

CLI Usage

You can import I18n RS directly into your project to customize and modify it using the opensass cli:

os add i18nrs yew