#!/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()