es-fluent-manager-bevy

Crates.ioes-fluent-manager-bevy
lib.rses-fluent-manager-bevy
version0.18.0
created_at2025-10-12 22:12:25.890047+00
updated_at2026-01-16 12:04:51.58317+00
descriptiones-fluent manager for Bevy
homepage
repositoryhttps://github.com/stayhydated/es-fluent
max_upload_size
id1879785
size189,929
stayhydated (stayhydated)

documentation

README

Docs Crates.io

es-fluent-manager-bevy

Seamless Bevy integration for es-fluent.

This plugin connects es-fluent's type-safe localization with Bevy's ECS and Asset system. It allows you to use standard #[derive(EsFluent)] types as components that automatically update when the game's language changes.

es-fluent-manager-bevy bevy
crates.io
0.18.x 0.18.x
0.17.x 0.17.x

Features

  • Asset Loading: Loads .ftl files via Bevy's AssetServer.
  • Hot Reloading: Supports hot-reloading of translations during development.
  • Reactive UI: The FluentText component automatically refreshes text when the locale changes.
  • Global Hook: Integrates with es-fluent's global state.

Quick Start

1. Setup

Add the plugin to your App and define your I18n module:

use bevy::prelude::*;
use es_fluent_manager_bevy::I18nPlugin;
use unic_langid::langid;

// a i18n.toml file must exist in the root of the crate
es_fluent_manager_bevy::define_i18n_module!();

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        // Initialize with default language
        .add_plugins(I18nPlugin::with_language(langid!("en-US")))
        .run();
}

2. Using in UI

Use the FluentText component wrapper for any type that implements ToFluentString (which #[derive(EsFluent)] provides).

use es_fluent::EsFluent;
use es_fluent_manager_bevy::FluentText;

#[derive(EsFluent, Clone, Component)]
pub enum UiMessage {
    StartGame,
    Settings,
}

fn spawn_menu(mut commands: Commands) {
    commands.spawn((
        // This text will automatically update if language changes
        FluentText::new(UiMessage::StartGame),
        Text::new(""),
    ));
}

3. Registering Components

For FluentText to work, you must register the specific inner type with the app so the plugin knows to update it:

app.register_fluent_text::<UiMessage>();

es-fluent-lang integration

If your type contains fields that use es_fluent_lang (for the Languages enum), you must implement RefreshForLocale and use register_fluent_text_from_locale instead:

use es_fluent_manager_bevy::RefreshForLocale;

#[derive(EsFluent, Clone, Component)]
pub enum UiMessage {
    LanguageHint { current_language: Languages },
}

impl RefreshForLocale for UiMessage {
    fn refresh_for_locale(&mut self, lang: &unic_langid::LanguageIdentifier) {
        match self {
            UiMessage::LanguageHint { current_language } => {
                *current_language = Languages::from(lang);
            }
        }
    }
}

// Register with:
app.register_fluent_text_from_locale::<UiMessage>();
Commit count: 444

cargo fmt