211 lines
7.0 KiB
PHP
Executable File
211 lines
7.0 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Helper para manejar traducciones en la aplicación
|
|
*
|
|
* Este archivo proporciona funciones para manejar traducciones de manera consistente
|
|
* en toda la aplicación, incluyendo soporte para múltiples idiomas y caché de traducciones.
|
|
*/
|
|
|
|
// Evitar acceso directo
|
|
defined('ROOT_PATH') || define('ROOT_PATH', dirname(__DIR__));
|
|
|
|
// Inicializar el array de caché de traducciones
|
|
$GLOBALS['_translations_cache'] = [];
|
|
|
|
/**
|
|
* Obtiene una traducción para la clave dada en el idioma actual del usuario
|
|
*
|
|
* @param string $key Clave de traducción
|
|
* @param array $params Parámetros para reemplazar en la cadena de traducción
|
|
* @param string|null $language Código de idioma (opcional, por defecto usa el idioma de sesión)
|
|
* @return string Texto traducido o la clave si no se encuentra la traducción
|
|
*/
|
|
function __($key, $params = [], $language = null) {
|
|
global $pdo; // Asumiendo que $pdo está disponible globalmente
|
|
|
|
// Si no se proporciona un idioma, usar el de la sesión o el predeterminado
|
|
if ($language === null) {
|
|
$language = $_SESSION['language'] ?? 'es';
|
|
}
|
|
|
|
// Clave para el caché
|
|
$cache_key = $language . '_' . $key;
|
|
|
|
// Verificar si la traducción está en caché
|
|
if (isset($GLOBALS['_translations_cache'][$cache_key])) {
|
|
$translation = $GLOBALS['_translations_cache'][$cache_key];
|
|
} else {
|
|
// Si no está en caché, buscarla en la base de datos
|
|
try {
|
|
$stmt = $pdo->prepare(
|
|
"SELECT `value` FROM translations
|
|
WHERE `key` = :key AND language_code = :language
|
|
LIMIT 1"
|
|
);
|
|
|
|
$stmt->execute([
|
|
':key' => $key,
|
|
':language' => $language
|
|
]);
|
|
|
|
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
$translation = $result ? $result['value'] : '';
|
|
|
|
// Almacenar en caché para futuras solicitudes
|
|
$GLOBALS['_translations_cache'][$cache_key] = $translation;
|
|
|
|
} catch (PDOException $e) {
|
|
// En caso de error, devolver la clave como último recurso
|
|
error_log("Error al obtener traducción: " . $e->getMessage());
|
|
return $key;
|
|
}
|
|
}
|
|
|
|
// Si no se encontró la traducción, devolver la clave
|
|
if (empty($translation)) {
|
|
// Opcional: Registrar claves faltantes para facilitar la localización
|
|
log_missing_translation($key, $language);
|
|
return $key;
|
|
}
|
|
|
|
// Reemplazar parámetros si se proporcionan
|
|
if (!empty($params) && is_array($params)) {
|
|
foreach ($params as $param => $value) {
|
|
$translation = str_replace(":$param", $value, $translation);
|
|
}
|
|
}
|
|
|
|
return $translation;
|
|
}
|
|
|
|
/**
|
|
* Registra claves de traducción faltantes para facilitar la localización
|
|
*
|
|
* @param string $key Clave de traducción faltante
|
|
* @param string $language Código de idioma
|
|
*/
|
|
function log_missing_translation($key, $language) {
|
|
$log_file = ROOT_PATH . '/logs/missing_translations.log';
|
|
$log_entry = sprintf(
|
|
"[%s] Missing translation: %s (Language: %s)\n",
|
|
date('Y-m-d H:i:s'),
|
|
$key,
|
|
$language
|
|
);
|
|
|
|
// Asegurarse de que el directorio de logs existe
|
|
if (!is_dir(dirname($log_file))) {
|
|
@mkdir(dirname($log_file), 0755, true);
|
|
}
|
|
|
|
// Registrar en el archivo de log
|
|
@file_put_contents($log_file, $log_entry, FILE_APPEND);
|
|
}
|
|
|
|
/**
|
|
* Obtiene la lista de idiomas disponibles
|
|
*
|
|
* @param bool $only_active Si es true, solo devuelve los idiomas activos
|
|
* @return array Lista de idiomas
|
|
*/
|
|
function get_available_languages($only_active = true) {
|
|
global $pdo;
|
|
|
|
try {
|
|
$sql = "SELECT code, name, native_name, flag_emoji, is_active
|
|
FROM languages";
|
|
|
|
if ($only_active) {
|
|
$sql .= " WHERE is_active = 1";
|
|
}
|
|
|
|
$sql .= " ORDER BY name";
|
|
|
|
$stmt = $pdo->query($sql);
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
} catch (PDOException $e) {
|
|
error_log("Error al obtener idiomas: " . $e->getMessage());
|
|
return [
|
|
['code' => 'es', 'name' => 'Spanish', 'native_name' => 'Español', 'flag_emoji' => '🇪🇸', 'is_active' => 1],
|
|
['code' => 'en', 'name' => 'English', 'native_name' => 'English', 'flag_emoji' => '🇬🇧', 'is_active' => 1]
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inicializa el sistema de traducciones en las plantillas
|
|
* Inyecta las traducciones necesarias para JavaScript
|
|
*
|
|
* @return string Código JavaScript con las traducciones (sin etiquetas <script>)
|
|
*/
|
|
function init_translations_for_js() {
|
|
global $pdo;
|
|
|
|
// Obtener el idioma actual
|
|
$language = $_SESSION['language'] ?? 'es';
|
|
|
|
// Obtener todas las traducciones para el idioma actual
|
|
try {
|
|
$stmt = $pdo->prepare(
|
|
"SELECT `key`, `value` FROM translations
|
|
WHERE language_code = :language"
|
|
);
|
|
|
|
$stmt->execute([':language' => $language]);
|
|
$translations = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
|
|
|
|
} catch (PDOException $e) {
|
|
error_log("Error al cargar traducciones para JS: " . $e->getMessage());
|
|
$translations = [];
|
|
}
|
|
|
|
// Devolver solo el código JavaScript (sin etiquetas <script>)
|
|
return "// Traducciones cargadas dinámicamente\n" .
|
|
"window.translations = " . json_encode($translations, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE) . ";\n";
|
|
}
|
|
|
|
/**
|
|
* Función para traducir texto en JavaScript
|
|
* Se debe llamar después de incluir el helper en el HTML
|
|
*/
|
|
function js_translation_function() {
|
|
echo <<<JS
|
|
<script>
|
|
/**
|
|
* Función para traducir texto en JavaScript
|
|
* @param {string} key - Clave de traducción
|
|
* @param {Object} params - Parámetros para reemplazar en la cadena
|
|
* @return {string} Texto traducido o la clave si no se encuentra
|
|
*/
|
|
function __(key, params = {}) {
|
|
let text = translations[key] || key;
|
|
|
|
// Reemplazar parámetros
|
|
Object.keys(params).forEach(param => {
|
|
text = text.replace(new RegExp(`:${param}`, 'g'), params[param]);
|
|
});
|
|
|
|
return text;
|
|
}
|
|
|
|
// Traducir elementos con el atributo data-translate
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const elements = document.querySelectorAll('[data-translate]');
|
|
elements.forEach(element => {
|
|
const key = element.getAttribute('data-translate');
|
|
if (translations[key]) {
|
|
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
|
|
element.placeholder = translations[key];
|
|
} else if (element.tagName === 'BUTTON' || element.tagName === 'A') {
|
|
element.textContent = translations[key];
|
|
} else {
|
|
element.textContent = translations[key];
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
JS;
|
|
}
|