1use std::borrow::Cow;
2use std::env;
3use std::error::Report;
4use std::sync::Arc;
5
6pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle};
7use tracing::{debug, trace};
8
9use crate::error::{TranslateError, TranslateErrorKind};
10use crate::{DiagArg, DiagMessage, FluentBundle, Style};
11
12pub fn to_fluent_args<'iter>(iter: impl Iterator<Item = DiagArg<'iter>>) -> FluentArgs<'static> {
18 let mut args = if let Some(size) = iter.size_hint().1 {
19 FluentArgs::with_capacity(size)
20 } else {
21 FluentArgs::new()
22 };
23
24 for (k, v) in iter {
25 args.set(k.clone(), v.clone());
26 }
27
28 args
29}
30
31#[derive(#[automatically_derived]
impl ::core::clone::Clone for Translator {
#[inline]
fn clone(&self) -> Translator {
Translator {
fluent_bundle: ::core::clone::Clone::clone(&self.fluent_bundle),
fallback_fluent_bundle: ::core::clone::Clone::clone(&self.fallback_fluent_bundle),
}
}
}Clone)]
32pub struct Translator {
33 pub fluent_bundle: Option<Arc<FluentBundle>>,
36 pub fallback_fluent_bundle: LazyFallbackBundle,
40}
41
42impl Translator {
43 pub fn with_fallback_bundle(
44 resources: Vec<&'static str>,
45 with_directionality_markers: bool,
46 ) -> Translator {
47 Translator {
48 fluent_bundle: None,
49 fallback_fluent_bundle: crate::fallback_fluent_bundle(
50 resources,
51 with_directionality_markers,
52 ),
53 }
54 }
55
56 pub fn translate_messages(
58 &self,
59 messages: &[(DiagMessage, Style)],
60 args: &FluentArgs<'_>,
61 ) -> Cow<'_, str> {
62 Cow::Owned(
63 messages
64 .iter()
65 .map(|(m, _)| self.translate_message(m, args).map_err(Report::new).unwrap())
66 .collect::<String>(),
67 )
68 }
69
70 pub fn translate_message<'a>(
72 &'a self,
73 message: &'a DiagMessage,
74 args: &'a FluentArgs<'_>,
75 ) -> Result<Cow<'a, str>, TranslateError<'a>> {
76 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/translation.rs:76",
"rustc_errors::translation", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(76u32),
::tracing_core::__macro_support::Option::Some("rustc_errors::translation"),
::tracing_core::field::FieldSet::new(&["message", "args"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&message) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&args) as
&dyn Value))])
});
} else { ; }
};trace!(?message, ?args);
77 let (identifier, attr) = match message {
78 DiagMessage::Str(msg) => {
79 return Ok(Cow::Borrowed(msg));
80 }
81 DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
82 };
83 let translate_with_bundle =
84 |bundle: &'a FluentBundle| -> Result<Cow<'_, str>, TranslateError<'_>> {
85 let message = bundle
86 .get_message(identifier)
87 .ok_or(TranslateError::message(identifier, args))?;
88 let value = match attr {
89 Some(attr) => message
90 .get_attribute(attr)
91 .ok_or(TranslateError::attribute(identifier, args, attr))?
92 .value(),
93 None => message.value().ok_or(TranslateError::value(identifier, args))?,
94 };
95 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/translation.rs:95",
"rustc_errors::translation", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(95u32),
::tracing_core::__macro_support::Option::Some("rustc_errors::translation"),
::tracing_core::field::FieldSet::new(&["message", "value"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&message) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&value) as
&dyn Value))])
});
} else { ; }
};debug!(?message, ?value);
96
97 let mut errs = ::alloc::vec::Vec::new()vec![];
98 let translated = bundle.format_pattern(value, Some(args), &mut errs);
99 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_errors/src/translation.rs:99",
"rustc_errors::translation", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(99u32),
::tracing_core::__macro_support::Option::Some("rustc_errors::translation"),
::tracing_core::field::FieldSet::new(&["translated",
"errs"], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&translated)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&errs) as
&dyn Value))])
});
} else { ; }
};debug!(?translated, ?errs);
100 if errs.is_empty() {
101 Ok(translated)
102 } else {
103 Err(TranslateError::fluent(identifier, args, errs))
104 }
105 };
106
107 try {
108 match self.fluent_bundle.as_ref().map(|b| translate_with_bundle(b)) {
109 Some(Ok(t)) => t,
111
112 Some(Err(
116 primary @ TranslateError::One {
117 kind: TranslateErrorKind::MessageMissing, ..
118 },
119 )) => translate_with_bundle(&self.fallback_fluent_bundle)
120 .map_err(|fallback| primary.and(fallback))?,
121
122 Some(Err(primary))
127 if truecfg!(debug_assertions)
128 && env::var("RUSTC_TRANSLATION_NO_DEBUG_ASSERT").is_err() =>
129 {
130 do yeet primary
131 }
132
133 Some(Err(primary)) => translate_with_bundle(&self.fallback_fluent_bundle)
136 .map_err(|fallback| primary.and(fallback))?,
137
138 None => translate_with_bundle(&self.fallback_fluent_bundle)
140 .map_err(|fallback| TranslateError::primary(identifier, args).and(fallback))?,
141 }
142 }
143 }
144}