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 49 of file Languages.cpp.

Function Documentation

void GetLanguages ( wxArrayString &  langCodes,
wxArrayString &  langNames 
)

Definition at line 132 of file Languages.cpp.

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

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

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

References GetLanguages().

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

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

Definition at line 51 of file Languages.cpp.

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

Referenced by GetLanguages().

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