Files
echoes-of-the-ash/scripts/convert_to_i18n.py

171 lines
5.8 KiB
Python

#!/usr/bin/env python3
"""
Convert game data JSON files to i18n-ready format.
Transforms plain text fields to inline translation objects.
Usage: python convert_to_i18n.py
"""
import json
from pathlib import Path
GAMEDATA_DIR = Path(__file__).parent.parent / 'gamedata'
# Fields that should be translated
TRANSLATABLE_FIELDS = ['name', 'description']
# Nested text fields in outcomes
OUTCOME_TEXT_FIELDS = ['success', 'failure', 'crit_success', 'crit_failure']
def convert_text_to_i18n(value: str) -> dict:
"""Convert a plain string to i18n format"""
if not value or not isinstance(value, str):
return value
return {
"en": value,
"es": "" # Empty - to be translated
}
def convert_item(item_id: str, item: dict) -> dict:
"""Convert an item to i18n format"""
result = {}
for key, value in item.items():
if key in TRANSLATABLE_FIELDS and isinstance(value, str):
result[key] = convert_text_to_i18n(value)
else:
result[key] = value
return result
def convert_location(location: dict) -> dict:
"""Convert a location to i18n format with nested interactable outcomes"""
result = {}
for key, value in location.items():
if key in TRANSLATABLE_FIELDS and isinstance(value, str):
result[key] = convert_text_to_i18n(value)
elif key == 'interactables' and isinstance(value, dict):
# Convert interactable outcome texts
result[key] = convert_interactables(value)
else:
result[key] = value
return result
def convert_interactables(interactables: dict) -> dict:
"""Convert interactable templates and outcomes to i18n format"""
result = {}
for inter_id, inter_data in interactables.items():
result[inter_id] = {}
for key, value in inter_data.items():
if key in TRANSLATABLE_FIELDS and isinstance(value, str):
result[inter_id][key] = convert_text_to_i18n(value)
elif key == 'actions' and isinstance(value, dict):
result[inter_id][key] = convert_actions(value)
elif key == 'outcomes' and isinstance(value, dict):
result[inter_id][key] = convert_outcomes(value)
else:
result[inter_id][key] = value
return result
def convert_actions(actions: dict) -> dict:
"""Convert action labels to i18n format"""
result = {}
for action_id, action_data in actions.items():
result[action_id] = {}
for key, value in action_data.items():
if key == 'label' and isinstance(value, str):
result[action_id][key] = convert_text_to_i18n(value)
else:
result[action_id][key] = value
return result
def convert_outcomes(outcomes: dict) -> dict:
"""Convert outcome text fields to i18n format"""
result = {}
for outcome_id, outcome_data in outcomes.items():
result[outcome_id] = {}
for key, value in outcome_data.items():
if key == 'text' and isinstance(value, dict):
result[outcome_id][key] = {}
for text_key, text_value in value.items():
if text_key in OUTCOME_TEXT_FIELDS and isinstance(text_value, str) and text_value:
result[outcome_id][key][text_key] = convert_text_to_i18n(text_value)
else:
result[outcome_id][key][text_key] = text_value
else:
result[outcome_id][key] = value
return result
def convert_npc(npc: dict) -> dict:
"""Convert an NPC to i18n format"""
result = {}
for key, value in npc.items():
if key in TRANSLATABLE_FIELDS and isinstance(value, str):
result[key] = convert_text_to_i18n(value)
else:
result[key] = value
return result
def convert_interactable_template(interactable: dict) -> dict:
"""Convert an interactable template to i18n format"""
result = {}
for key, value in interactable.items():
if key in TRANSLATABLE_FIELDS and isinstance(value, str):
result[key] = convert_text_to_i18n(value)
elif key == 'actions' and isinstance(value, dict):
result[key] = convert_actions(value)
else:
result[key] = value
return result
def convert_file(filename: str, converter, key_name: str):
"""Convert a JSON file to i18n format"""
filepath = GAMEDATA_DIR / filename
print(f"Converting {filename}...")
with open(filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
if key_name in data:
if isinstance(data[key_name], dict):
# items.json format: {"items": {"item_id": {...}, ...}}
data[key_name] = {
item_id: converter(item_id, item) if key_name == 'items' else converter(item)
for item_id, item in data[key_name].items()
}
elif isinstance(data[key_name], list):
# locations.json format: {"locations": [{...}, ...]}
data[key_name] = [converter(item) for item in data[key_name]]
# Write back
output_file = GAMEDATA_DIR / f'{filename.replace(".json", "_i18n.json")}'
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
print(f" -> Saved to {output_file.name}")
def main():
print("Converting game data to i18n format...\n")
convert_file('items.json', convert_item, 'items')
convert_file('locations.json', convert_location, 'locations')
convert_file('npcs.json', convert_npc, 'npcs')
convert_file('interactables.json', convert_interactable_template, 'interactables')
print("\nDone! Review *_i18n.json files, then rename to replace originals.")
print("Spanish translations are empty - add them in the web-map editor.")
if __name__ == '__main__':
main()