Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Getting started

This tutorial creates a Rust binary that generates a fallback Fluent resource and prints a typed localized message. Run the commands from a Cargo package with both src/lib.rs and src/main.rs; the CLI discovers localizable types through library targets.

Install dependencies

Add the facade, embedded manager, locale identifier, and build helper:

[dependencies]
es-fluent = "0.18"
es-fluent-manager-embedded = "0.18"
unic-langid = "0.9"

[build-dependencies]
es-fluent-build = "0.18"

Install the Cargo subcommand:

cargo install es-fluent-cli --locked

Configure locale assets

Create i18n.toml next to Cargo.toml:

fallback_language = "en"
assets_dir = "assets/locales"

Create the fallback locale directory:

mkdir -p assets/locales/en

Create Cargo’s default custom-build target to track locale changes and write the strict fallback-message catalog:

// build.rs
fn main() {
    es_fluent_build::track_i18n_assets();
}

See Configure a project for the package-local missing-message policy, feature-gated derives, namespace allowlists, additional domains, and validation settings.

Define the runtime module

Create a library-reachable manager module:

// src/i18n.rs
pub use es_fluent_manager_embedded::{
    EmbeddedI18n as I18n, EmbeddedInitError, LocalizationError,
};

es_fluent_manager_embedded::define_i18n_module!();

Define a typed message in the library target:

// src/lib.rs
pub mod i18n;

use es_fluent::EsFluent;

#[derive(EsFluent)]
pub struct Greeting<'a> {
    pub name: &'a str,
}

Generate fallback FTL

Verify the setup, then generate:

cargo es-fluent doctor
cargo es-fluent generate

For a package named my-crate, generation creates assets/locales/en/my-crate.ftl with an entry like:

## Greeting

greeting = Greeting { $name }

Replace the generated value with fallback-language copy:

## Greeting

greeting = Hello, { $name }!

Conservative generation preserves edited values on later runs.

Localize the message

A package named my-crate is imported as my_crate from its binary target:

// src/main.rs
use my_crate::{Greeting, i18n::I18n};
use unic_langid::langid;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let i18n = I18n::try_new_with_language(langid!("en"))?;
    println!("{}", i18n.localize_message(&Greeting { name: "Ada" }));
    Ok(())
}

Run the program:

cargo run

It prints:

Hello, Ada!

Continue the workflow

After adding or changing localizable types, use:

cargo es-fluent generate
cargo es-fluent status --all-locales

Add a translated locale with:

cargo es-fluent add-locale fr-FR

Then edit the seeded FTL and run cargo es-fluent check --all-locales. See CLI reference for command behavior and Runtime managers for Dioxus and Bevy setup.