Audacity  2.2.2
Typedefs | Functions
Languages.cpp File Reference

Determine installed languages. More...

#include "Audacity.h"
#include <wx/defs.h>
#include <wx/hashmap.h>
#include <wx/intl.h>
#include <wx/textfile.h>
#include "Languages.h"
#include "FileNames.h"
#include "AudacityApp.h"
#include <unordered_map>

Go to the source code of this file.

Typedefs

using LangHash = std::unordered_map< wxString, wxString >
 

Functions

static bool TranslationExists (wxArrayString &audacityPathList, wxString code)
 
wxString GetSystemLanguageCode ()
 
void GetLanguages (wxArrayString &langCodes, wxArrayString &langNames)
 

Detailed Description

Determine installed languages.

Figure out what translations are installed and return a list of language codes (like "es", "fr", or "pt-br") and corresponding language names (like "Español", "Français", and "Português"). We use our own list of translations of language names (i.e. "Français" instead of "French") but we fallback on the language name in wxWidgets if we don't have it listed.

This code is designed to work well with all of the current languages, but adapt to any language that wxWidgets supports. Other languages will only be supported if they're added to the database using wxLocale::AddLanguage.

But for the most part, this means that somebody could add a NEW translation and have it work immediately.

Definition in file Languages.cpp.

Typedef Documentation

using LangHash = std::unordered_map<wxString, wxString>

Definition at line 47 of file Languages.cpp.

Function Documentation

void GetLanguages ( wxArrayString &  langCodes,
wxArrayString &  langNames 
)

Definition at line 130 of file Languages.cpp.

References AudacityApp::AddUniquePathToPathList(), AudacityApp::audacityPathList, name, TranslationExists(), and wxGetApp().

Referenced by GetSystemLanguageCode(), LangChoiceDialog::LangChoiceDialog(), and GUIPrefs::Populate().

