Files
Shiip-of-Hakinian-Espanol-A…/PLAN_TRADUCCION.md
2026-03-30 10:05:53 +00:00

7.7 KiB

Plan de Implementación del Sistema de Traducción

Objetivo

Crear un sistema de traducción dinámico que permita cargar idiomas desde archivos JSON externos sin modificar los textos hardcodeados existentes. Los textos en el código bleiben en inglés como fallback por defecto.


1. Funcionamiento Clave

1.1 Comportamiento

  • Sin carpeta de idiomas: El juego funciona exactamente como ahora con los textos hardcodeados en inglés
  • Con carpeta de idiomas: Cuando el usuario selecciona un idioma, se carga el JSON y se traducen los textos disponibles
  • Fallback: Si una traducción no existe en el JSON, se usa el texto hardcodeado (inglés)

1.2 Carpeta de Idiomas (opcional)

/lenguajes/
  ├── Espanol.json
  ├── Portugues.json
  └── (otros idiomas).json

Nota: No se requiere English.json porque el inglés ya está hardcodeado en el código.


2. Archivos a Crear

Archivo Descripción
soh/soh/SohGui/LanguageManager.h Header del manager de idiomas
soh/soh/SohGui/LanguageManager.cpp Implementación del manager
lenguajes/Espanol.json Traducción español (ejemplo)
lenguajes/Portugues.json Traducción portugués (ejemplo)

3. Archivos a Modificar

Archivo Cambios
soh/soh/SohGui/SohMenuSettings.cpp Agregar selector de idioma dinámico en configuración

Nota: Los demás archivos del menú NO necesitan modificación. La función de traducción se aplica automáticamente a todos los textos existentes.


4. Formato de Archivos JSON

4.1 Estructura del JSON

{
  "language": "Español",
  "strings": {
    "Settings": "Configuración",
    "Enhancements": "Mejoras",
    "Randomizer": "Randomizer",
    "Network": "Red",
    "Dev Tools": "Herramientas de Desarrollo",
    "Enabled": "Activado",
    "Disabled": "Desactivado",
    "Apply": "Aplicar",
    "Cancel": "Cancelar"
  }
}

4.2 Espanol.json (Ejemplo)

{
  "language": "Español",
  "strings": {
    "Settings": "Configuración",
    "Enhancements": "Mejoras",
    "Randomizer": "Randomizer",
    "Network": "Red",
    "Dev Tools": "Herramientas de Desarrollo",
    "General Settings": "Configuración General",
    "Graphics": "Gráficos",
    "Audio": "Audio",
    "Controls": "Controles",
    "Enabled": "Activado",
    "Disabled": "Desactivado",
    "On": "Activado",
    "Off": "Desactivado",
    "Yes": "Sí",
    "No": "No",
    "Apply": "Aplicar",
    "Cancel": "Cancelar",
    "Resolution": "Resolución",
    "FPS Limit": "Límite de FPS",
    "VSync": "Sincronización Vertical",
    "Master Volume": "Volumen Principal",
    "Music Volume": "Volumen de Música",
    "SFX Volume": "Volumen de Efectos",
    "Anti-aliasing (MSAA)": "Antialiasing (MSAA)"
  }
}

5. Implementación del LanguageManager

5.1 LanguageManager.h

class LanguageManager {
public:
    static LanguageManager& Instance();
    
    void Init();
    void LoadLanguage(const std::string& languageName);
    std::string GetString(const std::string& key);
    std::vector<std::string> GetAvailableLanguages();
    std::string GetCurrentLanguage();
    bool IsTranslationLoaded();
    
private:
    std::string currentLanguage;
    std::map<std::string, std::string> translations;
    bool translationLoaded;
    
    void ScanLanguageFiles();
    bool LoadJsonFile(const std::string& path);
};

5.2 Lógica de Funcionamiento

std::string LanguageManager::GetString(const std::string& key) {
    // Si no hay traducción cargada, retorna el texto hardcodeado (ingles)
    if (!translationLoaded || translations.empty()) {
        return key;
    }
    
    // Busca la traducción
    auto it = translations.find(key);
    if (it != translations.end()) {
        return it->second;
    }
    
    // Si no encuentra la traducción, retorna el texto hardcodeado
    return key;
}

