Files
Palmr/apps/web/scripts/check_translations.py
Daniel Luiz Alves 4e841b272c feat: implement translation management system and enhance localization support
- Added a new translation management system to automate synchronization, validation, and translation of internationalization files.
- Introduced scripts for running translation operations, including checking status, synchronizing keys, and auto-translating strings.
- Updated package.json with new translation-related commands for easier access.
- Enhanced localization files across multiple languages with new keys and improved translations.
- Integrated download functionality for share files in the UI, allowing users to download multiple files seamlessly.
- Refactored components to support new download features and improved user experience.
2025-06-23 12:11:52 -03:00

231 lines
8.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Script to check translation status and identify strings that need translation.
"""
import json
from pathlib import Path
from typing import Dict, Any, List, Tuple
import argparse
def load_json_file(file_path: Path) -> Dict[str, Any]:
"""Load a JSON file."""
try:
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
print(f"Error loading {file_path}: {e}")
return {}
def get_all_string_values(data: Dict[str, Any], prefix: str = '') -> List[Tuple[str, str]]:
"""Extract all strings from nested JSON with their keys."""
strings = []
for key, value in data.items():
current_key = f"{prefix}.{key}" if prefix else key
if isinstance(value, str):
strings.append((current_key, value))
elif isinstance(value, dict):
strings.extend(get_all_string_values(value, current_key))
return strings
def check_untranslated_strings(file_path: Path) -> Tuple[int, int, List[str]]:
"""Check for untranslated strings in a file."""
data = load_json_file(file_path)
if not data:
return 0, 0, []
all_strings = get_all_string_values(data)
untranslated = []
for key, value in all_strings:
if value.startswith('[TO_TRANSLATE]'):
untranslated.append(key)
return len(all_strings), len(untranslated), untranslated
def compare_languages(reference_file: Path, target_file: Path) -> Dict[str, Any]:
"""Compare two language files."""
reference_data = load_json_file(reference_file)
target_data = load_json_file(target_file)
if not reference_data or not target_data:
return {}
reference_strings = dict(get_all_string_values(reference_data))
target_strings = dict(get_all_string_values(target_data))
# Find common keys
common_keys = set(reference_strings.keys()) & set(target_strings.keys())
# Check identical strings (possibly untranslated)
identical_strings = []
for key in common_keys:
if reference_strings[key] == target_strings[key] and len(reference_strings[key]) > 3:
identical_strings.append(key)
return {
'total_reference': len(reference_strings),
'total_target': len(target_strings),
'common_keys': len(common_keys),
'identical_strings': identical_strings
}
def generate_translation_report(messages_dir: Path, reference_file: str = 'en-US.json'):
"""Generate complete translation report."""
reference_path = messages_dir / reference_file
if not reference_path.exists():
print(f"Reference file not found: {reference_path}")
return
# Load reference data
reference_data = load_json_file(reference_path)
reference_strings = dict(get_all_string_values(reference_data))
total_reference_strings = len(reference_strings)
print(f"📊 TRANSLATION REPORT")
print(f"Reference: {reference_file} ({total_reference_strings} strings)")
print("=" * 80)
# Find all JSON files
json_files = [f for f in messages_dir.glob('*.json') if f.name != reference_file]
if not json_files:
print("No translation files found")
return
reports = []
for json_file in sorted(json_files):
total_strings, untranslated_count, untranslated_keys = check_untranslated_strings(json_file)
comparison = compare_languages(reference_path, json_file)
# Calculate percentages
completion_percentage = (total_strings / total_reference_strings) * 100 if total_reference_strings > 0 else 0
untranslated_percentage = (untranslated_count / total_strings) * 100 if total_strings > 0 else 0
reports.append({
'file': json_file.name,
'total_strings': total_strings,
'untranslated_count': untranslated_count,
'untranslated_keys': untranslated_keys,
'completion_percentage': completion_percentage,
'untranslated_percentage': untranslated_percentage,
'identical_strings': comparison.get('identical_strings', [])
})
# Sort by completion percentage
reports.sort(key=lambda x: x['completion_percentage'], reverse=True)
print(f"{'LANGUAGE':<15} {'COMPLETENESS':<12} {'STRINGS':<15} {'UNTRANSLATED':<15} {'POSSIBLE MATCHES'}")
print("-" * 80)
for report in reports:
language = report['file'].replace('.json', '')
completion = f"{report['completion_percentage']:.1f}%"
strings_info = f"{report['total_strings']}/{total_reference_strings}"
untranslated_info = f"{report['untranslated_count']} ({report['untranslated_percentage']:.1f}%)"
identical_count = len(report['identical_strings'])
# Choose icon based on completeness
if report['completion_percentage'] >= 100:
icon = "" if report['untranslated_count'] == 0 else "⚠️"
elif report['completion_percentage'] >= 90:
icon = "🟡"
else:
icon = "🔴"
print(f"{icon} {language:<13} {completion:<12} {strings_info:<15} {untranslated_info:<15} {identical_count}")
print("\n" + "=" * 80)
# Show details of problematic files
problematic_files = [r for r in reports if r['untranslated_count'] > 0 or r['completion_percentage'] < 100]
if problematic_files:
print("📋 DETAILS OF FILES THAT NEED ATTENTION:")
print()
for report in problematic_files:
language = report['file'].replace('.json', '')
print(f"🔍 {language.upper()}:")
if report['completion_percentage'] < 100:
missing_count = total_reference_strings - report['total_strings']
print(f" • Missing {missing_count} strings ({100 - report['completion_percentage']:.1f}%)")
if report['untranslated_count'] > 0:
print(f"{report['untranslated_count']} strings marked as [TO_TRANSLATE]")
if report['untranslated_count'] <= 10:
print(" • Untranslated keys:")
for key in report['untranslated_keys']:
print(f" - {key}")
else:
print(" • First 10 untranslated keys:")
for key in report['untranslated_keys'][:10]:
print(f" - {key}")
print(f" ... and {report['untranslated_count'] - 10} more")
if report['identical_strings']:
identical_count = len(report['identical_strings'])
print(f"{identical_count} strings identical to English (possibly untranslated)")
if identical_count <= 5:
for key in report['identical_strings']:
value = reference_strings.get(key, '')[:50]
print(f" - {key}: \"{value}...\"")
else:
for key in report['identical_strings'][:5]:
value = reference_strings.get(key, '')[:50]
print(f" - {key}: \"{value}...\"")
print(f" ... and {identical_count - 5} more")
print()
else:
print("🎉 All translations are complete!")
print("=" * 80)
print("💡 TIPS:")
print("• Use 'python3 sync_translations.py --dry-run' to see what would be added")
print("• Use 'python3 sync_translations.py' to synchronize all translations")
print("• Strings marked with [TO_TRANSLATE] need manual translation")
print("• Strings identical to English may need translation")
def main():
parser = argparse.ArgumentParser(
description='Check translation status and identify strings that need translation'
)
parser.add_argument(
'--messages-dir',
type=Path,
default=Path(__file__).parent.parent / 'messages',
help='Directory containing message files (default: ../messages)'
)
parser.add_argument(
'--reference',
default='en-US.json',
help='Reference file (default: en-US.json)'
)
args = parser.parse_args()
if not args.messages_dir.exists():
print(f"Directory not found: {args.messages_dir}")
return 1
generate_translation_report(args.messages_dir, args.reference)
return 0
if __name__ == '__main__':
exit(main())