Source code
Revision control
Copy as Markdown
Other Tools
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 }
}
}