5.3 Funcionalidades Principales

  1. Escaneo de idiomas: Al iniciar, escanea la carpeta /lenguajes/ y detecta archivos .json
  2. Carga bajo demanda: Solo carga el JSON cuando el usuario selecciona un idioma
  3. Fallback seguro: Si no existe la traducción, retorna el texto hardcodeado
  4. Selector dinámico: Genera opciones basadas en archivos encontrados (sin hardcodear nombres)

6. Ejemplo de Uso en el Código

6.1 Sin cambios en el código existente

Los textos hardcodeados permanecen exactamente igual:

// El código queda igual, NO se cambia a L("key")
AddWidget(path, "Settings", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Language", WIDGET_CVAR_COMBOBOX);
AddWidget(path, "Enabled", WIDGET_CVAR_CHECKBOX);

6.2 La traducción se aplica automáticamente

La función GetString() intercepta los textos y los traduce:

// Internamente en AddWidget o donde se muestra el texto:
std::string displayText = LanguageManager::Instance().GetString("Settings");
// Si hay español cargado, retorna "Configuración"
// Si no hay traducción, retorna "Settings" (el texto original)

6.3 Cómo funciona

  • Los textos en el código bleiben en inglés
  • La función GetString() se llama al momento de mostrar el texto
  • Si hay una traducción cargada y existe la clave, retorna la traducción
  • Si no hay traducción o no existe la clave, retorna el texto original (hardcodeado)

7. Selector de Idioma

7.1 Ubicación

En SohMenuSettings.cpp dentro del menú de configuración

7.2 Comportamiento

  • Muestra todos los archivos .json encontrados en /lenguajes/
  • El nombre del archivo (sin extensión) se muestra en el selector
  • Al seleccionar un idioma, carga el archivo JSON correspondiente
  • Por defecto (sin acción del usuario), funciona con textos hardcodeados

7.3 Ejemplo de implementación del selector

// El selector se genera dinámicamente
std::vector<std::string> languages = LanguageManager::Instance().GetAvailableLanguages();
// languages = {"Espanol", "Portugues", ...} (nombres de archivos JSON)

// Mostrar en el menú
AddWidget(path, "Language", WIDGET_CVAR_COMBOBOX)
    .Options(languages);

8. Proceso de Implementación (Orden Sugerido)

Fase 1: Fundamentos

  1. Crear LanguageManager.h/cpp
  2. Crear estructura de carpetas /lenguajes/

Fase 2: Integración

  1. Modificar SohMenuSettings.cpp para agregar selector de idioma dinámico
  2. Conectar el selector con LanguageManager

Fase 3: Pruebas

  1. Crear Espanol.json de prueba
  2. Probar cambio de idioma

9. Notas Importantes

  • Textos hardcodeados permanecen: El código no se modifica, los textos en inglés quedan como están
  • Sin carpeta de idiomas funciona igual: Si no existe la carpeta, el juego funciona exactamente como antes
  • Fallback automático: Si falta una traducción, se muestra el texto original
  • Selector dinámico: Los nombres de idiomas vienen de los archivos JSON, no están hardcodeados
  • Fácil agregar idiomas: Solo hay que crear un nuevo archivo .json en la carpeta

10. Archivos de Referencia con Textos Hardcodeados

SohGui (ya analizados)

  • SohMenu_hardcoded.txt
  • SohMenuSettings_hardcoded.txt
  • SohMenuEnhancements_hardcoded.txt
  • SohMenuRandomizer_hardcoded.txt
  • SohMenuNetwork_hardcoded.txt
  • SohMenuDevTools_hardcoded.txt
  • SohMenuBar_hardcoded.txt
  • ResolutionEditor_hardcoded.txt

11. Diferencias con el Plan Anterior

Aspecto Plan Anterior Plan Actual
English.json Obligatorio No necesario (hardcodeado es fallback)
Reemplazo de textos Sí, en todos los archivos No, solo agregar función GetString
Archivos a modificar 8+ archivos Solo 1 archivo (SohMenuSettings.cpp)
Funcionamiento sin carpeta Requiere English.json Funciona igual que antes