diff --git a/i18n-helpers/src/xgettext.rs b/i18n-helpers/src/xgettext.rs index 339991ed..a7b80594 100644 --- a/i18n-helpers/src/xgettext.rs +++ b/i18n-helpers/src/xgettext.rs @@ -21,7 +21,7 @@ use anyhow::{anyhow, Context}; use mdbook::renderer::RenderContext; use mdbook::BookItem; use polib::catalog::Catalog; -use polib::message::Message; +use polib::message::{Message, MessageMutView, MessageView}; use polib::metadata::CatalogMetadata; use pulldown_cmark::{Event, Tag}; @@ -41,7 +41,7 @@ fn strip_link(text: &str) -> String { fn add_message(catalog: &mut Catalog, msgid: &str, source: &str) { let sources = match catalog.find_message(None, msgid, None) { - Some(msg) => wrap_sources(&format!("{}\n{}", msg.source(), source)), + Some(msg) => format!("{}\n{}", msg.source(), source), None => String::from(source), }; let message = Message::build_singular() @@ -76,6 +76,16 @@ fn build_source>(path: P, lineno: usize, granularity: usize } } +fn dedup_sources(catalog: &mut Catalog) { + for mut message in catalog.messages_mut() { + let mut lines: Vec<&str> = message.source().lines().collect(); + lines.dedup(); + + let wrapped_source = wrap_sources(&lines.join("\n")); + *message.source_mut() = wrapped_source; + } +} + /// Build catalog from RenderContext /// /// # Arguments @@ -144,6 +154,8 @@ where } } + dedup_sources(&mut catalog); + Ok(catalog) } @@ -398,4 +410,39 @@ mod tests { Ok(()) } + + #[test] + fn test_create_catalog_lineno_granularity_duplicates() -> anyhow::Result<()> { + let (ctx, _tmp) = create_render_context(&[ + ( + "book.toml", + "[book]\n\ + [output.xgettext]\n\ + granularity = 3", + ), + ("src/SUMMARY.md", "- [Foo](foo.md)"), + ( + "src/foo.md", + "Bar\n\ + \n\ + Bar\n\ + \n\ + Bar\n", + ), + ])?; + + let catalog = create_catalog(&ctx, std::fs::read_to_string)?; + assert_eq!( + catalog + .messages() + .map(|msg| (msg.source(), msg.msgid())) + .collect::>(), + &[ + ("src/SUMMARY.md:1", "Foo"), + ("src/foo.md:1 src/foo.md:3", "Bar"), + ] + ); + + Ok(()) + } }