#localization #fluent #generate-static

fluent-static-codegen

Automatically generate Rust functions from Fluent message files for streamlined localization in Rust applications

12 releases (4 breaking)

0.5.0 Aug 19, 2024
0.4.1 Aug 16, 2024
0.3.2 Aug 8, 2024
0.2.4 Jun 6, 2024
0.1.0 May 24, 2024

#187 in Internationalization (i18n)

Download history 356/week @ 2024-05-23 177/week @ 2024-05-30 261/week @ 2024-06-06 9/week @ 2024-06-13 255/week @ 2024-08-01 391/week @ 2024-08-08 320/week @ 2024-08-15 55/week @ 2024-08-22 20/week @ 2024-08-29

878 downloads per month

MIT license

66KB
1.5K SLoC

fluent-static-codegen

Part of fluent-static library responsible for generating Rust code from Fluent resources.

The project is heavily relying on fluent-rs for parsing and processing Fluent resources.

Usage

Fluent resources

The code generator requires that Fluent resources adhere to the naming convention: <l10n_root>/<language_id>/<bundle_name>.

Cargo dependencies

Add fluent-static-codegen to project's build-dependencies section

[build-dependencies]
fluent-static-codegen = "*"

Build script

The fluent-static-codegen requires Cargo Build Script to operate.


use fluent_static_codegen::{generate, FunctionPerMessageCodeGenerator};
use std::{env, fs, path::Path};

pub fn main() {
    generate!("./l10n/", FunctionPerMessageCodeGenerator::new("en-US"), "l10n");
}
  

Code generation

Generated code naming conventions

  • Fluent message names converted to Rust snake_cased identifiers
    • my-message -> my_message
    • msgTest -> msg_test
    • msg1 -> msg_1
  • Fluent message variables mapped to snake_cased indentifiers also
  • Fluent message attributes mapped to <message_name>_<attribute_name>
    • my-button.title -> my_button_title

Fluent message mapped to a function

The fluent_static_codegen::FunctionPerMessageCodeGenerator generates module per each message_bundle and maps messages to a functions

pub mod <bundle_name> {
    use fluent_static::fluent_bundle::{FluentValue, FluentError};
    use fluent_static::Message;

    pub fn <fluent_message_no_args>(language_id: impl AsRef<str>) -> Message {
    }

    pub fn <fluent_message_with_args>(language_id: impl AsRef<str>, var1: impl Into<FluentValue>>, ...) -> Result<Message, FluentError> {
    }
}

Fluent message mapped to a method

fluent_static_codegen::FunctionPerMessageCodeGenerator generates struct per each message_bundle and maps messages to the struct's public methods

pub mod <bundle_name>
    use fluent_static::fluent_bundle::{FluentValue, FluentError};
    use fluent_static::Message;

    pub struct <BundleName>Bundle {
    }

    impl <BundleName>Bundle {
        pub fn all_languages() -> &'static [&'static str] {
        }

        pub fn current_language(&self) -> &LanguageSpec {
        }

        pub fn <fluent_message_no_args>(&self) -> Message {
        }

        pub fn <fluent_message_some_args>(&self, name: impl Into<FluentValue>, ...) -> Result<Message, FluentError> {
        }
    }
}  

Setting FluentBundle options

    let generator = FunctionPerMessageCodeGenerator::new_with_options(
        "en",
        FluentBundleOptions {
            use_isolating: false,
            transform_fn: Some("crate::util::fluent_value_transformer".to_string()),
            format_fn: Some("crate::util::fluent_formatter".to_string()),
        },
    );
    generate!("./l10n/", generator, "l10n");

Compile-time validation

The following conditions are validated at compilation time to ensure that each message in a bundle_name is correctly defined:

  1. The message must be defined across all supported languages.
  2. All instances of the message must share the identical set of variables (if any variables exist).
  3. Message attributes must remain consistent across all languages.

A compile-time error will be raised if any of these conditions are not met, guaranteeing consistency and correctness across different language implementations.

Contributing

Contributions are welcome! Please feel free to submit pull requests, report bugs, and suggest features via the issue tracker.

License

This project is licensed under MIT license. Feel free to use, modify, and distribute it as per the license conditions.


Dependencies

~2.5MB
~50K SLoC