afegit suport multiidioma

afegida traducció al valencià
This commit is contained in:
2026-03-22 09:00:51 +01:00
parent 9b7abc7725
commit c6e2779429
80 changed files with 680 additions and 163 deletions

View File

@@ -0,0 +1,90 @@
#include "core/locale/locale.hpp"
#include <fstream>
#include <iostream>
#include <string>
#include "external/fkyaml_node.hpp" // Para fkyaml::node
#include "game/options.hpp" // Para Options::console
// [SINGLETON]
Locale* Locale::locale_ = nullptr;
// [SINGLETON] Crea el objeto con esta función estática
void Locale::init(const std::string& file_path) {
Locale::locale_ = new Locale();
Locale::locale_->loadFromFile(file_path);
}
// [SINGLETON] Destruye el objeto con esta función estática
void Locale::destroy() {
delete Locale::locale_;
Locale::locale_ = nullptr;
}
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
auto Locale::get() -> Locale* {
return Locale::locale_;
}
// Devuelve la traducción de la clave o la clave como fallback
auto Locale::get(const std::string& key) const -> std::string {
auto it = strings_.find(key);
if (it != strings_.end()) {
return it->second;
}
if (Options::console) {
std::cerr << "Locale: clave no encontrada: " << key << '\n';
}
return key;
}
// Aplana un nodo YAML de forma recursiva: {a: {b: "val"}} -> {"a.b" -> "val"}
void Locale::flatten(const void* node_ptr, const std::string& prefix) {
const auto& node = *static_cast<const fkyaml::node*>(node_ptr);
for (auto itr = node.begin(); itr != node.end(); ++itr) {
const std::string KEY = prefix.empty()
? itr.key().get_value<std::string>()
: prefix + "." + itr.key().get_value<std::string>();
const auto& value = itr.value();
if (value.is_mapping()) {
flatten(&value, KEY);
} else if (value.is_string()) {
strings_[KEY] = value.get_value<std::string>();
}
}
}
// Carga las traducciones desde el fichero YAML indicado
void Locale::loadFromFile(const std::string& file_path) {
if (file_path.empty()) {
if (Options::console) {
std::cerr << "Locale: ruta de fichero vacía, sin traducciones cargadas\n";
}
return;
}
std::ifstream file(file_path);
if (!file.is_open()) {
if (Options::console) {
std::cerr << "Locale: no se puede abrir " << file_path << '\n';
}
return;
}
try {
auto yaml = fkyaml::node::deserialize(file);
flatten(&yaml, "");
if (Options::console) {
std::cout << "Locale: " << strings_.size() << " traducciones cargadas desde " << file_path << '\n';
}
} catch (const fkyaml::exception& e) {
if (Options::console) {
std::cerr << "Locale: error al parsear YAML: " << e.what() << '\n';
}
}
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include <string>
#include <unordered_map>
// Clase Locale: gestiona las traducciones del juego (singleton)
// Las traducciones se cargan desde un fichero YAML en el inicio.
// No se permite cambio de idioma en caliente.
class Locale {
public:
static void init(const std::string& file_path); // Crea e inicializa el singleton
static void destroy(); // Destruye el singleton
static auto get() -> Locale*; // Devuelve el singleton
// Devuelve la traducción de la clave dada.
// Si la clave no existe, devuelve la propia clave como fallback.
[[nodiscard]] auto get(const std::string& key) const -> std::string;
private:
Locale() = default;
void loadFromFile(const std::string& file_path);
void flatten(const void* node_ptr, const std::string& prefix); // Aplana nodos YAML anidados
static Locale* locale_;
std::unordered_map<std::string, std::string> strings_;
};