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 | |