Skip to content

Commit 94334fb

Browse files
committed
initial commit
1 parent 43bba1d commit 94334fb

File tree

2 files changed

+198
-0
lines changed

2 files changed

+198
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import csv
2+
from pathlib import Path
3+
from ruamel.yaml import YAML # pip install ruamel.yaml
4+
5+
# -------- CONFIG --------
6+
TRANSLATION_CSV = r"C:\temp\translations.csv"
7+
LANGUAGE_KEY = "chinese_s"
8+
SOURCE_LANG = "en_us"
9+
# ------------------------
10+
11+
yaml = YAML()
12+
13+
14+
def build_lookup(csv_path):
15+
"""Build dictionary: {yaml_file: {key_type: {"en_us":..., "translation":...}}}"""
16+
lookup = {}
17+
18+
with open(csv_path, encoding="utf-8") as f:
19+
reader = csv.DictReader(f)
20+
21+
for row in reader:
22+
file = row["yaml_file"]
23+
key = row["key_type"]
24+
25+
en = row[SOURCE_LANG]
26+
tr = row[LANGUAGE_KEY]
27+
28+
lookup.setdefault(file, {}).setdefault(key, {})
29+
lookup[file][key] = {"en": en, "tr": tr}
30+
31+
return lookup
32+
33+
34+
def insert_translation(data, key_type, trans, node_path=""):
35+
"""Insert translation from CSV.
36+
Rule: write ONLY if CSV provides a non-empty translation; always overwrite."""
37+
if not isinstance(data, dict):
38+
return
39+
40+
translation = trans["tr"].strip()
41+
42+
if key_type in data:
43+
value = data[key_type]
44+
45+
# CASE A: scalar -> convert to dict
46+
if isinstance(value, str):
47+
print(f"[Scalar detected during import] {node_path}/{key_type} | Converting to multilingual")
48+
new_dict = {SOURCE_LANG: value}
49+
50+
if translation:
51+
new_dict[LANGUAGE_KEY] = translation
52+
print(f"[Write] {node_path}/{key_type} | {LANGUAGE_KEY} = '{translation}'")
53+
else:
54+
print(f"[Skip] CSV translation empty for {node_path}/{key_type}")
55+
56+
data[key_type] = new_dict
57+
return
58+
59+
# CASE B: dict
60+
elif isinstance(value, dict):
61+
# ensure en_us exists
62+
if SOURCE_LANG not in value:
63+
if len(value):
64+
first_key = next(iter(value.keys()))
65+
value[SOURCE_LANG] = value[first_key]
66+
print(f"[Promotion] No {SOURCE_LANG} → using '{first_key}' value")
67+
68+
# write only if CSV translation provided
69+
if translation:
70+
value[LANGUAGE_KEY] = translation
71+
print(f"[Write] {node_path}/{key_type} | Overwriting {LANGUAGE_KEY} = '{translation}'")
72+
else:
73+
print(f"[Skip] CSV translation empty for {node_path}/{key_type}")
74+
75+
# recurse deeper
76+
for k, v in data.items():
77+
child_path = f"{node_path}/{k}" if node_path else k
78+
insert_translation(v, key_type, trans, child_path)
79+
80+
81+
def main():
82+
lookup = build_lookup(TRANSLATION_CSV)
83+
84+
for yaml_file, fields in lookup.items():
85+
yaml_file = Path(yaml_file)
86+
87+
if not yaml_file.exists():
88+
print(f"[Missing] {yaml_file}")
89+
continue
90+
91+
try:
92+
with open(yaml_file, "r", encoding="utf-8") as f:
93+
data = yaml.load(f)
94+
95+
for key_type, trans in fields.items():
96+
insert_translation(data, key_type, trans)
97+
98+
with open(yaml_file, "w", encoding="utf-8") as f:
99+
yaml.dump(data, f)
100+
101+
print(f"[Updating] {yaml_file}")
102+
103+
except Exception as e:
104+
print(f"[ERROR] writing {yaml_file}: {e}")
105+
106+
107+
if __name__ == "__main__":
108+
main()
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import os
2+
from pathlib import Path
3+
from ruamel.yaml import YAML # pip install ruamel.yaml
4+
import csv
5+
6+
# -------- CONFIG --------
7+
BASE_DIR = r"C:\Program Files\pyRevit-Master\extensions\pyRevitTools.extension"
8+
OUTPUT_CSV = r"C:\temp\translations.csv"
9+
LANGUAGE_KEY = "chinese_s" # translation key to extract/merge
10+
SOURCE_LANG = "en_us" # main source language
11+
# ------------------------
12+
13+
yaml = YAML()
14+
15+
16+
def find_yaml_files(base_dir):
17+
for root, _, files in os.walk(base_dir):
18+
for f in files:
19+
if f.endswith(".yaml"):
20+
yield Path(root) / f
21+
22+
23+
def extract_field(path, field_name, value, results):
24+
"""Extracts English + existing translated value from dict or scalar."""
25+
# CASE 1: multilingual dict
26+
if isinstance(value, dict):
27+
# English (preferred)
28+
en = value.get(SOURCE_LANG)
29+
30+
# fallback to first language if no en_us exists
31+
if not en and len(value):
32+
first_key = next(iter(value.keys()))
33+
en = value[first_key]
34+
35+
# Existing translation to preserve
36+
tr = value.get(LANGUAGE_KEY, "")
37+
38+
if en:
39+
results.append([path, field_name, en, tr])
40+
return
41+
42+
# CASE 2: scalar string
43+
if isinstance(value, str):
44+
print(
45+
f"[Scalar detected] File: {path} | Field: {field_name} | Value: '{value}'"
46+
)
47+
results.append([path, field_name, value, ""])
48+
return
49+
50+
51+
def extract_values(data, path, results):
52+
"""Recursively walk through structure and extract fields."""
53+
if not isinstance(data, dict):
54+
return
55+
56+
for field_name in ("title", "tooltip"):
57+
if field_name in data:
58+
extract_field(path, field_name, data[field_name], results)
59+
60+
# recurse into children
61+
for k, v in data.items():
62+
child_path = f"{path}/{k}"
63+
extract_values(v, child_path, results)
64+
65+
66+
def main():
67+
results = []
68+
69+
for yaml_file in find_yaml_files(BASE_DIR):
70+
try:
71+
with open(yaml_file, "r", encoding="utf-8") as f:
72+
data = yaml.load(f)
73+
74+
extract_values(data, str(yaml_file), results)
75+
76+
except Exception as e:
77+
print(f"ERROR reading {yaml_file}: {e}")
78+
79+
# write CSV
80+
with open(OUTPUT_CSV, "w", newline="", encoding="utf-8") as f:
81+
writer = csv.writer(f)
82+
writer.writerow(["yaml_file", "key_type", SOURCE_LANG, LANGUAGE_KEY])
83+
for row in results:
84+
writer.writerow(row)
85+
86+
print(f"\nExtracted {len(results)} records to {OUTPUT_CSV}")
87+
88+
89+
if __name__ == "__main__":
90+
main()

0 commit comments

Comments
 (0)