Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/l10n.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,29 @@ jobs:
env:
RUST_BACKTRACE: "1"

l10n_embedded_locale_regression_test:
name: L10n/Embedded Locale Regression Test
runs-on: ubuntu-latest
env:
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache"
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.9
- name: Install/setup prerequisites
shell: bash
run: |
sudo apt-get -y update && sudo apt-get -y install libselinux1-dev
- name: Test embedded locale functionality for individual utilities
shell: bash
run: |
bash util/test_locale_regression.sh

l10n_locale_embedding_regression_test:
name: L10n/Locale Embedding Regression Test
runs-on: ubuntu-latest
Expand Down
69 changes: 68 additions & 1 deletion src/uucore/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let out_dir = env::var("OUT_DIR")?;

let mut embedded_file = File::create(Path::new(&out_dir).join("embedded_locales.rs"))?;

writeln!(embedded_file, "// Generated at compile time - do not edit")?;
writeln!(
embedded_file,
Expand Down Expand Up @@ -78,6 +77,14 @@ fn detect_target_utility() -> Option<String> {
}
}

// Auto-detect utility name from CARGO_PKG_NAME if it's a uu_* package
if let Ok(pkg_name) = env::var("CARGO_PKG_NAME") {
if let Some(util_name) = pkg_name.strip_prefix("uu_") {
println!("cargo:warning=Auto-detected utility name: {}", util_name);
return Some(util_name.to_string());
}
}

// Check for a build configuration file in the target directory
if let Ok(target_dir) = env::var("CARGO_TARGET_DIR") {
let config_path = std::path::Path::new(&target_dir).join("uucore_target_util.txt");
Expand Down Expand Up @@ -156,6 +163,9 @@ fn embed_all_utilities_locales(
// Discover all uu_* directories
let src_uu_dir = project_root.join("src/uu");
if !src_uu_dir.exists() {
// When src/uu doesn't exist (e.g., standalone uucore from crates.io),
// embed a static list of utility locales that are commonly used
embed_static_utility_locales(embedded_file)?;
return Ok(());
}

Expand Down Expand Up @@ -202,3 +212,60 @@ fn embed_all_utilities_locales(
embedded_file.flush()?;
Ok(())
}

fn embed_static_utility_locales(
embedded_file: &mut std::fs::File,
) -> Result<(), Box<dyn std::error::Error>> {
use std::env;

writeln!(
embedded_file,
" // Static utility locales for crates.io builds"
)?;

let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap_or_default();
let Some(registry_dir) = Path::new(&manifest_dir).parent() else {
return Ok(()); // nothing to scan
};

// First, try to embed uucore locales - critical for common translations like "Usage:"
let uucore_locale_file = Path::new(&manifest_dir).join("locales/en-US.ftl");
if uucore_locale_file.is_file() {
let content = std::fs::read_to_string(&uucore_locale_file)?;
writeln!(embedded_file, " // Common uucore locale")?;
writeln!(
embedded_file,
" locales.insert(\"uucore/en-US.ftl\", r###\"{content}\"###);"
)?;
writeln!(embedded_file)?;
}

// Collect and sort for deterministic builds
let mut entries: Vec<_> = std::fs::read_dir(registry_dir)?
.filter_map(Result::ok)
.collect();
entries.sort_by_key(|e| e.file_name());

for entry in entries {
let file_name = entry.file_name();
if let Some(dir_name) = file_name.to_str() {
// Match uu_<util>-<version>
if let Some((util_part, _)) = dir_name.split_once('-') {
if let Some(util_name) = util_part.strip_prefix("uu_") {
let locale_file = entry.path().join("locales/en-US.ftl");
if locale_file.is_file() {
let content = std::fs::read_to_string(&locale_file)?;
writeln!(embedded_file, " // Locale for {util_name}")?;
writeln!(
embedded_file,
" locales.insert(\"{util_name}/en-US.ftl\", r###\"{content}\"###);"
)?;
writeln!(embedded_file)?;
}
}
}
}
}

Ok(())
}
34 changes: 34 additions & 0 deletions util/test_locale_regression.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash

echo "Testing embedded locale functionality to prevent crates.io regression..."
INSTALL_DIR="$(pwd)/test-install-dir"
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
utilities_to_test=("cp" "mv" "ln")

for util in "${utilities_to_test[@]}"; do
echo "Testing $util..."
cargo install --path "src/uu/$util" --root "$INSTALL_DIR" --force --quiet
binary_path="$INSTALL_DIR/bin/$util"
help_output=$("$binary_path" --help 2>&1)

# Check for regression indicators
if echo "$help_output" | grep -q "common-usage"; then
echo "✗ CRITICAL REGRESSION: $util shows untranslated 'common-usage' key"
echo "Help output:"
echo "$help_output"
exit 1
fi

# Verify proper "Usage:" label
if echo "$help_output" | grep -q "Usage:"; then
echo "✓ $util shows properly translated 'Usage:' label"
else
echo "✗ CRITICAL REGRESSION: $util missing 'Usage:' label"
echo "Help output:"
echo "$help_output"
exit 1
fi
done

echo "All tests passed!"
Loading