1 use rustc_error_messages::{
2 fluent_bundle::resolver::errors::{ReferenceKind, ResolverError},
3 FluentArgs, FluentError,
10 pub enum TranslateError<'args> {
12 id: &'args Cow<'args, str>,
13 args: &'args FluentArgs<'args>,
14 kind: TranslateErrorKind<'args>,
17 primary: Box<TranslateError<'args>>,
18 fallback: Box<TranslateError<'args>>,
22 impl<'args> TranslateError<'args> {
23 pub fn message(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
24 Self::One { id, args, kind: TranslateErrorKind::MessageMissing }
26 pub fn primary(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
27 Self::One { id, args, kind: TranslateErrorKind::PrimaryBundleMissing }
30 id: &'args Cow<'args, str>,
31 args: &'args FluentArgs<'args>,
34 Self::One { id, args, kind: TranslateErrorKind::AttributeMissing { attr } }
36 pub fn value(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
37 Self::One { id, args, kind: TranslateErrorKind::ValueMissing }
41 id: &'args Cow<'args, str>,
42 args: &'args FluentArgs<'args>,
43 errs: Vec<FluentError>,
45 Self::One { id, args, kind: TranslateErrorKind::Fluent { errs } }
48 pub fn and(self, fallback: TranslateError<'args>) -> TranslateError<'args> {
49 Self::Two { primary: Box::new(self), fallback: Box::new(fallback) }
54 pub enum TranslateErrorKind<'args> {
57 AttributeMissing { attr: &'args str },
59 Fluent { errs: Vec<FluentError> },
62 impl fmt::Display for TranslateError<'_> {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 use TranslateErrorKind::*;
67 Self::One { id, args, kind } => {
68 writeln!(f, "failed while formatting fluent string `{id}`: ")?;
70 MessageMissing => writeln!(f, "message was missing")?,
71 PrimaryBundleMissing => writeln!(f, "the primary bundle was missing")?,
72 AttributeMissing { attr } => {
73 writeln!(f, "the attribute `{attr}` was missing")?;
74 writeln!(f, "help: add `.{attr} = <message>`")?;
76 ValueMissing => writeln!(f, "the value was missing")?,
80 FluentError::ResolverError(ResolverError::Reference(
81 ReferenceKind::Message { id, .. }
82 | ReferenceKind::Variable { id, .. },
84 if args.iter().any(|(arg_id, _)| arg_id == id) {
87 "argument `{id}` exists but was not referenced correctly"
89 writeln!(f, "help: try using `{{${id}}}` instead")?;
93 "the fluent string has an argument `{id}` that was not found."
96 args.iter().map(|(a, _v)| a).collect();
98 [] => writeln!(f, "help: no arguments are available")?,
101 "help: the argument `{one}` is available"
103 [first, middle @ .., last] => {
104 write!(f, "help: the arguments `{first}`")?;
106 write!(f, ", `{a}`")?;
108 writeln!(f, " and `{last}` are available")?;
113 _ => writeln!(f, "{err}")?,
119 // If someone cares about primary bundles, they'll probably notice it's missing
120 // regardless or will be using `debug_assertions`
121 // so we skip the arm below this one to avoid confusing the regular user.
122 Self::Two { primary: box Self::One { kind: PrimaryBundleMissing, .. }, fallback } => {
123 fmt::Display::fmt(fallback, f)?;
125 Self::Two { primary, fallback } => {
128 "first, fluent formatting using the primary bundle failed:\n {primary}\n \
129 while attempting to recover by using the fallback bundle instead, another error occurred:\n{fallback}"
137 impl Error for TranslateError<'_> {}