Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Namespaces and file splitting

Namespaces route selected types into separate .ftl files instead of the default {crate}.ftl resource. EsFluent, EsFluentLabel, and EsFluentVariants support the same namespace modes.

Use exactly one namespace source for each generated output. When multiple derives are combined on one type, either inherit a shared namespace from #[fluent(namespace = ...)] or set one on the specific #[fluent_label(...)] / #[fluent_variants(...)] output, but do not combine those namespace sources.

Output layout

DeclarationFile path
No namespaceassets_dir/{locale}/{crate}.ftl
With namespaceassets_dir/{locale}/{crate}/{namespace}.ftl

When namespaces are enabled through the manager macros, the configured namespace files are the canonical per-locale resources. {crate}.ftl remains an optional mixed-mode resource for non-namespaced messages when it exists.

Namespace modes

Explicit string

namespace = "name" sets an explicit string namespace. Literal namespaces must be safe locale-relative paths: no empty segments, ./.., backslashes, absolute paths, surrounding whitespace, or .ftl suffix.

use es_fluent::EsFluent;

#[derive(EsFluent)]
#[fluent(namespace = "ui")]
pub struct Button<'a>(pub &'a str);

This writes the key to assets_dir/{locale}/{crate}/ui.ftl.

File stem

namespace = file uses the source file’s stem as the namespace.

use es_fluent::EsFluent;

// In src/components/dialog.rs
#[derive(EsFluent)]
#[fluent(namespace = file)]
pub struct Dialog {
    pub title: String,
}

A type in src/components/dialog.rs maps to namespace dialog.

File relative

namespace = file_relative uses the file path relative to the crate root, strips src/, and removes the extension.

use es_fluent::EsFluent;

// In src/ui/button.rs
#[derive(EsFluent)]
#[fluent(namespace = file_relative)]
pub enum Gender {
    Male,
    Female,
    Other(String),
}

A type in src/ui/button.rs maps to namespace ui/button.

Folder

namespace = folder uses the source file’s parent folder.

use es_fluent::EsFluentLabel;

// In src/user/profile.rs
#[derive(EsFluentLabel)]
#[fluent(namespace = folder)]
pub enum FolderStatus {
    Active,
    Inactive,
}

A type in src/user/profile.rs maps to namespace user.

Folder relative

namespace = folder_relative uses the parent folder path relative to the crate root, stripping src/ when nested and keeping src for root module files.

use es_fluent::EsFluentLabel;

// In src/screens/user/profile.rs
#[derive(EsFluentLabel)]
#[fluent(namespace = folder_relative)]
pub struct FolderUserProfile;

A type in src/screens/user/profile.rs maps to namespace screens/user. With namespace = folder, the same file would map only to user.

Quick reference

SyntaxExample source fileResulting namespace
namespace = "name"anyname
namespace = filesrc/ui/button.rsbutton
namespace = file_relativesrc/ui/button.rsui/button
namespace = foldersrc/screens/ui/button.rsui
namespace = folder_relativesrc/screens/ui/button.rsscreens/ui

Validation

Literal string namespaces are validated at compile time as safe relative namespace paths. If namespaces = [...] is set in your i18n.toml, both the compiler and the CLI validate that explicit string-based namespaces used by your code match the provided allowlist. File-based and folder-based namespaces bypass allowlist validation because they’re derived automatically from the source tree.