diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-07-14 14:40:26 +0000 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-08-11 22:59:38 +0000 |
| commit | 5e115bb29295faf2e4d8fc619059279cee2fa628 (patch) | |
| tree | df0f7a42346784540a10c09782d85502a46ce569 /android | |
| parent | 1595af8a77c2574aac466150031d5f1ed865fd27 (diff) | |
| download | mullvadvpn-5e115bb29295faf2e4d8fc619059279cee2fa628.tar.xz mullvadvpn-5e115bb29295faf2e4d8fc619059279cee2fa628.zip | |
Handle translation messages with parameters
Diffstat (limited to 'android')
| -rw-r--r-- | android/translations-converter/src/android.rs | 13 | ||||
| -rw-r--r-- | android/translations-converter/src/gettext.rs | 11 | ||||
| -rw-r--r-- | android/translations-converter/src/main.rs | 11 |
3 files changed, 29 insertions, 6 deletions
diff --git a/android/translations-converter/src/android.rs b/android/translations-converter/src/android.rs index 2481d27a4e..c9554902ac 100644 --- a/android/translations-converter/src/android.rs +++ b/android/translations-converter/src/android.rs @@ -9,6 +9,7 @@ use std::{ lazy_static! { static ref LINE_BREAKS: Regex = Regex::new(r"\s*\n\s*").unwrap(); static ref APOSTROPHES: Regex = Regex::new(r"\\'").unwrap(); + static ref PARAMETERS: Regex = Regex::new(r"%[0-9]*\$").unwrap(); } /// Contents of an Android string resources file. @@ -77,11 +78,19 @@ impl StringResource { /// /// The name is the resource ID, and the value will be properly escaped. pub fn new(name: String, value: &str) -> Self { - let value = value + let value_with_parameters = value .replace(r"\", r"\\") .replace("\"", "\\\"") .replace(r"'", r"\'"); + let mut parts = value_with_parameters.split("%"); + let mut value = parts.next().unwrap().to_owned(); + + for (index, part) in parts.enumerate() { + value.push_str(&format!("%{}$", index + 1)); + value.push_str(part); + } + StringResource { name, value } } @@ -93,6 +102,8 @@ impl StringResource { let value = LINE_BREAKS.replace_all(&self.value, " "); // Unescape apostrophes let value = APOSTROPHES.replace_all(&value, "'"); + // Mark where parameters are positioned, removing the parameter index + let value = PARAMETERS.replace_all(&value, "%"); self.value = value.into_owned(); } diff --git a/android/translations-converter/src/gettext.rs b/android/translations-converter/src/gettext.rs index 8f10ff6f8d..b4b241502d 100644 --- a/android/translations-converter/src/gettext.rs +++ b/android/translations-converter/src/gettext.rs @@ -8,6 +8,7 @@ use std::{ lazy_static! { static ref APOSTROPHE_VARIATION: Regex = Regex::new("’").unwrap(); + static ref PARAMETERS: Regex = Regex::new(r"%\([^)]*\)").unwrap(); } /// A message entry in a gettext translation file. @@ -33,8 +34,10 @@ pub fn load_file(file_path: impl AsRef<Path>) -> Vec<MsgEntry> { if let Some(msg_id) = parse_line(line, "msgid \"", "\"") { current_id = Some(normalize(msg_id)); } else { - if let Some(value) = parse_line(line, "msgstr \"", "\"").map(String::from) { + if let Some(translation) = parse_line(line, "msgstr \"", "\"") { if let Some(id) = current_id.take() { + let value = normalize(translation); + entries.push(MsgEntry { id, value }); } } @@ -59,5 +62,9 @@ fn parse_line<'l>(line: &'l str, prefix: &str, suffix: &str) -> Option<&'l str> fn normalize(string: &str) -> String { // Use a single common apostrophe character - APOSTROPHE_VARIATION.replace_all(&string, "'").into_owned() + let string = APOSTROPHE_VARIATION.replace_all(&string, "'"); + // Mark where parameters are positioned, removing the parameter name + let string = PARAMETERS.replace_all(&string, "%"); + + string.into_owned() } diff --git a/android/translations-converter/src/main.rs b/android/translations-converter/src/main.rs index 0ec1b2e34f..487f86122c 100644 --- a/android/translations-converter/src/main.rs +++ b/android/translations-converter/src/main.rs @@ -7,9 +7,14 @@ //! new Android strings file for the respective locale. //! //! To make the comparison work on most strings, the Android and gettext messages are normalized -//! first. This means that new lines in the XML files are removed and collapsed into a single space -//! and there is also a small workaround for having different apostrophe characters in the GUI in -//! some messages. +//! first. This means that new lines in the XML files are removed and collapsed into a single space, +//! the message parameters are changed so that they are in a common format, and there is also a +//! small workaround for having different apostrophe characters in the GUI in some messages. +//! +//! One dangerous assumption for the normalization is that the named parameters for the GUI are +//! supplied in the declared order on Android. This is because it's not possible to figure out the +//! order when only named parameters are used, and Android strings only supported numbered +//! parameters. //! //! Note that this conversion procedure is very raw and likely very brittle, so while it works for //! most cases, it is important to keep in mind that this is just a helper tool and manual steps are |
