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