### Complete Fluent ResourceManager Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-resmgr.md A full example demonstrating the lifecycle of using ResourceManager: creating it, loading a bundle with fallback, adding built-in functions, getting and formatting a message, and handling errors. ```rust use fluent_resmgr::ResourceManager; use fluent_bundle::FluentArgs; use unic_langid::langid; // 1. Create resource manager with path scheme let mgr = ResourceManager::new("./translations/{locale}/{res_id}".to_string()); // 2. Load a bundle for a specific locale with fallback let mut bundle = mgr.get_bundle( vec![langid!("en-US"), langid!("en")], vec!["app.ftl".to_string()], )?; // 3. Add custom functions if needed bundle.add_builtins()?; // 4. Get a message and format it let msg = bundle.get_message("greeting") .expect("Message not found"); let mut args = FluentArgs::new(); args.set("name", "Alice"); let mut errors = vec![]; let pattern = msg.value().expect("No value"); let formatted = bundle.format_pattern(&pattern, Some(&args), &mut errors); println!("Result: {}", formatted); // 5. Report any formatting errors for error in errors { eprintln!("Formatting error: {}", error); } ``` -------------------------------- ### Simple Command Line Application Example Source: https://github.com/projectfluent/fluent-rs/blob/main/fluent-bundle/examples/README.md Demonstrates a basic command-line application with localization handled by Fluent. This is a good starting point for understanding Fluent integration. ```Rust use fluent_bundle::{FluentBundle, FluentResource}; use unic_langtag::LanguageTag; fn main() { // Create a FluentBundle for English. let mut bundle = FluentBundle::new(&[LanguageTag::parse("en-US").unwrap()]); // Load a simple message. let msg_text = "hello-world = Hello, {{ name }}!"; let res = FluentResource::try_new(msg_text.to_string()).expect("Failed to parse message."); bundle.add_resource(res); // Get the message and format it. let msg = bundle.get_message("hello-world").expect("Message not found."); let mut args = std::collections::HashMap::new(); args.insert("name", "World".into()); let formatted = bundle.format_message(msg, Some(&args)); println!("{}", formatted); } ``` -------------------------------- ### Localization::with_env Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-fallback.md Example of creating a Localization instance using ResourceManager. Demonstrates how to specify resources, sync mode, locales, and the generator. ```rust use fluent_fallback::Localization; use fluent_fallback::types::{ResourceType, ToResourceId}; use fluent_resmgr::ResourceManager; use unic_langid::langid; let res_mgr = ResourceManager::new("./translations/{locale}/".to_string()); let loc = Localization::with_env( vec![ "app.ftl".into(), "errors.ftl".to_resource_id(ResourceType::Optional), ], true, // synchronous vec![langid!("en-US"), langid!("en")], res_mgr, ); ``` -------------------------------- ### Rust Integration Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-fallback.md Sets up ResourceManager and Localization to load resources from a specified directory and format messages. Handles synchronous loading and error reporting. ```rust use fluent_fallback::{Localization, types::{ResourceType, ToResourceId}}; use fluent_resmgr::ResourceManager; use unic_langid::langid; // Create resource manager pointing to locale directory structure let res_mgr = ResourceManager::new("./translations/{locale}/".to_string()); // Create localization with required and optional resources let loc = Localization::with_env( vec![ "app.ftl".into(), "errors.ftl".into(), "help.ftl".to_resource_id(ResourceType::Optional), ], true, // synchronous vec![langid!("en-US"), langid!("en")], res_mgr, ); // Format messages let bundles = loc.bundles(); let mut errors = vec![]; let message = bundles.format_value_sync("greeting", None, &mut errors) .expect("Failed to retrieve bundles"); if let Some(text) = message { println!("Greeting: {}", text); } else { println!("Message not found"); for error in &errors { eprintln!("Error: {:?}", error); } } ``` -------------------------------- ### Localization::on_change Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-fallback.md Example of calling the on_change method on a Localization instance after updating locales in the LocalesProvider. ```rust // After updating locales in the LocalesProvider loc.on_change(); ``` -------------------------------- ### Complete Example: Multiple Formatters with IntlLangMemoizer Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Illustrates the usage of IntlLangMemoizer with multiple custom memoizable formatters (NumberFormatter and DateFormatter) and demonstrates caching behavior. This example requires implementing the Memoizable trait for custom types. ```rust use intl_memoizer::{IntlLangMemoizer, Memoizable}; use unic_langid::LanguageIdentifier; // Formatter 1: Number formatter struct NumberFormatter { locale: LanguageIdentifier, digits: u8, } impl Memoizable for NumberFormatter { type Args = u8; type Error = String; fn construct(lang: LanguageIdentifier, digits: Self::Args) -> Result { Ok(NumberFormatter { locale: lang, digits }) } } // Formatter 2: Date formatter struct DateFormatter { locale: LanguageIdentifier, style: String, } impl Memoizable for DateFormatter { type Args = String; type Error = String; fn construct(lang: LanguageIdentifier, style: Self::Args) -> Result { Ok(DateFormatter { locale: lang, style }) } } fn main() -> Result<(), String> { let memoizer = IntlLangMemoizer::new("en-US".parse()?); // Use number formatter let num_result = memoizer.with_try_get::(2, |fmt| { format!("Number formatted with {} digits", fmt.digits) })?; // Use date formatter let date_result = memoizer.with_try_get::( "short".to_string(), |fmt| { format!("Date formatted as {}", fmt.style) }, )?; println!("{}", num_result); println!("{}", date_result); // Reusing same formatters (from cache) let num_result2 = memoizer.with_try_get::(2, |fmt| { format!("Reused: {} digits", fmt.digits) })?; println!("{}", num_result2); Ok(()) } ``` -------------------------------- ### Localization::bundles Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-fallback.md Example of accessing the Bundles struct from a Localization instance. ```rust let bundles = loc.bundles(); ``` -------------------------------- ### Basic Fluent Bundle Setup and Usage in Rust Source: https://github.com/projectfluent/fluent-rs/blob/main/fluent/README.md Demonstrates how to initialize a FluentBundle, add FTL resources, and format messages with variables. This is the primary way to use the fluent-rs library for localization. ```rust use fluent::{FluentBundle, FluentResource}; use unic_langid::langid; fn main() { let ftl_string = "hello-world = Hello, world!".to_owned(); let res = FluentResource::try_new(ftl_string) .expect("Failed to parse an FTL string."); let langid_en = langid!("en-US"); let mut bundle = FluentBundle::new(vec![langid_en]); bundle.add_resource(&res) .expect("Failed to add FTL resources to the bundle."); let msg = bundle.get_message("hello-world") .expect("Message doesn't exist."); let mut errors = vec![]; let pattern = msg.value .expect("Message has no value."); let value = bundle.format_pattern(&pattern, None, &mut errors); assert_eq!(&value, "Hello, world!"); } ``` -------------------------------- ### Example Usage of IntlLangMemoizer::new Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Demonstrates how to create a new IntlLangMemoizer for a specific locale like 'en-US'. Ensure the LanguageIdentifier is parsed correctly. ```rust use intl_memoizer::IntlLangMemoizer; use unic_langid::LanguageIdentifier; let lang: LanguageIdentifier = "en-US".parse().expect("Failed to parse."); let memoizer = IntlLangMemoizer::new(lang); ``` -------------------------------- ### FTL Syntax Example Source: https://github.com/projectfluent/fluent-rs/blob/main/fluent/README.md An example of the FTL (Fluent Translation List) syntax, showcasing how to define a simple message with a variable. This syntax is used in .ftl files. ```fluent hello-user = Hello, { $username }! ``` -------------------------------- ### ResourceManager Path Scheme Examples Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/configuration.md Demonstrates different template string formats for ResourceManager's path_scheme, including simple, nested, and variant structures with .ftl extensions. ```rust // Simple structure ResourceManager::new("./translations/{locale}/{res_id}") // Result: ./translations/en-US/app.ftl ``` ```rust // Nested structure ResourceManager::new("./i18n/lang-{locale}/{res_id}") // Result: ./i18n/lang-en-US/app.ftl ``` ```rust // Variant with .ftl extension ResourceManager::new("./res/{locale}/{res_id}.ftl") // Result: ./res/en-US/app.ftl ``` -------------------------------- ### Basic Pseudolocalization with Fluent Bundle Source: https://github.com/projectfluent/fluent-rs/blob/main/fluent-pseudo/README.md Demonstrates how to use the `fluent-pseudo` crate to apply pseudolocalization to a Fluent bundle. This example shows setting up a bundle, defining a transformation function, and formatting a message with pseudolocalization applied. ```rust use fluent_bundle::{FluentBundle, FluentResource}; use unic_langid::langid; use fluent_pseudo::transform; fn transform_wrapper(s: &str) -> Cow { // Not flipped and elongated pseudolocalization. transform(s, false, true, false) } fn main() { let ftl_string = "hello-world = Hello, world!".to_owned(); let res = FluentResource::try_new(ftl_string) .expect("Could not parse an FTL string."); let langid_en = langid!("en"); let mut bundle = FluentBundle::new(vec![langid_en]); // Set pseudolocalization bundle.set_transform(Some(transform_wrapper)); bundle.add_resource(&res) .expect("Failed to add FTL resources to the bundle."); let msg = bundle.get_message("hello-world") .expect("Failed to retrieve a message."); let val = msg.value.expect("Message has no value."); let mut errors = vec![]; let value = bundle.format_pattern(val, None, &mut errors); assert_eq!(&value, "Ħḗḗŀŀǿǿ Ẇǿǿřŀḓ!"); } ``` -------------------------------- ### FTL Syntax Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/configuration.md Demonstrates the basic syntax for Fluent Translation List (FTL) files, including message identifiers, multi-line values, terms, attributes, and comments. ```ftl # Block comment ## Resource comment hello = Hello, world! -user = Alice greeting = Welcome, { -user }! .tooltip = Friendly greeting message-count = { $count -> [one] You have one message *[other] You have { $count } messages } ``` -------------------------------- ### Example Usage of IntlLangMemoizer::with_try_get Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Shows how to use with_try_get to obtain a Formatter. The first call constructs the formatter, while subsequent calls with the same arguments reuse the existing instance. ```rust use intl_memoizer::{IntlLangMemoizer, Memoizable}; use unic_langid::LanguageIdentifier; struct Formatter { locale: LanguageIdentifier, prefix: String, } impl Memoizable for Formatter { type Args = String; type Error = (); fn construct(lang: LanguageIdentifier, prefix: Self::Args) -> Result { Ok(Formatter { locale: lang, prefix, }) } } let memoizer = IntlLangMemoizer::new("en-US".parse().unwrap()); // First call: constructs the formatter let result1 = memoizer.with_try_get::( "prefix:".to_string(), |formatter| { format!("{} formatted", formatter.prefix) } )?; // Second call with same args: reuses the formatter let result2 = memoizer.with_try_get::( "prefix:".to_string(), |formatter| { format!("{} formatted again", formatter.prefix) } )?; ``` -------------------------------- ### Create New FluentBundle Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-bundle.md Initializes a new `FluentBundle` instance with a specified list of locales for fallback resolution. This is the starting point for managing translations. ```rust pub fn new(locales: Vec) -> Self> ``` ```rust use fluent_bundle::FluentBundle; use unic_langid::langid; let langid_en = langid!("en-US"); let bundle = FluentBundle::new(vec![langid_en]); ``` -------------------------------- ### Example Implementation of Memoizable Trait Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md This example shows how to implement the `Memoizable` trait for a `DateFormatter`. It defines `Args` as `String` and `Error` as `String`, and provides a `construct` method that validates the format style. ```rust use intl_memoizer::Memoizable; use unic_langid::LanguageIdentifier; #[derive(Debug, Clone)] struct DateFormatter { locale: LanguageIdentifier, format_style: String, } impl Memoizable for DateFormatter { // No args needed for this simple example type Args = String; type Error = String; fn construct(lang: LanguageIdentifier, format_style: Self::Args) -> Result { if format_style.is_empty() { Err("Format style cannot be empty".to_string()) } else { Ok(DateFormatter { locale: lang, format_style, }) } } } ``` -------------------------------- ### FluentError::ResolverError Example Triggers Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/errors.md Shows examples of errors that can occur during message pattern resolution and formatting. ```rust // Missing variable referenced in pattern bundle.format_pattern(&pattern, None, &mut errors); // → ResolverError for missing $variableName // Type mismatch in function bundle.add_function("MYLEN", |args, _| match args { [FluentValue::String(s)] => s.len().into(), _ => FluentValue::Error, // Returns Error variant }); // Invalid plural expression ``` -------------------------------- ### LocalesProvider Static Implementation Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-fallback.md Provides a static implementation of the LocalesProvider trait using a vector of language identifiers. ```rust use fluent_fallback::env::LocalesProvider; use unic_langid::LanguageIdentifier; struct StaticLocales(Vec); impl LocalesProvider for StaticLocales { type Iter = std::vec::IntoIter; fn locales(&self) -> Self::Iter { self.0.clone().into_iter() } } ``` -------------------------------- ### Integrating Pseudolocalization with Fluent Bundles Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-pseudo.md Shows how to enable and use pseudolocalization within a Fluent bundle. This example demonstrates setting a transformation function on the bundle, which is conditionally applied based on an environment variable. ```rust use fluent::FluentBundle; use fluent_bundle::FluentResource; use fluent_pseudo; use unic_langid::langid; fn main() -> Result<(), Box> { let ftl = r#" app-title = Localization Testing message = Hello, { $name }! button = Click me "#; let resource = FluentResource::try_new(ftl.to_string())?; let mut bundle = FluentBundle::new(vec![langid!("en-US")]); bundle.add_resource(resource)?; // Enable pseudolocalization for testing let enable_pseudo = std::env::var("PSEUDO").is_ok(); if enable_pseudo { // Use the dom variant to preserve any HTML in messages bundle.set_transform(Some(|s| { fluent_pseudo::transform_dom(s, false, true, true) })); } // Format messages normally - they're transformed if enabled let msg = bundle.get_message("message")?; let pattern = msg.value()?; let mut args = fluent::fluent_args!["name" => "World"]; let mut errors = vec![]; let result = bundle.format_pattern(&pattern, Some(&args), &mut errors); println!("{}", result); // Without PSEUDO: Hello, World! // With PSEUDO: [Ħeeŀŀo, Ẇoořŀḓ!] Ok(()) } ``` -------------------------------- ### Example FTL with Missing Value Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/errors.md Illustrates an FTL resource where a message exists but has no value pattern, leading to a MissingValue error. ```ftl button = .label = OK .tooltip = Click to confirm ``` -------------------------------- ### IntlMemoizer::with_try_get Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Gets or constructs a formatter for a given locale, then passes it to a callback function for processing. ```APIDOC ## IntlMemoizer::with_try_get ### Description Gets or constructs a formatter for the specified locale and passes it to a callback. ### Parameters #### Path Parameters - **lang** (`LanguageIdentifier`) - Required - Locale for the formatter - **args** (`I::Args`) - Required - Formatter constructor arguments - **callback** (`U`) - Required - Function using the formatter ### Returns `Ok(R)` with callback result, or `Err(I::Error)` on failure ### Example ```rust let result = memoizer.with_try_get::( langid!("en-US"), "config".to_string(), |formatter| format!("Result: {}", formatter.prefix), )?; ``` ``` -------------------------------- ### Use High-Level Localization API Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/NAVIGATION.md Demonstrates using the ResourceManager and Localization types for a higher-level API to manage translations. Suitable for application-wide localization setup. ```rust let mgr = ResourceManager::new("./translations/{locale}/{res_id}"); let loc = Localization::with_env( vec!["app.ftl".into()], true, vec![langid!("en-US")], mgr, ); let bundles = loc.bundles(); let mut errors = vec![]; let msg = bundles.format_value_sync("greeting", None, &mut errors)?; ``` -------------------------------- ### Create a new empty FluentArgs instance Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-args.md Use `FluentArgs::new()` to create an empty argument map. This is the simplest way to start collecting arguments. ```rust use fluent_bundle::FluentArgs; let mut args = FluentArgs::new(); ``` -------------------------------- ### IntlLangMemoizer::with_try_get Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Gets or constructs a memoized formatter, then passes it to a callback function for processing. It handles both retrieval of existing formatters and construction of new ones. ```APIDOC ## IntlLangMemoizer::with_try_get ### Description Gets or constructs a memoized formatter, then passes it to a callback. This method efficiently manages formatter instances, reusing them when possible. ### Method `with_try_get` ### Parameters #### Path Parameters - **args** (`I::Args`) - Required - Arguments for the formatter constructor - **callback** (`U`) - Required - Function that uses the formatter and returns a result ### Returns - `Result` - `Ok(R)` with callback result, or `Err(I::Error)` on construction failure ### Behavior 1. Checks if a formatter of type `I` with the given args is already memoized 2. If found, reuses it 3. If not found, constructs a new instance via `I::construct()` 4. Passes the formatter to the callback 5. Returns the callback's result ### Example ```rust use intl_memoizer::{IntlLangMemoizer, Memoizable}; use unic_langid::LanguageIdentifier; struct Formatter { locale: LanguageIdentifier, prefix: String, } impl Memoizable for Formatter { type Args = String; type Error = (); fn construct(lang: LanguageIdentifier, prefix: Self::Args) -> Result { Ok(Formatter { locale: lang, prefix, }) } } let memoizer = IntlLangMemoizer::new("en-US".parse().unwrap()); // First call: constructs the formatter let result1 = memoizer.with_try_get::( "prefix:".to_string(), |formatter| { format!("{} formatted", formatter.prefix) } )?; // Second call with same args: reuses the formatter let result2 = memoizer.with_try_get::( "prefix:".to_string(), |formatter| { format!("{} formatted again", formatter.prefix) } )?; ``` ``` -------------------------------- ### Get or construct a formatter with error handling Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Safely retrieves or constructs a formatter for a specified locale, passing it to a callback function. Handles potential errors during formatter construction. Use this when formatter creation might fail. ```rust let result = memoizer.with_try_get::( langid!("en-US"), "config".to_string(), |formatter| format!("Result: {}", formatter.prefix), )?; ``` -------------------------------- ### Get FluentAttribute ID Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-bundle.md Retrieves the identifier (key) of a FluentAttribute. Use this to get the name of the attribute. ```rust pub fn id(&self) -> &'m str ``` ```rust let attr = msg.attributes().next().expect("Failed to retrieve an attribute."); println!("ID: {}", attr.id()); ``` -------------------------------- ### Basic Resource Manager Usage Source: https://github.com/projectfluent/fluent-rs/blob/main/fluent-resmgr/README.md Demonstrates how to initialize a ResourceManager, retrieve a locale bundle, and format a message. Ensure the resource path is correctly configured. ```rust use fluent_resmgr::resource_manager::ResourceManager; fn main() { let mgr = ResourceManager::new("./examples/resources/{locale}/{res_id}".into()); let bundle = mgr.get_bundle(locales, resources); let value = bundle.format_value("hello-world", None); assert_eq!(&value, "Hello, world!"); } ``` -------------------------------- ### Initialize Localization Context Source: https://github.com/projectfluent/fluent-rs/blob/main/fluent-fallback/README.md Demonstrates how to create a new Localization instance with a list of resource identifiers and a closure to generate FluentBundle instances. This is useful for setting up the initial localization context for an application. ```rust use fluent_fallback::Localization; fn main() { // generate_messages is a closure that returns an iterator over FluentBundle // instances. let loc = Localization::new(vec!["simple.ftl".into()], generate_messages); let value = bundle.format_value("hello-world", None); assert_eq!(&value, "Hello, world!"); } ``` -------------------------------- ### Bump Version of Fluent-rs Packages Source: https://github.com/projectfluent/fluent-rs/blob/main/docs/local-testing-firefox.md Use cargo-release to bump the patch version of all fluent-rs packages. Ensure cargo-release is installed via 'cargo install cargo-release'. ```bash cargo release version patch -p fluent -p fluent-bundle -p fluent-fallback -p fluent-pseudo -p fluent-syntax -p fluent-testing -p intl-memoizer --execute ``` -------------------------------- ### Creating Concurrent Bundles with FluentBundle Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Demonstrates how to create a FluentBundle using a concurrent IntlLangMemoizer for multi-threaded environments. Ensure you import the necessary types. ```rust use fluent_bundle::FluentBundle; use fluent_bundle::concurrent::IntlLangMemoizer as ConcurrentMemoizer; use unic_ucd::language::LanguageIdentifier; // Create a concurrent memoizer let memoizer = ConcurrentMemoizer::new(langid!("en-US")); // Create a bundle with concurrent memoizer let bundle: FluentBundle<_, ConcurrentMemoizer> = FluentBundle::new_concurrent(vec![langid!("en-US")]); ``` -------------------------------- ### Get an argument value from FluentArgs Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-args.md Use the `get` method to retrieve an argument's value by its key. It returns an `Option<&FluentValue>`, which is `Some` if the key exists and `None` otherwise. ```rust if let Some(value) = args.get("user") { println!("User: {:?}", value); } ``` -------------------------------- ### Basic File Path Resolution Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-resmgr.md Demonstrates the basic string replacement for {locale} and {res_id} in a file path. ```text path_scheme: "./translations/{locale}/{res_id}" locale: "en-US" res_id: "app.ftl" result: "./translations/en-US/app.ftl" ``` -------------------------------- ### Handling MissingMessage Error Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/errors.md Example of how to trigger and catch a MissingMessage error when a message ID is not found. ```rust let bundles = loc.bundles(); let mut errors = vec![]; bundles.format_value_sync("nonexistent-message", None, &mut errors)?; // → errors contains LocalizationError::MissingMessage ``` -------------------------------- ### Parse, Create, and Format a Message Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/README.md Demonstrates the basic workflow of parsing an FTL string, creating a bundle, adding the resource, and formatting a message with arguments. Handles potential errors during parsing and formatting. ```rust use fluent_bundle::{FluentBundle, FluentResource}; use fluent_locale::langid; // Assume locales and args are defined elsewhere let locales = vec![langid!("en-US")]; let args = fluent_bundle::FluentArgs::new(); let ftl_string = "id = Hello, world!"; // 1. Parse let resource = FluentResource::try_new(ftl_string.to_string())?; // 2. Create bundle let mut bundle = FluentBundle::new(locales); bundle.add_resource(resource)?; // 3. Get and format message let msg = bundle.get_message("id")?; let pattern = msg.value()?; let mut errors = vec![]; let result = bundle.format_pattern(&pattern, Some(&args), &mut errors); println!("{:?}", result); ``` -------------------------------- ### FluentError::ParserError Example Triggers Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/errors.md Illustrates syntax errors that trigger ParserError during FTL parsing. ```rust // Invalid identifier (starts with number) FluentResource::try_new("123msg = Value".to_string()); // Unmatched braces FluentResource::try_new("msg = { incomplete".to_string()); // Invalid syntax FluentResource::try_new("msg = { $var.invalid }".to_string()); ``` -------------------------------- ### Basic Fluent Bundle Usage in Rust Source: https://github.com/projectfluent/fluent-rs/blob/main/fluent-bundle/README.md Demonstrates the core functionality of loading an FTL string, creating a bundle for a specific locale, adding the resource, retrieving a message, and formatting its value. Ensure the unic-langid crate is available for locale creation. ```rust use fluent_bundle::{FluentBundle, FluentResource}; use unic_langid::langid; fn main() { let ftl_string = "hello-world = Hello, world!".to_owned(); let res = FluentResource::try_new(ftl_string) .expect("Could not parse an FTL string."); let langid_en = langid!("en"); let mut bundle = FluentBundle::new(vec![langid_en]); bundle.add_resource(&res) .expect("Failed to add FTL resources to the bundle."); let msg = bundle.get_message("hello-world") .expect("Failed to retrieve a message."); let val = msg.value.expect("Message has no value."); let mut errors = vec![]; let value = bundle.format_pattern(val, None, &mut errors); assert_eq!(&value, "Hello, world!"); } ``` -------------------------------- ### Handling Resolver Error Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/errors.md Example of how a Resolver error can occur during pattern resolution when message arguments are missing. ```rust // Message references $name but we don't provide it let msg = bundle.get_message("greeting").unwrap(); let pattern = msg.value().unwrap(); let mut errors = vec![]; bundle.format_pattern(&pattern, None, &mut errors); // → errors contains ResolverError for missing $name ``` -------------------------------- ### FluentError::Overriding Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/errors.md Demonstrates triggering an Overriding error when adding a resource with a duplicate entry ID. ```rust use fluent_bundle::{FluentBundle, FluentResource}; use unic_langid::langid; let res1 = FluentResource::try_new("msg = Hello".to_string()).unwrap(); let res2 = FluentResource::try_new("msg = Hi".to_string()).unwrap(); let mut bundle = FluentBundle::new(vec![langid!("en-US")]); bundle.add_resource(&res1).ok(); bundle.add_resource(&res2); // Returns Err([FluentError::Overriding { kind: Message, id: "msg" }]) ``` -------------------------------- ### Localization Constructor with Environment Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/configuration.md Use `with_env` to initialize `Localization` with resources, I/O mode, locales, and a resource manager. Ensure all required resources are provided for bundle validity. ```rust pub fn with_env

