227 lines
6.8 KiB
Python
227 lines
6.8 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Extract strings for translation and create Spanish .po files
|
||
|
|
"""
|
||
|
|
import os
|
||
|
|
import re
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
# Directories
|
||
|
|
TEMPLATES_DIR = Path('templates')
|
||
|
|
TRANSLATIONS_DIR = Path('translations')
|
||
|
|
|
||
|
|
# Find all template files
|
||
|
|
def find_template_files():
|
||
|
|
template_files = []
|
||
|
|
for root, dirs, files in os.walk(TEMPLATES_DIR):
|
||
|
|
for file in files:
|
||
|
|
if file.endswith('.html'):
|
||
|
|
template_files.append(Path(root) / file)
|
||
|
|
return template_files
|
||
|
|
|
||
|
|
# Extract strings from templates
|
||
|
|
def extract_strings_from_file(filepath):
|
||
|
|
strings = set()
|
||
|
|
with open(filepath, 'r', encoding='utf-8') as f:
|
||
|
|
content = f.read()
|
||
|
|
|
||
|
|
# Find all _('...') and gettext('...') calls
|
||
|
|
pattern = r"[\"'](?:_|gettext)\([\"']([^\"']+)[\"']\)"
|
||
|
|
matches = re.findall(r"\{\{\s*_\('([^']+)'\)\s*\}\}", content)
|
||
|
|
matches += re.findall(r"\{\{\s*gettext\('([^']+)'\)\s*\}\}", content)
|
||
|
|
|
||
|
|
return matches
|
||
|
|
|
||
|
|
# Create .pot file
|
||
|
|
def create_pot_file(strings):
|
||
|
|
pot_content = """msgid ""
|
||
|
|
msgstr ""
|
||
|
|
"Project-Id-Version: Tablet Management System\n"
|
||
|
|
"POT-Creation-Date: 2026-06-20\n"
|
||
|
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||
|
|
"Last-Translator: \n"
|
||
|
|
"Language-Team: \n"
|
||
|
|
"Language: en\n"
|
||
|
|
"MIME-Version: 1.0\n"
|
||
|
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||
|
|
"Content-Transfer-Encoding: 8bit\n"
|
||
|
|
|
||
|
|
"""
|
||
|
|
|
||
|
|
for string in sorted(strings):
|
||
|
|
pot_content += f'msgid "{string}"\n'
|
||
|
|
pot_content += 'msgstr ""\n\n'
|
||
|
|
|
||
|
|
return pot_content
|
||
|
|
|
||
|
|
# Create Spanish .po file
|
||
|
|
def create_es_po_file(strings):
|
||
|
|
# Spanish translations
|
||
|
|
translations = {
|
||
|
|
# Navigation
|
||
|
|
'Tablet Management System': 'Sistema de Gestión de Tablets',
|
||
|
|
'Home': 'Inicio',
|
||
|
|
'Add Tablet': 'Añadir Tablet',
|
||
|
|
'Add User': 'Añadir Usuario',
|
||
|
|
'Loan Tablet': 'Prestar Tablet',
|
||
|
|
'History': 'Historial',
|
||
|
|
'User Loans': 'Préstamos por Usuario',
|
||
|
|
'Non-Loanable Devices': 'Dispositivos No Prestables',
|
||
|
|
'Project Management': 'Gestión de Proyectos',
|
||
|
|
|
||
|
|
# Language
|
||
|
|
'Language': 'Idioma',
|
||
|
|
'English': 'Inglés',
|
||
|
|
'Español': 'Español',
|
||
|
|
|
||
|
|
# Common
|
||
|
|
'Search': 'Buscar',
|
||
|
|
'Filter': 'Filtrar',
|
||
|
|
'Status': 'Estado',
|
||
|
|
'Actions': 'Acciones',
|
||
|
|
'Details': 'Detalles',
|
||
|
|
'View': 'Ver',
|
||
|
|
'All': 'Todos',
|
||
|
|
'Active': 'Activo',
|
||
|
|
'Inactive': 'Inactivo',
|
||
|
|
'Available': 'Disponible',
|
||
|
|
'Returned': 'Devuelto',
|
||
|
|
'Never': 'Nunca',
|
||
|
|
'N/A': 'N/D',
|
||
|
|
'Yes': 'Sí',
|
||
|
|
'No': 'No',
|
||
|
|
'Showing': 'Mostrando',
|
||
|
|
'to': 'a',
|
||
|
|
'of': 'de',
|
||
|
|
'Previous': 'Anterior',
|
||
|
|
'Next': 'Siguiente',
|
||
|
|
'Page': 'Página',
|
||
|
|
|
||
|
|
# User Loans
|
||
|
|
'User Loans': 'Préstamos por Usuario',
|
||
|
|
'Search Users': 'Buscar Usuarios',
|
||
|
|
'Loan Status': 'Estado de Préstamo',
|
||
|
|
'All Users': 'Todos los Usuarios',
|
||
|
|
'With Active Loans': 'Con Préstamos Activos',
|
||
|
|
'No Active Loans': 'Sin Préstamos Activos',
|
||
|
|
'Search by name or identification...': 'Buscar por nombre o identificación...',
|
||
|
|
'users': 'usuarios',
|
||
|
|
'No users found': 'No se encontraron usuarios',
|
||
|
|
'No users match your search for': 'Ningún usuario coincide con tu búsqueda de',
|
||
|
|
'Clear Filters': 'Limpiar Filtros',
|
||
|
|
|
||
|
|
# Table Headers
|
||
|
|
'User': 'Usuario',
|
||
|
|
'Identification': 'Identificación',
|
||
|
|
'Active Loans': 'Préstamos Activos',
|
||
|
|
'Last Loan Date': 'Fecha del Último Préstamo',
|
||
|
|
'Tablet': 'Tablet',
|
||
|
|
'Model': 'Modelo',
|
||
|
|
'Serial Number': 'Número de Serie',
|
||
|
|
'Notes': 'Notas',
|
||
|
|
'Borrower': 'Prestatario',
|
||
|
|
'Loan Date': 'Fecha de Préstamo',
|
||
|
|
'Return Date': 'Fecha de Devolución',
|
||
|
|
'Not returned': 'No devuelto',
|
||
|
|
|
||
|
|
# Buttons
|
||
|
|
'Loan': 'Prestar',
|
||
|
|
'Return': 'Devolver',
|
||
|
|
'Add': 'Añadir',
|
||
|
|
'Save': 'Guardar',
|
||
|
|
'Cancel': 'Cancelar',
|
||
|
|
'Delete': 'Eliminar',
|
||
|
|
'Edit': 'Editar',
|
||
|
|
'Update': 'Actualizar',
|
||
|
|
|
||
|
|
# Messages
|
||
|
|
'Tablet Management System - Internal Tool': 'Sistema de Gestión de Tablets - Herramienta Interna',
|
||
|
|
'No available tablets': 'No hay tablets disponibles',
|
||
|
|
'No active loans': 'No hay préstamos activos',
|
||
|
|
'No loan history for this user': 'Este usuario no tiene historial de préstamos',
|
||
|
|
|
||
|
|
# Forms
|
||
|
|
'Brand': 'Marca',
|
||
|
|
'Model': 'Modelo',
|
||
|
|
'Serial Number': 'Número de Serie',
|
||
|
|
'Name': 'Nombre',
|
||
|
|
'Email': 'Correo Electrónico',
|
||
|
|
'Phone': 'Teléfono',
|
||
|
|
'Identification': 'Identificación',
|
||
|
|
'Date': 'Fecha',
|
||
|
|
'Notes': 'Notas',
|
||
|
|
'Required field': 'Campo obligatorio',
|
||
|
|
|
||
|
|
# Status
|
||
|
|
'Active Loans': 'Préstamos Activos',
|
||
|
|
'Returned': 'Devueltos',
|
||
|
|
}
|
||
|
|
|
||
|
|
po_content = """msgid ""
|
||
|
|
msgstr ""
|
||
|
|
"Project-Id-Version: Tablet Management System\n"
|
||
|
|
"POT-Creation-Date: 2026-06-20\n"
|
||
|
|
"PO-Revision-Date: 2026-06-20\n"
|
||
|
|
"Last-Translator: Auto-generated\n"
|
||
|
|
"Language-Team: \n"
|
||
|
|
"Language: es\n"
|
||
|
|
"MIME-Version: 1.0\n"
|
||
|
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||
|
|
"Content-Transfer-Encoding: 8bit\n"
|
||
|
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||
|
|
|
||
|
|
"""
|
||
|
|
|
||
|
|
for string in sorted(strings):
|
||
|
|
msgid = string
|
||
|
|
msgstr = translations.get(string, '')
|
||
|
|
po_content += f'msgid "{msgid}"\n'
|
||
|
|
po_content += f'msgstr "{msgstr}"\n\n'
|
||
|
|
|
||
|
|
return po_content
|
||
|
|
|
||
|
|
# Main
|
||
|
|
def main():
|
||
|
|
print("Extracting strings for translation...")
|
||
|
|
|
||
|
|
# Find all template files
|
||
|
|
template_files = find_template_files()
|
||
|
|
print(f"Found {len(template_files)} template files")
|
||
|
|
|
||
|
|
# Extract all strings
|
||
|
|
all_strings = set()
|
||
|
|
for filepath in template_files:
|
||
|
|
strings = extract_strings_from_file(filepath)
|
||
|
|
all_strings.update(strings)
|
||
|
|
|
||
|
|
print(f"Found {len(all_strings)} unique strings")
|
||
|
|
|
||
|
|
# Create .pot file
|
||
|
|
pot_content = create_pot_file(all_strings)
|
||
|
|
pot_path = TRANSLATIONS_DIR / 'messages.pot'
|
||
|
|
with open(pot_path, 'w', encoding='utf-8') as f:
|
||
|
|
f.write(pot_content)
|
||
|
|
print(f"Created {pot_path}")
|
||
|
|
|
||
|
|
# Create Spanish .po file
|
||
|
|
es_po_content = create_es_po_file(all_strings)
|
||
|
|
es_dir = TRANSLATIONS_DIR / 'es' / 'LC_MESSAGES'
|
||
|
|
es_dir.mkdir(parents=True, exist_ok=True)
|
||
|
|
es_po_path = es_dir / 'messages.po'
|
||
|
|
with open(es_po_path, 'w', encoding='utf-8') as f:
|
||
|
|
f.write(es_po_content)
|
||
|
|
print(f"Created {es_po_path}")
|
||
|
|
|
||
|
|
# Create English .po file
|
||
|
|
en_dir = TRANSLATIONS_DIR / 'en' / 'LC_MESSAGES'
|
||
|
|
en_dir.mkdir(parents=True, exist_ok=True)
|
||
|
|
en_po_path = en_dir / 'messages.po'
|
||
|
|
with open(en_po_path, 'w', encoding='utf-8') as f:
|
||
|
|
f.write(create_pot_file(all_strings))
|
||
|
|
print(f"Created {en_po_path}")
|
||
|
|
|
||
|
|
print("\n✅ Translation files created!")
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
main()
|