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::snippet::Style;
11use crate::{DiagArg, DiagMessage, FluentBundle};
12
13pub fn to_fluent_args<'iter>(iter: impl Iterator<Item = DiagArg<'iter>>) -> FluentArgs<'static> {
19 let mut args = if let Some(size) = iter.size_hint().1 {
20 FluentArgs::with_capacity(size)
21 } else {
22 FluentArgs::new()
23 };
24
25 for (k, v) in iter {
26 args.set(k.clone(), v.clone());
27 }
28
29 args
30}
31
32#[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)]
33pub struct Translator {
34 pub fluent_bundle: Option<Arc<FluentBundle>>,
37 pub fallback_fluent_bundle: LazyFallbackBundle,
41}
42
43impl Translator {
44 pub fn with_fallback_bundle(
45 resources: Vec<&'static str>,
46 with_directionality_markers: bool,
47 ) -> Translator {
48 Translator {
49 fluent_bundle: None,
50 fallback_fluent_bundle: crate::fallback_fluent_bundle(
51 resources,
52 with_directionality_markers,
53 ),
54 }
55 }
56
57 pub fn translate_messages(
59 &self,
60 messages: &[(DiagMessage, Style)],
61 args: &FluentArgs<'_>,
62 ) -> Cow<'_, str> {
63 Cow::Owned(
64 messages
65 .iter()
66 .map(|(m, _)| self.translate_message(m, args).map_err(Report::new).unwrap())
67 .collect::<String>(),
68 )
69 }
70
71 pub fn translate_message<'a>(
73 &'a self,
74 message: &'a DiagMessage,
75 args: &'a FluentArgs<'_>,
76 ) -> Result<Cow<'a, str>, TranslateError<'a>> {
77 {
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:77",
"rustc_errors::translation", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(77u32),
::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);
78 let (identifier, attr) = match message {
79 DiagMessage::Str(msg) | DiagMessage::Translated(msg) => {
80 return Ok(Cow::Borrowed(msg));
81 }
82 DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
83 };
84 let translate_with_bundle =
85 |bundle: &'a FluentBundle| -> Result<Cow<'_, str>, TranslateError<'_>> {
86 let message = bundle
87 .get_message(identifier)
88 .ok_or(TranslateError::message(identifier, args))?;
89 let value = match attr {
90 Some(attr) => message
91 .get_attribute(attr)
92 .ok_or(TranslateError::attribute(identifier, args, attr))?
93 .value(),
94 None => message.value().ok_or(TranslateError::value(identifier, args))?,
95 };
96 {
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:96",
"rustc_errors::translation", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(96u32),
::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);
97
98 let mut errs = ::alloc::vec::Vec::new()vec![];
99 let translated = bundle.format_pattern(value, Some(args), &mut errs);
100 {
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:100",
"rustc_errors::translation", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(100u32),
::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);
101 if errs.is_empty() {
102 Ok(translated)
103 } else {
104 Err(TranslateError::fluent(identifier, args, errs))
105 }
106 };
107
108 try {
109 match self.fluent_bundle.as_ref().map(|b| translate_with_bundle(b)) {
110 Some(Ok(t)) => t,
112
113 Some(Err(
117 primary @ TranslateError::One {
118 kind: TranslateErrorKind::MessageMissing, ..
119 },
120 )) => translate_with_bundle(&self.fallback_fluent_bundle)
121 .map_err(|fallback| primary.and(fallback))?,
122
123 Some(Err(primary))
128 if truecfg!(debug_assertions)
129 && env::var("RUSTC_TRANSLATION_NO_DEBUG_ASSERT").is_err() =>
130 {
131 do yeet primary
132 }
133
134 Some(Err(primary)) => translate_with_bundle(&self.fallback_fluent_bundle)
137 .map_err(|fallback| primary.and(fallback))?,
138
139 None => translate_with_bundle(&self.fallback_fluent_bundle)
141 .map_err(|fallback| TranslateError::primary(identifier, args).and(fallback))?,
142 }
143 }
144 }
145}