Skip to content

Commit 23115ea

Browse files
committed
Document FluentMessage and FluentAttribute
1 parent cce506e commit 23115ea

File tree

4 files changed

+317
-143
lines changed

4 files changed

+317
-143
lines changed

fluent-bundle/src/bundle.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,102 @@ use crate::resolver::{ResolveValue, Scope, WriteValue};
2525
use crate::resource::FluentResource;
2626
use crate::types::FluentValue;
2727

28+
/// A collection of localization messages for a single locale, which are meant
29+
/// to be used together in a single view, widget or any other UI abstraction.
30+
///
31+
/// # Examples
32+
///
33+
/// ```
34+
/// use fluent_bundle::{FluentBundle, FluentResource, FluentValue, FluentArgs};
35+
/// use unic_langid::langid;
36+
///
37+
/// let ftl_string = String::from("intro = Welcome, { $name }.");
38+
/// let resource = FluentResource::try_new(ftl_string)
39+
/// .expect("Could not parse an FTL string.");
40+
///
41+
/// let langid_en = langid!("en-US");
42+
/// let mut bundle = FluentBundle::new(vec![langid_en]);
43+
///
44+
/// bundle.add_resource(&resource)
45+
/// .expect("Failed to add FTL resources to the bundle.");
46+
///
47+
/// let mut args = FluentArgs::new();
48+
/// args.set("name", FluentValue::from("Rustacean"));
49+
///
50+
/// let msg = bundle.get_message("intro").expect("Message doesn't exist.");
51+
/// let mut errors = vec![];
52+
/// let pattern = msg.value().expect("Message has no value.");
53+
/// let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
54+
/// assert_eq!(&value, "Welcome, \u{2068}Rustacean\u{2069}.");
55+
///
56+
/// ```
57+
///
58+
/// # `FluentBundle` Life Cycle
59+
///
60+
/// ## Create a bundle
61+
///
62+
/// To create a bundle, call [`FluentBundle::new`] with a locale list that represents the best
63+
/// possible fallback chain for a given locale. The simplest case is a one-locale list.
64+
///
65+
/// Fluent uses [`LanguageIdentifier`] which can be created using `langid!` macro.
66+
///
67+
/// ## Add Resources
68+
///
69+
/// Next, call [`add_resource`] one or more times, supplying translations in the FTL syntax.
70+
///
71+
/// Since [`FluentBundle`] is generic over anything that can borrow a [`FluentResource`],
72+
/// one can use [`FluentBundle`] to own its resources, store references to them,
73+
/// or even [`Rc<FluentResource>`] or [`Arc<FluentResource>`].
74+
///
75+
/// The [`FluentBundle`] instance is now ready to be used for localization.
76+
///
77+
/// ## Format
78+
///
79+
/// To format a translation, call [`get_message`] to retrieve a [`FluentMessage`],
80+
/// and then call [`format_pattern`] on the message value or attribute in order to
81+
/// retrieve the translated string.
82+
///
83+
/// The result of [`format_pattern`] is an [`Cow<str>`]. It is
84+
/// recommended to treat the result as opaque from the perspective of the program and use it only
85+
/// to display localized messages. Do not examine it or alter in any way before displaying. This
86+
/// is a general good practice as far as all internationalization operations are concerned.
87+
///
88+
/// If errors were encountered during formatting, they will be
89+
/// accumulated in the [`Vec<FluentError>`] passed as the third argument.
90+
///
91+
/// While they are not fatal, they usually indicate problems with the translation,
92+
/// and should be logged or reported in a way that allows the developer to notice
93+
/// and fix them.
94+
///
95+
///
96+
/// # Locale Fallback Chain
97+
///
98+
/// [`FluentBundle`] stores messages in a single locale, but keeps a locale fallback chain for the
99+
/// purpose of language negotiation with i18n formatters. For instance, if date and time formatting
100+
/// are not available in the first locale, [`FluentBundle`] will use its `locales` fallback chain
101+
/// to negotiate a sensible fallback for date and time formatting.
102+
///
103+
/// # Concurrency
104+
///
105+
/// As you may have noticed, `FluentBundle` is a specialization of [`FluentBundle`]
106+
/// which works with an [`IntlMemoizer`][] over `RefCell`.
107+
/// In scenarios where the memoizer must work concurrently, there's an implementation of
108+
/// `IntlMemoizer` that uses `Mutex` and there's [`concurrent::FluentBundle`] which works with that.
109+
///
110+
/// [`add_resource`]: ./bundle/struct.FluentBundle.html#method.add_resource
111+
/// [`FluentBundle::new`]: ./bundle/struct.FluentBundle.html#method.new
112+
/// [`FluentMessage`]: ./struct.FluentMessage.html
113+
/// [`FluentBundle`]: ./type.FluentBundle.html
114+
/// [`FluentResource`]: ./struct.FluentResource.html
115+
/// [`get_message`]: ./bundle/struct.FluentBundle.html#method.get_message
116+
/// [`format_pattern`]: ./bundle/struct.FluentBundle.html#method.format_pattern
117+
/// [`Cow<str>`]: http://doc.rust-lang.org/std/borrow/enum.Cow.html
118+
/// [`Rc<FluentResource>`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
119+
/// [`Arc<FluentResource>`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
120+
/// [`LanguageIdentifier`]: https://crates.io/crates/unic-langid
121+
/// [`IntlMemoizer`]: https://github.com/projectfluent/fluent-rs/tree/master/intl-memoizer
122+
/// [`Vec<FluentError>`]: ./enum.FluentError.html
123+
/// [`concurrent::FluentBundle`]: ./concurrent/type.FluentBundle.html
28124
pub struct FluentBundle<R, M> {
29125
pub locales: Vec<LanguageIdentifier>,
30126
pub(crate) resources: Vec<R>,

fluent-bundle/src/lib.rs

Lines changed: 11 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,8 @@
1010
//!
1111
//! * [`FluentMessage`] - A single translation unit
1212
//! * [`FluentResource`] - A list of [`FluentMessage`] units
13-
//! * [`FluentBundle`] - A collection of [`FluentResource`] lists
14-
//! * [`FluentArgs`] - A list of [`FluentValue`] elements used to resolve a [`FluentMessage`] value
15-
//!
16-
//! # 1) Message
17-
//!
18-
//! [`FluentMessage`] is the core unit of the system.
19-
//! It has an identifier, a value and a list of attributes.
20-
//!
21-
//! The identifier is a key that must be unique within a [`FluentResource`] to
22-
//! which the message belongs to.
23-
//!
24-
//! The shape of the message must also contain a value, attributes or both.
25-
//!
26-
//! ### Simple Message
27-
//!
28-
//! ```text
29-
//! hello-world = Hello, { $user }!
30-
//! ```
31-
//!
32-
//! ### Compound Message
33-
//!
34-
//! ```text
35-
//! confirm-modal = Are you sure?
36-
//! .confirm = Yes
37-
//! .cancel = No
38-
//! .tooltip = Closing the window will lose all unsaved data.
39-
//! ```
40-
//!
41-
//! # 2) Resource
42-
//!
43-
//! [`FluentResource`] wraps an [`Abstract Syntax Tree`](../fluent_syntax/ast/index.html) produced by the
44-
//! [`parser`](../fluent_syntax/parser/index.html) and provides an access to a list
45-
//! of its entries.
46-
//!
47-
//! A good mental model for a resource is a single FTL file, but in the future
48-
//! there's nothing preventing a resource from being stored in a data base,
49-
//! pre-parsed format or in some other structured form.
13+
//! * [`FluentBundle`](crate::bundle::FluentBundle) - A collection of [`FluentResource`] lists
14+
//! * [`FluentArgs`] - A list of elements used to resolve a [`FluentMessage`] value
5015
//!
5116
//! # 3) Bundle
5217
//!
@@ -69,7 +34,7 @@
6934
//! # 4) Arguments & Values
7035
//!
7136
//! [`FluentArgs`] is a collection, similar to a `HashMap`, which stores a key-value pair list of
72-
//! arguments provided by the developer to the [`format_pattern`](FluentBundle::format_pattern) method.
37+
//! arguments provided by the developer to the [`format_pattern`](crate::bundle::FluentBundle::format_pattern) method.
7338
//! Those arguments are used during message formatting to resolve selections, or can be
7439
//! interpolated into the message as a variable.
7540
//!
@@ -153,8 +118,8 @@
153118
//! [`FluentValue`]: ./types/enum.FluentValue.html
154119
//! [`FluentArgs`]: ./struct.FluentArgs.html
155120
mod args;
156-
mod bundle;
157-
pub mod concurrent;
121+
pub mod bundle;
122+
mod concurrent;
158123
mod entry;
159124
mod errors;
160125
pub mod memoizer;
@@ -164,105 +129,14 @@ mod resource;
164129
pub mod types;
165130

166131
pub use args::FluentArgs;
167-
use bundle::FluentBundle as FluentBundleBase;
168-
169-
/// A collection of localization messages for a single locale, which are meant
170-
/// to be used together in a single view, widget or any other UI abstraction.
171-
///
172-
/// # Examples
173-
///
174-
/// ```
175-
/// use fluent_bundle::{FluentBundle, FluentResource, FluentValue, FluentArgs};
176-
/// use unic_langid::langid;
177-
///
178-
/// let ftl_string = String::from("intro = Welcome, { $name }.");
179-
/// let resource = FluentResource::try_new(ftl_string)
180-
/// .expect("Could not parse an FTL string.");
181-
///
182-
/// let langid_en = langid!("en-US");
183-
/// let mut bundle = FluentBundle::new(vec![langid_en]);
184-
///
185-
/// bundle.add_resource(&resource)
186-
/// .expect("Failed to add FTL resources to the bundle.");
187-
///
188-
/// let mut args = FluentArgs::new();
189-
/// args.set("name", FluentValue::from("Rustacean"));
190-
///
191-
/// let msg = bundle.get_message("intro").expect("Message doesn't exist.");
192-
/// let mut errors = vec![];
193-
/// let pattern = msg.value().expect("Message has no value.");
194-
/// let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
195-
/// assert_eq!(&value, "Welcome, \u{2068}Rustacean\u{2069}.");
196-
///
197-
/// ```
198-
///
199-
/// # `FluentBundle` Life Cycle
200-
///
201-
/// ## Create a bundle
202-
///
203-
/// To create a bundle, call [`FluentBundle::new`] with a locale list that represents the best
204-
/// possible fallback chain for a given locale. The simplest case is a one-locale list.
205-
///
206-
/// Fluent uses [`LanguageIdentifier`] which can be created using `langid!` macro.
207-
///
208-
/// ## Add Resources
209-
///
210-
/// Next, call [`add_resource`] one or more times, supplying translations in the FTL syntax.
211-
///
212-
/// Since [`FluentBundle`] is generic over anything that can borrow a [`FluentResource`],
213-
/// one can use [`FluentBundle`] to own its resources, store references to them,
214-
/// or even [`Rc<FluentResource>`] or [`Arc<FluentResource>`].
215-
///
216-
/// The [`FluentBundle`] instance is now ready to be used for localization.
217-
///
218-
/// ## Format
219-
///
220-
/// To format a translation, call [`get_message`] to retrieve a [`FluentMessage`],
221-
/// and then call [`format_pattern`] on the message value or attribute in order to
222-
/// retrieve the translated string.
223-
///
224-
/// The result of [`format_pattern`] is an [`Cow<str>`]. It is
225-
/// recommended to treat the result as opaque from the perspective of the program and use it only
226-
/// to display localized messages. Do not examine it or alter in any way before displaying. This
227-
/// is a general good practice as far as all internationalization operations are concerned.
228-
///
229-
/// If errors were encountered during formatting, they will be
230-
/// accumulated in the [`Vec<FluentError>`] passed as the third argument.
231-
///
232-
/// While they are not fatal, they usually indicate problems with the translation,
233-
/// and should be logged or reported in a way that allows the developer to notice
234-
/// and fix them.
235-
///
236-
///
237-
/// # Locale Fallback Chain
238-
///
239-
/// [`FluentBundle`] stores messages in a single locale, but keeps a locale fallback chain for the
240-
/// purpose of language negotiation with i18n formatters. For instance, if date and time formatting
241-
/// are not available in the first locale, [`FluentBundle`] will use its `locales` fallback chain
242-
/// to negotiate a sensible fallback for date and time formatting.
243-
///
244-
/// # Concurrency
132+
/// Specialized [`FluentBundle`](crate::bundle::FluentBundle) over
133+
/// non-concurrent [`IntlLangMemoizer`](intl_memoizer::IntlLangMemoizer).
245134
///
246-
/// As you may have noticed, `FluentBundle` is a specialization of [`FluentBundle`]
247-
/// which works with an [`IntlMemoizer`][] over `RefCell`.
248-
/// In scenarios where the memoizer must work concurrently, there's an implementation of
249-
/// `IntlMemoizer` that uses `Mutex` and there's [`concurrent::FluentBundle`] which works with that.
135+
/// This is the basic variant of the [`FluentBundle`](crate::bundle::FluentBundle).
250136
///
251-
/// [`add_resource`]: ./bundle/struct.FluentBundle.html#method.add_resource
252-
/// [`FluentBundle::new`]: ./bundle/struct.FluentBundle.html#method.new
253-
/// [`FluentMessage`]: ./struct.FluentMessage.html
254-
/// [`FluentBundle`]: ./type.FluentBundle.html
255-
/// [`FluentResource`]: ./struct.FluentResource.html
256-
/// [`get_message`]: ./bundle/struct.FluentBundle.html#method.get_message
257-
/// [`format_pattern`]: ./bundle/struct.FluentBundle.html#method.format_pattern
258-
/// [`Cow<str>`]: http://doc.rust-lang.org/std/borrow/enum.Cow.html
259-
/// [`Rc<FluentResource>`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
260-
/// [`Arc<FluentResource>`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
261-
/// [`LanguageIdentifier`]: https://crates.io/crates/unic-langid
262-
/// [`IntlMemoizer`]: https://github.com/projectfluent/fluent-rs/tree/master/intl-memoizer
263-
/// [`Vec<FluentError>`]: ./enum.FluentError.html
264-
/// [`concurrent::FluentBundle`]: ./concurrent/type.FluentBundle.html
265-
pub type FluentBundle<R> = FluentBundleBase<R, intl_memoizer::IntlLangMemoizer>;
137+
/// The concurrent specialization, can be constructed with
138+
/// [`FluentBundle::new_concurrent`](crate::bundle::FluentBundle::new_concurrent).
139+
pub type FluentBundle<R> = bundle::FluentBundle<R, intl_memoizer::IntlLangMemoizer>;
266140
pub use errors::FluentError;
267141
pub use message::{FluentAttribute, FluentMessage};
268142
pub use resource::FluentResource;

0 commit comments

Comments
 (0)