summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-07-14 14:40:26 +0000
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-08-11 22:59:38 +0000
commit5e115bb29295faf2e4d8fc619059279cee2fa628 (patch)
treedf0f7a42346784540a10c09782d85502a46ce569 /android
parent1595af8a77c2574aac466150031d5f1ed865fd27 (diff)
downloadmullvadvpn-5e115bb29295faf2e4d8fc619059279cee2fa628.tar.xz
mullvadvpn-5e115bb29295faf2e4d8fc619059279cee2fa628.zip
Handle translation messages with parameters
Diffstat (limited to 'android')
-rw-r--r--android/translations-converter/src/android.rs13
-rw-r--r--android/translations-converter/src/gettext.rs11
-rw-r--r--android/translations-converter/src/main.rs11
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