1use std::borrow::Cow;
2use std::env;
3use std::error::Report;
4use std::sync::Arc;
5
6pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle};
7use rustc_error_messages::{langid, register_functions};
8use tracing::{debug, trace};
9
10use crate::error::{TranslateError, TranslateErrorKind};
11use crate::fluent_bundle::FluentResource;
12use crate::{DiagArg, DiagMessage, FluentBundle, Style, fluent_bundle};
13
14pub fn to_fluent_args<'iter>(iter: impl Iterator<Item = DiagArg<'iter>>) -> FluentArgs<'static> {
20 let mut args = if let Some(size) = iter.size_hint().1 {
21 FluentArgs::with_capacity(size)
22 } else {
23 FluentArgs::new()
24 };
25
26 for (k, v) in iter {
27 args.set(k.clone(), v.clone());
28 }
29
30 args
31}
32
33#[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)]
34pub struct Translator {
35 pub fluent_bundle: Option<Arc<FluentBundle>>,
38 pub fallback_fluent_bundle: LazyFallbackBundle,
42}
43
44impl Translator {
45 pub fn with_fallback_bundle(
46 resources: Vec<&'static str>,
47 with_directionality_markers: bool,
48 ) -> Translator {
49 Translator {
50 fluent_bundle: None,
51 fallback_fluent_bundle: crate::fallback_fluent_bundle(
52 resources,
53 with_directionality_markers,
54 ),
55 }
56 }
57
58 pub fn translate_messages(
60 &self,
61 messages: &[(DiagMessage, Style)],
62 args: &FluentArgs<'_>,
63 ) -> Cow<'_, str> {
64 Cow::Owned(
65 messages
66 .iter()
67 .map(|(m, _)| self.translate_message(m, args).map_err(Report::new).unwrap())
68 .collect::<String>(),
69 )
70 }
71
72 pub fn translate_message<'a>(
74 &'a self,
75 message: &'a DiagMessage,
76 args: &'a FluentArgs<'_>,
77 ) -> Result<Cow<'a, str>, TranslateError<'a>> {
78 {
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:78",
"rustc_errors::translation", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(78u32),
::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);
79 let (identifier, attr) = match message {
80 DiagMessage::Str(msg) => {
81 return Ok(Cow::Borrowed(msg));
82 }
83 DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
84 DiagMessage::Inline(msg) => {
88 const GENERATED_MSG_ID: &str = "generated_msg";
89 let resource =
90 FluentResource::try_new(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} = {1}\n", GENERATED_MSG_ID,
msg))
})format!("{GENERATED_MSG_ID} = {msg}\n")).unwrap();
91 let mut bundle = fluent_bundle::FluentBundle::new(<[_]>::into_vec(::alloc::boxed::box_new([{
#[allow(dead_code)]
enum ProcMacroHack { Value = ("\"en-US\"", 0).1, }
macro_rules! proc_macro_call {
() =>
{
unsafe
{
$crate :: LanguageIdentifier ::
from_raw_parts_unchecked(unsafe
{
$crate :: subtags :: Language ::
from_raw_unchecked(28261u64)
}, None,
Some(unsafe
{
$crate :: subtags :: Region :: from_raw_unchecked(21333u32)
}), None)
}
}
}
unsafe {
::unic_langid_macros::LanguageIdentifier::from_raw_parts_unchecked(unsafe
{
::unic_langid_macros::subtags::Language::from_raw_unchecked(28261u64)
}, None,
Some(unsafe {
::unic_langid_macros::subtags::Region::from_raw_unchecked(21333u32)
}), None)
}
}]))vec![langid!("en-US")]);
92 bundle.set_use_isolating(false);
93 bundle.add_resource(resource).unwrap();
94 register_functions(&mut bundle);
95 let message = bundle.get_message(GENERATED_MSG_ID).unwrap();
96 let value = message.value().unwrap();
97
98 let mut errs = ::alloc::vec::Vec::new()vec![];
99 let translated = bundle.format_pattern(value, Some(args), &mut errs).to_string();
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 return if errs.is_empty() {
102 Ok(Cow::Owned(translated))
103 } else {
104 Err(TranslateError::fluent(&Cow::Borrowed(GENERATED_MSG_ID), args, errs))
105 };
106 }
107 };
108 let translate_with_bundle =
109 |bundle: &'a FluentBundle| -> Result<Cow<'_, str>, TranslateError<'_>> {
110 let message = bundle
111 .get_message(identifier)
112 .ok_or(TranslateError::message(identifier, args))?;
113 let value = match attr {
114 Some(attr) => message
115 .get_attribute(attr)
116 .ok_or(TranslateError::attribute(identifier, args, attr))?
117 .value(),
118 None => message.value().ok_or(TranslateError::value(identifier, args))?,
119 };
120 {
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:120",
"rustc_errors::translation", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(120u32),
::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);
121
122 let mut errs = ::alloc::vec::Vec::new()vec![];
123 let translated = bundle.format_pattern(value, Some(args), &mut errs);
124 {
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:124",
"rustc_errors::translation", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_errors/src/translation.rs"),
::tracing_core::__macro_support::Option::Some(124u32),
::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);
125 if errs.is_empty() {
126 Ok(translated)
127 } else {
128 Err(TranslateError::fluent(identifier, args, errs))
129 }
130 };
131
132 try {
133 match self.fluent_bundle.as_ref().map(|b| translate_with_bundle(b)) {
134 Some(Ok(t)) => t,
136
137 Some(Err(
141 primary @ TranslateError::One {
142 kind: TranslateErrorKind::MessageMissing, ..
143 },
144 )) => translate_with_bundle(&self.fallback_fluent_bundle)
145 .map_err(|fallback| primary.and(fallback))?,
146
147 Some(Err(primary))
152 if truecfg!(debug_assertions)
153 && env::var("RUSTC_TRANSLATION_NO_DEBUG_ASSERT").is_err() =>
154 {
155 do yeet primary
156 }
157
158 Some(Err(primary)) => translate_with_bundle(&self.fallback_fluent_bundle)
161 .map_err(|fallback| primary.and(fallback))?,
162
163 None => translate_with_bundle(&self.fallback_fluent_bundle)
165 .map_err(|fallback| TranslateError::primary(identifier, args).and(fallback))?,
166 }
167 }
168 }
169}
170
171#[macro_export]
176macro_rules! inline_fluent {
177 ($inline: literal) => {
178 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed($inline))
179 };
180}