#compile-time #localization #fluent #system #check #macro

macro i18n-embed-fl

Macro to perform compile time checks when using the i18n-embed crate and the fluent localization system

24 releases

new 0.9.3 Jan 6, 2025
0.9.2 Oct 21, 2024
0.9.1 Aug 8, 2024
0.8.0 Feb 1, 2024
0.2.0 Oct 17, 2020

#87 in Internationalization (i18n)

Download history 9603/week @ 2024-09-20 11061/week @ 2024-09-27 10348/week @ 2024-10-04 9788/week @ 2024-10-11 8346/week @ 2024-10-18 7088/week @ 2024-10-25 8806/week @ 2024-11-01 7853/week @ 2024-11-08 6596/week @ 2024-11-15 7106/week @ 2024-11-22 9147/week @ 2024-11-29 9158/week @ 2024-12-06 12306/week @ 2024-12-13 9449/week @ 2024-12-20 7759/week @ 2024-12-27 8566/week @ 2025-01-03

39,845 downloads per month
Used in 73 crates (21 directly)

MIT license

150KB
2.5K SLoC

i18n-embed-fl crates.io badge docs.rs badge license badge github actions badge

This crate provides a macro to perform compile time checks when using the i18n-embed crate and the fluent localization system.

See docs, and i18n-embed for more information.

Changelog

Example

Set up a minimal i18n.toml in your crate root to use with cargo-i18n (see cargo i18n for more information on the configuration file format):

# (Required) The language identifier of the language used in the
# source code for gettext system, and the primary fallback language
# (for which all strings must be present) when using the fluent
# system.
fallback_language = "en-GB"

# Use the fluent localization system.
[fluent]
# (Required) The path to the assets directory.
# The paths inside the assets directory should be structured like so:
# `assets_dir/{language}/{domain}.ftl`
assets_dir = "i18n"

Create a fluent localization file for the en-GB language in i18n/en-GB/{domain}.ftl, where domain is the rust path of your crate (_ instead of -):

hello-arg = Hello {$name}!

Simple set up of the FluentLanguageLoader, and obtaining a message formatted with an argument:

use i18n_embed::{
    fluent::{fluent_language_loader, FluentLanguageLoader},
    LanguageLoader,
};
use i18n_embed_fl::fl;
use rust_embed::RustEmbed;

#[derive(RustEmbed)]
#[folder = "i18n/"]
struct Localizations;

let loader: FluentLanguageLoader = fluent_language_loader!();
loader
    .load_languages(&Localizations, &[loader.fallback_language().clone()])
    .unwrap();

assert_eq!(
    "Hello \u{2068}Bob 23\u{2069}!",
    // Compile time check for message id, and the `name` argument,
    // to ensure it matches what is specified in the `fallback_language`'s
    // fluent resource file.
    fl!(loader, "hello-arg", name = format!("Bob {}", 23))
)

Convenience Macro

You will notice that this macro requires loader to be specified in every call. For you project you may have access to a statically defined loader, and you can create a convenience macro wrapper so this doesn't need to be imported and specified every time.

macro_rules! fl {
    ($message_id:literal) => {{
        i18n_embed_fl::fl!($crate::YOUR_STATIC_LOADER, $message_id)
    }};

    ($message_id:literal, $($args:expr),*) => {{
        i18n_embed_fl::fl!($crate::YOUR_STATIC_LOADER, $message_id, $($args), *)
    }};
}

This can now be invoked like so: fl!("message-id"), fl!("message-id", args) and fl!("message-id", arg = "value").

Dependencies

~5–12MB
~125K SLoC