From 2168b9cea1f4f76b55426591a9bcc308a620194f Mon Sep 17 00:00:00 2001 From: michael-kerscher Date: Wed, 22 May 2024 19:34:11 +0200 Subject: [PATCH] Keep Inline HTML tags in the translated text group while ignoring block level HTML tags (#195) * Keep Inline HTML tags in the translated text group while ignoring block level HTML tags * rewrite the matches!() macro into a proper match while handling Html|InlineHtml events. --- i18n-helpers/src/gettext.rs | 18 +++++++ i18n-helpers/src/lib.rs | 98 ++++++++++++++++++++++++++++------- i18n-helpers/src/normalize.rs | 28 ++++++++++ 3 files changed, 126 insertions(+), 18 deletions(-) diff --git a/i18n-helpers/src/gettext.rs b/i18n-helpers/src/gettext.rs index 7a1e667c..8c1eb31c 100644 --- a/i18n-helpers/src/gettext.rs +++ b/i18n-helpers/src/gettext.rs @@ -244,6 +244,24 @@ mod tests { ); } + #[test] + fn test_translate_inline_html() { + let catalog = create_catalog(&[("foo bar baz", "FOO BAR BAZ")]); + assert_eq!( + translate("foo bar baz", &catalog), + "FOO BAR BAZ" + ); + } + + #[test] + fn test_translate_block_html() { + let catalog = create_catalog(&[("foo", "FOO"), ("bar", "BAR")]); + assert_eq!( + translate("
\n\nfoo\n\n
\n\nbar\n\n
", &catalog), + "
\n\nFOO\n\n
\n\nBAR\n\n
" + ); + } + #[test] fn test_translate_table() { let catalog = create_catalog(&[ diff --git a/i18n-helpers/src/lib.rs b/i18n-helpers/src/lib.rs index 32720cd8..e7c5be8c 100644 --- a/i18n-helpers/src/lib.rs +++ b/i18n-helpers/src/lib.rs @@ -368,14 +368,32 @@ pub fn group_events<'a>(events: &'a [(usize, Event<'a>)]) -> Vec> { ctx.comments.push(comment); } - // Otherwise, treat as a skipping group. _ => { - if let State::Translate(_) = state { - let mut next_groups; - (next_groups, ctx) = state.into_groups(idx, events, ctx); - groups.append(&mut next_groups); - - state = State::Skip(idx); + match event { + Event::Html(_) => { + // Otherwise, treat as a skipping group if this is a block level Html tag + if let State::Translate(_) = state { + let mut next_groups; + (next_groups, ctx) = state.into_groups(idx, events, ctx); + groups.append(&mut next_groups); + + state = State::Skip(idx); + } + } + Event::InlineHtml(_) => + // If we're currently skipping, then a new + // translatable group starts here. + { + if let State::Skip(_) = state { + let mut next_groups; + (next_groups, ctx) = state.into_groups(idx, events, ctx); + groups.append(&mut next_groups); + + state = State::Translate(idx); + } + } + // this code is inside a match of Event::{Html|InlineHtml}, other types are not possible + _ => unreachable!(), } } } @@ -964,13 +982,21 @@ mod tests { } #[test] - fn extract_messages_empty_html() { - assert_extract_messages("", &[]); + fn extract_messages_keep_empty_inline_html() { + // Keep inline html tags + assert_extract_messages("", &[(1, "")]); } #[test] - fn extract_messages_whitespace_only() { - assert_extract_messages(" ", &[]); + fn extract_messages_keep_whitespace_inline_html() { + // span is an inline html tag so even whitespace is kept as is + assert_extract_messages(" ", &[(1, " ")]); + } + + #[test] + fn extract_messages_ignore_whitespace_only_block_html() { + // Whitespace in block level html tags is ignored + assert_extract_messages("

", &[]); } #[test] @@ -1028,13 +1054,36 @@ mod tests { #[test] fn extract_messages_inline_html() { - // HTML tags are skipped, but text inside is extracted: + // Inline HTML tag is kept as is in the translation. assert_extract_messages( - "Hi ", - &[ - (1, "Hi "), // - (1, "alert('there');"), - ], + "Hi from Rust", + &[(1, "Hi from Rust")], + ); + } + + #[test] + fn extract_messages_block_html() { + // block level HTML tag is skipped, but text inside is extracted. + assert_extract_messages( + "
\n\ + \n\ + Beware of the dog!\n\ + \n\ +
", + &[(3, "Beware of the dog!")], + ); + } + + #[test] + fn extract_messages_mixed_html() { + // block level HTML tag is skipped, but text inside is extracted with inline html as is. + assert_extract_messages( + "
\n\ + \n\ + Hi from Rust\n\ + \n\ +
", + &[(3, "Hi from Rust")], ); } @@ -1481,7 +1530,20 @@ But *this* should! } #[test] - fn extract_messages_inline_skips() { + fn extract_messages_block_html_skip() { + // The comment is a block level html tag. + assert_extract_messages( + "\n\ + This is ignored\n\ + \n\ + but this is not", + &[(4, "but this is not")], + ); + } + + #[test] + fn extract_messages_inline_html_skips() { + // The comment is an inline html tag. assert_extract_messages( " this should be translated but not this. diff --git a/i18n-helpers/src/normalize.rs b/i18n-helpers/src/normalize.rs index 68207ee6..864389f2 100644 --- a/i18n-helpers/src/normalize.rs +++ b/i18n-helpers/src/normalize.rs @@ -460,6 +460,34 @@ mod tests { ); } + #[test] + fn test_normalize_inline_html() { + // Inline tags are kept as is. + let catalog = create_catalog(&[("foo bar", "FOO BAR")]); + assert_normalized_messages_eq( + catalog, + &[exact("foo bar", "FOO BAR")], + ); + } + + #[test] + fn test_normalize_block_html() { + // Block level tags are not translated. + let catalog = create_catalog(&[( + "
\n\ + \n\ + foo\n\ + \n\ +
", + "
\n\ + \n\ + FOO\n\ + \n\ +
", + )]); + assert_normalized_messages_eq(catalog, &[exact("foo", "FOO")]); + } + #[test] fn test_normalize_disappearing_html() { // Normalizing "" results in no messages.