#include "../include/Translation.hpp" #include #include #include #include namespace gsr { std::string Translation::get_system_language() { const char* lang = getenv("LANGUAGE"); if (!lang || !lang[0]) lang = getenv("LC_ALL"); if (!lang || !lang[0]) lang = getenv("LC_MESSAGES"); if (!lang || !lang[0]) lang = getenv("LANG"); if (lang && lang[0]) { std::string lang_str(lang); // we usually need only two symbols size_t underscore = lang_str.find('_'); if (underscore != std::string::npos) { return lang_str.substr(0, underscore); } size_t dot = lang_str.find('.'); if (dot != std::string::npos) { return lang_str.substr(0, dot); } return lang_str; } return "en"; } void Translation::process_escapes(std::string& str) { size_t pos = 0; while ((pos = str.find("\\n", pos)) != std::string::npos) { str.replace(pos, 2, "\n"); pos += 1; } } bool Translation::is_language_supported(const char* lang) { if(strcmp(lang, "en") == 0) return true; std::string paths[] = { std::string("translations/") + lang + ".txt", std::string(this->translations_directory) + lang + ".txt" }; for (const auto& path : paths) { std::ifstream file(path); if (file.is_open()) { return true; } } return false; } bool Translation::load_language(const char* lang) { translations.clear(); if(lang[0] == '\0') lang = "en"; if (!is_language_supported(lang)) { fprintf(stderr, "Warning: language '%s' is not supported\n", lang); return false; } current_language = lang; if (strcmp(lang, "en") == 0) { return true; // english is the base } std::string paths[] = { std::string("translations/") + lang + ".txt", std::string(this->translations_directory) + lang + ".txt" }; for (const auto& path : paths) { std::ifstream file(path); if (!file.is_open()) continue; std::string line; while (std::getline(file, line)) { if (line.empty() || line[0] == '#') continue; size_t eq_pos = line.find('='); if (eq_pos == std::string::npos) continue; std::string key = line.substr(0, eq_pos); std::string value = line.substr(eq_pos + 1); // Process escape sequences in both key and value process_escapes(key); process_escapes(value); translations[key] = value; } fprintf(stderr, "Info: Loaded translation file for '%s' from %s\n", lang, path.c_str()); return true; } fprintf(stderr, "Warning: translation file for '%s' not found\n", lang); return false; } Translation& Translation::instance() { static Translation tr; return tr; } void Translation::init(const char* translations_directory, const char* initial_language) { if(initial_language && initial_language[0] == '\0') initial_language = nullptr; this->translations_directory = translations_directory; load_language(initial_language == nullptr ? get_system_language().c_str() : initial_language); } bool Translation::plural_numbers_are_complex() { if ( current_language == "ru" || current_language == "uk" || current_language == "pl" || current_language == "cs" || current_language == "sk" || current_language == "hr" || current_language == "sl" ) { return true; } return current_language != "en"; } std::string Translation::get_complex_plural_number_key(const char* key, int number) { std::string s_key = key; if (current_language == "ru" || current_language == "uk") { int n = number % 100; if (n >= 11 && n <= 14) { return s_key + "_many"; } n = number % 10; if (n == 1) { return s_key + "_one"; } if (n >= 2 && n <= 4) { return s_key + "_few"; } return s_key + "_many"; } else if (current_language == "pl") { int n = number % 100; if (n >= 12 && n <= 14) { return s_key + "_many"; } n = number % 10; if (n == 1) { return s_key + "_one"; } if (n >= 2 && n <= 4) { return s_key + "_few"; } return s_key + "_many"; } // Add more languages as needed return key; // default fallback } const char* Translation::translate(const char* key) { auto it = translations.find(key); if (it != translations.end()) { return it->second.c_str(); } #ifndef DNDEBUG if(current_language != "en") fprintf(stderr, "Warning: translation key '%s' not found\n", key); #endif return key; // falling back if nothing found } }