MetaImGUI 1.0.0
ImGui Application Template for C++20
Loading...
Searching...
No Matches
Localization.cpp
Go to the documentation of this file.
1/*
2 MetaImGUI
3 Copyright (C) 2026 A P Nicholson
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17*/
18
19#include "Localization.h"
20
21#include "Logger.h"
22
23#include <nlohmann/json.hpp>
24
25#include <fstream>
26
27using json = nlohmann::json;
28
29namespace MetaImGUI {
30
31// ============================================================================
32// WARNING: DO NOT ADD BUILT-IN TRANSLATIONS HERE!
33// ============================================================================
34// All translations MUST come from resources/translations/translations.json
35// This is the SINGLE SOURCE OF TRUTH for all translations.
36//
37// Having two sources of translations (built-in + JSON) causes:
38// - Maintenance nightmares (keeping them in sync)
39// - Bugs when one is updated but not the other
40// - Confusion about which translation is actually being used
41//
42// If translations.json fails to load, the application should:
43// 1. Log a clear ERROR message
44// 2. Return translation keys as-is (they serve as English fallback)
45// 3. Be obvious to developers/users that something is wrong
46// ============================================================================
47
48Localization::Localization() : m_currentLanguage("en") {
49 // Translations are loaded via LoadTranslations() - see warning above
50}
51
53 static Localization instance;
54 return instance;
55}
56
57void Localization::SetLanguage(const std::string& languageCode) {
58 if (m_translations.contains(languageCode)) {
59 m_currentLanguage = languageCode;
60 LOG_INFO("Language set to: {}", languageCode);
61 } else {
62 LOG_ERROR("Language not available: {}", languageCode);
63 }
64}
65
67 return m_currentLanguage;
68}
69
70std::vector<std::string> Localization::GetAvailableLanguages() const {
71 std::vector<std::string> languages;
72 languages.reserve(m_translations.size());
73 for (const auto& pair : m_translations) {
74 languages.push_back(pair.first);
75 }
76 return languages;
77}
78
79std::string Localization::Tr(const std::string& key) const {
80 // Try current language
81 auto langIt = m_translations.find(m_currentLanguage);
82 if (langIt != m_translations.end()) {
83 auto keyIt = langIt->second.find(key);
84 if (keyIt != langIt->second.end()) {
85 return keyIt->second;
86 }
87 }
88
89 // Fallback to English
90 if (m_currentLanguage != "en") {
91 auto enIt = m_translations.find("en");
92 if (enIt != m_translations.end()) {
93 auto keyIt = enIt->second.find(key);
94 if (keyIt != enIt->second.end()) {
95 return keyIt->second;
96 }
97 }
98 }
99
100 // Return key if not found
101 return key;
102}
103
104void Localization::AddTranslation(const std::string& languageCode, const std::string& key, const std::string& value) {
105 m_translations[languageCode][key] = value;
106}
107
108bool Localization::LoadTranslations(const std::string& filepath) {
109 try {
110 std::ifstream file(filepath);
111 if (!file.is_open()) {
112 LOG_ERROR("Failed to open translations file: {}", filepath);
113 return false;
114 }
115
116 json j = json::parse(file);
117
118 for (const auto& [languageCode, translations] : j.items()) {
119 for (const auto& [key, value] : translations.items()) {
120 AddTranslation(languageCode, key, value.get<std::string>());
121 }
122 }
123
124 LOG_INFO("Loaded translations from: {}", filepath);
125 return true;
126 } catch (const std::exception& e) {
127 LOG_ERROR("Failed to load translations: {}", e.what());
128 return false;
129 }
130}
131
132} // namespace MetaImGUI
nlohmann::json json
#define LOG_INFO(...)
Definition Logger.h:218
#define LOG_ERROR(...)
Definition Logger.h:220
Simple localization/internationalization system.
static Localization & Instance()
Get singleton instance.
void SetLanguage(const std::string &languageCode)
Set current language.
std::vector< std::string > GetAvailableLanguages() const
Get list of available languages.
std::string Tr(const std::string &key) const
Get translated string.
bool LoadTranslations(const std::string &filepath)
Load translations from JSON file.
std::string GetCurrentLanguage() const
Get current language code.
void AddTranslation(const std::string &languageCode, const std::string &key, const std::string &value)
Add translation for a language.