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.
101 mod args;
102 pub mod bundle;
103 mod concurrent;
104 mod entry;
105 mod errors;
106 #[doc(hidden)]
107 pub mod memoizer;
108 mod message;
109 #[doc(hidden)]
110 pub mod resolver;
111 mod resource;
112 pub mod types;
113 
114 pub 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).
122 pub type FluentBundle<R> = bundle::FluentBundle<R, intl_memoizer::IntlLangMemoizer>;
123 pub use errors::FluentError;
124 pub use message::{FluentAttribute, FluentMessage};
125 pub use resource::FluentResource;
126 #[doc(inline)]
127 pub use types::FluentValue;
128