| use fluent_syntax::ast; |
| |
| /// [`FluentAttribute`] is a component of a compound [`FluentMessage`]. |
| /// |
| /// It represents a key-value pair providing a translation of a component |
| /// of a user interface widget localized by the given message. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// use fluent_bundle::{FluentResource, FluentBundle}; |
| /// |
| /// let source = r#" |
| /// |
| /// confirm-modal = Are you sure? |
| /// .confirm = Yes |
| /// .cancel = No |
| /// .tooltip = Closing the window will lose all unsaved data. |
| /// |
| /// "#; |
| /// |
| /// let resource = FluentResource::try_new(source.to_string()) |
| /// .expect("Failed to parse the resource."); |
| /// |
| /// let mut bundle = FluentBundle::default(); |
| /// bundle.add_resource(resource) |
| /// .expect("Failed to add a resource."); |
| /// |
| /// let msg = bundle.get_message("confirm-modal") |
| /// .expect("Failed to retrieve a message."); |
| /// |
| /// let mut err = vec![]; |
| /// |
| /// let attributes = msg.attributes().map(|attr| { |
| /// bundle.format_pattern(attr.value(), None, &mut err) |
| /// }).collect::<Vec<_>>(); |
| /// |
| /// assert_eq!(attributes[0], "Yes"); |
| /// assert_eq!(attributes[1], "No"); |
| /// assert_eq!(attributes[2], "Closing the window will lose all unsaved data."); |
| /// ``` |
| #[derive(Debug, PartialEq)] |
| pub struct FluentAttribute<'m> { |
| node: &'m ast::Attribute<&'m str>, |
| } |
| |
| impl<'m> FluentAttribute<'m> { |
| /// Retrieves an id of an attribute. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use fluent_bundle::{FluentResource, FluentBundle}; |
| /// # let source = r#" |
| /// # confirm-modal = |
| /// # .confirm = Yes |
| /// # "#; |
| /// # let resource = FluentResource::try_new(source.to_string()) |
| /// # .expect("Failed to parse the resource."); |
| /// # let mut bundle = FluentBundle::default(); |
| /// # bundle.add_resource(resource) |
| /// # .expect("Failed to add a resource."); |
| /// let msg = bundle.get_message("confirm-modal") |
| /// .expect("Failed to retrieve a message."); |
| /// |
| /// let attr1 = msg.attributes().next() |
| /// .expect("Failed to retrieve an attribute."); |
| /// |
| /// assert_eq!(attr1.id(), "confirm"); |
| /// ``` |
| pub fn id(&self) -> &'m str { |
| self.node.id.name |
| } |
| |
| /// Retrieves an value of an attribute. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use fluent_bundle::{FluentResource, FluentBundle}; |
| /// # let source = r#" |
| /// # confirm-modal = |
| /// # .confirm = Yes |
| /// # "#; |
| /// # let resource = FluentResource::try_new(source.to_string()) |
| /// # .expect("Failed to parse the resource."); |
| /// # let mut bundle = FluentBundle::default(); |
| /// # bundle.add_resource(resource) |
| /// # .expect("Failed to add a resource."); |
| /// let msg = bundle.get_message("confirm-modal") |
| /// .expect("Failed to retrieve a message."); |
| /// |
| /// let attr1 = msg.attributes().next() |
| /// .expect("Failed to retrieve an attribute."); |
| /// |
| /// let mut err = vec![]; |
| /// |
| /// let value = attr1.value(); |
| /// assert_eq!( |
| /// bundle.format_pattern(value, None, &mut err), |
| /// "Yes" |
| /// ); |
| /// ``` |
| pub fn value(&self) -> &'m ast::Pattern<&'m str> { |
| &self.node.value |
| } |
| } |
| |
| impl<'m> From<&'m ast::Attribute<&'m str>> for FluentAttribute<'m> { |
| fn from(attr: &'m ast::Attribute<&'m str>) -> Self { |
| FluentAttribute { node: attr } |
| } |
| } |
| |
| /// [`FluentMessage`] is a basic translation unit of the Fluent system. |
| /// |
| /// The instance of a message is returned from the |
| /// [`FluentBundle::get_message`](crate::bundle::FluentBundle::get_message) |
| /// method, for the lifetime of the [`FluentBundle`](crate::bundle::FluentBundle) instance. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// use fluent_bundle::{FluentResource, FluentBundle}; |
| /// |
| /// let source = r#" |
| /// |
| /// hello-world = Hello World! |
| /// |
| /// "#; |
| /// |
| /// let resource = FluentResource::try_new(source.to_string()) |
| /// .expect("Failed to parse the resource."); |
| /// |
| /// let mut bundle = FluentBundle::default(); |
| /// bundle.add_resource(resource) |
| /// .expect("Failed to add a resource."); |
| /// |
| /// let msg = bundle.get_message("hello-world") |
| /// .expect("Failed to retrieve a message."); |
| /// |
| /// assert!(msg.value().is_some()); |
| /// ``` |
| /// |
| /// That value can be then passed to |
| /// [`FluentBundle::format_pattern`](crate::bundle::FluentBundle::format_pattern) to be formatted |
| /// within the context of a given [`FluentBundle`](crate::bundle::FluentBundle) instance. |
| /// |
| /// # Compound Message |
| /// |
| /// A message may contain a `value`, but it can also contain a list of [`FluentAttribute`] elements. |
| /// |
| /// If a message contains attributes, it is called a "compound" message. |
| /// |
| /// In such case, the message contains a list of key-value attributes that represent |
| /// different translation values associated with a single translation unit. |
| /// |
| /// This is useful for scenarios where a [`FluentMessage`] is associated with a |
| /// complex User Interface widget which has multiple attributes that need to be translated. |
| /// ```text |
| /// confirm-modal = Are you sure? |
| /// .confirm = Yes |
| /// .cancel = No |
| /// .tooltip = Closing the window will lose all unsaved data. |
| /// ``` |
| #[derive(Debug, PartialEq)] |
| pub struct FluentMessage<'m> { |
| node: &'m ast::Message<&'m str>, |
| } |
| |
| impl<'m> FluentMessage<'m> { |
| /// Retrieves an option of a [`ast::Pattern`](fluent_syntax::ast::Pattern). |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use fluent_bundle::{FluentResource, FluentBundle}; |
| /// # let source = r#" |
| /// # hello-world = Hello World! |
| /// # "#; |
| /// # let resource = FluentResource::try_new(source.to_string()) |
| /// # .expect("Failed to parse the resource."); |
| /// # let mut bundle = FluentBundle::default(); |
| /// # bundle.add_resource(resource) |
| /// # .expect("Failed to add a resource."); |
| /// let msg = bundle.get_message("hello-world") |
| /// .expect("Failed to retrieve a message."); |
| /// |
| /// if let Some(value) = msg.value() { |
| /// let mut err = vec![]; |
| /// assert_eq!( |
| /// bundle.format_pattern(value, None, &mut err), |
| /// "Hello World!" |
| /// ); |
| /// # assert_eq!(err.len(), 0); |
| /// } |
| /// ``` |
| pub fn value(&self) -> Option<&'m ast::Pattern<&'m str>> { |
| self.node.value.as_ref() |
| } |
| |
| /// An iterator over [`FluentAttribute`] elements. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use fluent_bundle::{FluentResource, FluentBundle}; |
| /// # let source = r#" |
| /// # hello-world = |
| /// # .label = This is a label |
| /// # .accesskey = C |
| /// # "#; |
| /// # let resource = FluentResource::try_new(source.to_string()) |
| /// # .expect("Failed to parse the resource."); |
| /// # let mut bundle = FluentBundle::default(); |
| /// # bundle.add_resource(resource) |
| /// # .expect("Failed to add a resource."); |
| /// let msg = bundle.get_message("hello-world") |
| /// .expect("Failed to retrieve a message."); |
| /// |
| /// let mut err = vec![]; |
| /// |
| /// for attr in msg.attributes() { |
| /// let _ = bundle.format_pattern(attr.value(), None, &mut err); |
| /// } |
| /// # assert_eq!(err.len(), 0); |
| /// ``` |
| pub fn attributes(&self) -> impl Iterator<Item = FluentAttribute<'m>> { |
| self.node.attributes.iter().map(Into::into) |
| } |
| |
| /// Retrieve a single [`FluentAttribute`] element. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use fluent_bundle::{FluentResource, FluentBundle}; |
| /// # let source = r#" |
| /// # hello-world = |
| /// # .label = This is a label |
| /// # .accesskey = C |
| /// # "#; |
| /// # let resource = FluentResource::try_new(source.to_string()) |
| /// # .expect("Failed to parse the resource."); |
| /// # let mut bundle = FluentBundle::default(); |
| /// # bundle.add_resource(resource) |
| /// # .expect("Failed to add a resource."); |
| /// let msg = bundle.get_message("hello-world") |
| /// .expect("Failed to retrieve a message."); |
| /// |
| /// let mut err = vec![]; |
| /// |
| /// if let Some(attr) = msg.get_attribute("label") { |
| /// assert_eq!( |
| /// bundle.format_pattern(attr.value(), None, &mut err), |
| /// "This is a label" |
| /// ); |
| /// } |
| /// # assert_eq!(err.len(), 0); |
| /// ``` |
| pub fn get_attribute(&self, key: &str) -> Option<FluentAttribute<'m>> { |
| self.node |
| .attributes |
| .iter() |
| .find(|attr| attr.id.name == key) |
| .map(Into::into) |
| } |
| } |
| |
| impl<'m> From<&'m ast::Message<&'m str>> for FluentMessage<'m> { |
| fn from(msg: &'m ast::Message<&'m str>) -> Self { |
| FluentMessage { node: msg } |
| } |
| } |