1//! Fluent is a modern localization system designed to improve how software is translated.
2//!
3//! `fluent-bundle` is a mid-level component of the [Fluent Localization
4//! System](https://www.projectfluent.org).
5//!
6//! The crate builds on top of the low level [`fluent-syntax`](../fluent-syntax) package, and provides
7//! foundational types and structures required for executing localization at runtime.
8//!
9//! There are four core concepts to understand Fluent runtime:
10//!
11//! * [`FluentMessage`] - A single translation unit
12//! * [`FluentResource`] - A list of [`FluentMessage`] units
13//! * [`FluentBundle`](crate::bundle::FluentBundle) - A collection of [`FluentResource`] lists
14//! * [`FluentArgs`] - A list of elements used to resolve a [`FluentMessage`] value
15//!
16//! ## Example
17//!
18//! ```
19//! use fluent_bundle::{FluentBundle, FluentValue, FluentResource, FluentArgs};
20//! // Used to provide a locale for the bundle.
21//! use unic_langid::langid;
22//!
23//! // 1. Crate a FluentResource
24//!
25//! let ftl_string = r#"
26//!
27//! hello-world = Hello, world!
28//! intro = Welcome, { $name }.
29//!
30//! "#.to_string();
31//!
32//! let res = FluentResource::try_new(ftl_string)
33//! .expect("Failed to parse an FTL string.");
34//!
35//!
36//! // 2. Crate a FluentBundle
37//!
38//! let langid_en = langid!("en-US");
39//! let mut bundle = FluentBundle::new(vec![langid_en]);
40//!
41//!
42//! // 3. Add the resource to the bundle
43//!
44//! bundle
45//! .add_resource(res)
46//! .expect("Failed to add FTL resources to the bundle.");
47//!
48//!
49//! // 4. Retrieve a FluentMessage from the bundle
50//!
51//! let msg = bundle.get_message("hello-world")
52//! .expect("Message doesn't exist.");
53//!
54//!
55//! // 5. Format the value of the simple message
56//!
57//! let mut errors = vec![];
58//!
59//! let pattern = msg.value()
60//! .expect("Message has no value.");
61//!
62//! let value = bundle.format_pattern(&pattern, None, &mut errors);
63//!
64//! assert_eq!(
65//! bundle.format_pattern(&pattern, None, &mut errors),
66//! "Hello, world!"
67//! );
68//!
69//! // 6. Format the value of the message with arguments
70//!
71//! let mut args = FluentArgs::new();
72//! args.set("name", "John");
73//!
74//! let msg = bundle.get_message("intro")
75//! .expect("Message doesn't exist.");
76//!
77//! let pattern = msg.value()
78//! .expect("Message has no value.");
79//!
80//! // The FSI/PDI isolation marks ensure that the direction of
81//! // the text from the variable is not affected by the translation.
82//! assert_eq!(
83//! bundle.format_pattern(&pattern, Some(&args), &mut errors),
84//! "Welcome, \u{2068}John\u{2069}."
85//! );
86//! ```
87//!
88//! # Ergonomics & Higher Level APIs
89//!
90//! Reading the example, you may notice how verbose it feels.
91//! Many core methods are fallible, others accumulate errors, and there
92//! are intermediate structures used in operations.
93//!
94//! This is intentional as it serves as building blocks for variety of different
95//! scenarios allowing implementations to handle errors, cache and
96//! optimize results.
97//!
98//! At the moment it is expected that users will use
99//! the `fluent-bundle` crate directly, while the ecosystem
100//! matures and higher level APIs are being developed.
101mod args;
102pub mod bundle;
103mod concurrent;
104mod entry;
105mod errors;
106#[doc(hidden)]
107pub mod memoizer;
108mod message;
109#[doc(hidden)]
110pub mod resolver;
111mod resource;
112pub mod types;
113
114pub use args::FluentArgs;
115/// Specialized [`FluentBundle`](crate::bundle::FluentBundle) over
116/// non-concurrent [`IntlLangMemoizer`](intl_memoizer::IntlLangMemoizer).
117///
118/// This is the basic variant of the [`FluentBundle`](crate::bundle::FluentBundle).
119///
120/// The concurrent specialization, can be constructed with
121/// [`FluentBundle::new_concurrent`](crate::bundle::FluentBundle::new_concurrent).
122pub type FluentBundle<R> = bundle::FluentBundle<R, intl_memoizer::IntlLangMemoizer>;
123pub use errors::FluentError;
124pub use message::{FluentAttribute, FluentMessage};
125pub use resource::FluentResource;
126#[doc(inline)]
127pub use types::FluentValue;
128