43#include <wx/filename.h>
45#include <wx/stdpaths.h>
46#include <wx/textfile.h>
50#include <unordered_map>
52using LangHash = std::unordered_map<wxString, TranslatableString>;
59 for (
const auto &path : pathList) {
60 ff = path + wxFILE_SEP_PATH + pattern;
61 wxDir::GetAllFiles(ff.GetPath(), &results, ff.GetFullName(), wxDIR_FILES);
73 return (results.size() > 0);
77#include <CoreFoundation/CFPreferences.h>
78#include <wx/osx/core/cfstring.h>
85 wxArrayString langCodes;
90 const wxLanguageInfo *info;
97 const wxCFStringRef appleLocale((CFStringRef)CFPreferencesCopyAppValue(CFSTR(
"AppleLocale"),
98 kCFPreferencesCurrentApplication));
100 const auto localeString = appleLocale.AsString();
103 info = wxLocale::FindLanguageInfo(localeString);
109 wxString langCode = localeString.Left(2);
110 info = wxLocale::FindLanguageInfo(langCode);
115 const auto sysLang = wxLocale::GetSystemLanguage();
116 info = wxLocale::GetLanguageInfo(sysLang);
121 wxString fullCode = info->CanonicalName;
122 if (fullCode.length() < 2)
125 wxString code = fullCode.Left(2);
128 for(i=0; i<langCodes.size(); i++) {
129 if (langCodes[i] == fullCode)
132 if (langCodes[i] == code)
143 static const char *
const utf8Names[] = {
145"ar \330\247\331\204\330\271\330\261\330\250\331\212\330\251",
146"be \320\221\320\265\320\273\320\260\321\200\321\203\321\201\320\272\320\260\321\217",
147"bg \320\221\321\212\320\273\320\263\320\260\321\200\321\201\320\272\320\270",
148"bn \340\246\254\340\246\276\340\246\202\340\246\262\340\246\276",
151"ca_ES@valencia Valenci\303\240",
153"cs \304\214e\305\241tina",
157"el \316\225\316\273\316\273\316\267\316\275\316\271\316\272\316\254",
161"eu_ES Euskara (Espainiako)",
162"fa \331\201\330\247\330\261\330\263\333\214",
167"he \327\242\327\221\327\250\327\231\327\252",
168"hi \340\244\271\340\244\277\340\244\250\340\245\215\340\244\246\340\245\200",
171"hy \325\200\325\241\325\265\325\245\326\200\325\245\325\266",
172"id Bahasa Indonesia",
174"ja \346\227\245\346\234\254\350\252\236",
175"ka \341\203\245\341\203\220\341\203\240\341\203\227\341\203\243\341\203\232\341\203\230",
176"km \341\236\201\341\237\201\341\236\230\341\236\232\341\236\227\341\236\266\341\236\237\341\236\266",
177"ko \355\225\234\352\265\255\354\226\264",
179"mk \320\234\320\260\320\272\320\265\320\264\320\276\320\275\321\201\320\272\320\270",
180"mr \340\244\256\340\244\260\340\244\276\340\244\240\340\245\200",
181"my \341\200\231\341\200\274\341\200\224\341\200\272\341\200\231\341\200\254\341\200\205\341\200\254",
186"pt Portugu\303\252s",
187"pt_BR Portugu\303\252s (Brasil)",
188"ro Rom\303\242n\304\203",
189"ru \320\240\321\203\321\201\321\201\320\272\320\270\320\271",
190"sk Sloven\304\215ina",
191"sl Sloven\305\241\304\215ina",
192"sr_RS \320\241\321\200\320\277\321\201\320\272\320\270",
195"ta \340\256\244\340\256\256\340\256\277\340\256\264\340\257\215",
196"tg \320\242\320\276\322\267\320\270\320\272\323\243",
197"tr T\303\274rk\303\247e",
198"uk \320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260",
199"vi Ti\341\272\277ng Vi\341\273\207t",
200"zh_CN \344\270\255\346\226\207\357\274\210\347\256\200\344\275\223\357\274\211",
201"zh_TW \344\270\255\346\226\207\357\274\210\347\271\201\351\253\224\357\274\211",
205 wxArrayString tempCodes;
209 const LangHash localLanguageName = []{
211 for (
auto utf8Name : utf8Names )
213 auto str = wxString::FromUTF8(utf8Name);
214 auto code =
str.BeforeFirst(
' ');
215 auto name =
str.AfterFirst(
' ');
218 return localLanguageName;
221#if defined(__WXGTK__)
224 pathNorm.Normalize();
225 const wxString newPath{ pathNorm.GetFullPath() };
226 if (pathList.end() ==
227 std::find(pathList.begin(), pathList.end(), newPath))
228 pathList.push_back(newPath);
234 for (
auto end = localLanguageName.end(), i = localLanguageName.begin();
237 const wxLanguageInfo *info = wxLocale::FindLanguageInfo(i->first);
240 wxASSERT(info != NULL);
244 wxString fullCode = info->CanonicalName;
245 wxString code = fullCode.Left(2);
259 if (fullCode.length() < 2)
262 auto found = localLanguageName.find( code );
263 if ( found !=
end ) {
264 name = found->second;
266 found = localLanguageName.find( fullCode );
267 if ( found !=
end ) {
268 name = found->second;
275 if (!tempHash[code].empty())
279 tempCodes.push_back(code);
280 tempNames.push_back(
name);
281 tempHash[code] =
name;
293 code =
wxT(
"en-simple");
294 auto name =
XO(
"Simplified");
296 tempCodes.push_back(code);
297 tempNames.push_back(
name);
298 tempHash[code] =
name;
305 for(j=0; j<tempNames.size(); j++){
306 reverseHash[tempNames[j]] = tempCodes[j];
312 langNames.push_back(
XO(
"System"));
313 langCodes.push_back(
wxT(
"System"));
315 for(j=0; j<tempNames.size(); j++) {
316 langNames.push_back(tempNames[j]);
317 langCodes.push_back(reverseHash[tempNames[j]]);
326 wxString result = lang;
330#if defined(__WXMAC__)
338 wxSetEnv(
wxT(
"LANG"),
wxT(
"en_US.UTF-8"));
341 const wxLanguageInfo *info = NULL;
342 if (!lang.empty() && lang !=
wxT(
"System")) {
344 info = wxLocale::FindLanguageInfo(lang);
350 info = wxLocale::FindLanguageInfo(result);
356 sLocale = std::make_unique<wxLocale>(info->Language);
358 for(
const auto &path : pathList )
359 sLocale->AddCatalogLookupPathPrefix( path );
367 sLocale->AddCatalog(
"audacity");
376 using future1 =
decltype(
std::unordered_map< TranslatableString, wxString > ReverseLangHash
static bool TranslationExists(const FilePaths &pathList, wxString code)
std::unordered_map< wxString, TranslatableString > LangHash
static void FindFilesInPathList(const wxString &pattern, const FilePaths &pathList, FilePaths &results)
bool TranslationLess(const TranslatableString &a, const TranslatableString &b)
A commonly needed sort comparator, which depends on the language setting.
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
std::vector< TranslatableString > TranslatableStrings
static void Init()
Initialize internationalisation support. Call this once at program start.
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
wxString GetSystemLanguageCode(const FilePaths &pathList)
static std::unique_ptr< wxLocale > sLocale
static wxString sLocaleName
void GetLanguages(FilePaths pathList, wxArrayString &langCodes, TranslatableStrings &langNames)
wxString SetLang(const FilePaths &pathList, const wxString &lang)
const char * end(const char *str) noexcept