Bevy manager
Use es-fluent-manager-bevy to connect typed messages to Bevy ECS,
assets, and reactive UI text.
Add the manager
[dependencies]
bevy = "0.19"
es-fluent = "0.18"
es-fluent-manager-bevy = "0.19"
unic-langid = "0.9"
Register package resources from a library-reachable module:
// src/i18n.rs
es_fluent_manager_bevy::define_i18n_module!();
Install the plugin
use bevy::prelude::*;
use es_fluent_manager_bevy::I18nPlugin;
use unic_langid::langid;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(I18nPlugin::with_language(langid!("en")))
.run();
}
Generated manager modules contribute their configured resources. Link every owner library in a multi-crate application; the host does not copy dependency FTL.
Fallback-locale message values are compile-time checked through
es-fluent-build. Set missing_message_policy = "fallback-str" in the owning
package’s i18n.toml when BevyI18n and FluentText<T> should render
snake_case source names after locale fallback is exhausted.
Localize UI text
Derive BevyFluentText for component types that should refresh when
the locale changes, then wrap values in FluentText<T>:
use bevy::prelude::*;
use es_fluent::EsFluent;
use es_fluent_manager_bevy::{BevyFluentText, FluentText};
#[derive(BevyFluentText, Clone, Component, EsFluent)]
enum UiMessage {
StartGame,
Settings,
}
fn spawn_menu(mut commands: Commands) {
commands.spawn((
FluentText::new(UiMessage::StartGame),
Text::new(""),
));
}
Only a type used directly as FluentText<T> needs registration.
Nested message fields are formatted when the parent value refreshes.
If a named struct field or named enum variant field depends on the requested
locale, mark it with #[locale]. Its type must implement
TryFrom<&LanguageIdentifier>. The derive generates locale refresh
behavior and registration.
For an external type that cannot derive BevyFluentText, register it
manually with register_fluent_text::<T>().
Localize in systems
Request BevyI18n as a system parameter:
use es_fluent_manager_bevy::BevyI18n;
fn update_title(i18n: BevyI18n) {
let title = i18n.localize_message(&UiMessage::Settings);
// Apply the title to application state.
let _ = title;
}
Use RequestedLanguageId for the latest user request and
ActiveLanguageId for the published locale. Failed asset reloads or
locale switches keep the last accepted locale active.
Order application systems
The plugin labels localization phases with I18nSet. Use Bevy’s
.before(...) and .after(...) APIs when an application
system must run around locale synchronization or text refresh:
use bevy::prelude::*;
use es_fluent_manager_bevy::I18nSet;
fn persist_locale() {}
fn update_window_title() {}
app.add_systems(Update, persist_locale.after(I18nSet::LocaleSync));
app.add_systems(PostUpdate, update_window_title.after(I18nSet::TextUpdate));