Skip to content

Commit 9346968

Browse files
committed
Refactor formatting and improve plural parsing logic
Reformats code for better readability, especially in test cases and match arms. Improves error handling and clarity in the Android plurals resource parser, and updates test assertions for consistency.
1 parent 447c9f3 commit 9346968

3 files changed

Lines changed: 75 additions & 31 deletions

File tree

langcodec/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "langcodec"
3-
version = "0.4.0"
3+
version = "0.4.1"
44
edition = "2024"
55
description = "Universal localization file toolkit for Rust. Supports Apple, Android, and CSV formats."
66
license = "MIT"

langcodec/src/converter.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -626,8 +626,13 @@ mod tests {
626626
)
627627
.unwrap();
628628

629-
convert(&input, FormatType::CSV, &output, FormatType::AndroidStrings(Some("en".into())))
630-
.unwrap();
629+
convert(
630+
&input,
631+
FormatType::CSV,
632+
&output,
633+
FormatType::AndroidStrings(Some("en".into())),
634+
)
635+
.unwrap();
631636

632637
// Read back as Android to verify
633638
let android = crate::formats::AndroidStringsFormat::read_from(&output).unwrap();
@@ -665,7 +670,10 @@ mod tests {
665670
},
666671
entries: vec![Entry {
667672
id: "apples".into(),
668-
value: Translation::Plural(Plural { id: "apples".into(), forms }),
673+
value: Translation::Plural(Plural {
674+
id: "apples".into(),
675+
forms,
676+
}),
669677
comment: Some("Count apples".into()),
670678
status: EntryStatus::Translated,
671679
custom: HashMap::new(),
@@ -677,8 +685,13 @@ mod tests {
677685
xc.write_to(&input).unwrap();
678686

679687
// Convert to Android (English)
680-
convert(&input, FormatType::Xcstrings, &output, FormatType::AndroidStrings(Some("en".into())))
681-
.unwrap();
688+
convert(
689+
&input,
690+
FormatType::Xcstrings,
691+
&output,
692+
FormatType::AndroidStrings(Some("en".into())),
693+
)
694+
.unwrap();
682695

683696
// Read back as Android
684697
let android = crate::formats::AndroidStringsFormat::read_from(&output).unwrap();
@@ -698,7 +711,7 @@ mod tests {
698711
PluralCategory::Many => ("many", i.value.clone()),
699712
})
700713
.collect();
701-
qs.sort_by(|a, b| a.0.cmp(&b.0));
714+
qs.sort_by(|a, b| a.0.cmp(b.0));
702715
assert!(qs.iter().any(|(q, v)| *q == "one" && v == "One apple"));
703716
assert!(qs.iter().any(|(q, v)| *q == "other" && v == "%d apples"));
704717
}

langcodec/src/formats/android_strings.rs

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,17 @@ impl Parser for Format {
100100
items.sort_by(|a, b| a.quantity.cmp(&b.quantity));
101101
for item in &items {
102102
let mut it = BytesStart::new("item");
103-
it.push_attribute(("quantity", match item.quantity {
104-
PluralCategory::Zero => "zero",
105-
PluralCategory::One => "one",
106-
PluralCategory::Two => "two",
107-
PluralCategory::Few => "few",
108-
PluralCategory::Many => "many",
109-
PluralCategory::Other => "other",
110-
}));
103+
it.push_attribute((
104+
"quantity",
105+
match item.quantity {
106+
PluralCategory::Zero => "zero",
107+
PluralCategory::One => "one",
108+
PluralCategory::Two => "two",
109+
PluralCategory::Few => "few",
110+
PluralCategory::Many => "many",
111+
PluralCategory::Other => "other",
112+
},
113+
));
111114
xml_writer.write_event(Event::Start(it))?;
112115
xml_writer.write_event(Event::Text(BytesText::new(&item.value)))?;
113116
xml_writer.write_event(Event::End(BytesEnd::new("item")))?;
@@ -165,11 +168,7 @@ impl From<Resource> for Format {
165168

166169
impl From<Format> for Resource {
167170
fn from(value: Format) -> Self {
168-
let mut entries: Vec<Entry> = value
169-
.strings
170-
.iter()
171-
.map(StringResource::to_entry)
172-
.collect();
171+
let mut entries: Vec<Entry> = value.strings.iter().map(StringResource::to_entry).collect();
173172

174173
// Convert plurals to entries
175174
for pr in &value.plurals {
@@ -191,7 +190,10 @@ impl From<Format> for Resource {
191190
};
192191
entries.push(Entry {
193192
id: pr.name.clone(),
194-
value: Translation::Plural(Plural { id: pr.name.clone(), forms }),
193+
value: Translation::Plural(Plural {
194+
id: pr.name.clone(),
195+
forms,
196+
}),
195197
comment: None,
196198
status,
197199
custom: HashMap::new(),
@@ -323,7 +325,8 @@ fn parse_plurals_resource<R: BufRead>(
323325
_ => {}
324326
}
325327
}
326-
let name = name.ok_or_else(|| Error::InvalidResource("plurals tag missing 'name'".to_string()))?;
328+
let name =
329+
name.ok_or_else(|| Error::InvalidResource("plurals tag missing 'name'".to_string()))?;
327330

328331
let mut buf = Vec::new();
329332
let mut items: Vec<PluralItem> = Vec::new();
@@ -339,17 +342,22 @@ fn parse_plurals_resource<R: BufRead>(
339342
quantity = PluralCategory::from_str(&v).ok();
340343
}
341344
}
342-
let quantity = quantity.ok_or_else(|| Error::InvalidResource("item missing 'quantity'".to_string()))?;
345+
let quantity = quantity
346+
.ok_or_else(|| Error::InvalidResource("item missing 'quantity'".to_string()))?;
343347
// Read text content until End(item)
344348
let mut value = String::new();
345349
let mut local_buf = Vec::new();
346350
loop {
347351
match xml_reader.read_event_into(&mut local_buf) {
348352
Ok(Event::Text(e)) => {
349-
value.push_str(&e.unescape().map_err(Error::XmlParse)?.to_string());
353+
value.push_str(e.unescape().map_err(Error::XmlParse)?.as_ref());
350354
}
351355
Ok(Event::End(ref end)) if end.name().as_ref() == b"item" => break,
352-
Ok(Event::Eof) => return Err(Error::InvalidResource("Unexpected EOF inside <item>".to_string())),
356+
Ok(Event::Eof) => {
357+
return Err(Error::InvalidResource(
358+
"Unexpected EOF inside <item>".to_string(),
359+
));
360+
}
353361
Ok(_) => {}
354362
Err(e) => return Err(Error::XmlParse(e)),
355363
}
@@ -358,14 +366,22 @@ fn parse_plurals_resource<R: BufRead>(
358366
items.push(PluralItem { quantity, value });
359367
}
360368
Ok(Event::End(ref end)) if end.name().as_ref() == b"plurals" => break,
361-
Ok(Event::Eof) => return Err(Error::InvalidResource("Unexpected EOF inside <plurals>".to_string())),
369+
Ok(Event::Eof) => {
370+
return Err(Error::InvalidResource(
371+
"Unexpected EOF inside <plurals>".to_string(),
372+
));
373+
}
362374
Ok(_) => {}
363375
Err(e) => return Err(Error::XmlParse(e)),
364376
}
365377
buf.clear();
366378
}
367379

368-
Ok(PluralsResource { name, items, translatable })
380+
Ok(PluralsResource {
381+
name,
382+
items,
383+
translatable,
384+
})
369385
}
370386

371387
#[cfg(test)]
@@ -484,10 +500,17 @@ mod tests {
484500
forms.insert(PluralCategory::Other, "%d files".to_string());
485501

486502
let resource = Resource {
487-
metadata: Metadata { language: "en".into(), domain: String::new(), custom: HashMap::new() },
503+
metadata: Metadata {
504+
language: "en".into(),
505+
domain: String::new(),
506+
custom: HashMap::new(),
507+
},
488508
entries: vec![Entry {
489509
id: "files".into(),
490-
value: Translation::Plural(Plural { id: "files".into(), forms }),
510+
value: Translation::Plural(Plural {
511+
id: "files".into(),
512+
forms,
513+
}),
491514
comment: None,
492515
status: EntryStatus::Translated,
493516
custom: HashMap::new(),
@@ -499,7 +522,15 @@ mod tests {
499522
assert_eq!(fmt.plurals.len(), 1);
500523
let pr = &fmt.plurals[0];
501524
assert_eq!(pr.name, "files");
502-
assert!(pr.items.iter().any(|i| matches!(i.quantity, PluralCategory::One) && i.value == "One file"));
503-
assert!(pr.items.iter().any(|i| matches!(i.quantity, PluralCategory::Other) && i.value == "%d files"));
525+
assert!(
526+
pr.items
527+
.iter()
528+
.any(|i| matches!(i.quantity, PluralCategory::One) && i.value == "One file")
529+
);
530+
assert!(
531+
pr.items
532+
.iter()
533+
.any(|i| matches!(i.quantity, PluralCategory::Other) && i.value == "%d files")
534+
);
504535
}
505536
}

0 commit comments

Comments
 (0)