Summary
Make a proc-macro crate ply-locales that provides compile-checked, type-safe Project Fluent localization with full IDE autocomplete for Rust applications and Ply Engine.
Motivation
Localization is essential for applications, but existing solutions either rely on runtime string lookups without autocomplete (i18n-embed) or require verbose struct and enum derives (es-fluent). We need compile-checked Fluent messages that generate typed functions directly in user modules with rust-analyzer autocomplete, doc hover previews, and zero runtime boilerplate.
Proposed API
#[ply_locales("locales")]
mod t;
// Optional
#[ply_locales("locales", default = "nl-NL")]
mod strings;
fn render(ui: &mut Ui) {
ui.text(&t::welcome_user("Alice", 3), |c| c.font_size(18));
ui.text(&t::save_button(), |c| c.font_size(14));
}
t::set_locale("es-ES");
let current = t::current_locale();
let available = t::available_locales();
Behavior
- Supports both locale directories (
locales/en-US/*.ftl) and single locale files (locales/en-US.ftl).
- The
default attribute argument is optional and defaults to "en-US" when omitted.
- Parses Fluent files at compile time using
fluent-syntax to extract message keys, variable references, and message text.
- Generates typed functions inside the decorated module with names converted to snake_case.
- Function arguments are inferred from variable references in each message and accept
impl Into<FluentValue>.
- All generated message functions return
String.
- Generated functions include doc comments containing the raw message definition from the default locale for IDE hover previews.
- Emits
include_str! for all discovered .ftl files so Cargo and rust-analyzer re-evaluate the macro when translations change.
- Includes an internal
build.rs that detects nightly proc_macro::tracked_path support via autocfg so the whole directory can be tracked, falling back to file tracking on stable.
- Runtime bundles are parsed lazily on first access and cached in an internal
RwLock<BTreeMap>.
- Variable mismatches between other locales for the same message key cause readable compile errors.
- Missing message keys in non-default locales trigger compile warnings and fall back to the default locale bundle at runtime.
- Additional message keys in non-default locales trigger compile warnings and can't be used.
ply_locales (and its runtime fluent dependency) can be added to the dependencies and prelude by enabling the l10n feature.
- Usage doesn't rely on
ply-engine and ply-locales can be installed into any rust project separately.
Summary
Make a proc-macro crate
ply-localesthat provides compile-checked, type-safe Project Fluent localization with full IDE autocomplete for Rust applications and Ply Engine.Motivation
Localization is essential for applications, but existing solutions either rely on runtime string lookups without autocomplete (
i18n-embed) or require verbose struct and enum derives (es-fluent). We need compile-checked Fluent messages that generate typed functions directly in user modules with rust-analyzer autocomplete, doc hover previews, and zero runtime boilerplate.Proposed API
Behavior
locales/en-US/*.ftl) and single locale files (locales/en-US.ftl).defaultattribute argument is optional and defaults to"en-US"when omitted.fluent-syntaxto extract message keys, variable references, and message text.impl Into<FluentValue>.String.include_str!for all discovered.ftlfiles so Cargo and rust-analyzer re-evaluate the macro when translations change.build.rsthat detects nightlyproc_macro::tracked_pathsupport viaautocfgso the whole directory can be tracked, falling back to file tracking on stable.RwLock<BTreeMap>.ply_locales(and its runtime fluent dependency) can be added to the dependencies andpreludeby enabling thel10nfeature.ply-engineandply-localescan be installed into any rust project separately.