summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-07-13 21:34:21 +0000
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-08-11 22:59:38 +0000
commitf833d26e5a14519bfd363d5c79f3227c4419f5d1 (patch)
treeab679a5e33066b221de22ca3d6a180e19d1dc041 /android
parent03b7ab4bacb627198ee45ec9dbce627c29f871a5 (diff)
downloadmullvadvpn-f833d26e5a14519bfd363d5c79f3227c4419f5d1.tar.xz
mullvadvpn-f833d26e5a14519bfd363d5c79f3227c4419f5d1.zip
Refactor Android string resource normalization
Diffstat (limited to 'android')
-rw-r--r--android/translations-converter/Cargo.toml1
-rw-r--r--android/translations-converter/src/android.rs28
-rw-r--r--android/translations-converter/src/main.rs19
3 files changed, 38 insertions, 10 deletions
diff --git a/android/translations-converter/Cargo.toml b/android/translations-converter/Cargo.toml
index fab9c4484d..2b32cd9303 100644
--- a/android/translations-converter/Cargo.toml
+++ b/android/translations-converter/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+lazy_static = "1"
regex = "1"
serde = { version = "1", features = ["derive"] }
serde-xml-rs = "0.4"
diff --git a/android/translations-converter/src/android.rs b/android/translations-converter/src/android.rs
index 9a7fd1c99a..2481d27a4e 100644
--- a/android/translations-converter/src/android.rs
+++ b/android/translations-converter/src/android.rs
@@ -1,9 +1,16 @@
+use lazy_static::lazy_static;
+use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{
fmt::{self, Display, Formatter},
ops::{Deref, DerefMut},
};
+lazy_static! {
+ static ref LINE_BREAKS: Regex = Regex::new(r"\s*\n\s*").unwrap();
+ static ref APOSTROPHES: Regex = Regex::new(r"\\'").unwrap();
+}
+
/// Contents of an Android string resources file.
///
/// This type can be created directly deserializing the `strings.xml` file.
@@ -31,6 +38,15 @@ impl StringResources {
entries: Vec::new(),
}
}
+
+ /// Normalize the strings into a common format.
+ ///
+ /// Allows the string values to be compared to the gettext messages.
+ pub fn normalize(&mut self) {
+ for entry in &mut self.entries {
+ entry.normalize();
+ }
+ }
}
impl Deref for StringResources {
@@ -68,6 +84,18 @@ impl StringResource {
StringResource { name, value }
}
+
+ /// Normalize the string value into a common format.
+ ///
+ /// Makes it possible to compare the Android strings with the gettext messages.
+ pub fn normalize(&mut self) {
+ // Collapse line breaks present in the XML file
+ let value = LINE_BREAKS.replace_all(&self.value, " ");
+ // Unescape apostrophes
+ let value = APOSTROPHES.replace_all(&value, "'");
+
+ self.value = value.into_owned();
+ }
}
// Unfortunately, direct serialization to XML isn't working correctly.
diff --git a/android/translations-converter/src/main.rs b/android/translations-converter/src/main.rs
index 09296f87fe..24bf06a574 100644
--- a/android/translations-converter/src/main.rs
+++ b/android/translations-converter/src/main.rs
@@ -3,8 +3,12 @@
//! The procedure for converting the translations is relatively simple. The base Android string
//! resources file is first loaded, and then each gettext translation file is loaded and compared to
//! the Android base strings. For every translation string that matches exactly the Android base
-//! string value, the translated string is used in the new Android strings file for the respective
-//! locale.
+//! string value (after a normalization pass described below), the translated string is used in the
+//! 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 apostrophes are unescaped.
//!
//! 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
@@ -13,7 +17,6 @@
mod android;
mod gettext;
-use regex::Regex;
use std::{
collections::HashMap,
fs::{self, File},
@@ -24,21 +27,17 @@ fn main() {
let resources_dir = Path::new("../src/main/res");
let strings_file = File::open(resources_dir.join("values/strings.xml"))
.expect("Failed to open string resources file");
- let string_resources: android::StringResources =
+ let mut string_resources: android::StringResources =
serde_xml_rs::from_reader(strings_file).expect("Failed to read string resources file");
- let line_breaks = Regex::new(r"\s*\n\s*").unwrap();
- let apostrophes = Regex::new(r"\\'").unwrap();
+ string_resources.normalize();
let known_strings: HashMap<_, _> = string_resources
.into_iter()
.map(|string| {
let android_id = string.name;
- let without_line_breaks = line_breaks.replace_all(&string.value, " ");
- let without_escaped_apostrophes = apostrophes.replace_all(&without_line_breaks, "'");
- let string_value = without_escaped_apostrophes.into_owned();
- (string_value, android_id)
+ (string.value, android_id)
})
.collect();