Skip to content

Commit 676d329

Browse files
committed
remove i18n as feature
1 parent 20cfab8 commit 676d329

File tree

5 files changed

+153
-236
lines changed

5 files changed

+153
-236
lines changed

build.rs

Lines changed: 8 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -113,123 +113,19 @@ pub fn main() {
113113
}
114114
}
115115

116-
/// Generate embedded locale strings from .ftl files
116+
// Include the shared build logic
117+
mod build_common;
118+
119+
/// Generate embedded locale strings from .ftl files using shared logic
117120
///
118121
/// # Errors
119122
///
120123
/// Returns an error if file operations fail or if there are I/O issues
121124
fn generate_embedded_locale_strings(
122125
out_dir: &str,
123-
crates: &[String],
126+
_crates: &[String],
124127
) -> Result<(), Box<dyn std::error::Error>> {
125-
use std::collections::HashMap;
126-
use std::fs;
127-
128-
let mut all_strings = HashMap::new();
129-
130-
// Collect all English strings from all utilities
131-
for krate in crates {
132-
let locale_path = format!("src/uu/{krate}/locales/en-US.ftl");
133-
if Path::new(&locale_path).exists() {
134-
let content = fs::read_to_string(&locale_path)?;
135-
136-
// Parse the Fluent file and extract key-value pairs
137-
for line in content.lines() {
138-
let line = line.trim();
139-
if line.is_empty() || line.starts_with('#') {
140-
continue;
141-
}
142-
143-
if let Some(equals_pos) = line.find(" = ") {
144-
let key = line[..equals_pos].trim();
145-
let value = line[equals_pos + 3..].trim();
146-
all_strings.insert(key.to_string(), value.to_string());
147-
}
148-
}
149-
}
150-
}
151-
152-
// Also collect common locale strings from uucore if they exist
153-
let common_locale_path = "src/uucore/locales/en-US.ftl";
154-
if Path::new(&common_locale_path).exists() {
155-
let content = fs::read_to_string(common_locale_path)?;
156-
for line in content.lines() {
157-
let line = line.trim();
158-
if line.is_empty() || line.starts_with('#') {
159-
continue;
160-
}
161-
162-
if let Some(equals_pos) = line.find(" = ") {
163-
let key = line[..equals_pos].trim();
164-
let value = line[equals_pos + 3..].trim();
165-
all_strings.insert(key.to_string(), value.to_string());
166-
}
167-
}
168-
}
169-
170-
// Generate Rust code with embedded strings as individual consts
171-
let mut embedded_file = File::create(Path::new(out_dir).join("embedded_locale.rs"))?;
172-
173-
writeln!(embedded_file, "// Generated at compile time - do not edit")?;
174-
writeln!(embedded_file)?;
175-
176-
// Generate individual const strings
177-
for (key, value) in &all_strings {
178-
// Create a valid Rust identifier from the key
179-
let const_name = key
180-
.chars()
181-
.map(|c| if c.is_alphanumeric() { c } else { '_' })
182-
.collect::<String>()
183-
.to_uppercase();
184-
185-
// Ensure it doesn't start with a number
186-
let const_name = if const_name.chars().next().unwrap_or('_').is_numeric() {
187-
format!("S_{const_name}")
188-
} else {
189-
const_name
190-
};
191-
192-
// Escape the value for Rust string literal
193-
let escaped_value = value
194-
.replace('\\', "\\\\")
195-
.replace('"', "\\\"")
196-
.replace('\n', "\\n");
197-
writeln!(
198-
embedded_file,
199-
"pub const {const_name}: &str = {escaped_value:?};"
200-
)?;
201-
}
202-
203-
writeln!(embedded_file)?;
204-
205-
// Generate lookup function
206-
writeln!(
207-
embedded_file,
208-
"pub fn get_embedded_string(id: &str) -> Option<&'static str> {{"
209-
)?;
210-
writeln!(embedded_file, " match id {{")?;
211-
212-
for key in all_strings.keys() {
213-
let const_name = key
214-
.chars()
215-
.map(|c| if c.is_alphanumeric() { c } else { '_' })
216-
.collect::<String>()
217-
.to_uppercase();
218-
219-
// Ensure it doesn't start with a number
220-
let const_name = if const_name.chars().next().unwrap_or('_').is_numeric() {
221-
format!("S_{const_name}")
222-
} else {
223-
const_name
224-
};
225-
226-
writeln!(embedded_file, " {key:?} => Some({const_name}),")?;
227-
}
228-
229-
writeln!(embedded_file, " _ => None,")?;
230-
writeln!(embedded_file, " }}")?;
231-
writeln!(embedded_file, "}}")?;
232-
233-
embedded_file.flush()?;
234-
Ok(())
128+
// Use current directory as project root for the main build script
129+
let project_root = Path::new(".");
130+
build_common::generate_embedded_locale_strings(out_dir, project_root)
235131
}