( resources: Vec, sync: bool, locales: Vec, generator: G, ) -> Self ``` ```rust use fluent_fallback::Localization; use fluent_fallback::types::{ResourceType, ToResourceId}; use fluent_resmgr::ResourceManager; use unic_langid::langid; let res_mgr = ResourceManager::new("./translations/{locale}/{res_id}".to_string()); let loc = Localization::with_env( vec![ "app.ftl".into(), // Required "errors.ftl".into(), // Required "help.ftl".to_resource_id(ResourceType::Optional), // Optional ], true, // Synchronous I/O vec![ langid!("en-US"), langid!("en"), ], res_mgr, ); ``` -------------------------------- ### Create FluentNumber Instance Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-value.md Demonstrates creating a new FluentNumber with a default set of options. Requires importing FluentNumber and FluentNumberOptions. ```rust use fluent_bundle::types::{FluentNumber, FluentNumberOptions}; let num = FluentNumber::new(42.0, FluentNumberOptions::default()); ``` -------------------------------- ### Get original FTL source string Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-resource.md The `source` method returns a reference to the original FTL string used to create the FluentResource. ```rust let source_code = resource.source(); println!("{}", source_code); ``` -------------------------------- ### Format a Simple Message in Rust Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/README.md Demonstrates basic message formatting using FluentResource and FluentBundle. Ensure the FTL content is correctly parsed and added to the bundle. ```rust use fluent::FluentBundle; use fluent_bundle::FluentResource; use unic_langid::langid; // Create a resource from FTL let ftl = r#" greeting = Hello, { $name }! "#; let resource = FluentResource::try_new(ftl.to_string()) .expect("Failed to parse FTL"); // Create a bundle let mut bundle = FluentBundle::new(vec![langid!("en-US")]); bundle.add_resource(resource) .expect("Failed to add resource"); // Format a message with arguments let msg = bundle.get_message("greeting") .expect("Message not found"); let mut args = fluent::fluent_args![ "name" => "Alice" ]; let mut errors = vec![]; let pattern = msg.value().expect("No value"); let result = bundle.format_pattern(&pattern, Some(&args), &mut errors); println!("{}", result); // Output: Hello, Alice! ``` -------------------------------- ### Get FluentAttribute Value Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-bundle.md Retrieves the pattern representing the value of a FluentAttribute. This is useful for formatting or inspecting the content associated with an attribute key. ```rust pub fn value(&self) -> &'m ast::Pattern<&'m str> ``` ```rust let value = attr.value(); let formatted = bundle.format_pattern(value, None, &mut errors); ``` -------------------------------- ### Localization::with_env Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-fallback.md Creates a Localization instance with a static list of locales and resources. ```APIDOC ## Localization::with_env ### Description Creates a `Localization` with a static locale list. ### Method `pub fn with_env

(resources: Vec, sync: bool, locales: Vec, generator: G) -> Self` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Description | |-----------|------|-------------| | resources | `Vec` | List of resource identifiers (FTL files) | | sync | `bool` | `true` for synchronous I/O, `false` for async | | locales | `Vec` | Static list of locales to use | | generator | `G` | Bundle generator (e.g., ResourceManager) | ### Returns New `Localization` instance ### Example ```rust use fluent_fallback::Localization; use fluent_fallback::types::{ResourceType, ToResourceId}; use fluent_resmgr::ResourceManager; use unic_langid::langid; let res_mgr = ResourceManager::new("./translations/{locale}/".to_string()); let loc = Localization::with_env( vec![ "app.ftl".into(), "errors.ftl".to_resource_id(ResourceType::Optional), ], true, // synchronous vec![langid!("en-US"), langid!("en")], res_mgr, ); ``` ``` -------------------------------- ### Get FluentMessage Value Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-bundle.md Retrieves the value pattern of a FluentMessage. Use this when you need to format or inspect the primary content of a translation message. ```rust pub fn value(&self) -> Option<&'m ast::Pattern<&'m str>> ``` ```rust if let Some(value) = msg.value() { let mut errors = vec![]; let formatted = bundle.format_pattern(value, None, &mut errors); } ``` -------------------------------- ### Most Common Fluent-rs Methods Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/NAVIGATION.md Highlights key methods for interacting with Fluent bundles, including creation, resource addition, message retrieval, and formatting. ```rust FluentBundle::new() // Create bundle bundle.add_resource() // Add translations bundle.get_message() // Get a message bundle.format_pattern() // Format with arguments bundle.add_function() // Register custom function bundle.add_builtins() // Add built-in functions ``` -------------------------------- ### Create FluentNumber with Custom Options Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-value.md Illustrates creating a FluentNumber with specific formatting options, including minimum fraction digits and currency type. Uses `Default::default()` for unspecified fields. ```rust use fluent_bundle::types::{FluentNumber, FluentNumberOptions, FluentNumberType}; let options = FluentNumberOptions { minimumFractionDigits: Some(2), maximumFractionDigits: Some(2), r#type: Some(FluentNumberType::Currency("USD".to_string())), ..Default::default() }; let num = FluentNumber::new(19.99, options); ``` -------------------------------- ### Iterate over FTL entries Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-resource.md Use the `entries` method to get an iterator over all messages and terms within the FluentResource. This allows processing each localization entry. ```rust use fluent_syntax::ast; for entry in resource.entries() { match entry { ast::Entry::Message(msg) => println!("Message: {}", msg.id.name), ast::Entry::Term(term) => println!("Term: {}", term.id.name), _ => {} } } ``` -------------------------------- ### Add Resources to Bundle Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/README.md Shows how to add FTL resources to a `FluentBundle`. Demonstrates the difference between `add_resource` (fails on duplicates) and `add_resource_overriding` (overrides duplicates). ```rust use fluent_bundle::{FluentBundle, FluentResource}; use fluent_locale::langid; let locales = vec![langid!("en-US")]; let mut bundle = FluentBundle::new(locales); let resource1 = FluentResource::try_new("key1 = Value 1")?.to_owned(); let resource2 = FluentResource::try_new("key1 = Value 2")?.to_owned(); // Resources can override or fail on duplicates bundle.add_resource(resource1)?; // Fails on duplicates bundle.add_resource_overriding(resource2); // Overrides duplicates ``` -------------------------------- ### ToResourceId Trait Example Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-fallback.md Demonstrates converting strings into ResourceId using the ToResourceId trait. Use `.into()` for required resources and `.to_resource_id()` for optional ones. ```rust use fluent_fallback::types::{ResourceType, ToResourceId}; let required_resource = "app.ftl".into(); // Becomes ResourceId::Required("app.ftl") let optional_resource = "help.ftl".to_resource_id(ResourceType::Optional); // ResourceId::Optional("help.ftl") ``` -------------------------------- ### Create FluentValue from String and &str Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-value.md Demonstrates creating FluentValue instances from string literals and String objects using the `into()` method. ```rust use fluent_bundle::FluentValue; // From &str let val: FluentValue = "hello".into(); // From String let val: FluentValue = String::from("world").into(); ``` -------------------------------- ### FluentBundle::new Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-bundle.md Creates a new `FluentBundle` with the specified locale list. This is the entry point for initializing a bundle for a specific language or set of fallback languages. ```APIDOC ## FluentBundle::new ### Description Creates a new bundle with the specified locale list. ### Method `new` ### Parameters #### Path Parameters - **locales** (`Vec`) - Required - Locale fallback chain for the bundle ### Returns A new `FluentBundle` instance. ### Example ```rust use fluent_bundle::FluentBundle; use unic_langid::langid; let langid_en = langid!("en-US"); let bundle = FluentBundle::new(vec![langid_en]); ``` ``` -------------------------------- ### Implementing FluentType for Custom DateTime Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-value.md Example of implementing the FluentType trait for a custom MyDateTime struct. This includes the necessary trait methods and usage as a FluentValue. ```rust use fluent_bundle::types::FluentType; use std::borrow::Cow; use std::fmt; #[derive(Debug, Clone, PartialEq)] struct MyDateTime { year: u16, month: u8, day: u8, } impl FluentType for MyDateTime { fn duplicate(&self) -> Box { Box::new(self.clone()) } fn as_string(&self, _intls: &intl_memoizer::IntlLangMemoizer) -> Cow<'static, str> { Cow::Owned(format!("{}-{:02}-{:02}", self.year, self.month, self.day)) } fn as_string_threadsafe( &self, _intls: &intl_memoizer::concurrent::IntlLangMemoizer, ) -> Cow<'static, str> { Cow::Owned(format!("{}-{:02}-{:02}", self.year, self.month, self.day)) } } impl PartialEq for dyn FluentType + Send { fn eq(&self, other: &Self) -> bool { // Implementation... true } } // Usage let date = MyDateTime { year: 2024, month: 6, day: 28, }; let value = FluentValue::Custom(Box::new(date)); ``` -------------------------------- ### Setting Values with FluentArgs Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-value.md Demonstrates how to use FluentArgs::set to add values of different types, which are automatically converted to FluentValue. Also shows direct assignment of a FluentValue::Error. ```rust use fluent_bundle::{FluentArgs, FluentValue}; let mut args = FluentArgs::new(); // Values are automatically converted to FluentValue args.set("count", 42); // Becomes FluentValue::Number args.set("name", "Alice"); // Becomes FluentValue::String args.set("price", 19.99); // Becomes FluentValue::Number // Direct FluentValue args.set("error", FluentValue::Error); ``` -------------------------------- ### Partial Parsing with FluentResource::try_new Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/errors.md Shows how to use try_new to parse a resource, which returns a partial resource and errors if parsing is not fully successful. ```rust use fluent_bundle::FluentResource; // try_new returns Ok on success, Err((resource, errors)) with partial resource let result = FluentResource::try_new(ftl_string); match result { Ok(resource) => { // Perfect parse } Err((resource, errors)) => { // Resource available despite errors eprintln!("Warnings during parse:"); for error in &errors { eprintln!(" {}", error); } // Can still use partial resource let entries_count = resource.entries().count(); println!("Partial resource has {} entries", entries_count); } } ``` -------------------------------- ### Enable Pseudo-Localization Transform Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/README.md Demonstrates how to enable pseudo-localization for testing purposes by setting a transformation function on the `FluentBundle`. This transforms all output text to aid in visual testing. ```rust use fluent_bundle::{FluentBundle, FluentResource}; use fluent_locale::langid; // Assume fluent_pseudo is a dependency // use fluent_pseudo; // Mocking fluent_pseudo::transform for demonstration fn mock_transform(text: &str) -> String { format!("[pseudo:{}] ", text) } let locales = vec![langid!("en-US")]; let mut bundle = FluentBundle::new(locales); let resource = FluentResource::try_new("hello = Hello")?; bundle.add_resource(resource)?; // Set the pseudo-localization transform bundle.set_transform(Some(mock_transform)); let msg = bundle.get_message("hello")?; let pattern = msg.value()?; let mut errors = vec![]; let result = bundle.format_pattern(&pattern, None, &mut errors); assert_eq!(result, Ok("[pseudo:Hello]".to_string())); ``` -------------------------------- ### Get or create a per-locale memoizer Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Retrieves an existing IntlLangMemoizer for a given locale or creates a new one if it doesn't exist. This is useful for accessing locale-specific formatting logic. ```rust use unic_langid::langid; let lang_memoizer = memoizer.get_for_lang(langid!("en-US")); ``` -------------------------------- ### Configure IntlLangMemoizer for Specialized Formatting Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/configuration.md Demonstrates creating and using an IntlLangMemoizer for specialized formatting tasks. Formatters are lazily constructed upon their first use. ```rust use intl_memoizer::IntlLangMemoizer; use unic_langid::langid; let memoizer = IntlLangMemoizer::new(langid!("en-US")); // Formatters are lazily constructed on first use let result = memoizer.with_try_get::( my_args, |formatter| formatter.format(value) )?; ``` -------------------------------- ### Get Independent FluentBundles for Each Locale Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-resmgr.md Create an iterator that yields independent FluentBundles for each specified locale. Each bundle contains messages only from its own locale, and the locale list does not form a fallback chain. ```rust use fluent_resmgr::ResourceManager; use unic_langid::langid; let mgr = ResourceManager::new("./translations/{locale}/{res_id}".to_string()); // Get independent bundles for each locale let bundles = mgr.get_bundles( vec![langid!("en-US"), langid!("fr"), langid!("de")], vec!["app.ftl".to_string(), "errors.ftl".to_string()], ); for result in bundles { match result { Ok(bundle) => { let locale = &bundle.locales[0]; println!("Loaded bundle for {}", locale); } Err(errors) => { eprintln!("Failed to load bundle: {:?}", errors); } } } ``` -------------------------------- ### IntlLangMemoizer::new Method Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Creates a new IntlLangMemoizer instance for a given locale. This is the entry point for using the memoizer. ```rust pub fn new(lang: LanguageIdentifier) -> Self> ``` -------------------------------- ### Create FluentArgs using the fluent! macro Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-args.md The `fluent!` macro from the `fluent` crate provides a concise syntax for creating `FluentArgs` instances, equivalent to manual construction. ```rust use fluent::fluent_args; let args = fluent_args![ "name" => "John", "emailCount" => 5, ]; ``` -------------------------------- ### Get FluentBundle with Fallback Chain Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-resmgr.md Obtain a single FluentBundle for multiple locales, establishing a fallback chain. Messages are loaded from the first locale, while subsequent locales are used for formatters. ```rust use fluent_resmgr::ResourceManager; use unic_langid::langid; let mgr = ResourceManager::new("./translations/{locale}/{res_id}".to_string()); // Get bundle with fallback: en-US -> en -> (formatters only) let bundle = mgr.get_bundle( vec![langid!("en-US"), langid!("en")], vec!["app.ftl".to_string(), "errors.ftl".to_string()], )?; ``` -------------------------------- ### Update Local Dependency Path in Cargo.toml Source: https://github.com/projectfluent/fluent-rs/blob/main/docs/local-testing-firefox.md Modify the Cargo.toml file in the Firefox codebase to point to your local fluent-rs packages using the 'path' attribute. This example shows updating fluent-fallback. ```toml fluent-fallback = { path = "../../../../../fluent-rs/fluent-fallback" } ``` -------------------------------- ### Create a new IntlMemoizer Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/intl-memoizer.md Instantiates a new IntlMemoizer. This is the entry point for managing locale-specific formatters. ```rust use intl_memoizer::IntlMemoizer; let memoizer = IntlMemoizer::new(); ``` -------------------------------- ### Vendor Rust Dependencies in Firefox Source: https://github.com/projectfluent/fluent-rs/blob/main/docs/local-testing-firefox.md Run the './mach vendor rust' command from the root of the mozilla-unified directory to fetch and vendor the Rust dependencies. ```bash ./mach vendor rust ``` -------------------------------- ### Multiple Placeholder Replacements Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-resmgr.md Shows how multiple instances of {locale} are replaced in a file path. ```text "./lang/{locale}/lib/{locale}/{res_id}" // Becomes: "./lang/en-US/lib/en-US/app.ftl" ``` -------------------------------- ### Parse FTL and Inspect AST Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/api-reference/fluent-syntax.md Demonstrates how to parse Fluent (FTL) strings and traverse the resulting Abstract Syntax Tree (AST) to inspect messages, terms, and comments. ```rust use fluent_syntax::{parser, ast}; let ftl = r#"# # Main application greeting greeting = Hello, { $name }! .tooltip = Greets the user with their name # Plural example messages-count = { $count -> [one] You have one message *[other] You have { $count } messages } #"#; let resource = parser::parse(ftl) .expect("Failed to parse FTL"); for entry in &resource.body { match entry { ast::Entry::Message(msg) => { println!("Message: {}", msg.id.name); if let Some(value) = &msg.value { println!(" Value pattern has {} elements", value.elements.len()); } for attr in &msg.attributes { println!(" Attribute: {}", attr.id.name); } } ast::Entry::Term(term) => { println!("Term: {}", term.id.name); } ast::Entry::Comment(comment) => { println!("Comment: {}", comment.content); } } } ``` -------------------------------- ### Rust: Handling Parser Errors with FluentResource Source: https://github.com/projectfluent/fluent-rs/blob/main/_autodocs/errors.md Demonstrates how to catch and process parsing errors when creating a FluentResource. The resource is still available for partial AST access even if errors occur. ```rust use fluent_bundle::FluentResource; let ftl = "this is not valid ftl!!!"; match FluentResource::try_new(ftl.to_string()) { Ok(resource) => println!("Parsed successfully"), Err((resource, errors)) => { // Resource is still available with partial AST eprintln!("Parse errors:"); for error in errors { eprintln!(" Line {}: {}", error.line, error.message); } } } ```