#!/usr/bin/env python3 """ Script to automatically wrap untranslated strings with Django's translation function. This script helps identify and fix untranslated strings in Django views.py files. """ import re import sys from pathlib import Path def add_translation_import(content): """Add translation import if not present.""" if 'from django.utils.translation import gettext_lazy as _' in content: return content # Find the imports section and add the translation import import_pattern = r'(from django\.contrib import messages)' replacement = r'\1\nfrom django.utils.translation import gettext_lazy as _' if re.search(import_pattern, content): content = re.sub(import_pattern, replacement, content, count=1) else: # Try another common import import_pattern = r'(from django\.shortcuts import.*)' if re.search(import_pattern, content): content = re.sub(import_pattern, replacement, content, count=1) return content def wrap_messages(content): """Wrap Django messages with translation function.""" patterns = [ # messages.success/error/warning/info with single quotes (r"messages\.(success|error|warning|info)\(([^,]+),\s*'([^']+)'\)", r"messages.\1(\2, _('\3'))"), # messages.success/error/warning/info with double quotes (r'messages\.(success|error|warning|info)\(([^,]+),\s*"([^"]+)"\)', r'messages.\1(\2, _("\3"))'), ] for pattern, replacement in patterns: content = re.sub(pattern, replacement, content) return content def wrap_context_strings(content): """Wrap context dictionary strings with translation function.""" patterns = [ # context['key'] = 'value' with single quotes (r"context\[(['\"])([^'\"]+)\1\]\s*=\s*'([^']+)'", r"context[\1\2\1] = _('\3')"), # context['key'] = "value" with double quotes (r'context\[(["\'])([^"\']+)\1\]\s*=\s*"([^"]+)"', r'context[\1\2\1] = _("\3")'), ] for pattern, replacement in patterns: content = re.sub(pattern, replacement, content) return content def wrap_class_attributes(content): """Wrap class attribute strings with translation function.""" patterns = [ # success_message = "text" (r'(\s+success_message\s*=\s*)"([^"]+)"', r'\1_("\2")'), # success_message = 'text' (r"(\s+success_message\s*=\s*)'([^']+)'", r"\1_('\2')"), ] for pattern, replacement in patterns: content = re.sub(pattern, replacement, content) return content def process_file(filepath): """Process a single file to add translations.""" print(f"Processing {filepath}...") with open(filepath, 'r', encoding='utf-8') as f: content = f.read() original_content = content # Apply transformations content = add_translation_import(content) content = wrap_messages(content) content = wrap_context_strings(content) content = wrap_class_attributes(content) if content != original_content: with open(filepath, 'w', encoding='utf-8') as f: f.write(content) print(f"✓ Updated {filepath}") return True else: print(f"- No changes needed for {filepath}") return False def main(): """Main function.""" if len(sys.argv) > 1: files = [Path(f) for f in sys.argv[1:]] else: # Default files to process files = [ Path('core/views.py'), Path('finance/views.py'), Path('medical/views.py'), Path('slp/views.py'), Path('aba/views.py'), Path('hr/views.py'), ] updated = 0 for filepath in files: if filepath.exists(): if process_file(filepath): updated += 1 else: print(f"✗ File not found: {filepath}") print(f"\n{'='*50}") print(f"Summary: {updated} file(s) updated") print(f"{'='*50}") print("\nNext steps:") print("1. Review the changes in each file") print("2. Run: python manage.py makemessages -l ar") print("3. Translate strings in locale/ar/LC_MESSAGES/django.po") print("4. Run: python manage.py compilemessages") if __name__ == '__main__': main()