Skip to content

Commit fc3cca2

Browse files
committed
sess: try sysroot candidates for fluent bundle
Instead of checking only the user provided sysroot or the default (when no sysroot is provided), search user provided sysroot and then check default sysroots for locale requested by the user. Signed-off-by: David Wood <[email protected]>
1 parent 4e1927d commit fc3cca2

File tree

5 files changed

+94
-42
lines changed

5 files changed

+94
-42
lines changed

compiler/rustc_error_messages/src/lib.rs

+39-30
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::error::Error;
1111
use std::fmt;
1212
use std::fs;
1313
use std::io;
14-
use std::path::Path;
14+
use std::path::{Path, PathBuf};
1515
use tracing::{instrument, trace};
1616

1717
#[cfg(parallel_compiler)]
@@ -45,7 +45,7 @@ pub enum TranslationBundleError {
4545
/// Failed to add `FluentResource` to `FluentBundle`.
4646
AddResource(FluentError),
4747
/// `$sysroot/share/locale/$locale` does not exist.
48-
MissingLocale(io::Error),
48+
MissingLocale,
4949
/// Cannot read directory entries of `$sysroot/share/locale/$locale`.
5050
ReadLocalesDir(io::Error),
5151
/// Cannot read directory entry of `$sysroot/share/locale/$locale`.
@@ -62,9 +62,7 @@ impl fmt::Display for TranslationBundleError {
6262
write!(f, "could not parse ftl file: {}", e)
6363
}
6464
TranslationBundleError::AddResource(e) => write!(f, "failed to add resource: {}", e),
65-
TranslationBundleError::MissingLocale(e) => {
66-
write!(f, "missing locale directory: {}", e)
67-
}
65+
TranslationBundleError::MissingLocale => write!(f, "missing locale directory"),
6866
TranslationBundleError::ReadLocalesDir(e) => {
6967
write!(f, "could not read locales dir: {}", e)
7068
}
@@ -84,7 +82,7 @@ impl Error for TranslationBundleError {
8482
TranslationBundleError::ReadFtl(e) => Some(e),
8583
TranslationBundleError::ParseFtl(e) => Some(e),
8684
TranslationBundleError::AddResource(e) => Some(e),
87-
TranslationBundleError::MissingLocale(e) => Some(e),
85+
TranslationBundleError::MissingLocale => None,
8886
TranslationBundleError::ReadLocalesDir(e) => Some(e),
8987
TranslationBundleError::ReadLocalesDirEntry(e) => Some(e),
9088
TranslationBundleError::LocaleIsNotDir => None,
@@ -113,7 +111,8 @@ impl From<Vec<FluentError>> for TranslationBundleError {
113111
/// (overriding any conflicting messages).
114112
#[instrument(level = "trace")]
115113
pub fn fluent_bundle(
116-
sysroot: &Path,
114+
mut user_provided_sysroot: Option<PathBuf>,
115+
mut sysroot_candidates: Vec<PathBuf>,
117116
requested_locale: Option<LanguageIdentifier>,
118117
additional_ftl_path: Option<&Path>,
119118
with_directionality_markers: bool,
@@ -140,33 +139,43 @@ pub fn fluent_bundle(
140139

141140
// If the user requests the default locale then don't try to load anything.
142141
if !requested_fallback_locale && let Some(requested_locale) = requested_locale {
143-
let mut sysroot = sysroot.to_path_buf();
144-
sysroot.push("share");
145-
sysroot.push("locale");
146-
sysroot.push(requested_locale.to_string());
147-
trace!(?sysroot);
148-
149-
let _ = sysroot.try_exists().map_err(TranslationBundleError::MissingLocale)?;
150-
151-
if !sysroot.is_dir() {
152-
return Err(TranslationBundleError::LocaleIsNotDir);
153-
}
154-
155-
for entry in sysroot.read_dir().map_err(TranslationBundleError::ReadLocalesDir)? {
156-
let entry = entry.map_err(TranslationBundleError::ReadLocalesDirEntry)?;
157-
let path = entry.path();
158-
trace!(?path);
159-
if path.extension().and_then(|s| s.to_str()) != Some("ftl") {
142+
let mut found_resources = false;
143+
for sysroot in user_provided_sysroot.iter_mut().chain(sysroot_candidates.iter_mut()) {
144+
sysroot.push("share");
145+
sysroot.push("locale");
146+
sysroot.push(requested_locale.to_string());
147+
trace!(?sysroot);
148+
149+
if !sysroot.exists() {
160150
trace!("skipping");
161151
continue;
162152
}
163153

164-
let resource_str =
165-
fs::read_to_string(path).map_err(TranslationBundleError::ReadFtl)?;
166-
let resource =
167-
FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?;
168-
trace!(?resource);
169-
bundle.add_resource(resource).map_err(TranslationBundleError::from)?;
154+
if !sysroot.is_dir() {
155+
return Err(TranslationBundleError::LocaleIsNotDir);
156+
}
157+
158+
for entry in sysroot.read_dir().map_err(TranslationBundleError::ReadLocalesDir)? {
159+
let entry = entry.map_err(TranslationBundleError::ReadLocalesDirEntry)?;
160+
let path = entry.path();
161+
trace!(?path);
162+
if path.extension().and_then(|s| s.to_str()) != Some("ftl") {
163+
trace!("skipping");
164+
continue;
165+
}
166+
167+
let resource_str =
168+
fs::read_to_string(path).map_err(TranslationBundleError::ReadFtl)?;
169+
let resource =
170+
FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?;
171+
trace!(?resource);
172+
bundle.add_resource(resource).map_err(TranslationBundleError::from)?;
173+
found_resources = true;
174+
}
175+
}
176+
177+
if !found_resources {
178+
return Err(TranslationBundleError::MissingLocale);
170179
}
171180
}
172181

compiler/rustc_interface/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
4444
let sess = build_session(
4545
sessopts,
4646
None,
47+
None,
4748
registry,
4849
DiagnosticOutput::Default,
4950
Default::default(),

compiler/rustc_interface/src/util.rs

+14
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,23 @@ pub fn create_session(
8383
// target_override is documented to be called before init(), so this is okay
8484
let target_override = codegen_backend.target_override(&sopts);
8585

86+
let bundle = match rustc_errors::fluent_bundle(
87+
sopts.maybe_sysroot.clone(),
88+
sysroot_candidates(),
89+
sopts.debugging_opts.translate_lang.clone(),
90+
sopts.debugging_opts.translate_additional_ftl.as_deref(),
91+
sopts.debugging_opts.translate_directionality_markers,
92+
) {
93+
Ok(bundle) => bundle,
94+
Err(e) => {
95+
early_error(sopts.error_format, &format!("failed to load fluent bundle: {e}"));
96+
}
97+
};
98+
8699
let mut sess = session::build_session(
87100
sopts,
88101
input_path,
102+
bundle,
89103
descriptions,
90104
diagnostic_output,
91105
lint_caps,

compiler/rustc_session/src/session.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
2020
use rustc_errors::json::JsonEmitter;
2121
use rustc_errors::registry::Registry;
2222
use rustc_errors::{
23-
fallback_fluent_bundle, fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
24-
EmissionGuarantee, ErrorGuaranteed, FluentBundle, MultiSpan,
23+
fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee,
24+
ErrorGuaranteed, FluentBundle, MultiSpan,
2525
};
2626
use rustc_macros::HashStable_Generic;
2727
pub use rustc_span::def_id::StableCrateId;
@@ -1162,6 +1162,7 @@ pub enum DiagnosticOutput {
11621162
pub fn build_session(
11631163
sopts: config::Options,
11641164
local_crate_source_file: Option<PathBuf>,
1165+
bundle: Option<Lrc<rustc_errors::FluentBundle>>,
11651166
registry: rustc_errors::registry::Registry,
11661167
diagnostics_output: DiagnosticOutput,
11671168
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -1214,16 +1215,17 @@ pub fn build_session(
12141215
hash_kind,
12151216
));
12161217

1217-
let bundle = fluent_bundle(
1218-
&sysroot,
1219-
sopts.debugging_opts.translate_lang.clone(),
1220-
sopts.debugging_opts.translate_additional_ftl.as_deref(),
1221-
sopts.debugging_opts.translate_directionality_markers,
1222-
)
1223-
.expect("failed to load fluent bundle");
12241218
let fallback_bundle =
1225-
fallback_fluent_bundle(sopts.debugging_opts.translate_directionality_markers)
1226-
.expect("failed to load fallback fluent bundle");
1219+
match fallback_fluent_bundle(sopts.debugging_opts.translate_directionality_markers) {
1220+
Ok(bundle) => bundle,
1221+
Err(e) => {
1222+
early_error(
1223+
sopts.error_format,
1224+
&format!("failed to load fallback fluent bundle: {e}"),
1225+
);
1226+
}
1227+
};
1228+
12271229
let emitter =
12281230
default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle, write_dest);
12291231

src/test/run-make/translation/Makefile

+27-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ normal: basic-translation.rs
1515
custom: basic-translation.rs basic-translation.ftl
1616
$(RUSTC) $< -Ztranslate-additional-ftl=$(CURDIR)/basic-translation.ftl 2>&1 | grep "this is a test message"
1717

18-
# Make a local copy of the sysroot and add the custom locale to it.
18+
# Check that a locale can be loaded from the sysroot given a language
19+
# identifier by making a local copy of the sysroot and adding the custom locale
20+
# to it.
1921
sysroot: basic-translation.rs basic-translation.ftl
2022
mkdir $(FAKEROOT)
2123
ln -s $(SYSROOT)/* $(FAKEROOT)
@@ -31,3 +33,27 @@ sysroot: basic-translation.rs basic-translation.ftl
3133
mkdir -p $(FAKEROOT)/share/locale/zh-CN/
3234
ln -s $(CURDIR)/basic-translation.ftl $(FAKEROOT)/share/locale/zh-CN/basic-translation.ftl
3335
$(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 | grep "this is a test message"
36+
37+
# Check that the compiler errors out when the sysroot requested cannot be
38+
# found. This test might start failing if there actually exists a Klingon
39+
# translation of rustc's error messages.
40+
sysroot-missing:
41+
$(RUSTC) $< -Ztranslate-lang=tlh 2>&1 || grep "missing locale directory"
42+
43+
# Check that the compiler errors out when the sysroot requested cannot be
44+
# found. This test might start failing if there actually exists a Klingon
45+
# translation of rustc's error messages.
46+
sysroot-invalid: basic-translation.rs basic-translation.ftl
47+
mkdir $(FAKEROOT)
48+
ln -s $(SYSROOT)/* $(FAKEROOT)
49+
rm -f $(FAKEROOT)/lib
50+
mkdir $(FAKEROOT)/lib
51+
ln -s $(SYSROOT)/lib/* $(FAKEROOT)/lib
52+
rm -f $(FAKEROOT)/lib/rustlib
53+
mkdir $(FAKEROOT)/lib/rustlib
54+
ln -s $(SYSROOT)/lib/rustlib/* $(FAKEROOT)/lib/rustlib
55+
rm -f $(FAKEROOT)/lib/rustlib/src
56+
mkdir $(FAKEROOT)/lib/rustlib/src
57+
ln -s $(SYSROOT)/lib/rustlib/src/* $(FAKEROOT)/lib/rustlib/src
58+
touch $(FAKEROOT)/share/locale/zh-CN/
59+
$(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 || grep "`\$sysroot/share/locales/\$locale` is not a directory"

0 commit comments

Comments
 (0)