#include "core/locale/locale.hpp" #include #include #include #include "external/fkyaml_node.hpp" // Para fkyaml::node #include "game/options.hpp" // Para Options::console // [SINGLETON] Locale* Locale::instance = nullptr; // [SINGLETON] Crea el objeto con esta función estática void Locale::init(const std::string& file_path) { // NOLINT(readability-convert-member-functions-to-static) Locale::instance = new Locale(); Locale::instance->loadFromFile(file_path); } // [SINGLETON] Destruye el objeto con esta función estática void Locale::destroy() { delete Locale::instance; Locale::instance = nullptr; } // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él auto Locale::get() -> Locale* { return Locale::instance; } // Devuelve la traducción de la clave o la clave como fallback auto Locale::get(const std::string& key) const -> std::string { // NOLINT(readability-convert-member-functions-to-static) 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) { // NOLINT(readability-convert-member-functions-to-static) const auto& node = *static_cast(node_ptr); for (auto itr = node.begin(); itr != node.end(); ++itr) { const std::string KEY = prefix.empty() ? itr.key().get_value() : prefix + "." + itr.key().get_value(); const auto& value = itr.value(); if (value.is_mapping()) { flatten(&value, KEY); } else if (value.is_string()) { strings_[KEY] = value.get_value(); } } } // Carga las traducciones desde el fichero YAML indicado void Locale::loadFromFile(const std::string& file_path) { // NOLINT(readability-convert-member-functions-to-static) 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'; } } }