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