1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-08-01 19:18:28 -04:00

i18n: term overhaul

- Delete ~160-ish useless terms
- Add context to more terms
- Add a mechanism to duplicate the same terms with different contexts
- sync
This commit is contained in:
bbedward
2026-07-16 12:15:20 -04:00
parent 6c45413d7a
commit 3c0f2cbc48
83 changed files with 19570 additions and 20947 deletions
+82 -41
View File
@@ -18,11 +18,29 @@ def spans_overlap(a, b):
def extract_qstr_strings(root_dir):
translations = defaultdict(lambda: {'contexts': set(), 'occurrences': []})
translations = defaultdict(lambda: {
'contexts': set(),
'real_contexts': defaultdict(list),
'occurrences': [],
'plain_occurrences': []
})
qstr_patterns = [
(re.compile(r'qsTr\(\s*"((?:\\.|[^"\\])*)"\s*\)'), '"'),
(re.compile(r"qsTr\(\s*'((?:\\.|[^'\\])*)'\s*\)"), "'")
]
# I18n.tr(term, context, true) -- the literal `true` flag uploads the
# context as a real POEditor context, giving (term, context) its own
# translation slot. Must be on one line with a literal `true`.
i18n_real_context_patterns = [
(
re.compile(r'I18n\.tr\(\s*"((?:\\.|[^"\\])*)"\s*,\s*"((?:\\.|[^"\\])*)"\s*,\s*true\s*\)'),
'"'
),
(
re.compile(r"I18n\.tr\(\s*'((?:\\.|[^'\\])*)'\s*,\s*'((?:\\.|[^'\\])*)'\s*,\s*true\s*\)"),
"'"
)
]
i18n_context_patterns = [
(
re.compile(r'I18n\.tr\(\s*"((?:\\.|[^"\\])*)"\s*,\s*"((?:\\.|[^"\\])*)"\s*\)'),
@@ -46,75 +64,96 @@ def extract_qstr_strings(root_dir):
for pattern, quote in qstr_patterns:
for match in pattern.finditer(line):
term = decode_string_literal(match.group(1), quote)
translations[term]['occurrences'].append({
'file': str(relative_path),
'line': line_num
})
occ = {'file': str(relative_path), 'line': line_num}
translations[term]['occurrences'].append(occ)
translations[term]['plain_occurrences'].append(occ)
real_spans = []
for pattern, quote in i18n_real_context_patterns:
for match in pattern.finditer(line):
term = decode_string_literal(match.group(1), quote)
context = decode_string_literal(match.group(2), quote)
occ = {'file': str(relative_path), 'line': line_num}
translations[term]['real_contexts'][context].append(occ)
translations[term]['occurrences'].append(occ)
real_spans.append(match.span())
context_spans = []
for pattern, quote in i18n_context_patterns:
for match in pattern.finditer(line):
if any(spans_overlap(match.span(), span) for span in real_spans):
continue
term = decode_string_literal(match.group(1), quote)
context = decode_string_literal(match.group(2), quote)
occ = {'file': str(relative_path), 'line': line_num}
translations[term]['contexts'].add(context)
translations[term]['occurrences'].append({
'file': str(relative_path),
'line': line_num
})
translations[term]['occurrences'].append(occ)
translations[term]['plain_occurrences'].append(occ)
context_spans.append(match.span())
for pattern, quote in i18n_simple_patterns:
for match in pattern.finditer(line):
if any(spans_overlap(match.span(), span) for span in context_spans):
if any(spans_overlap(match.span(), span) for span in real_spans + context_spans):
continue
term = decode_string_literal(match.group(1), quote)
translations[term]['occurrences'].append({
'file': str(relative_path),
'line': line_num
})
occ = {'file': str(relative_path), 'line': line_num}
translations[term]['occurrences'].append(occ)
translations[term]['plain_occurrences'].append(occ)
return translations
def area_tags(occurrences):
tags = set()
for occ in occurrences:
path = occ['file']
if path.startswith('dms-plugins/'):
tags.add('plugin-' + path.split('/')[1].lower())
elif path.startswith(('Modules/Settings/', 'Modals/Settings/')):
tags.add('settings')
else:
tags.add('shell')
return sorted(tags)
def create_poeditor_json(translations):
poeditor_data = []
for term, data in sorted(translations.items()):
references = []
if data['plain_occurrences']:
references = [f"{occ['file']}:{occ['line']}" for occ in data['plain_occurrences']]
contexts = sorted(data['contexts']) if data['contexts'] else []
comment = " | ".join(contexts) if contexts else ""
for occ in data['occurrences']:
ref = f"{occ['file']}:{occ['line']}"
references.append(ref)
poeditor_data.append({
"term": term,
"context": term,
"reference": ", ".join(references),
"comment": comment,
"tags": area_tags(data['plain_occurrences'])
})
contexts = sorted(data['contexts']) if data['contexts'] else []
comment = " | ".join(contexts) if contexts else ""
entry = {
"term": term,
"context": term,
"reference": ", ".join(references),
"comment": comment
}
poeditor_data.append(entry)
for context in sorted(data['real_contexts']):
references = [f"{occ['file']}:{occ['line']}" for occ in data['real_contexts'][context]]
poeditor_data.append({
"term": term,
"context": context,
"reference": ", ".join(references),
"comment": "",
"tags": area_tags(data['real_contexts'][context])
})
return poeditor_data
def create_template_json(translations):
template_data = []
for term, data in sorted(translations.items()):
contexts = sorted(data['contexts']) if data['contexts'] else []
context_str = " | ".join(contexts) if contexts else ""
entry = {
"term": term,
return [
{
"term": entry["term"],
"translation": "",
"context": context_str,
"context": entry["context"],
"reference": "",
"comment": ""
"comment": entry["comment"]
}
template_data.append(entry)
return template_data
for entry in create_poeditor_json(translations)
]
def main():
script_dir = Path(__file__).parent
@@ -142,6 +181,8 @@ def main():
print(f" - Unique strings: {len(translations)}")
print(f" - Total occurrences: {sum(len(data['occurrences']) for data in translations.values())}")
print(f" - Strings with contexts: {sum(1 for data in translations.values() if data['contexts'])}")
print(f" - Real-context entries: {sum(len(data['real_contexts']) for data in translations.values())}")
print(f" - POEditor entries: {len(poeditor_data)}")
print(f" - Source file: {en_json_path}")
print(f" - Template file: {template_json_path}")