Initial commit: Complete multilingual website with translation system
This commit is contained in:
180
translation_manager.py
Normal file
180
translation_manager.py
Normal file
@@ -0,0 +1,180 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple JSON-based Translation Manager for Kobelly Web Solutions
|
||||
No compilation needed - just edit JSON files directly!
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import glob
|
||||
from flask import request, session, url_for
|
||||
from functools import wraps
|
||||
|
||||
# Supported languages
|
||||
SUPPORTED_LANGUAGES = ['en', 'de', 'fr', 'nl']
|
||||
|
||||
# Default language
|
||||
DEFAULT_LANGUAGE = 'en'
|
||||
|
||||
# Translation cache
|
||||
_translations = {}
|
||||
|
||||
def load_translations():
|
||||
"""Load all translation files into memory."""
|
||||
global _translations
|
||||
|
||||
if not os.path.exists('translations'):
|
||||
os.makedirs('translations')
|
||||
|
||||
for lang in SUPPORTED_LANGUAGES:
|
||||
lang_file = f'translations/{lang}.json'
|
||||
|
||||
if os.path.exists(lang_file):
|
||||
try:
|
||||
with open(lang_file, 'r', encoding='utf-8') as f:
|
||||
_translations[lang] = json.load(f)
|
||||
print(f"✓ Loaded {lang} translations ({len(_translations[lang])} keys)")
|
||||
except Exception as e:
|
||||
print(f"✗ Error loading {lang} translations: {e}")
|
||||
_translations[lang] = {}
|
||||
else:
|
||||
print(f"⚠ {lang} translation file not found, creating empty one")
|
||||
_translations[lang] = {}
|
||||
save_translations(lang, {})
|
||||
|
||||
def save_translations(lang, translations):
|
||||
"""Save translations for a specific language."""
|
||||
if not os.path.exists('translations'):
|
||||
os.makedirs('translations')
|
||||
|
||||
lang_file = f'translations/{lang}.json'
|
||||
try:
|
||||
with open(lang_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(translations, f, indent=2, ensure_ascii=False)
|
||||
_translations[lang] = translations
|
||||
print(f"✓ Saved {lang} translations")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"✗ Error saving {lang} translations: {e}")
|
||||
return False
|
||||
|
||||
def get_current_language():
|
||||
"""Get the current language from session or request."""
|
||||
# Check session first
|
||||
if 'language' in session:
|
||||
return session['language']
|
||||
|
||||
# Check request parameter
|
||||
if request.args.get('lang') in SUPPORTED_LANGUAGES:
|
||||
return request.args.get('lang')
|
||||
|
||||
# Check Accept-Language header
|
||||
if request.accept_languages:
|
||||
for lang in request.accept_languages:
|
||||
if lang[0] in SUPPORTED_LANGUAGES:
|
||||
return lang[0]
|
||||
|
||||
return DEFAULT_LANGUAGE
|
||||
|
||||
def set_language(lang):
|
||||
"""Set the current language in session."""
|
||||
if lang in SUPPORTED_LANGUAGES:
|
||||
session['language'] = lang
|
||||
print(f"✓ Language set to {lang}")
|
||||
return True
|
||||
print(f"✗ Invalid language: {lang}")
|
||||
return False
|
||||
|
||||
def translate(key, lang=None, **kwargs):
|
||||
"""Translate a key to the specified language."""
|
||||
if lang is None:
|
||||
lang = get_current_language()
|
||||
|
||||
# Get translation
|
||||
translation = _translations.get(lang, {}).get(key, key)
|
||||
|
||||
# Format with kwargs if provided
|
||||
if kwargs:
|
||||
try:
|
||||
translation = translation.format(**kwargs)
|
||||
except (KeyError, ValueError):
|
||||
# If formatting fails, return the key
|
||||
translation = key
|
||||
|
||||
return translation
|
||||
|
||||
def extract_strings():
|
||||
"""Extract all translatable strings from templates and create translation files."""
|
||||
print("📤 Extracting translatable strings...")
|
||||
|
||||
# Find all template files
|
||||
template_files = glob.glob('templates/**/*.html', recursive=True)
|
||||
|
||||
# Extract strings (this is a simplified version)
|
||||
# In practice, you'd want to parse the templates more thoroughly
|
||||
extracted_strings = set()
|
||||
|
||||
for template_file in template_files:
|
||||
try:
|
||||
with open(template_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
# Look for common patterns (this is simplified)
|
||||
# You might want to use a proper template parser
|
||||
lines = content.split('\n')
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if line and not line.startswith('{') and not line.startswith('<!--'):
|
||||
# Simple extraction - you might want to improve this
|
||||
if len(line) > 3 and not line.startswith('<'):
|
||||
extracted_strings.add(line)
|
||||
except Exception as e:
|
||||
print(f"Error reading {template_file}: {e}")
|
||||
|
||||
# Create translation structure
|
||||
translations = {}
|
||||
for string in sorted(extracted_strings):
|
||||
translations[string] = string
|
||||
|
||||
# Save for each language
|
||||
for lang in SUPPORTED_LANGUAGES:
|
||||
save_translations(lang, translations)
|
||||
|
||||
print(f"✓ Extracted {len(extracted_strings)} strings")
|
||||
return translations
|
||||
|
||||
def create_language_selector():
|
||||
"""Create HTML for language selector."""
|
||||
current_lang = get_current_language()
|
||||
|
||||
html = '<div class="language-selector">'
|
||||
for lang in SUPPORTED_LANGUAGES:
|
||||
lang_name = {
|
||||
'en': 'English',
|
||||
'de': 'Deutsch',
|
||||
'fr': 'Français',
|
||||
'nl': 'Nederlands'
|
||||
}.get(lang, lang.upper())
|
||||
|
||||
active_class = 'active' if lang == current_lang else ''
|
||||
html += f'<a href="?lang={lang}" class="lang-link {active_class}">{lang_name}</a>'
|
||||
html += '</div>'
|
||||
|
||||
return html
|
||||
|
||||
# Flask integration
|
||||
def init_app(app):
|
||||
"""Initialize the translation system with Flask app."""
|
||||
load_translations()
|
||||
|
||||
@app.context_processor
|
||||
def inject_translations():
|
||||
return {
|
||||
'translate': translate,
|
||||
'get_current_language': get_current_language,
|
||||
'create_language_selector': create_language_selector
|
||||
}
|
||||
|
||||
# Convenience function for templates
|
||||
def t(key, **kwargs):
|
||||
"""Short alias for translate function."""
|
||||
return translate(key, **kwargs)
|
||||
Reference in New Issue
Block a user