131 {
132  static const char *const utf8Names[] = {
133 "af Afrikaans",
134 "ar \330\247\331\204\330\271\330\261\330\250\331\212\330\251",
135 "be \320\221\320\265\320\273\320\260\321\200\321\203\321\201\320\272\320\260\321\217",
136 "bg \320\221\321\212\320\273\320\263\320\260\321\200\321\201\320\272\320\270",
137 "bn \340\246\254\340\246\276\340\246\202\340\246\262\340\246\276",
138 "bs Bosanski",
139 "ca Catal\303\240",
140 "[email protected] Valenci\303\240",
141 "cs \304\214e\305\241tina",
142 "cy Cymraeg",
143 "da Dansk",
144 "de Deutsch",
145 "el \316\225\316\273\316\273\316\267\316\275\316\271\316\272\316\254",
146 "en English",
147 "es Espa\303\261ol",
148 "eu Euskara",
149 "eu_ES Euskara (Espainiako)",
150 "fa \331\201\330\247\330\261\330\263\333\214",
151 "fi Suomi",
152 "fr Fran\303\247ais",
153 "ga Gaeilge",
154 "gl Galego",
155 "he \327\242\327\221\327\250\327\231\327\252",
156 "hi \340\244\271\340\244\277\340\244\250\340\245\215\340\244\246\340\245\200",
157 "hr Hrvatski",
158 "hu Magyar",
159 "hy \325\200\325\241\325\265\325\245\326\200\325\245\325\266",
160 "id Bahasa Indonesia",
161 "it Italiano",
162 "ja \346\227\245\346\234\254\350\252\236",
163 "ka \341\203\245\341\203\220\341\203\240\341\203\227\341\203\243\341\203\232\341\203\230",
164 "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",
165 "ko \355\225\234\352\265\255\354\226\264",
166 "lt Lietuvi\305\263",
167 "mk \320\234\320\260\320\272\320\265\320\264\320\276\320\275\321\201\320\272\320\270",
168 "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",
169 "nb Norsk",
170 "nl Nederlands",
171 "oc Occitan",
172 "pl Polski",
173 "pt Portugu\303\252s",
174 "pt_BR Portugu\303\252s (Brasil)",
175 "ro Rom\303\242n\304\203",
176 "ru \320\240\321\203\321\201\321\201\320\272\320\270\320\271",
177 "sk Sloven\304\215ina",
178 "sl Sloven\305\241\304\215ina",
179 "sr_RS \320\241\321\200\320\277\321\201\320\272\320\270",
180 "[email protected] Srpski",
181 "sv Svenska",
182 "ta \340\256\244\340\256\256\340\256\277\340\256\264\340\257\215",
183 "tg \320\242\320\276\322\267\320\270\320\272\323\243",
184 "tr T\303\274rk\303\247e",
185 "uk \320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260",
186 "vi Ti\341\272\277ng Vi\341\273\207t",
187 "zh_CN \344\270\255\346\226\207\357\274\210\347\256\200\344\275\223\357\274\211",
188 "zh_TW \344\270\255\346\226\207\357\274\210\347\271\201\351\253\224\357\274\211",
189  };
190 
191  wxArrayString tempNames;
192  wxArrayString tempCodes;
193  LangHash localLanguageName;
194  LangHash reverseHash;
195  LangHash tempHash;
196 
197  for ( auto utf8Name : utf8Names )
198  {
199  auto str = wxString::FromUTF8(utf8Name);
200  auto code = str.BeforeFirst(' ');
201  auto name = str.AfterFirst(' ');
202  localLanguageName[code] = name;
203  }
204 
205  wxArrayString audacityPathList = wxGetApp().audacityPathList;
206 
207 #if defined(__WXGTK__)
208  wxGetApp().AddUniquePathToPathList(wxString::Format(wxT("%s/share/locale"),
209  wxT(INSTALL_PREFIX)),
210  audacityPathList);
211 #endif
212 
213  // For each language in our list we look for a corresponding entry in
214  // wxLocale.
215  for (LangHash::iterator i = localLanguageName.begin();
216  i != localLanguageName.end();
217  i++)
218  {
219  const wxLanguageInfo *info = wxLocale::FindLanguageInfo(i->first);
220 
221  if (!info) {
222  wxASSERT(info != NULL);
223  continue;
224  }
225 
226  wxString fullCode = info->CanonicalName;
227  wxString code = fullCode.Left(2);
228  wxString name = info->Description;
229 
230  // Logic: Languages codes are sometimes hierarchical, with a
231  // general language code and then a subheading. For example,
232  // zh_TW for Traditional Chinese and zh_CN for Simplified
233  // Chinese - but just zh for Chinese in general. First we look
234  // for the full code, like zh_TW. If that doesn't exist, we
235  // look for a code corresponding to the first two letters.
236  // Note that if the language for a fullCode exists but we only
237  // have a name for the short code, we will use the short code's
238  // name but associate it with the full code. This allows someone
239  // to drop in a NEW language and still get reasonable behavior.
240 
241  if (fullCode.Length() < 2)
242  continue;
243 
244  if (localLanguageName[code] != wxT("")) {
245  name = localLanguageName[code];
246  }
247  if (localLanguageName[fullCode] != wxT("")) {
248  name = localLanguageName[fullCode];
249  }
250 
251  if (TranslationExists(audacityPathList, fullCode)) {
252  code = fullCode;
253  }
254 
255  if (tempHash[code] != wxT(""))
256  continue;
257 
258  if (TranslationExists(audacityPathList, code) || code==wxT("en")) {
259  tempCodes.Add(code);
260  tempNames.Add(name);
261  tempHash[code] = name;
262 
263 /* wxLogDebug(wxT("code=%s name=%s fullCode=%s name=%s -> %s"),
264  code, localLanguageName[code],
265  fullCode, localLanguageName[fullCode],
266  name);*/
267  }
268  }
269 
270  // JKC: Adding language for simplified audacity.
271  {
272  wxString code;
273  wxString name;
274  code = wxT("en-simple");
275  name = wxT("Simplified");
276  if (TranslationExists(audacityPathList, code) ) {
277  tempCodes.Add(code);
278  tempNames.Add(name);
279  tempHash[code] = name;
280  }
281  }
282 
283 
284  // Sort
285  unsigned int j;
286  for(j=0; j<tempNames.GetCount(); j++){
287  reverseHash[tempNames[j]] = tempCodes[j];
288  }
289 
290  tempNames.Sort();
291 
292  // Add system language
293  langNames.Add(wxT("System"));
294  langCodes.Add(wxT(""));
295 
296  for(j=0; j<tempNames.GetCount(); j++) {
297  langNames.Add(tempNames[j]);
298  langCodes.Add(reverseHash[tempNames[j]]);
299  }
300 }
static bool TranslationExists(wxArrayString &audacityPathList, wxString code)
Definition: Languages.cpp:49
std::unordered_map< wxString, wxString > LangHash
Definition: Languages.cpp:47
static void AddUniquePathToPathList(const wxString &path, wxArrayString &pathList)
const wxChar * name
Definition: Distortion.cpp:94
wxArrayString audacityPathList
A list of directories that should be searched for Audacity files (plug-ins, help files, etc.).
Definition: AudacityApp.h:138
AudacityApp & wxGetApp()
wxString GetSystemLanguageCode ( )

Definition at line 76 of file Languages.cpp.

References GetLanguages().

Referenced by AudacityApp::InitLang(), InitPreferences(), LangChoiceDialog::LangChoiceDialog(), and LangChoiceDialog::OnOk().

77 {
78  wxArrayString langCodes;
79  wxArrayString langNames;
80 
81  GetLanguages(langCodes, langNames);
82 
83  int sysLang = wxLocale::GetSystemLanguage();
84 
85  const wxLanguageInfo *info;
86 
87 #ifdef __WXMAC__
88  // PRL: Bug 1227, system language on Mac may not be right because wxW3 is
89  // dependent on country code too in wxLocale::GetSystemLanguage().
90 
91  if (sysLang == wxLANGUAGE_UNKNOWN)
92  {
93  // wxW3 did a too-specific lookup of language and country, when
94  // there is nothing for that combination; try it by language alone.
95 
96  // The following lines are cribbed from that function.
97  wxCFRef<CFLocaleRef> userLocaleRef(CFLocaleCopyCurrent());
98  wxCFStringRef str(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleLanguageCode)));
99  auto lang = str.AsString();
100 
101  // Now avoid wxLocale::GetLanguageInfo(), instead calling:
102  info = wxLocale::FindLanguageInfo(lang);
103  }
104  else
105 #endif
106  {
107  info = wxLocale::GetLanguageInfo(sysLang);
108  }
109 
110  if (info) {
111  wxString fullCode = info->CanonicalName;
112  if (fullCode.Length() < 2)
113  return wxT("en");
114 
115  wxString code = fullCode.Left(2);
116  unsigned int i;
117 
118  for(i=0; i<langCodes.GetCount(); i++) {
119  if (langCodes[i] == fullCode)
120  return fullCode;
121 
122  if (langCodes[i] == code)
123  return code;
124  }
125  }
126 
127  return wxT("en");
128 }
void GetLanguages(wxArrayString &langCodes, wxArrayString &langNames)
Definition: Languages.cpp:130
static bool TranslationExists ( wxArrayString &  audacityPathList,
wxString  code 
)
static

Definition at line 49 of file Languages.cpp.

References AudacityApp::FindFilesInPathList(), and wxGetApp().

Referenced by GetLanguages().

50 {
51  wxArrayString results;
52  wxGetApp().FindFilesInPathList(wxString::Format(wxT("%s/audacity.mo"),
53  code),
54  audacityPathList,
55  results);
56 #if defined(__WXMAC__)
57  wxGetApp().FindFilesInPathList(wxString::Format(wxT("%s.lproj/audacity.mo"),
58  code),
59  audacityPathList,
60  results);
61 #endif
62 
63  wxGetApp().FindFilesInPathList(wxString::Format(wxT("%s/LC_MESSAGES/audacity.mo"),
64  code),
65  audacityPathList,
66  results);
67 
68  return (results.GetCount() > 0);
69 }
static void FindFilesInPathList(const wxString &pattern, const wxArrayString &pathList, wxArrayString &results, int flags=wxDIR_FILES)
AudacityApp & wxGetApp()