Enhance translation sync and update translation files

Improved the translation sync script to better handle dotted reference keys and type mismatches, ensuring more robust merging and reporting of missing translations. Updated German and English translation files to use flattened keys for certain options, expanded tool descriptions, and added or reorganized many UI strings for new features and improved clarity.
This commit is contained in:
Ludy87 2025-10-26 22:50:59 +01:00
parent e806844980
commit c8d4a02299
No known key found for this signature in database
GPG Key ID: 92696155E0220F94
3 changed files with 2289 additions and 661 deletions

View File

@ -75,6 +75,66 @@ def collect_leaf_paths(obj: Any, base_path: str) -> list[str]:
return [base_path]
def _prune_empty_parent_stack(
stack: list[tuple[JsonDict, str, Any]]
) -> None:
"""Remove empty dictionaries along a captured parent stack."""
child_empty = True
for idx in range(len(stack) - 1, -1, -1):
parent, key, child = stack[idx]
if idx == len(stack) - 1:
parent.pop(key, None)
child_empty = len(parent) == 0
else:
if child_empty and isinstance(child, dict) and len(child) == 0:
parent.pop(key, None)
child_empty = len(parent) == 0
else:
child_empty = False
if not child_empty:
break
def relocate_dotted_reference_keys(ref: Any, target: Any) -> None:
"""Align target structure with dotted keys defined in the reference."""
if not (is_mapping(ref) and is_mapping(target)):
return
for key in ref:
if "." not in key:
continue
if key in target:
continue
segments = key.split(".")
current = target
stack: list[tuple[JsonDict, str, Any]] = []
valid_path = True
for segment in segments:
if not (is_mapping(current) and segment in current):
valid_path = False
break
next_current = current[segment]
stack.append((current, segment, next_current))
current = next_current
if not valid_path:
continue
target[key] = deepcopy(current)
_prune_empty_parent_stack(stack)
for key, ref_val in ref.items():
if "." in key:
continue
if key in target:
relocate_dotted_reference_keys(ref_val, target[key])
def record_missing_leaf(
path: str, *, stats: MergeStats, ignored_paths: set[str]
) -> None:
@ -206,7 +266,10 @@ def deep_merge_and_collect(
- Tracks missing keys and how many leaf nodes are missing (for %).
- Optionally prunes extra keys that don't exist in the reference.
"""
if is_mapping(ref) and is_mapping(target):
ref_is_mapping = is_mapping(ref)
target_is_mapping = is_mapping(target)
if ref_is_mapping and target_is_mapping:
merged: JsonDict = {}
# Walk reference keys in order so we keep the same structure/order
@ -257,10 +320,37 @@ def deep_merge_and_collect(
return merged
if ref_is_mapping != target_is_mapping:
stats.added += 1
stats.missing_leafs += count_leaves(ref)
leaf_paths = collect_leaf_paths(ref, path)
if leaf_paths:
for leaf_path in leaf_paths:
record_missing_leaf(
leaf_path,
stats=stats,
ignored_paths=ignored_paths,
)
else:
record_missing_leaf(
path,
stats=stats,
ignored_paths=ignored_paths,
)
return deepcopy(ref)
# Non-dict values → keep existing translation; if it's None, count it as missing
if target is None:
record_missing_leaf(path, stats=stats, ignored_paths=ignored_paths)
return deepcopy(target if target is not None else ref)
return deepcopy(ref)
if type(target) is not type(ref):
stats.added += 1
stats.missing_leafs += count_leaves(ref)
record_missing_leaf(path, stats=stats, ignored_paths=ignored_paths)
return deepcopy(ref)
return deepcopy(target)
def order_like_reference(ref: Any, obj: Any) -> Any:

View File

@ -797,18 +797,8 @@
"merge": {
"tags": "zusammenführen,seitenvorgänge,back end,serverseitig",
"title": "Zusammenführen",
"removeDigitalSignature": {
"tooltip": {
"description": "Digitale Signaturen werden beim Zusammenführen von Dateien ungültig. Aktivieren Sie diese Option, um sie aus der endgültigen zusammengeführten PDF zu entfernen.",
"title": "Digitale Signatur entfernen"
}
},
"generateTableOfContents": {
"tooltip": {
"description": "Erstellt automatisch ein klickbares Inhaltsverzeichnis in der zusammengeführten PDF basierend auf den ursprünglichen Dateinamen und Seitenzahlen.",
"title": "Inhaltsverzeichnis generieren"
}
},
"removeDigitalSignature": "Remove digital signature in the merged file?",
"generateTableOfContents": "Generate table of contents in the merged file?",
"removeDigitalSignature.tooltip": {
"title": "Remove Digital Signature",
"description": "Digital signatures will be invalidated when merging files. Check this to remove them from the final merged PDF."
@ -2506,10 +2496,22 @@
"reset": "Auf vollständiges PDF zurücksetzen",
"coordinates": {
"title": "Position und Größe",
"x": "X-Position",
"y": "Y-Position",
"width": "Breite",
"height": "Höhe"
"x": {
"label": "X Position",
"desc": "Left edge (points)"
},
"y": {
"label": "Y Position",
"desc": "Bottom edge (points)"
},
"width": {
"label": "Width",
"desc": "Crop width (points)"
},
"height": {
"label": "Height",
"desc": "Crop height (points)"
}
},
"error": {
"invalidArea": "Zuschneidebereich überschreitet die PDF-Grenzen",
@ -3575,29 +3577,17 @@
"options": {
"title": "Bereinigungs-Optionen",
"note": "Wählen Sie die Elemente aus, die Sie aus der PDF entfernen möchten. Mindestens eine Option muss ausgewählt werden.",
"removeJavaScript": {
"desc": "JavaScript-Aktionen und Skripte aus der PDF entfernen"
},
"removeJavaScript": "Remove JavaScript",
"removeJavaScript.desc": "Remove JavaScript actions and scripts from the PDF",
"removeEmbeddedFiles": {
"desc": "Alle in der PDF eingebetteten Dateien entfernen"
},
"removeEmbeddedFiles": "Remove Embedded Files",
"removeEmbeddedFiles.desc": "Remove any files embedded within the PDF",
"removeXMPMetadata": {
"desc": "XMP-Metadaten aus der PDF entfernen"
},
"removeXMPMetadata": "Remove XMP Metadata",
"removeXMPMetadata.desc": "Remove XMP metadata from the PDF",
"removeMetadata": {
"desc": "Dokumentinformations-Metadaten (Titel, Autor usw.) entfernen"
},
"removeMetadata": "Remove Document Metadata",
"removeMetadata.desc": "Remove document information metadata (title, author, etc.)",
"removeLinks": {
"desc": "Externe Links und Launch-Aktionen aus der PDF entfernen"
},
"removeLinks": "Remove Links",
"removeLinks.desc": "Remove external links and launch actions from the PDF",
"removeFonts": {
"desc": "Eingebettete Schriftarten aus der PDF entfernen"
},
"removeFonts": "Remove Fonts",
"removeFonts.desc": "Remove embedded fonts from the PDF"
}
},

File diff suppressed because it is too large Load Diff