Skip to content

Commit 5c44952

Browse files
committed
Fix the ftl things a bit more
1 parent 94534cf commit 5c44952

File tree

4 files changed

+96
-48
lines changed

4 files changed

+96
-48
lines changed

build/util.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export function getEnvVars(target?: string): Record<string, string> {
5555
HFST_SYSROOT: sysroot,
5656
CG3_SYSROOT: sysroot,
5757
LIBTORCH_STATIC: "1",
58+
LIBTORCH_INCLUDE: sysroot,
5859
};
5960

6061
// Use clang-cl on Windows for C/C++ compilation

src/modules/divvun/suggest.rs

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,31 @@ use std::io::Write;
1313
use std::ops::Deref;
1414
use std::{collections::HashMap, fs, sync::Arc};
1515

16+
fn encode_unicode_identifier(s: &str) -> String {
17+
let mut result = String::new();
18+
19+
for ch in s.chars() {
20+
match ch {
21+
'a'..='z' => result.push(ch),
22+
'A'..='Z' => result.push(ch.to_ascii_lowercase()),
23+
'0'..='9' => result.push(ch),
24+
'-' => result.push(ch),
25+
' ' => result.push('-'),
26+
c if c.is_ascii_punctuation() => result.push('_'),
27+
c => {
28+
let code_point = c as u32;
29+
if code_point <= 0xFFFF {
30+
result.push_str(&format!("_u{:04X}", code_point));
31+
} else {
32+
result.push_str(&format!("_U{:06X}", code_point));
33+
}
34+
}
35+
}
36+
}
37+
38+
result
39+
}
40+
1641
#[derive(Deserialize)]
1742
struct ErrorJsonEntry {
1843
id: Option<String>,
@@ -1148,24 +1173,28 @@ impl<'a> Suggester<'a> {
11481173

11491174
// Use FluentLoader for message resolution
11501175
let mut args = FluentArgs::new();
1151-
args.set("1", c.form.as_str());
1152-
1153-
let mut msg = match self
1154-
.fluent_loader
1155-
.get_message(Some(&self.locale), err_id, Some(&args))
1156-
{
1157-
Ok((title, desc)) => (title, desc),
1158-
Err(_) => {
1159-
// Fallback to default locale if message not found
1160-
match self.fluent_loader.get_message(None, err_id, Some(&args)) {
1161-
Ok((title, desc)) => (title, desc),
1162-
Err(_) => {
1163-
tracing::debug!("WARNING: No Fluent message for \"{}\"", err_id);
1164-
(err_id.to_string(), err_id.to_string())
1176+
args.set("arg1", c.form.as_str());
1177+
1178+
// Mangle the error ID to match FTL keys
1179+
let ftl_key = encode_unicode_identifier(err_id);
1180+
1181+
let mut msg =
1182+
match self
1183+
.fluent_loader
1184+
.get_message(Some(&self.locale), &ftl_key, Some(&args))
1185+
{
1186+
Ok((title, desc)) => (title, desc),
1187+
Err(_) => {
1188+
// Fallback to default locale if message not found
1189+
match self.fluent_loader.get_message(None, &ftl_key, Some(&args)) {
1190+
Ok((title, desc)) => (title, desc),
1191+
Err(_) => {
1192+
tracing::debug!("WARNING: No Fluent message for \"{}\"", ftl_key);
1193+
(err_id.to_string(), err_id.to_string())
1194+
}
11651195
}
11661196
}
1167-
}
1168-
};
1197+
};
11691198
// End set msg
11701199
// Begin set beg, end, form, rep:
11711200
let mut start = c.pos;

xml-conv/src/fluent.rs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ pub fn to_fluent(doc: &ErrorDocument, lang: &str) -> String {
7373
fn format_default(default: &Default, lang: &str) -> String {
7474
let mut output = String::new();
7575

76+
// Add comment with original title if it was mangled
77+
let simple_id = format!("err-{}", default.original_title);
78+
if default.id != simple_id {
79+
output.push_str(&format!(
80+
"# err-{}\n",
81+
default.original_title.to_lowercase()
82+
));
83+
}
84+
7685
// Add comment showing all patterns/IDs
7786
output.push_str("## Default patterns: ");
7887
let patterns: Vec<String> = default
@@ -95,16 +104,18 @@ fn format_default(default: &Default, lang: &str) -> String {
95104
// Use the stable kebab-case ID
96105
output.push_str(&format!("{} = {}\n", default.id, title));
97106
output.push_str(&format!(" .desc = {}\n", convert_variables(desc)));
98-
add_refs(&mut output, None);
99107

100108
output
101109
}
102110

103111
fn format_error(error: &Error, lang: &str) -> String {
104112
let mut output = String::new();
105113

106-
// Use error ID directly as message ID
107-
let message_id = &error.id;
114+
// Add comment with original ID if it was mangled
115+
let simple_id = format!("err-{}", error.original_id);
116+
if error.id != simple_id {
117+
output.push_str(&format!("# err-{}\n", error.original_id.to_lowercase()));
118+
}
108119

109120
// Get title and description for this language
110121
let missing_title = format!("[Missing title for {}]", lang);
@@ -113,41 +124,29 @@ fn format_error(error: &Error, lang: &str) -> String {
113124
let desc = error.body.descriptions.get(lang).unwrap_or(&missing_desc);
114125

115126
// Format the message
116-
output.push_str(&format!("{} = {}\n", message_id, title));
127+
output.push_str(&format!("{} = {}\n", error.id, title));
117128
output.push_str(&format!(" .desc = {}\n", convert_variables(desc)));
118129

119-
// Add references
120-
add_refs(&mut output, error.header.references.as_ref());
121-
122130
output
123131
}
124132

125-
fn add_refs(output: &mut String, references: Option<&Vec<crate::Reference>>) {
126-
// Add references if any
127-
if let Some(references) = references {
128-
for (i, reference) in references.iter().enumerate() {
129-
output.push_str(&format!(" .ref-{} = {}\n", i + 1, reference.n));
130-
}
131-
}
132-
}
133-
134133
fn convert_variables(text: &str) -> String {
135-
// Convert $1, $2, etc. to {$1}, {$2}, etc. for Fluent
134+
// Convert $1, $2, etc. to {$arg1}, {$arg2}, etc. for Fluent
136135
let mut result = text.to_string();
137136

138-
// Replace quoted variables like "$1" with "{$1}"
137+
// Replace quoted variables like "$1" with "{$arg1}"
139138
for i in 1..=9 {
140139
let old_pattern = format!("\"${}\"", i);
141-
let new_pattern = format!("{{${}}}", i);
140+
let new_pattern = format!("{{$arg{}}}", i);
142141
result = result.replace(&old_pattern, &new_pattern);
143142
}
144143

145-
// Replace unquoted variables like $1 with {$1}
144+
// Replace unquoted variables like $1 with {$arg1}
146145
for i in 1..=9 {
147146
let old_pattern = format!("${}", i);
148-
let new_pattern = format!("{{${}}}", i);
147+
let new_pattern = format!("{{$arg{}}}", i);
149148
// Only replace if not already in braces
150-
if !result.contains(&format!("{{${}}}", i)) {
149+
if !result.contains(&format!("{{$arg{}}}", i)) {
151150
result = result.replace(&old_pattern, &new_pattern);
152151
}
153152
}
@@ -177,15 +176,20 @@ pub fn generate_errors_metadata(doc: &ErrorDocument) -> Result<String> {
177176
}
178177
}
179178

180-
metadata.insert(default.id.clone(), Value::Array(patterns));
179+
let key = format!(
180+
"err-{}",
181+
default.original_title.to_lowercase().replace(' ', "-")
182+
);
183+
metadata.insert(key, Value::Array(patterns));
181184
}
182185

183186
// Add ordinary errors
184187
for error in &doc.errors {
185188
let mut id_obj = Map::new();
186-
id_obj.insert("id".to_string(), Value::String(error.id.clone()));
189+
id_obj.insert("id".to_string(), Value::String(error.original_id.clone()));
187190
let patterns = vec![Value::Object(id_obj)];
188-
metadata.insert(error.id.clone(), Value::Array(patterns));
191+
let key = format!("err-{}", error.original_id.to_lowercase().replace(' ', "-"));
192+
metadata.insert(key, Value::Array(patterns));
189193
}
190194

191195
// Convert to pretty-printed JSON

xml-conv/src/lib.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub struct ErrorDocument {
1414
#[derive(Debug, Serialize, Deserialize)]
1515
pub struct Default {
1616
pub id: String,
17+
pub original_title: String,
1718
pub ids: Vec<Id>,
1819
pub header: Header,
1920
pub body: Body,
@@ -22,6 +23,7 @@ pub struct Default {
2223
#[derive(Debug, Serialize, Deserialize)]
2324
pub struct Error {
2425
pub id: String,
26+
pub original_id: String,
2527
pub header: Header,
2628
pub body: Body,
2729
}
@@ -202,25 +204,28 @@ fn parse_default(element: &Element, doc: &Document) -> Result<Default> {
202204
let body = body.ok_or_else(|| anyhow!("Missing body in default"))?;
203205

204206
// Generate encoded ID from English title
205-
let id = header
207+
let original_title = header
206208
.titles
207209
.get("en")
208-
.map(|title| encode_unicode_identifier(title))
210+
.cloned()
209211
.unwrap_or_else(|| "unknown-default".to_string());
212+
let id = format!("err-{}", encode_unicode_identifier(&original_title));
210213

211214
Ok(Default {
212215
id,
216+
original_title,
213217
ids,
214218
header,
215219
body,
216220
})
217221
}
218222

219223
fn parse_error(element: &Element, doc: &Document) -> Result<Error> {
220-
let id = element
224+
let original_id = element
221225
.attribute(doc, "id")
222-
.ok_or_else(|| anyhow!("Error missing id attribute"))?;
223-
let id = encode_unicode_identifier(id);
226+
.ok_or_else(|| anyhow!("Error missing id attribute"))?
227+
.to_string();
228+
let id = format!("err-{}", encode_unicode_identifier(&original_id));
224229

225230
let mut header = None;
226231
let mut body = None;
@@ -239,6 +244,7 @@ fn parse_error(element: &Element, doc: &Document) -> Result<Error> {
239244

240245
Ok(Error {
241246
id,
247+
original_id,
242248
header: header.ok_or_else(|| anyhow!("Missing header in error"))?,
243249
body: body.ok_or_else(|| anyhow!("Missing body in error"))?,
244250
})
@@ -277,7 +283,11 @@ fn parse_header(element: &Element, doc: &Document) -> Result<Header> {
277283
for child in element.children(doc) {
278284
match child.name(doc) {
279285
"title" => {
280-
let lang = child.attribute(doc, "lang").unwrap_or("en").to_string();
286+
let lang = child
287+
.attribute(doc, "xml:lang")
288+
.or_else(|| child.attribute(doc, "lang"))
289+
.unwrap_or("en")
290+
.to_string();
281291
let text = get_element_text(&child, doc);
282292
titles.insert(lang, text);
283293
}
@@ -298,7 +308,11 @@ fn parse_body(element: &Element, doc: &Document) -> Result<Body> {
298308
for child in element.children(doc) {
299309
match child.name(doc) {
300310
"description" => {
301-
let lang = child.attribute(doc, "lang").unwrap_or("en").to_string();
311+
let lang = child
312+
.attribute(doc, "xml:lang")
313+
.or_else(|| child.attribute(doc, "lang"))
314+
.unwrap_or("en")
315+
.to_string();
302316
let text = get_element_text(&child, doc);
303317
descriptions.insert(lang, text);
304318
}

0 commit comments

Comments
 (0)