mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-02-01 20:10:35 +01:00
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:
parent
e806844980
commit
c8d4a02299
94
.github/scripts/sync_translations.py
vendored
94
.github/scripts/sync_translations.py
vendored
@ -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:
|
||||
|
||||
@ -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
Loading…
Reference in New Issue
Block a user