Merge pull request #4436 from ace20022/ext_sub_details
[vuplus_xbmc] / xbmc / LangInfo.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "LangInfo.h"
22 #include "Application.h"
23 #include "FileItem.h"
24 #include "Util.h"
25 #include "filesystem/Directory.h"
26 #include "guilib/GUIFontManager.h"
27 #include "guilib/LocalizeStrings.h"
28 #include "pvr/PVRManager.h"
29 #include "settings/AdvancedSettings.h"
30 #include "settings/lib/Setting.h"
31 #include "settings/Settings.h"
32 #include "utils/CharsetConverter.h"
33 #include "utils/log.h"
34 #include "utils/LangCodeExpander.h"
35 #include "utils/StringUtils.h"
36 #include "utils/Weather.h"
37 #include "utils/XBMCTinyXML.h"
38
39 using namespace std;
40 using namespace PVR;
41
42 #define TEMP_UNIT_STRINGS 20027
43
44 #define SPEED_UNIT_STRINGS 20200
45
46 CLangInfo::CRegion::CRegion(const CRegion& region)
47 {
48   m_strName=region.m_strName;
49   m_forceUnicodeFont=region.m_forceUnicodeFont;
50   m_strGuiCharSet=region.m_strGuiCharSet;
51   m_strSubtitleCharSet=region.m_strSubtitleCharSet;
52   m_strDVDMenuLanguage=region.m_strDVDMenuLanguage;
53   m_strDVDAudioLanguage=region.m_strDVDAudioLanguage;
54   m_strDVDSubtitleLanguage=region.m_strDVDSubtitleLanguage;
55   m_strLangLocaleName = region.m_strLangLocaleName;
56   m_strLangLocaleCodeTwoChar = region.m_strLangLocaleCodeTwoChar;
57   m_strRegionLocaleName = region.m_strRegionLocaleName;
58
59   m_strDateFormatShort=region.m_strDateFormatShort;
60   m_strDateFormatLong=region.m_strDateFormatLong;
61   m_strTimeFormat=region.m_strTimeFormat;
62   m_strMeridiemSymbols[MERIDIEM_SYMBOL_PM]=region.m_strMeridiemSymbols[MERIDIEM_SYMBOL_PM];
63   m_strMeridiemSymbols[MERIDIEM_SYMBOL_AM]=region.m_strMeridiemSymbols[MERIDIEM_SYMBOL_AM];
64   m_strTimeFormat=region.m_strTimeFormat;
65   m_tempUnit=region.m_tempUnit;
66   m_speedUnit=region.m_speedUnit;
67   m_strTimeZone = region.m_strTimeZone;
68 }
69
70 CLangInfo::CRegion::CRegion()
71 {
72   SetDefaults();
73 }
74
75 CLangInfo::CRegion::~CRegion()
76 {
77
78 }
79
80 void CLangInfo::CRegion::SetDefaults()
81 {
82   m_strName="N/A";
83   m_forceUnicodeFont=false;
84   m_strGuiCharSet="CP1252";
85   m_strSubtitleCharSet="CP1252";
86   m_strDVDMenuLanguage="en";
87   m_strDVDAudioLanguage="en";
88   m_strDVDSubtitleLanguage="en";
89   m_strLangLocaleName = "English";
90   m_strLangLocaleCodeTwoChar = "en";
91
92   m_strDateFormatShort="DD/MM/YYYY";
93   m_strDateFormatLong="DDDD, D MMMM YYYY";
94   m_strTimeFormat="HH:mm:ss";
95   m_tempUnit=TEMP_UNIT_CELSIUS;
96   m_speedUnit=SPEED_UNIT_KMH;
97   m_strTimeZone.clear();
98 }
99
100 void CLangInfo::CRegion::SetTempUnit(const CStdString& strUnit)
101 {
102   if (strUnit.Equals("F"))
103     m_tempUnit=TEMP_UNIT_FAHRENHEIT;
104   else if (strUnit.Equals("K"))
105     m_tempUnit=TEMP_UNIT_KELVIN;
106   else if (strUnit.Equals("C"))
107     m_tempUnit=TEMP_UNIT_CELSIUS;
108   else if (strUnit.Equals("Re"))
109     m_tempUnit=TEMP_UNIT_REAUMUR;
110   else if (strUnit.Equals("Ra"))
111     m_tempUnit=TEMP_UNIT_RANKINE;
112   else if (strUnit.Equals("Ro"))
113     m_tempUnit=TEMP_UNIT_ROMER;
114   else if (strUnit.Equals("De"))
115     m_tempUnit=TEMP_UNIT_DELISLE;
116   else if (strUnit.Equals("N"))
117     m_tempUnit=TEMP_UNIT_NEWTON;
118 }
119
120 void CLangInfo::CRegion::SetSpeedUnit(const CStdString& strUnit)
121 {
122   if (strUnit.Equals("kmh"))
123     m_speedUnit=SPEED_UNIT_KMH;
124   else if (strUnit.Equals("mpmin"))
125     m_speedUnit=SPEED_UNIT_MPMIN;
126   else if (strUnit.Equals("mps"))
127     m_speedUnit=SPEED_UNIT_MPS;
128   else if (strUnit.Equals("fth"))
129     m_speedUnit=SPEED_UNIT_FTH;
130   else if (strUnit.Equals("ftm"))
131     m_speedUnit=SPEED_UNIT_FTMIN;
132   else if (strUnit.Equals("fts"))
133     m_speedUnit=SPEED_UNIT_FTS;
134   else if (strUnit.Equals("mph"))
135     m_speedUnit=SPEED_UNIT_MPH;
136   else if (strUnit.Equals("kts"))
137     m_speedUnit=SPEED_UNIT_KTS;
138   else if (strUnit.Equals("beaufort"))
139     m_speedUnit=SPEED_UNIT_BEAUFORT;
140   else if (strUnit.Equals("inchs"))
141     m_speedUnit=SPEED_UNIT_INCHPS;
142   else if (strUnit.Equals("yards"))
143     m_speedUnit=SPEED_UNIT_YARDPS;
144   else if (strUnit.Equals("fpf"))
145     m_speedUnit=SPEED_UNIT_FPF;
146 }
147
148 void CLangInfo::CRegion::SetTimeZone(const CStdString& strTimeZone)
149 {
150   m_strTimeZone = strTimeZone;
151 }
152
153 // set the locale associated with this region global. This affects string
154 // sorting & transformations
155 void CLangInfo::CRegion::SetGlobalLocale()
156 {
157   CStdString strLocale;
158   if (m_strRegionLocaleName.length() > 0)
159   {
160     strLocale = m_strLangLocaleName + "_" + m_strRegionLocaleName;
161 #ifdef TARGET_POSIX
162     strLocale += ".UTF-8";
163 #endif
164   }
165
166   CLog::Log(LOGDEBUG, "trying to set locale to %s", strLocale.c_str());
167
168   // We need to set the locale to only change the collate. Otherwise,
169   // decimal separator is changed depending of the current language
170   // (ie. "," in French or Dutch instead of "."). This breaks atof() and
171   // others similar functions.
172 #if defined(TARGET_FREEBSD) || defined(TARGET_DARWIN_OSX)
173   // on FreeBSD and darwin libstdc++ is compiled with "generic" locale support
174   if (setlocale(LC_COLLATE, strLocale.c_str()) == NULL
175   || setlocale(LC_CTYPE, strLocale.c_str()) == NULL)
176   {
177     strLocale = "C";
178     setlocale(LC_COLLATE, strLocale.c_str());
179     setlocale(LC_CTYPE, strLocale.c_str());
180   }
181 #else
182   locale current_locale = locale::classic(); // C-Locale
183   try
184   {
185     locale lcl = locale(strLocale);
186     strLocale = lcl.name();
187     current_locale = current_locale.combine< collate<wchar_t> >(lcl);
188     current_locale = current_locale.combine< ctype<wchar_t> >(lcl);
189
190     assert(use_facet< numpunct<char> >(current_locale).decimal_point() == '.');
191
192   } catch(...) {
193     current_locale = locale::classic();
194     strLocale = "C";
195   }
196
197   locale::global(current_locale);
198 #endif
199   g_charsetConverter.resetSystemCharset();
200   CLog::Log(LOGINFO, "global locale set to %s", strLocale.c_str());
201 }
202
203 CLangInfo::CLangInfo()
204 {
205   SetDefaults();
206 }
207
208 CLangInfo::~CLangInfo()
209 {
210 }
211
212 void CLangInfo::OnSettingChanged(const CSetting *setting)
213 {
214   if (setting == NULL)
215     return;
216
217   const std::string &settingId = setting->GetId();
218   if (settingId == "locale.audiolanguage")
219     SetAudioLanguage(((CSettingString*)setting)->GetValue());
220   else if (settingId == "locale.subtitlelanguage")
221     SetSubtitleLanguage(((CSettingString*)setting)->GetValue());
222   else if (settingId == "locale.language")
223   {
224     if (!SetLanguage(((CSettingString*)setting)->GetValue()))
225       ((CSettingString*)CSettings::Get().GetSetting("locale.language"))->Reset();
226   }
227   else if (settingId == "locale.country")
228   {
229     g_langInfo.SetCurrentRegion(((CSettingString*)setting)->GetValue());
230     g_weatherManager.Refresh(); // need to reset our weather, as temperatures need re-translating.
231   }
232 }
233
234 bool CLangInfo::Load(const std::string& strFileName, bool onlyCheckLanguage /*= false*/)
235 {
236   SetDefaults();
237
238   CXBMCTinyXML xmlDoc;
239   if (!xmlDoc.LoadFile(strFileName))
240   {
241     CLog::Log(onlyCheckLanguage ? LOGDEBUG : LOGERROR, "unable to load %s: %s at line %d", strFileName.c_str(), xmlDoc.ErrorDesc(), xmlDoc.ErrorRow());
242     return false;
243   }
244
245   TiXmlElement* pRootElement = xmlDoc.RootElement();
246   if (pRootElement->ValueStr() != "language")
247   {
248     CLog::Log(onlyCheckLanguage ? LOGDEBUG : LOGERROR, "%s Doesn't contain <language>", strFileName.c_str());
249     return false;
250   }
251
252   if (pRootElement->Attribute("locale"))
253     m_defaultRegion.m_strLangLocaleName = pRootElement->Attribute("locale");
254
255 #ifdef TARGET_WINDOWS
256   // Windows need 3 chars isolang code
257   if (m_defaultRegion.m_strLangLocaleName.length() == 2)
258   {
259     if (! g_LangCodeExpander.ConvertTwoToThreeCharCode(m_defaultRegion.m_strLangLocaleName, m_defaultRegion.m_strLangLocaleName, true))
260       m_defaultRegion.m_strLangLocaleName = "";
261   }
262
263   if (!g_LangCodeExpander.ConvertWindowsToGeneralCharCode(m_defaultRegion.m_strLangLocaleName, m_languageCodeGeneral))
264     m_languageCodeGeneral = "";
265 #else
266   if (m_defaultRegion.m_strLangLocaleName.length() != 3)
267   {
268     if (!g_LangCodeExpander.ConvertToThreeCharCode(m_languageCodeGeneral, m_defaultRegion.m_strLangLocaleName, !onlyCheckLanguage))
269       m_languageCodeGeneral = "";
270   }
271   else
272     m_languageCodeGeneral = m_defaultRegion.m_strLangLocaleName;
273 #endif
274
275   CStdString tmp;
276   if (g_LangCodeExpander.ConvertToTwoCharCode(tmp, m_defaultRegion.m_strLangLocaleName))
277     m_defaultRegion.m_strLangLocaleCodeTwoChar = tmp;
278
279   const TiXmlNode *pCharSets = pRootElement->FirstChild("charsets");
280   if (pCharSets && !pCharSets->NoChildren())
281   {
282     const TiXmlNode *pGui = pCharSets->FirstChild("gui");
283     if (pGui && !pGui->NoChildren())
284     {
285       CStdString strForceUnicodeFont = ((TiXmlElement*) pGui)->Attribute("unicodefont");
286
287       if (strForceUnicodeFont.Equals("true"))
288         m_defaultRegion.m_forceUnicodeFont=true;
289
290       m_defaultRegion.m_strGuiCharSet=pGui->FirstChild()->Value();
291     }
292
293     const TiXmlNode *pSubtitle = pCharSets->FirstChild("subtitle");
294     if (pSubtitle && !pSubtitle->NoChildren())
295       m_defaultRegion.m_strSubtitleCharSet=pSubtitle->FirstChild()->Value();
296   }
297
298   const TiXmlNode *pDVD = pRootElement->FirstChild("dvd");
299   if (pDVD && !pDVD->NoChildren())
300   {
301     const TiXmlNode *pMenu = pDVD->FirstChild("menu");
302     if (pMenu && !pMenu->NoChildren())
303       m_defaultRegion.m_strDVDMenuLanguage=pMenu->FirstChild()->Value();
304
305     const TiXmlNode *pAudio = pDVD->FirstChild("audio");
306     if (pAudio && !pAudio->NoChildren())
307       m_defaultRegion.m_strDVDAudioLanguage=pAudio->FirstChild()->Value();
308
309     const TiXmlNode *pSubtitle = pDVD->FirstChild("subtitle");
310     if (pSubtitle && !pSubtitle->NoChildren())
311       m_defaultRegion.m_strDVDSubtitleLanguage=pSubtitle->FirstChild()->Value();
312   }
313
314   const TiXmlNode *pRegions = pRootElement->FirstChild("regions");
315   if (pRegions && !pRegions->NoChildren())
316   {
317     const TiXmlElement *pRegion=pRegions->FirstChildElement("region");
318     while (pRegion)
319     {
320       CRegion region(m_defaultRegion);
321       region.m_strName=pRegion->Attribute("name");
322       if (region.m_strName.empty())
323         region.m_strName="N/A";
324
325       if (pRegion->Attribute("locale"))
326         region.m_strRegionLocaleName = pRegion->Attribute("locale");
327
328 #ifdef TARGET_WINDOWS
329       // Windows need 3 chars regions code
330       if (region.m_strRegionLocaleName.length() == 2)
331       {
332         if (! g_LangCodeExpander.ConvertLinuxToWindowsRegionCodes(region.m_strRegionLocaleName, region.m_strRegionLocaleName))
333           region.m_strRegionLocaleName = "";
334       }
335 #endif
336
337       const TiXmlNode *pDateLong=pRegion->FirstChild("datelong");
338       if (pDateLong && !pDateLong->NoChildren())
339         region.m_strDateFormatLong=pDateLong->FirstChild()->Value();
340
341       const TiXmlNode *pDateShort=pRegion->FirstChild("dateshort");
342       if (pDateShort && !pDateShort->NoChildren())
343         region.m_strDateFormatShort=pDateShort->FirstChild()->Value();
344
345       const TiXmlElement *pTime=pRegion->FirstChildElement("time");
346       if (pTime && !pTime->NoChildren())
347       {
348         region.m_strTimeFormat=pTime->FirstChild()->Value();
349         region.m_strMeridiemSymbols[MERIDIEM_SYMBOL_AM]=pTime->Attribute("symbolAM");
350         region.m_strMeridiemSymbols[MERIDIEM_SYMBOL_PM]=pTime->Attribute("symbolPM");
351       }
352
353       const TiXmlNode *pTempUnit=pRegion->FirstChild("tempunit");
354       if (pTempUnit && !pTempUnit->NoChildren())
355         region.SetTempUnit(pTempUnit->FirstChild()->Value());
356
357       const TiXmlNode *pSpeedUnit=pRegion->FirstChild("speedunit");
358       if (pSpeedUnit && !pSpeedUnit->NoChildren())
359         region.SetSpeedUnit(pSpeedUnit->FirstChild()->Value());
360
361       const TiXmlNode *pTimeZone=pRegion->FirstChild("timezone");
362       if (pTimeZone && !pTimeZone->NoChildren())
363         region.SetTimeZone(pTimeZone->FirstChild()->Value());
364
365       m_regions.insert(PAIR_REGIONS(region.m_strName, region));
366
367       pRegion=pRegion->NextSiblingElement("region");
368     }
369
370     if (!onlyCheckLanguage)
371     {
372       const CStdString& strName = CSettings::Get().GetString("locale.country");
373       SetCurrentRegion(strName);
374     }
375   }
376   g_charsetConverter.reinitCharsetsFromSettings();
377
378   if (!onlyCheckLanguage)
379     LoadTokens(pRootElement->FirstChild("sorttokens"), g_advancedSettings.m_vecTokens);
380
381   return true;
382 }
383
384 bool CLangInfo::CheckLanguage(const std::string& language)
385 {
386   CLangInfo li;
387   return li.Load("special://xbmc/language/" + language + "/langinfo.xml", true);
388 }
389
390 void CLangInfo::LoadTokens(const TiXmlNode* pTokens, vector<CStdString>& vecTokens)
391 {
392   if (pTokens && !pTokens->NoChildren())
393   {
394     const TiXmlElement *pToken = pTokens->FirstChildElement("token");
395     while (pToken)
396     {
397       CStdString strSep= " ._";
398       if (pToken->Attribute("separators"))
399         strSep = pToken->Attribute("separators");
400       if (pToken->FirstChild() && pToken->FirstChild()->Value())
401       {
402         if (strSep.empty())
403           vecTokens.push_back(pToken->FirstChild()->Value());
404         else
405           for (unsigned int i=0;i<strSep.size();++i)
406             vecTokens.push_back(CStdString(pToken->FirstChild()->Value())+strSep[i]);
407       }
408       pToken = pToken->NextSiblingElement();
409     }
410   }
411 }
412
413 void CLangInfo::SetDefaults()
414 {
415   m_regions.clear();
416
417   //Reset default region
418   m_defaultRegion.SetDefaults();
419
420   // Set the default region, we may be unable to load langinfo.xml
421   m_currentRegion=&m_defaultRegion;
422   
423   m_languageCodeGeneral = "eng";
424 }
425
426 CStdString CLangInfo::GetGuiCharSet() const
427 {
428   CStdString strCharSet;
429   strCharSet=CSettings::Get().GetString("locale.charset");
430   if (strCharSet=="DEFAULT")
431     strCharSet=m_currentRegion->m_strGuiCharSet;
432
433   return strCharSet;
434 }
435
436 CStdString CLangInfo::GetSubtitleCharSet() const
437 {
438   CStdString strCharSet=CSettings::Get().GetString("subtitles.charset");
439   if (strCharSet=="DEFAULT")
440     strCharSet=m_currentRegion->m_strSubtitleCharSet;
441
442   return strCharSet;
443 }
444
445 bool CLangInfo::SetLanguage(const std::string &strLanguage)
446 {
447   string strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
448   if (!Load(strLangInfoPath))
449     return false;
450
451   if (ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
452   {
453     CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
454     CStdString strFontSet;
455     if (!g_fontManager.GetFirstFontSetUnicode(strFontSet))
456       CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
457   }
458
459   if (!g_localizeStrings.Load("special://xbmc/language/", strLanguage))
460     return false;
461
462   // also tell our weather and skin to reload as these are localized
463   g_weatherManager.Refresh();
464   g_PVRManager.LocalizationChanged();
465   g_application.ReloadSkin();
466
467   return true;
468 }
469
470 bool CLangInfo::CheckLoadLanguage(const std::string &language)
471 {
472   return Load("special://xbmc/language/" + language + "/langinfo.xml", true);
473 }
474
475 // three char language code (not win32 specific)
476 const CStdString& CLangInfo::GetAudioLanguage() const
477 {
478   if (!m_audioLanguage.empty())
479     return m_audioLanguage;
480
481   return m_languageCodeGeneral;
482 }
483
484 void CLangInfo::SetAudioLanguage(const std::string& language)
485 {
486   if (language.empty()
487     || StringUtils::EqualsNoCase(language, "default")
488     || StringUtils::EqualsNoCase(language, "original")
489     || !g_LangCodeExpander.ConvertToThreeCharCode(m_audioLanguage, language))
490     m_audioLanguage.clear();
491 }
492
493 // three char language code (not win32 specific)
494 const CStdString& CLangInfo::GetSubtitleLanguage() const
495 {
496   if (!m_subtitleLanguage.empty())
497     return m_subtitleLanguage;
498
499   return m_languageCodeGeneral;
500 }
501
502 void CLangInfo::SetSubtitleLanguage(const std::string& language)
503 {
504   if (language.empty()
505     || StringUtils::EqualsNoCase(language, "default")
506     || StringUtils::EqualsNoCase(language, "original")
507     || !g_LangCodeExpander.ConvertToThreeCharCode(m_subtitleLanguage, language))
508     m_subtitleLanguage.clear();
509 }
510
511 // two character codes as defined in ISO639
512 const std::string CLangInfo::GetDVDMenuLanguage() const
513 {
514   CStdString code;
515   if (!g_LangCodeExpander.ConvertToTwoCharCode(code, m_currentRegion->m_strLangLocaleName))
516     code = m_currentRegion->m_strDVDMenuLanguage;
517   
518   return code;
519 }
520
521 // two character codes as defined in ISO639
522 const std::string CLangInfo::GetDVDAudioLanguage() const
523 {
524   CStdString code;
525   if (!g_LangCodeExpander.ConvertToTwoCharCode(code, m_audioLanguage))
526     code = m_currentRegion->m_strDVDAudioLanguage;
527   
528   return code;
529 }
530
531 // two character codes as defined in ISO639
532 const std::string CLangInfo::GetDVDSubtitleLanguage() const
533 {
534   CStdString code;
535   if (!g_LangCodeExpander.ConvertToTwoCharCode(code, m_subtitleLanguage))
536     code = m_currentRegion->m_strDVDSubtitleLanguage;
537   
538   return code;
539 }
540
541 const std::string CLangInfo::GetLanguageLocale(bool twochar /* = false */) const
542 {
543   if (twochar)
544     return m_currentRegion->m_strLangLocaleCodeTwoChar;
545
546   return m_currentRegion->m_strLangLocaleName;
547 }
548
549 const CStdString& CLangInfo::GetRegionLocale() const
550 {
551   return m_currentRegion->m_strRegionLocaleName;
552 }
553
554 // Returns the format string for the date of the current language
555 const CStdString& CLangInfo::GetDateFormat(bool bLongDate/*=false*/) const
556 {
557   if (bLongDate)
558     return m_currentRegion->m_strDateFormatLong;
559   else
560     return m_currentRegion->m_strDateFormatShort;
561 }
562
563 // Returns the format string for the time of the current language
564 const CStdString& CLangInfo::GetTimeFormat() const
565 {
566   return m_currentRegion->m_strTimeFormat;
567 }
568
569 const CStdString& CLangInfo::GetTimeZone() const
570 {
571   return m_currentRegion->m_strTimeZone;
572 }
573
574 // Returns the AM/PM symbol of the current language
575 const CStdString& CLangInfo::GetMeridiemSymbol(MERIDIEM_SYMBOL symbol) const
576 {
577   return m_currentRegion->m_strMeridiemSymbols[symbol];
578 }
579
580 // Fills the array with the region names available for this language
581 void CLangInfo::GetRegionNames(CStdStringArray& array)
582 {
583   for (ITMAPREGIONS it=m_regions.begin(); it!=m_regions.end(); ++it)
584   {
585     CStdString strName=it->first;
586     if (strName=="N/A")
587       strName=g_localizeStrings.Get(416);
588     array.push_back(strName);
589   }
590 }
591
592 // Set the current region by its name, names from GetRegionNames() are valid.
593 // If the region is not found the first available region is set.
594 void CLangInfo::SetCurrentRegion(const CStdString& strName)
595 {
596   ITMAPREGIONS it=m_regions.find(strName);
597   if (it!=m_regions.end())
598     m_currentRegion=&it->second;
599   else if (!m_regions.empty())
600     m_currentRegion=&m_regions.begin()->second;
601   else
602     m_currentRegion=&m_defaultRegion;
603
604   m_currentRegion->SetGlobalLocale();
605 }
606
607 // Returns the current region set for this language
608 const CStdString& CLangInfo::GetCurrentRegion() const
609 {
610   return m_currentRegion->m_strName;
611 }
612
613 CLangInfo::TEMP_UNIT CLangInfo::GetTempUnit() const
614 {
615   return m_currentRegion->m_tempUnit;
616 }
617
618 // Returns the temperature unit string for the current language
619 const CStdString& CLangInfo::GetTempUnitString() const
620 {
621   return g_localizeStrings.Get(TEMP_UNIT_STRINGS+m_currentRegion->m_tempUnit);
622 }
623
624 CLangInfo::SPEED_UNIT CLangInfo::GetSpeedUnit() const
625 {
626   return m_currentRegion->m_speedUnit;
627 }
628
629 // Returns the speed unit string for the current language
630 const CStdString& CLangInfo::GetSpeedUnitString() const
631 {
632   return g_localizeStrings.Get(SPEED_UNIT_STRINGS+m_currentRegion->m_speedUnit);
633 }
634
635 void CLangInfo::SettingOptionsLanguagesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current)
636 {
637   //find languages...
638   CFileItemList items;
639   XFILE::CDirectory::GetDirectory("special://xbmc/language/", items);
640
641   vector<string> vecLanguage;
642   for (int i = 0; i < items.Size(); ++i)
643   {
644     CFileItemPtr pItem = items[i];
645     if (pItem->m_bIsFolder)
646     {
647       if (StringUtils::EqualsNoCase(pItem->GetLabel(), ".svn") ||
648           StringUtils::EqualsNoCase(pItem->GetLabel(), "fonts") ||
649           StringUtils::EqualsNoCase(pItem->GetLabel(), "media"))
650         continue;
651
652       vecLanguage.push_back(pItem->GetLabel());
653     }
654   }
655
656   sort(vecLanguage.begin(), vecLanguage.end(), sortstringbyname());
657
658   for (unsigned int i = 0; i < vecLanguage.size(); ++i)
659     list.push_back(make_pair(vecLanguage[i], vecLanguage[i]));
660 }
661
662 void CLangInfo::SettingOptionsStreamLanguagesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current)
663 {
664   list.push_back(make_pair(g_localizeStrings.Get(308), "original"));
665   list.push_back(make_pair(g_localizeStrings.Get(309), "default"));
666
667   // get a list of language names
668   vector<string> languages = g_LangCodeExpander.GetLanguageNames();
669   sort(languages.begin(), languages.end(), sortstringbyname());
670   for (std::vector<std::string>::const_iterator language = languages.begin(); language != languages.end(); ++language)
671     list.push_back(make_pair(*language, *language));
672 }
673
674 void CLangInfo::SettingOptionsRegionsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current)
675 {
676   CStdStringArray regions;
677   g_langInfo.GetRegionNames(regions);
678   sort(regions.begin(), regions.end(), sortstringbyname());
679
680   bool match = false;
681   for (unsigned int i = 0; i < regions.size(); ++i)
682   {
683     CStdString region = regions[i];
684     list.push_back(make_pair(region, region));
685
686     if (!match && region.Equals(((CSettingString*)setting)->GetValue().c_str()))
687     {
688       match = true;
689       current = region;
690     }
691   }
692
693   if (!match && regions.size() > 0)
694     current = regions[0];
695 }