1 use fluent_syntax::ast;
3 /// [`FluentAttribute`] is a component of a compound [`FluentMessage`].
5 /// It represents a key-value pair providing a translation of a component
6 /// of a user interface widget localized by the given message.
11 /// use fluent_bundle::{FluentResource, FluentBundle};
15 /// confirm-modal = Are you sure?
18 /// .tooltip = Closing the window will lose all unsaved data.
22 /// let resource = FluentResource::try_new(source.to_string())
23 /// .expect("Failed to parse the resource.");
25 /// let mut bundle = FluentBundle::default();
26 /// bundle.add_resource(resource)
27 /// .expect("Failed to add a resource.");
29 /// let msg = bundle.get_message("confirm-modal")
30 /// .expect("Failed to retrieve a message.");
32 /// let mut err = vec![];
34 /// let attributes = msg.attributes().map(|attr| {
35 /// bundle.format_pattern(attr.value(), None, &mut err)
36 /// }).collect::<Vec<_>>();
38 /// assert_eq!(attributes[0], "Yes");
39 /// assert_eq!(attributes[1], "No");
40 /// assert_eq!(attributes[2], "Closing the window will lose all unsaved data.");
42 #[derive(Debug, PartialEq)]
43 pub struct FluentAttribute<'m> {
44 node: &'m ast::Attribute<&'m str>,
47 impl<'m> FluentAttribute<'m> {
48 /// Retrieves an id of an attribute.
53 /// # use fluent_bundle::{FluentResource, FluentBundle};
54 /// # let source = r#"
58 /// # let resource = FluentResource::try_new(source.to_string())
59 /// # .expect("Failed to parse the resource.");
60 /// # let mut bundle = FluentBundle::default();
61 /// # bundle.add_resource(resource)
62 /// # .expect("Failed to add a resource.");
63 /// let msg = bundle.get_message("confirm-modal")
64 /// .expect("Failed to retrieve a message.");
66 /// let attr1 = msg.attributes().next()
67 /// .expect("Failed to retrieve an attribute.");
69 /// assert_eq!(attr1.id(), "confirm");
71 pub fn id(&self) -> &'m str {
75 /// Retrieves an value of an attribute.
80 /// # use fluent_bundle::{FluentResource, FluentBundle};
81 /// # let source = r#"
85 /// # let resource = FluentResource::try_new(source.to_string())
86 /// # .expect("Failed to parse the resource.");
87 /// # let mut bundle = FluentBundle::default();
88 /// # bundle.add_resource(resource)
89 /// # .expect("Failed to add a resource.");
90 /// let msg = bundle.get_message("confirm-modal")
91 /// .expect("Failed to retrieve a message.");
93 /// let attr1 = msg.attributes().next()
94 /// .expect("Failed to retrieve an attribute.");
96 /// let mut err = vec![];
98 /// let value = attr1.value();
100 /// bundle.format_pattern(value, None, &mut err),
104 pub fn value(&self) -> &'m ast::Pattern<&'m str> {
109 impl<'m> From<&'m ast::Attribute<&'m str>> for FluentAttribute<'m> {
110 fn from(attr: &'m ast::Attribute<&'m str>) -> Self {
111 FluentAttribute { node: attr }
115 /// [`FluentMessage`] is a basic translation unit of the Fluent system.
117 /// The instance of a message is returned from the
118 /// [`FluentBundle::get_message`](crate::bundle::FluentBundle::get_message)
119 /// method, for the lifetime of the [`FluentBundle`](crate::bundle::FluentBundle) instance.
124 /// use fluent_bundle::{FluentResource, FluentBundle};
128 /// hello-world = Hello World!
132 /// let resource = FluentResource::try_new(source.to_string())
133 /// .expect("Failed to parse the resource.");
135 /// let mut bundle = FluentBundle::default();
136 /// bundle.add_resource(resource)
137 /// .expect("Failed to add a resource.");
139 /// let msg = bundle.get_message("hello-world")
140 /// .expect("Failed to retrieve a message.");
142 /// assert!(msg.value().is_some());
145 /// That value can be then passed to
146 /// [`FluentBundle::format_pattern`](crate::bundle::FluentBundle::format_pattern) to be formatted
147 /// within the context of a given [`FluentBundle`](crate::bundle::FluentBundle) instance.
149 /// # Compound Message
151 /// A message may contain a `value`, but it can also contain a list of [`FluentAttribute`] elements.
153 /// If a message contains attributes, it is called a "compound" message.
155 /// In such case, the message contains a list of key-value attributes that represent
156 /// different translation values associated with a single translation unit.
158 /// This is useful for scenarios where a [`FluentMessage`] is associated with a
159 /// complex User Interface widget which has multiple attributes that need to be translated.
161 /// confirm-modal = Are you sure?
164 /// .tooltip = Closing the window will lose all unsaved data.
166 #[derive(Debug, PartialEq)]
167 pub struct FluentMessage<'m> {
168 node: &'m ast::Message<&'m str>,
171 impl<'m> FluentMessage<'m> {
172 /// Retrieves an option of a [`ast::Pattern`](fluent_syntax::ast::Pattern).
177 /// # use fluent_bundle::{FluentResource, FluentBundle};
178 /// # let source = r#"
179 /// # hello-world = Hello World!
181 /// # let resource = FluentResource::try_new(source.to_string())
182 /// # .expect("Failed to parse the resource.");
183 /// # let mut bundle = FluentBundle::default();
184 /// # bundle.add_resource(resource)
185 /// # .expect("Failed to add a resource.");
186 /// let msg = bundle.get_message("hello-world")
187 /// .expect("Failed to retrieve a message.");
189 /// if let Some(value) = msg.value() {
190 /// let mut err = vec![];
192 /// bundle.format_pattern(value, None, &mut err),
195 /// # assert_eq!(err.len(), 0);
198 pub fn value(&self) -> Option<&'m ast::Pattern<&'m str>> {
199 self.node.value.as_ref()
202 /// An iterator over [`FluentAttribute`] elements.
207 /// # use fluent_bundle::{FluentResource, FluentBundle};
208 /// # let source = r#"
210 /// # .label = This is a label
213 /// # let resource = FluentResource::try_new(source.to_string())
214 /// # .expect("Failed to parse the resource.");
215 /// # let mut bundle = FluentBundle::default();
216 /// # bundle.add_resource(resource)
217 /// # .expect("Failed to add a resource.");
218 /// let msg = bundle.get_message("hello-world")
219 /// .expect("Failed to retrieve a message.");
221 /// let mut err = vec![];
223 /// for attr in msg.attributes() {
224 /// let _ = bundle.format_pattern(attr.value(), None, &mut err);
226 /// # assert_eq!(err.len(), 0);
228 pub fn attributes(&self) -> impl Iterator<Item = FluentAttribute<'m>> {
229 self.node.attributes.iter().map(Into::into)
232 /// Retrieve a single [`FluentAttribute`] element.
237 /// # use fluent_bundle::{FluentResource, FluentBundle};
238 /// # let source = r#"
240 /// # .label = This is a label
243 /// # let resource = FluentResource::try_new(source.to_string())
244 /// # .expect("Failed to parse the resource.");
245 /// # let mut bundle = FluentBundle::default();
246 /// # bundle.add_resource(resource)
247 /// # .expect("Failed to add a resource.");
248 /// let msg = bundle.get_message("hello-world")
249 /// .expect("Failed to retrieve a message.");
251 /// let mut err = vec![];
253 /// if let Some(attr) = msg.get_attribute("label") {
255 /// bundle.format_pattern(attr.value(), None, &mut err),
256 /// "This is a label"
259 /// # assert_eq!(err.len(), 0);
261 pub fn get_attribute(&self, key: &str) -> Option<FluentAttribute<'m>> {
265 .find(|attr| attr.id.name == key)
270 impl<'m> From<&'m ast::Message<&'m str>> for FluentMessage<'m> {
271 fn from(msg: &'m ast::Message<&'m str>) -> Self {
272 FluentMessage { node: msg }