diff options
| author | nippy <you@example.com> | 2026-04-18 13:49:56 +0200 |
|---|---|---|
| committer | nippy <you@example.com> | 2026-04-18 13:49:56 +0200 |
| commit | 5d94c0a7d44a2255b81815a52a7056a94a39842d (patch) | |
| tree | 759bdea9645c6a62f9e1e4c001f7d81cccd120d2 /raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/translations/extract_translations.py | |
| parent | e79cdf210b267f21a186255ce1a4d50029439d54 (diff) | |
| download | RaveOS-PKGBUILD-5d94c0a7d44a2255b81815a52a7056a94a39842d.tar.gz RaveOS-PKGBUILD-5d94c0a7d44a2255b81815a52a7056a94a39842d.zip | |
update Raveos themes
Diffstat (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/translations/extract_translations.py')
| -rwxr-xr-x | raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/translations/extract_translations.py | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/translations/extract_translations.py b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/translations/extract_translations.py new file mode 100755 index 0000000..5e78549 --- /dev/null +++ b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/translations/extract_translations.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +import ast +import re +import json +from pathlib import Path +from collections import defaultdict + + +def decode_string_literal(content, quote): + try: + return ast.literal_eval(f"{quote}{content}{quote}") + except (ValueError, SyntaxError): + return content + + +def spans_overlap(a, b): + return a[0] < b[1] and b[0] < a[1] + + +def extract_qstr_strings(root_dir): + translations = defaultdict(lambda: {'contexts': set(), 'occurrences': []}) + qstr_patterns = [ + (re.compile(r'qsTr\(\s*"((?:\\.|[^"\\])*)"\s*\)'), '"'), + (re.compile(r"qsTr\(\s*'((?:\\.|[^'\\])*)'\s*\)"), "'") + ] + i18n_context_patterns = [ + ( + re.compile(r'I18n\.tr\(\s*"((?:\\.|[^"\\])*)"\s*,\s*"((?:\\.|[^"\\])*)"\s*\)'), + '"' + ), + ( + re.compile(r"I18n\.tr\(\s*'((?:\\.|[^'\\])*)'\s*,\s*'((?:\\.|[^'\\])*)'\s*\)"), + "'" + ) + ] + i18n_simple_patterns = [ + (re.compile(r'I18n\.tr\(\s*"((?:\\.|[^"\\])*)"\s*\)'), '"'), + (re.compile(r"I18n\.tr\(\s*'((?:\\.|[^'\\])*)'\s*\)"), "'") + ] + + for qml_file in Path(root_dir).rglob('*.qml'): + relative_path = qml_file.relative_to(root_dir) + + with open(qml_file, 'r', encoding='utf-8') as f: + for line_num, line in enumerate(f, 1): + 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 + }) + + context_spans = [] + for pattern, quote in i18n_context_patterns: + for match in pattern.finditer(line): + term = decode_string_literal(match.group(1), quote) + context = decode_string_literal(match.group(2), quote) + translations[term]['contexts'].add(context) + translations[term]['occurrences'].append({ + 'file': str(relative_path), + 'line': line_num + }) + 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): + continue + term = decode_string_literal(match.group(1), quote) + translations[term]['occurrences'].append({ + 'file': str(relative_path), + 'line': line_num + }) + + return translations + +def create_poeditor_json(translations): + poeditor_data = [] + + for term, data in sorted(translations.items()): + references = [] + + for occ in data['occurrences']: + ref = f"{occ['file']}:{occ['line']}" + references.append(ref) + + 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) + + 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, + "translation": "", + "context": context_str, + "reference": "", + "comment": "" + } + template_data.append(entry) + + return template_data + +def main(): + script_dir = Path(__file__).parent + root_dir = script_dir.parent + translations_dir = script_dir + + print("Extracting qsTr() strings from QML files...") + translations = extract_qstr_strings(root_dir) + + print(f"Found {len(translations)} unique strings") + + poeditor_data = create_poeditor_json(translations) + en_json_path = translations_dir / 'en.json' + with open(en_json_path, 'w', encoding='utf-8') as f: + json.dump(poeditor_data, f, indent=2, ensure_ascii=False) + print(f"Created source language file: {en_json_path}") + + template_data = create_template_json(translations) + template_json_path = translations_dir / 'template.json' + with open(template_json_path, 'w', encoding='utf-8') as f: + json.dump(template_data, f, indent=2, ensure_ascii=False) + print(f"Created template file: {template_json_path}") + + print("\nSummary:") + 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" - Source file: {en_json_path}") + print(f" - Template file: {template_json_path}") + +if __name__ == '__main__': + main() |