build_common.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// This file is part of the uutils coreutils package.
2+
//
3+
// For the full copyright and license information, please view the LICENSE
4+
// file that was distributed with this source code.
5+
6+
use std::collections::HashMap;
7+
use std::fs::{self, File};
8+
use std::io::Write;
9+
use std::path::Path;
10+
11+
/// Generate embedded locale strings from .ftl files
12+
///
13+
/// # Arguments
14+
/// * `out_dir` - The output directory for generated files
15+
/// * `project_root` - The root directory of the project
16+
///
17+
/// # Errors
18+
///
19+
/// Returns an error if file operations fail or if there are I/O issues
20+
pub fn generate_embedded_locale_strings(
21+
out_dir: &str,
22+
project_root: &Path,
23+
) -> Result<(), Box<dyn std::error::Error>> {
24+
let mut all_strings = HashMap::new();
25+
26+
// Collect all English strings from all utilities
27+
let uu_dir = project_root.join("src/uu");
28+
if uu_dir.exists() {
29+
for entry in fs::read_dir(&uu_dir)? {
30+
let entry = entry?;
31+
let path = entry.path();
32+
if path.is_dir() {
33+
let locale_path = path.join("locales/en-US.ftl");
34+
if locale_path.exists() {
35+
let content = fs::read_to_string(&locale_path)?;
36+
parse_fluent_content(&content, &mut all_strings);
37+
}
38+
}
39+
}
40+
}
41+
42+
// Also collect common locale strings from uucore if they exist
43+
let common_locale_path = project_root.join("src/uucore/locales/en-US.ftl");
44+
if common_locale_path.exists() {
45+
let content = fs::read_to_string(&common_locale_path)?;
46+
parse_fluent_content(&content, &mut all_strings);
47+
}
48+
49+
// Generate Rust code with embedded strings
50+
generate_embedded_rust_code(out_dir, &all_strings)?;
51+
Ok(())
52+
}
53+
54+
/// Parse Fluent file content and extract key-value pairs
55+
fn parse_fluent_content(content: &str, all_strings: &mut HashMap<String, String>) {
56+
for line in content.lines() {
57+
let line = line.trim();
58+
if line.is_empty() || line.starts_with('#') {
59+
continue;
60+
}
61+
62+
if let Some(equals_pos) = line.find(" = ") {
63+
let key = line[..equals_pos].trim();
64+
let value = line[equals_pos + 3..].trim();
65+
all_strings.insert(key.to_string(), value.to_string());
66+
}
67+
}
68+
}
69+
70+
/// Generate Rust code with embedded strings as individual consts and lookup function
71+
///
72+
/// # Errors
73+
///
74+
/// Returns an error if file creation or writing operations fail
75+
fn generate_embedded_rust_code(
76+
out_dir: &str,
77+
all_strings: &HashMap<String, String>,
78+
) -> Result<(), Box<dyn std::error::Error>> {
79+
let mut embedded_file = File::create(Path::new(out_dir).join("embedded_locale.rs"))?;
80+
81+
writeln!(embedded_file, "// Generated at compile time - do not edit")?;
82+
writeln!(embedded_file)?;
83+
84+
// Generate individual const strings
85+
for (key, value) in all_strings {
86+
let const_name = create_rust_identifier(key);
87+
88+
// Escape the value for Rust string literal
89+
let escaped_value = value
90+
.replace('\\', "\\\\")
91+
.replace('"', "\\\"")
92+
.replace('\n', "\\n");
93+
writeln!(
94+
embedded_file,
95+
"pub const {const_name}: &str = {escaped_value:?};"
96+
)?;
97+
}
98+
99+
writeln!(embedded_file)?;
100+
101+
// Generate lookup function
102+
writeln!(
103+
embedded_file,
104+
"pub fn get_embedded_string(id: &str) -> Option<&'static str> {{"
105+
)?;
106+
writeln!(embedded_file, "match id {{")?;
107+
108+
for key in all_strings.keys() {
109+
let const_name = create_rust_identifier(key);
110+
writeln!(embedded_file, " {key:?} => Some({const_name}),")?;
111+
}
112+
113+
writeln!(embedded_file, " _ => None,")?;
114+
writeln!(embedded_file, " }}")?;
115+
writeln!(embedded_file, "}}")?;
116+
117+
embedded_file.flush()?;
118+
Ok(())
119+
}
120+
121+
/// Create a valid Rust identifier from a Fluent key
122+
fn create_rust_identifier(key: &str) -> String {
123+
let const_name = key
124+
.chars()
125+
.map(|c| if c.is_alphanumeric() { c } else { '_' })
126+
.collect::<String>()
127+
.to_uppercase();
128+
129+
// Ensure it doesn't start with a number
130+
if const_name.chars().next().unwrap_or('_').is_numeric() {
131+
format!("S_{const_name}")
132+
} else {
133+
const_name
134+
}
135+
}

0 commit comments

Comments
 (0)