From 593a1fe53bed1b1269e3f30f9dcea1f7c2956ee8 Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Fri, 8 Mar 2019 12:08:24 +0100
Subject: [PATCH] Added script to populate translated and contextualized
 strings if possible

---
 front/scripts/contextualize.py                | 82 +++++++++++++++++++
 .../i18n-populate-contextualized-strings.sh   | 21 +++++
 2 files changed, 103 insertions(+)
 create mode 100644 front/scripts/contextualize.py
 create mode 100755 front/scripts/i18n-populate-contextualized-strings.sh

diff --git a/front/scripts/contextualize.py b/front/scripts/contextualize.py
new file mode 100644
index 00000000..edff7214
--- /dev/null
+++ b/front/scripts/contextualize.py
@@ -0,0 +1,82 @@
+import argparse
+import polib
+
+
+def get_missing(entries):
+    """
+    Return a list of entries with:
+    - a msgcontext
+    - an empty msgstr
+    """
+    for e in entries:
+        if e.translated():
+            continue
+        yield e
+    return []
+
+
+def match(entries, other_entries):
+    """
+    Given two list of po entries, will return a list of 2-tuples with
+    match from the second list
+    """
+
+    by_id = {}
+    for e in other_entries:
+        is_translated = bool(e.msgstr)
+        if not is_translated:
+            continue
+        by_id[e.msgid] = e
+
+    matches = []
+    for e in entries:
+        matches.append((e, by_id.get(e.msgid)))
+
+    return matches
+
+
+def update(new, old):
+    """
+    Update a new po entry with translation from the first one (removing fuzzy if needed)
+    """
+    new.msgstr = old.msgstr
+    new.flags = [f for f in new.flags if f != "fuzzy"]
+
+
+def contextualize(old_po, new_po, edit=False):
+    old = polib.pofile(old_po)
+    new = polib.pofile(new_po)
+    missing = list(get_missing(new))
+    print(
+        "Found {} entries with contexts and missing translations ({} total)".format(
+            len(missing), len(new)
+        )
+    )
+    matches = match(missing, old)
+    found = [m for m in matches if m[1] is not None]
+    print("Found {} matching entries".format(len(found)))
+    if edit:
+        print("Applying changes")
+        for matched, matching in found:
+            update(matched, matching)
+        new.save()
+    else:
+        print("--no-dry-run not provided, not applying change")
+
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(
+        description="""
+        Given two .po file paths, it will populate empty contextualized messages
+        in the second one with matching message IDs from the first one, if any.
+
+        This is especially helpful when you add some contexts on existing translated strings
+        but don't want to have those being retranslated.
+    """
+    )
+    parser.add_argument("old_po", help="Path of the po file to use as a source")
+    parser.add_argument("new_po", help="Path of the po file to populate")
+    parser.add_argument("--no-dry-run", action="store_true")
+    args = parser.parse_args()
+
+    contextualize(old_po=args.old_po, new_po=args.new_po, edit=args.no_dry_run)
diff --git a/front/scripts/i18n-populate-contextualized-strings.sh b/front/scripts/i18n-populate-contextualized-strings.sh
new file mode 100755
index 00000000..fa47eb4d
--- /dev/null
+++ b/front/scripts/i18n-populate-contextualized-strings.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -eu
+
+# Typical use:
+# cp -r locales old_locales
+# ./scripts/i18n-extract.sh
+# ./scripts/i18n-populate-contextualized-strings.sh old_locales locales
+# Then review/commit the changes
+
+old_locales_dir=$1
+new_locales_dir=$2
+
+locales=$(tail -n +2 src/locales.js | sed -e 's/export default //' | jq '.locales[].code' | xargs echo)
+
+# Generate .po files for each available language.
+echo $locales
+for lang in $locales; do
+    echo "Fixing contexts for $lang…"
+    old_po_file=$old_locales_dir/$lang/LC_MESSAGES/app.po
+    new_po_file=$new_locales_dir/$lang/LC_MESSAGES/app.po
+    python3 ./scripts/contextualize.py $old_po_file $new_po_file --no-dry-run
+done;
-- 
GitLab