192 lines
6.9 KiB
Python
192 lines
6.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Comprehensive script to add i18n translation tags to all Django templates
|
|
"""
|
|
import os
|
|
import re
|
|
from pathlib import Path
|
|
|
|
# Patterns for text that should be translated
|
|
TRANSLATION_PATTERNS = [
|
|
# Simple text in common HTML elements
|
|
(r'>([A-Z][^<>{}\n]+?)</h[1-6]>', r'>{%% trans "%s" %%}</h'),
|
|
(r'>([A-Z][^<>{}\n]+?)</button>', r'>{%% trans "%s" %%}</button>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</label>', r'>{%% trans "%s" %%}</label>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</th>', r'>{%% trans "%s" %%}</th>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</a>', r'>{%% trans "%s" %%}</a>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</span>', r'>{%% trans "%s" %%}</span>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</p>', r'>{%% trans "%s" %%}</p>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</div>', r'>{%% trans "%s" %%}</div>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</li>', r'>{%% trans "%s" %%}</li>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</td>', r'>{%% trans "%s" %%}</td>'),
|
|
(r'>([A-Z][^<>{}\n]+?)</option>', r'>{%% trans "%s" %%}</option>'),
|
|
]
|
|
|
|
def add_i18n_load(content):
|
|
"""Add {% load i18n %} at the top if not present"""
|
|
if '{% load i18n %}' in content or '{%load i18n%}' in content:
|
|
return content
|
|
|
|
# Check if it extends a template
|
|
if content.strip().startswith('{% extends'):
|
|
# Add after extends
|
|
lines = content.split('\n')
|
|
for i, line in enumerate(lines):
|
|
if '{% extends' in line:
|
|
lines.insert(i + 1, '{% load i18n %}')
|
|
return '\n'.join(lines)
|
|
|
|
# Add at the very top
|
|
return '{% load i18n %}\n' + content
|
|
|
|
def wrap_text_in_trans(text):
|
|
"""Wrap text in {% trans %} tag"""
|
|
text = text.strip()
|
|
if not text or '{%' in text or '{{' in text:
|
|
return text
|
|
return f'{{% trans "{text}" %}}'
|
|
|
|
def process_template_content(content):
|
|
"""Process template content and add translation tags"""
|
|
lines = content.split('\n')
|
|
processed_lines = []
|
|
|
|
for line in lines:
|
|
original_line = line
|
|
|
|
# Skip lines that already have trans tags
|
|
if '{% trans' in line or '{%trans' in line:
|
|
processed_lines.append(line)
|
|
continue
|
|
|
|
# Skip lines with only Django template tags or variables
|
|
if line.strip().startswith('{%') or line.strip().startswith('{{'):
|
|
processed_lines.append(line)
|
|
continue
|
|
|
|
# Process specific patterns
|
|
# Button text
|
|
if '<button' in line and '</button>' in line:
|
|
match = re.search(r'>([^<>{}\n]+)</button>', line)
|
|
if match:
|
|
text = match.group(1).strip()
|
|
if text and not '{' in text and len(text) > 1:
|
|
line = line.replace(f'>{text}</button>', f'>{{% trans "{text}" %}}</button>')
|
|
|
|
# Link text
|
|
if '<a ' in line and '</a>' in line:
|
|
match = re.search(r'>([^<>{}\n]+)</a>', line)
|
|
if match:
|
|
text = match.group(1).strip()
|
|
if text and not '{' in text and len(text) > 1 and not text.startswith('<'):
|
|
line = line.replace(f'>{text}</a>', f'>{{% trans "{text}" %}}</a>')
|
|
|
|
# Label text
|
|
if '<label' in line and '</label>' in line:
|
|
match = re.search(r'>([^<>{}\n]+)</label>', line)
|
|
if match:
|
|
text = match.group(1).strip()
|
|
if text and not '{' in text and len(text) > 1:
|
|
line = line.replace(f'>{text}</label>', f'>{{% trans "{text}" %}}</label>')
|
|
|
|
# Heading text
|
|
for i in range(1, 7):
|
|
if f'<h{i}' in line and f'</h{i}>' in line:
|
|
match = re.search(rf'>([^<>{{}}\n]+)</h{i}>', line)
|
|
if match:
|
|
text = match.group(1).strip()
|
|
if text and not '{' in text and len(text) > 1:
|
|
line = line.replace(f'>{text}</h{i}>', f'>{{% trans "{text}" %}}</h{i}>')
|
|
|
|
# Table headers
|
|
if '<th' in line and '</th>' in line:
|
|
match = re.search(r'>([^<>{}\n]+)</th>', line)
|
|
if match:
|
|
text = match.group(1).strip()
|
|
if text and not '{' in text and len(text) > 1:
|
|
line = line.replace(f'>{text}</th>', f'>{{% trans "{text}" %}}</th>')
|
|
|
|
# Paragraph text (be careful with this one)
|
|
if '<p' in line and '</p>' in line and '<p>' in line:
|
|
match = re.search(r'<p>([^<>{}\n]+)</p>', line)
|
|
if match:
|
|
text = match.group(1).strip()
|
|
if text and not '{' in text and len(text) > 1:
|
|
line = line.replace(f'<p>{text}</p>', f'<p>{{% trans "{text}" %}}</p>')
|
|
|
|
# Placeholder attributes
|
|
if 'placeholder="' in line:
|
|
match = re.search(r'placeholder="([^"]+)"', line)
|
|
if match:
|
|
text = match.group(1)
|
|
if not '{' in text:
|
|
line = line.replace(f'placeholder="{text}"', f'placeholder="{{% trans \'{text}\' %}}"')
|
|
|
|
# Title attributes
|
|
if 'title="' in line and not '{% trans' in line:
|
|
match = re.search(r'title="([^"]+)"', line)
|
|
if match:
|
|
text = match.group(1)
|
|
if not '{' in text and len(text) > 2:
|
|
line = line.replace(f'title="{text}"', f'title="{{% trans \'{text}\' %}}"')
|
|
|
|
processed_lines.append(line)
|
|
|
|
return '\n'.join(processed_lines)
|
|
|
|
def process_template(filepath):
|
|
"""Process a single template file"""
|
|
print(f"Processing: {filepath}")
|
|
|
|
try:
|
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
original_content = content
|
|
|
|
# Add i18n load tag
|
|
content = add_i18n_load(content)
|
|
|
|
# Process content for translations
|
|
content = process_template_content(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: {filepath}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f" ✗ Error processing {filepath}: {e}")
|
|
return False
|
|
|
|
def main():
|
|
"""Main function to process all templates"""
|
|
base_dir = Path(__file__).parent
|
|
templates_dir = base_dir / 'templates'
|
|
|
|
if not templates_dir.exists():
|
|
print(f"Templates directory not found: {templates_dir}")
|
|
return
|
|
|
|
# Find all HTML files
|
|
html_files = sorted(list(templates_dir.rglob('*.html')))
|
|
|
|
print(f"Found {len(html_files)} template files")
|
|
print("=" * 80)
|
|
|
|
updated_count = 0
|
|
for html_file in html_files:
|
|
if process_template(html_file):
|
|
updated_count += 1
|
|
print()
|
|
|
|
print("=" * 80)
|
|
print(f"Completed! Updated {updated_count} out of {len(html_files)} files")
|
|
|
|
if __name__ == '__main__':
|
|
main()
|