i18n
Loading...
Searching...
No Matches
I18n.hpp
Go to the documentation of this file.
1
8#pragma once
9
10#include <string>
11#include <map>
12#include <concepts>
13
14#if defined(__APPLE__)
15 #include <CoreFoundation/CoreFoundation.h>
16#elif defined(__unix__) || defined(__linux__)
17 #include <locale>
18#endif
19
20#include "ILocale.hpp"
21
32template <typename T>
33struct is_tuple : std::false_type {};
34
46template <typename... Args>
47struct is_tuple<std::tuple<Args...>> : std::true_type {};
48
57template <typename T>
59
66template <typename Base, typename Derived>
67concept DerivedFrom = std::derived_from<Base, Derived>;
68
78template<LocaleInterface T>
79class I18n {
80
81 public:
82
88 static I18n<T>& getInstance() {
89 static I18n<T> instance;
90
91 return instance;
92 }
93
97 I18n(const I18n&) = delete;
98
102 I18n& operator=(const I18n&) = delete;
103
116 template <DerivedFrom<T>... T_Child>
118 // Uses a pack expansion to call injectLocale<T_Locale>() for every type in the parameter pack.
119 (this->setSupportedLocale<T_Child>(), ...);
120 if (!_locale)
121 setDefault();
122 }
123
135 template <IsTuple T_Tuple>
137 // 1. Decompose the type T_Tuple into a pack of types.
138 std::apply([this](auto... locals) {
139 (this->setSupportedLocale<std::decay_t<decltype(locals)>>(), ...);
140 }, T_Tuple{}); // T_Tuple{} creates a temporary instance just to enable std::apply
141 if (!_locale)
142 setDefault();
143 }
144
153 void setDefault() {
154 if (_supportedLocales.empty())
155 return;
156
157 if (!_systemCode.empty() && setLocale(_systemCode))
158 return;
159 if (setLocale("en"))
160 return;
161
162 _locale = _supportedLocales.begin()->second.get();
163 }
164
171 bool setLocale(const std::string& code) {
172 auto it = _supportedLocales.find(code);
173
174 if (it != _supportedLocales.end()) {
175 _locale = it->second.get();
176 return true;
177 }
178 return false;
179 }
180
186 T* getLocale() const {
187 return _locale;
188 }
189
190 private:
191 std::string _systemCode;
192 T* _locale = nullptr;
193 std::unordered_map<std::string, std::unique_ptr<T>> _supportedLocales;
194
195 private:
199 I18n() {
200 setSystemCode();
201 }
202
211 void setSystemCode() {
212 #if defined(__APPLE__)
213 CFLocaleRef locale = CFLocaleCopyCurrent();
214 if (!locale) _systemCode = "en"; // fallback
215
216 CFStringRef identifier = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleIdentifier);
217
218 char buffer[16] = {0};
219 if (CFStringGetCString(identifier, buffer, sizeof(buffer), kCFStringEncodingUTF8)) {
220 CFRelease(locale);
221 _systemCode = std::string(buffer, 2); // first 2 letters
222 }
223 CFRelease(locale);
224 #elif defined(__unix__) || defined(__linux__)
225 try {
226 std::locale loc(""); // system locale
227 std::string name = loc.name(); // e.g., "fr_FR.UTF-8"
228 if (!name.empty() && name != "C" && name != "POSIX")
229 _systemCode = name.substr(0, 2);
230 } catch (...) {}
231 #else
232 _systemCode = "en"; // fallback for other platforms
233 #endif
234 }
235
244 template <DerivedFrom<T> T_Child>
245 void setSupportedLocale() {
246 auto newInstance = std::make_unique<T_Child>();
247 std::string key = newInstance->languageCode();
248 _supportedLocales[key] = std::move(newInstance);
249 }
250
251};
Internationalization manager for a specific locale type.
Definition I18n.hpp:37
void setSupportedLocales()
Register a list of supported locales using template parameter pack.
Definition I18n.hpp:117
T * getLocale() const
Get the currently selected locale instance.
Definition I18n.hpp:186
void setDefault()
Sets the default locale to use if no other locale is selected.
Definition I18n.hpp:106
I18n & operator=(const I18n &)=delete
delete Move constructor
bool setLocale(const std::string &code)
Select a specific locale by code.
Definition I18n.hpp:124
static I18n< T > & getInstance()
Get the I18n singleton instance.
Definition I18n.hpp:88
I18n(const I18n &)=delete
delete Copy constructor
DerivedFrom is accept supportedLocal class only.
Definition I18n.hpp:67
Using is_tuple specialisation this concept verify if it's a tuple.
Definition I18n.hpp:58
Detect whether a type is a std::tuple or not.
Definition TypeTraits.hpp:79