1 /*
2 * This file is part of RawTherapee.
3 *
4 * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5 *
6 * RawTherapee is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * RawTherapee is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "multilangmgr.h"
20
21 #include <fstream>
22 #include <glib.h>
23 #ifdef WIN32
24 #include <windows.h>
25 #include <winnls.h>
26 #endif
27
28 namespace
29 {
30
31 // Maps standard locales to languages, e.g. "de-DE" to "Deutsch".
32 struct LocaleToLang : private std::map<std::pair<Glib::ustring, Glib::ustring>, Glib::ustring>
33 {
key__anon1e30759d0111::LocaleToLang34 static const std::pair<Glib::ustring, Glib::ustring> key (const Glib::ustring& major, const Glib::ustring& minor = Glib::ustring ())
35 {
36 return std::make_pair (major, minor);
37 }
38
LocaleToLang__anon1e30759d0111::LocaleToLang39 LocaleToLang ()
40 {
41 emplace (key ("ca", "ES"), "Catala");
42 emplace (key ("cs", "CZ"), "Czech");
43 emplace (key ("da", "DK"), "Dansk");
44 emplace (key ("de", "DE"), "Deutsch");
45 #ifdef __APPLE__
46 emplace (key ("en", "UK"), "English (UK)");
47 #else
48 emplace (key ("en", "GB"), "English (UK)");
49 #endif
50 emplace (key ("en", "US"), "English (US)");
51 emplace (key ("es", "ES"), "Espanol");
52 emplace (key ("eu", "ES"), "Euskara");
53 emplace (key ("fr", "FR"), "Francais");
54 emplace (key ("el", "GR"), "Greek");
55 emplace (key ("he", "IL"), "Hebrew");
56 emplace (key ("it", "IT"), "Italiano");
57 emplace (key ("ja", "JP"), "Japanese");
58 emplace (key ("lv", "LV"), "Latvian");
59 emplace (key ("hu", "HU"), "Magyar");
60 emplace (key ("nl", "NL"), "Nederlands");
61 emplace (key ("nn", "NO"), "Norsk BM");
62 emplace (key ("nb", "NO"), "Norsk BM");
63 emplace (key ("pl", "PL"), "Polish");
64 emplace (key ("pt", "PT"), "Portugues (Brasil)");
65 emplace (key ("ru", "RU"), "Russian");
66 emplace (key ("sr", "RS"), "Serbian (Cyrilic Characters)");
67 emplace (key ("sk", "SK"), "Slovak");
68 emplace (key ("fi", "FI"), "Suomi");
69 emplace (key ("sv", "SE"), "Swedish");
70 emplace (key ("tr", "TR"), "Turkish");
71 emplace (key ("zh", "CN"), "Chinese (Simplified)");
72 emplace (key ("zh", "SG"), "Chinese (Traditional)");
73 }
74
operator ()__anon1e30759d0111::LocaleToLang75 Glib::ustring operator() (const Glib::ustring& locale) const
76 {
77 Glib::ustring major, minor;
78
79 if (locale.length () >= 2) {
80 major = locale.substr (0, 2).lowercase ();
81 }
82
83 if (locale.length () >= 5) {
84 minor = locale.substr (3, 2).uppercase ();
85 }
86
87 // Look for matching language and country.
88 auto iterator = find (key (major, minor));
89
90 if (iterator != end ()) {
91 return iterator->second;
92 }
93
94 // Look for matching language only.
95 iterator = find (key (major, major.uppercase()));
96
97 if (iterator != end ()) {
98 return iterator->second;
99 }
100
101 return "default";
102 }
103
getLocale__anon1e30759d0111::LocaleToLang104 std::string getLocale(const Glib::ustring &language) const
105 {
106 for (auto &p : *this) {
107 if (p.second == language) {
108 std::string ret = p.first.first;
109 if (!p.first.second.empty()) {
110 ret += "_" + p.first.second;
111 }
112 return ret;
113 }
114 }
115 return "C";
116 }
117 };
118
119 const LocaleToLang localeToLang;
120
setGtkLanguage(const Glib::ustring & language)121 void setGtkLanguage(const Glib::ustring &language)
122 {
123 if(language != "default") { // nothing to change when using default
124 std::string lang = localeToLang.getLocale(language);
125 const gchar *env_langc = g_getenv("LANG");
126 if(env_langc) {
127 const std::string env_lang(env_langc);
128 if (!env_lang.empty()) {
129 const std::string::size_type suffix_pos = env_lang.find_first_of(".");
130 if (suffix_pos != std::string::npos) {
131 lang += env_lang.substr(suffix_pos);
132 }
133 }
134 }
135
136 g_setenv("LANG", lang.c_str(), true);
137 }
138 }
139
140 }
141
142 MultiLangMgr langMgr;
143
MultiLangMgr()144 MultiLangMgr::MultiLangMgr ()
145 {
146 }
147
load(const Glib::ustring & language,const std::vector<Glib::ustring> & fnames)148 void MultiLangMgr::load(const Glib::ustring &language, const std::vector<Glib::ustring> &fnames)
149 {
150 setGtkLanguage(language);
151
152 translations.clear();
153
154 for (const auto& fname : fnames) {
155 if(fname.empty()) {
156 continue;
157 }
158
159 std::ifstream file(fname.c_str());
160 if (!file.is_open()) {
161 continue;
162 }
163
164 std::string entry;
165 auto hint = translations.begin();
166 while (std::getline(file, entry)) {
167
168 if (entry.empty() || entry.front() == '#' || entry.front() == '!') {
169 continue;
170 }
171
172 std::string key, value;
173
174 std::istringstream line(entry);
175
176 if(std::getline(line, key, ';') && translations.find(key) == translations.end() && std::getline(line, value)) {
177 size_t pos = 0;
178 while((pos = value.find("\\n", pos)) != std::string::npos) {
179 value.replace(pos, 2, "\n");
180 pos++;
181 }
182 hint = translations.emplace_hint(hint, key, value);
183 }
184 }
185 }
186 }
187
getStr(const std::string & key) const188 Glib::ustring MultiLangMgr::getStr (const std::string& key) const
189 {
190 const auto iterator = translations.find(key);
191
192 if (iterator != translations.end()) {
193 return iterator->second;
194 }
195
196 return key;
197 }
198
isOSLanguageDetectSupported()199 bool MultiLangMgr::isOSLanguageDetectSupported ()
200 {
201 #if defined (WIN32) || defined (__linux__) || defined (__APPLE__)
202 return true;
203 #else
204 return false;
205 #endif
206 }
207
getOSUserLanguage()208 Glib::ustring MultiLangMgr::getOSUserLanguage ()
209 {
210 Glib::ustring langName ("default");
211
212 #if defined (WIN32)
213
214 const LCID localeID = GetUserDefaultLCID ();
215 TCHAR localeName[18];
216
217 const int langLen = GetLocaleInfo (localeID, LOCALE_SISO639LANGNAME, localeName, 9);
218 if (langLen <= 0) {
219 return langName;
220 }
221
222 localeName[langLen - 1] = '-';
223
224 const int countryLen = GetLocaleInfo (localeID, LOCALE_SISO3166CTRYNAME, &localeName[langLen], 9);
225 if (countryLen <= 0) {
226 return langName;
227 }
228
229 langName = localeToLang (localeName);
230
231 #elif defined (__linux__) || defined (__APPLE__)
232
233 // Query the current locale and force decimal point to dot.
234 const char *locale = getenv("LANG");
235 if (locale || (locale = setlocale (LC_CTYPE, ""))) {
236 langName = localeToLang (locale);
237 }
238
239 setlocale (LC_NUMERIC, "C");
240
241 #endif
242
243 return langName;
244 }
245