Last active
May 13, 2025 08:01
-
-
Save flodolo/a64de8a09e80dae7d40c37a3d4112bbb to your computer and use it in GitHub Desktop.
Firefox iOS completetion stats based on .strings files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
Script to determine localization completion based on .strings files. | |
""" | |
import re | |
import sys | |
from pathlib import Path | |
def find_strings_files(locale: str, root: Path): | |
"""Recursively find all .strings files in en-US.lproj directories.""" | |
search_path = root / "firefox-ios" | |
return search_path.rglob(f"{locale}.lproj/*.strings") | |
def extract_keys_from_strings_file(strings_path: Path, root: Path): | |
"""Extract all keys from a .strings file.""" | |
pattern = re.compile(r'^\s*"([^"]+)"\s*=') | |
keys = [] | |
strings_rel_path = strings_path.relative_to(root) | |
with strings_path.open("r", encoding="utf-8") as f: | |
for line in f: | |
match = pattern.match(line) | |
if match: | |
keys.append(f"{strings_rel_path}:{match.group(1)}") | |
return keys | |
def find_locales(root: Path): | |
"""Guess locales from firefox-ios/Client/*.lproj folders.""" | |
search_path = root / "firefox-ios" / "Client" | |
folders = search_path.glob("*.lproj") | |
locales = [ | |
str(locale.relative_to(search_path)).removesuffix(".lproj") | |
for locale in folders | |
if locale.is_dir() and locale.name not in ["en-US.lproj", "en.lproj"] | |
] | |
locales.sort() | |
return locales | |
def main(root_dir: Path): | |
ref_locale = "en-US" | |
# Gather all keys from the en-US .strings files | |
reference_keys = set() | |
for strings_file in find_strings_files(ref_locale, root_dir): | |
reference_keys.update(extract_keys_from_strings_file(strings_file, root_dir)) | |
locales = find_locales(root_dir) | |
stats = {} | |
total_ref_keys = len(reference_keys) | |
for locale in locales: | |
missing = 0 | |
# Gather all keys from the locale .strings files | |
locale_keys = set() | |
for strings_file in find_strings_files(locale, root_dir): | |
locale_keys.update(extract_keys_from_strings_file(strings_file, root_dir)) | |
for ref_key in reference_keys: | |
if ref_key.replace(ref_locale, locale) not in locale_keys: | |
missing += 1 | |
stats[locale] = { | |
"missing": missing, | |
"total": len(locale_keys), | |
"completion": round(((total_ref_keys - missing) / total_ref_keys) * 100, 2), | |
} | |
print("Locale completion stats:") | |
for locale in locales: | |
print(f" {locale}: {stats[locale]['completion']}%") | |
if __name__ == "__main__": | |
root = ( | |
Path(sys.argv[1]) | |
if len(sys.argv) > 1 | |
else sys.exit("Provide the path to the Firefox iOS repo.") | |
) | |
main(root) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment