///|
/// A branch in a `select`, `plural`, or `selectordinal` message argument.
pub struct MessageCase {
selector : String
nodes : Array[MessageNode]
} derive(Eq, Debug)
///|
/// The parsed representation of a localized message template.
///
/// Keeping the syntax tree public lets applications cache compiled templates,
/// inspect their arguments, and build tooling without reparsing source text.
pub(all) enum MessageNode {
Text(String)
Argument(String)
Select(String, Array[MessageCase])
Plural(String, Int, PluralKind, Array[MessageCase])
} derive(Eq, Debug)
///|
pub fn MessageCase::new(
selector : String,
nodes : Array[MessageNode],
) -> MessageCase {
{ selector, nodes }
}
///|
pub fn MessageCase::selector(self : MessageCase) -> String {
self.selector
}
///|
pub fn MessageCase::nodes(self : MessageCase) -> Array[MessageNode] {
self.nodes.copy()
}
///|
/// A reusable parsed message template.
pub struct MessageTemplate {
source : String
nodes : Array[MessageNode]
} derive(Eq, Debug)
///|
pub fn MessageTemplate::source(self : MessageTemplate) -> String {
self.source
}
///|
pub fn MessageTemplate::nodes(self : MessageTemplate) -> Array[MessageNode] {
self.nodes.copy()
}
///|
/// Collects argument names in first-use order without duplicates.
pub fn MessageTemplate::arguments(self : MessageTemplate) -> Array[String] {
let output : Array[String] = []
collect_message_arguments(self.nodes, output)
output
}
///|
fn collect_message_arguments(
nodes : Array[MessageNode],
output : Array[String],
) -> Unit {
for node in nodes {
match node {
Text(_) => ()
Argument(name) => push_unique_argument(output, name)
Select(name, cases) => {
push_unique_argument(output, name)
for branch in cases {
collect_message_arguments(branch.nodes, output)
}
}
Plural(name, _, _, cases) => {
push_unique_argument(output, name)
for branch in cases {
collect_message_arguments(branch.nodes, output)
}
}
}
}
}
///|
fn push_unique_argument(output : Array[String], name : String) -> Unit {
for current in output {
if current == name {
return
}
}
output.push(name)
}
///|
/// Returns the number of syntax-tree nodes, including nested branch content.
pub fn MessageTemplate::node_count(self : MessageTemplate) -> Int {
count_message_nodes(self.nodes)
}
///|
fn count_message_nodes(nodes : Array[MessageNode]) -> Int {
let mut count = 0
for node in nodes {
count = count + 1
match node {
Select(_, cases) | Plural(_, _, _, cases) =>
for branch in cases {
count = count + count_message_nodes(branch.nodes)
}
_ => ()
}
}
count
}