Thanks to visit codestin.com
Credit goes to lib.rs

88 releases

0.3.1 Dec 29, 2025
0.2.21 Dec 12, 2025
0.2.20 Nov 13, 2025
0.2.16 Jun 28, 2025
0.0.21 Mar 23, 2024

#38 in Internationalization (i18n)

Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App

2,060 downloads per month

MIT license

125KB
2.5K SLoC

leptos-fluent

Crates.io License Tests Book docs.rs Crates.io downloads Discord channel

Internationalization framework for Leptos using fluent-templates.

Installation

Add the following to your Cargo.toml file:

[dependencies]
leptos-fluent = "0.3"
axum = { version = "0.8", optional = true }

[features]
ssr = [
  "leptos-fluent/ssr",
  "leptos-fluent/axum",  # actix and axum are supported
  "dep:axum",
]

If you're using cargo-leptos to build your project, watch the locales/ folder with:

[package.metadata.leptos]
watch-additional-files = ["locales"]  # Relative to Cargo.toml

Usage

Giving the following directory structure:

.
├── 📄 Cargo.toml
├── 📁 locales
│   ├── 📁 en
│   │   └── 📄 main.ftl
│   └── 📁 es
│       └── 📄 main.ftl
└── 📁 src
    ├── 📄 main.rs
    └── 📄 lib.rs
# locales/en/main.ftl
hello-world = Hello, world!
hello-args = Hello, { $arg1 } and { $arg2 }!
# locales/es/main.ftl
hello-world = ¡Hola, mundo!
hello-args = ¡Hola, { $arg1 } y { $arg2 }!

You can use leptos-fluent as follows:

use leptos::prelude::*;
use leptos_fluent::{I18n, leptos_fluent, move_tr, tr};

#[component]
fn I18nProvider(children: Children) -> impl IntoView {
    // See all options in the reference at
    // https://mondeja.github.io/leptos-fluent/latest/leptos_fluent.html
    leptos_fluent! {
        children: children(),
        // Path to the locales directory, relative to Cargo.toml.
        locales: "./locales",
        // Initial language when the user don't load any with
        // the provided configuration.
        default_language: "en",
        // Check translations correctness in the specified files.
        #[cfg(all(debug_assertions, not(feature = "ssr")))]
        check_translations: true,

        // Client side options
        // -------------------
        // Synchronize `<html lang="...">` attribute with
        // current active language.
        sync_html_tag_lang: true,
        // Synchronize `<html dir="...">` attribute with `"ltr"`,
        // `"rtl"` or `"auto"` depending on active language.
        sync_html_tag_dir: true,
        // Update language on URL parameter when changes.
        set_language_to_url_param: true,
        // Set initial language of user from URL in local storage.
        initial_language_from_url_param_to_local_storage: true,
        // Set initial language of user from URL in a cookie.
        initial_language_from_url_param_to_cookie: true,
        // Key used to get and set the current language of the
        // user on local storage. By default is `"lang"`.
        local_storage_key: "language",
        // Get initial language from local storage if not found
        // in an URL param.
        initial_language_from_local_storage: true,
        // Set the initial language of the user from
        // local storage to a cookie.
        initial_language_from_local_storage_to_cookie: true,
        // Update language on local storage when changes.
        set_language_to_local_storage: true,
        // Get initial language from `navigator.languages`
        // if not found in local storage.
        initial_language_from_navigator: true,
        // Set initial language of user from navigator to local storage.
        initial_language_from_navigator_to_local_storage: true,
        // Set initial language of user from navigator to a cookie.
        initial_language_from_navigator_to_cookie: true,
        // Attributes to set for language cookie.
        // By default `""`.
        cookie_attrs: "Secure; Path=/; Max-Age=600",
        // Update language on cookie when the language changes.
        set_language_to_cookie: true,
        // Set initial language from a cookie to local storage.
        initial_language_from_cookie_to_local_storage: true,

        // Server side options
        // -------------------
        // Set initial language from the `Accept-Language`
        // header of the request.
        initial_language_from_accept_language_header: true,

        // Server and client side options
        // ------------------------------
        // Name of the cookie to get and set the current active
        // language. By default `"lf-lang"`.
        cookie_name: "lang",
        // Set initial language from cookie.
        initial_language_from_cookie: true,
        // URL parameter to use setting the language in the URL.
        // By default `"lang"`.
        url_param: "lang",
        // Set initial language of the user from an URL parameter.
        initial_language_from_url_param: true,

        // Desktop applications (feature `system`)
        // ---------------------------------------
        // Set initial language from the system locale.
        initial_language_from_system: true,
        // Set initial language of the user from
        // the system locale to a data file.
        initial_language_from_system_to_data_file: true,
        // Get initial language from a data file.
        initial_language_from_data_file: true,
        // Key to use to name the data file. Should be unique per
        // application. By default `"leptos-fluent"`.
        data_file_key: "my-app",
        // Set the language selected to a data file.
        set_language_to_data_file: true,
    }
}

#[component]
pub fn App() -> impl IntoView {
    view! {
        <I18nProvider>
            <TranslatableComponent/>
            <LanguageSelector/>
        </I18nProvider>
    }
}

#[component]
fn TranslatableComponent() -> impl IntoView {
    // Use `tr!` and `move_tr!` macros to translate strings:
    view! {
        <p>
            <span>{move || tr!("hello-world")}</span>
            <span>{move_tr!("hello-args", {
                "arg1" => "foo",
                "arg2" => "bar",
            })}</span>
        </p>
    }

    // The `tr!` macro must be inside a reactive context or the
    // translation will not be updated on the fly when the language changes.
}

#[component]
fn LanguageSelector() -> impl IntoView {
    // `expect_context::<leptos_fluent::I18n>()` to get the i18n context
    // `i18n.languages` exposes a static array with the available languages
    // `i18n.language.get()` to get the active language
    // `i18n.language.set(lang)` to set the active language

    let i18n = expect_context::<I18n>();

    view! {
        <fieldset>
            {
                move || i18n.languages.iter().map(|lang| {
                    view! {
                        <div>
                            <input
                                type="radio"
                                id=lang
                                name="language"
                                value=lang
                                checked=&i18n.language.get() == lang
                                on:click=move |_| i18n.language.set(lang)
                            />
                            <label for=lang>{lang.name}</label>
                        </div>
                    }
                }).collect::<Vec<_>>()
            }
        </fieldset>
    }
}

Features

  • Server Side Rendering: ssr
  • Actix Web integration: actix
  • Axum integration: axum
  • Nightly toolchain: nightly
  • Desktop applications: system
  • JSON languages file: json
  • YAML languages file: yaml
  • JSON5 languages file: json5
  • Tracing support: tracing
  • Debugging: debug

Resources

Dependencies

~25–44MB
~660K SLoC