Stirling-PDF/scripts/convert_properties_to_json.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

113 lines
3.8 KiB
Python
Raw Permalink Normal View History

2025-05-29 17:26:32 +01:00
#!/usr/bin/env python3
"""
Convert Java .properties files to JSON for react-i18next
Preserves hierarchical structure and handles special cases
"""
import os
import json
import re
from pathlib import Path
def properties_to_dict(file_path):
"""Convert .properties file to nested dictionary"""
result = {}
with open(file_path, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
# Skip empty lines and comments
if not line or line.startswith('#'):
continue
# Handle key=value pairs
if '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
# Handle multiline values (ending with \)
while value.endswith('\\'):
next_line = next(f, '').strip()
value = value[:-1] + next_line
# Create nested structure from dot notation
set_nested_value(result, key, value)
return result
def set_nested_value(dictionary, key_path, value):
"""Set value in nested dictionary using dot notation"""
keys = key_path.split('.')
current = dictionary
for key in keys[:-1]:
if key not in current:
current[key] = {}
elif not isinstance(current[key], dict):
# Convert existing string value to nested object
old_value = current[key]
current[key] = {"_value": old_value}
current = current[key]
final_key = keys[-1]
if final_key in current and isinstance(current[final_key], dict):
# If the final key already exists as an object, store the value under "_value"
current[final_key]["_value"] = value
else:
current[final_key] = value
def convert_all_properties():
"""Convert all messages_*.properties files to JSON"""
# Get project root
script_dir = Path(__file__).parent
project_root = script_dir.parent
resources_dir = project_root / 'src' / 'main' / 'resources'
output_dir = project_root / 'frontend' / 'public' / 'locales'
# Create output directory
output_dir.mkdir(parents=True, exist_ok=True)
# Find all .properties files
properties_files = list(resources_dir.glob('messages*.properties'))
converted_count = 0
for props_file in properties_files:
# Extract locale from filename
filename = props_file.name
if filename == 'messages.properties':
locale = 'en' # Default locale
else:
# Extract locale from messages_en_US.properties format
locale_match = re.match(r'messages_(.+)\.properties', filename)
if locale_match:
locale = locale_match.group(1)
# Convert Java locale format to standard (en_US -> en-US)
locale = locale.replace('_', '-')
else:
continue
print(f"Converting {filename} -> {locale}.json")
# Convert to dictionary
data = properties_to_dict(props_file)
# Create locale directory
locale_dir = output_dir / locale
locale_dir.mkdir(exist_ok=True)
# Write translation.json (react-i18next default namespace)
output_file = locale_dir / 'translation.json'
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
converted_count += 1
print(f"\nConverted {converted_count} language files to {output_dir}")
print("Languages available:", [d.name for d in output_dir.iterdir() if d.is_dir()])
if __name__ == '__main__':
convert_all_properties()