i18n
Translation lookup
Loading...
Searching...
No Matches
I18n.hpp
Go to the documentation of this file.
1
11#pragma once
12
13#include <string>
14#include <memory>
15#include <unordered_map>
16#include <tuple>
17#include <utility>
18#include <type_traits>
19
20#include "ILocale.hpp"
21#include "TypeTraits.hpp"
22
23#if defined(__APPLE__)
24 #include <CoreFoundation/CoreFoundation.h>
25#elif defined(__unix__) || defined(__linux__)
26 #include <locale>
27#endif
28
29
39template<typename T, typename = typename std::enable_if<is_derived_from<T, ILocale>::value>::type>
40class I18n {
41
42 public:
43
49 static I18n<T>& getInstance() {
50 static I18n<T> instance;
51
52 return instance;
53 }
54
58 I18n(const I18n&) = delete;
59
63 I18n& operator=(const I18n&) = delete;
64
74 template<typename... T_Child>
75 typename std::enable_if<all_derived<T, T_Child...>::value, void>::type
77 // C++11 pack expansion via initializer list trick
78 auto l = { (setSupportedLocale<T_Child>(), 0)... };
79 (void)l; //silence !
80 if (!_locale) setDefault();
81 }
82
83
92 template<typename T_Tuple>
93 typename std::enable_if<is_tuple<T_Tuple>::value, void>::type
95 registerTupleLocales_using_index<T_Tuple>(
96 typename make_index_sequence_impl<std::tuple_size<T_Tuple>::value>::type{}
97 );
98 if (!_locale) setDefault();
99 }
100
109 void setDefault() {
110 if (_supportedLocales.empty())
111 return;
112
113 if (!_systemCode.empty() && setLocale(_systemCode))
114 return;
115 if (setLocale("en"))
116 return;
117
118 _locale = _supportedLocales.begin()->second.get();
119 }
120
127 bool setLocale(const std::string& code) {
128 typename std::unordered_map<std::string, std::unique_ptr<T>>::iterator it = _supportedLocales.find(code);
129
130 if (it != _supportedLocales.end()) {
131 _locale = it->second.get();
132 return true;
133 }
134 return false;
135 }
136
142 T* getLocale() const {
143 return _locale;
144 }
145
146 private:
147 std::string _systemCode;
148 T* _locale = nullptr;
149 std::unordered_map<std::string, std::unique_ptr<T>> _supportedLocales;
150
151 private:
155 I18n() {
156 setSystemCode();
157 }
158
167 void setSystemCode() {
168 #if defined(__APPLE__)
169 // Use explicit casts and checks for C++11 compatibility
170 CFLocaleRef locale = CFLocaleCopyCurrent();
171 if (!locale) {
172 _systemCode = "en"; // fallback
173 return;
174 }
175
176 CFStringRef identifier = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleIdentifier);
177
178 char buffer[16] = {0};
179 if (CFStringGetCString(identifier, buffer, sizeof(buffer), kCFStringEncodingUTF8)) {
180 _systemCode = std::string(buffer, 2); // first 2 letters
181 } else {
182 _systemCode = "en"; // second fallback
183 }
184 CFRelease(locale);
185 #elif defined(__unix__) || defined(__linux__)
186 try {
187 // C++11 locale handling
188 std::locale loc(""); // system locale
189 std::string name = loc.name(); // e.g., "fr_FR.UTF-8"
190 if (!name.empty() && name != "C" && name != "POSIX")
191 _systemCode = name.substr(0, 2);
192 } catch (...) {
193 _systemCode = "en"; // fallback on error
194 }
195 #else
196 _systemCode = "en"; // fallback for other platforms
197
198#endif
199 }
200
209 template <typename T_Child, typename = typename std::enable_if<is_derived_from<T_Child, T>::value>::type>
210 void setSupportedLocale() {
211 // C++11 replacement for std::make_unique (C++14)
212 std::unique_ptr<T_Child> newInstance(new T_Child());
213 std::string key = newInstance->languageCode();
214 _supportedLocales[key] = std::move(newInstance);
215 }
216
217 template<typename Tuple, std::size_t... Is>
218 void registerTupleLocales_using_index(index_sequence<Is...>) {
219 // C++11 Pack Expansion via initializer list trick
220 auto l = { (setSupportedLocale<typename std::tuple_element<Is, Tuple>::type>(), 0)... };
221 (void)l;
222 }
223
224};
225
Internationalization manager for a specific locale type.
Definition I18n.hpp:40
T * getLocale() const
Get the currently selected locale instance.
Definition I18n.hpp:142
void setDefault()
Sets the default locale to use if no other locale is selected.
Definition I18n.hpp:109
I18n & operator=(const I18n &)=delete
delete Move constructor
std::enable_if< all_derived< T, T_Child... >::value, void >::type setSupportedLocales()
Register a list of supported locales using template parameter pack.
Definition I18n.hpp:76
bool setLocale(const std::string &code)
Select a specific locale by code.
Definition I18n.hpp:127
static I18n< T > & getInstance()
Get the I18n singleton instance.
Definition I18n.hpp:49
I18n(const I18n &)=delete
delete Copy constructor
std::enable_if< is_tuple< T_Tuple >::value, void >::type setSupportedLocales()
Register supported locales using a std::tuple of types. Each type must derive from T and be default-c...
Definition I18n.hpp:94
Trait to check if all types in a pack are derived from a base type.
Definition TypeTraits.hpp:40
Base Type to represent a sequence of compile time indice.
Definition TypeTraits.hpp:105
recursive template to generate the sequence
Definition TypeTraits.hpp:114