2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
22 #include "Application.h"
23 #include "ApplicationMessenger.h"
26 #include "filesystem/Directory.h"
27 #include "guilib/GUIFontManager.h"
28 #include "guilib/LocalizeStrings.h"
29 #include "pvr/PVRManager.h"
30 #include "settings/AdvancedSettings.h"
31 #include "settings/lib/Setting.h"
32 #include "settings/Settings.h"
33 #include "utils/CharsetConverter.h"
34 #include "utils/log.h"
35 #include "utils/LangCodeExpander.h"
36 #include "utils/StringUtils.h"
37 #include "utils/Weather.h"
38 #include "utils/XBMCTinyXML.h"
43 #define TEMP_UNIT_STRINGS 20027
45 #define SPEED_UNIT_STRINGS 20200
47 CLangInfo::CRegion::CRegion(const CRegion& region)
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;
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;
71 CLangInfo::CRegion::CRegion()
76 CLangInfo::CRegion::~CRegion()
81 void CLangInfo::CRegion::SetDefaults()
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";
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();
101 void CLangInfo::CRegion::SetTempUnit(const CStdString& strUnit)
103 if (strUnit.Equals("F"))
104 m_tempUnit=TEMP_UNIT_FAHRENHEIT;
105 else if (strUnit.Equals("K"))
106 m_tempUnit=TEMP_UNIT_KELVIN;
107 else if (strUnit.Equals("C"))
108 m_tempUnit=TEMP_UNIT_CELSIUS;
109 else if (strUnit.Equals("Re"))
110 m_tempUnit=TEMP_UNIT_REAUMUR;
111 else if (strUnit.Equals("Ra"))
112 m_tempUnit=TEMP_UNIT_RANKINE;
113 else if (strUnit.Equals("Ro"))
114 m_tempUnit=TEMP_UNIT_ROMER;
115 else if (strUnit.Equals("De"))
116 m_tempUnit=TEMP_UNIT_DELISLE;
117 else if (strUnit.Equals("N"))
118 m_tempUnit=TEMP_UNIT_NEWTON;
121 void CLangInfo::CRegion::SetSpeedUnit(const CStdString& strUnit)
123 if (strUnit.Equals("kmh"))
124 m_speedUnit=SPEED_UNIT_KMH;
125 else if (strUnit.Equals("mpmin"))
126 m_speedUnit=SPEED_UNIT_MPMIN;
127 else if (strUnit.Equals("mps"))
128 m_speedUnit=SPEED_UNIT_MPS;
129 else if (strUnit.Equals("fth"))
130 m_speedUnit=SPEED_UNIT_FTH;
131 else if (strUnit.Equals("ftm"))
132 m_speedUnit=SPEED_UNIT_FTMIN;
133 else if (strUnit.Equals("fts"))
134 m_speedUnit=SPEED_UNIT_FTS;
135 else if (strUnit.Equals("mph"))
136 m_speedUnit=SPEED_UNIT_MPH;
137 else if (strUnit.Equals("kts"))
138 m_speedUnit=SPEED_UNIT_KTS;
139 else if (strUnit.Equals("beaufort"))
140 m_speedUnit=SPEED_UNIT_BEAUFORT;
141 else if (strUnit.Equals("inchs"))
142 m_speedUnit=SPEED_UNIT_INCHPS;
143 else if (strUnit.Equals("yards"))
144 m_speedUnit=SPEED_UNIT_YARDPS;
145 else if (strUnit.Equals("fpf"))
146 m_speedUnit=SPEED_UNIT_FPF;
149 void CLangInfo::CRegion::SetTimeZone(const CStdString& strTimeZone)
151 m_strTimeZone = strTimeZone;
154 // set the locale associated with this region global. This affects string
155 // sorting & transformations
156 void CLangInfo::CRegion::SetGlobalLocale()
158 CStdString strLocale;
159 if (m_strRegionLocaleName.length() > 0)
161 strLocale = m_strLangLocaleName + "_" + m_strRegionLocaleName;
163 strLocale += ".UTF-8";
167 CLog::Log(LOGDEBUG, "trying to set locale to %s", strLocale.c_str());
169 // We need to set the locale to only change the collate. Otherwise,
170 // decimal separator is changed depending of the current language
171 // (ie. "," in French or Dutch instead of "."). This breaks atof() and
172 // others similar functions.
173 #if defined(TARGET_FREEBSD) || defined(TARGET_DARWIN_OSX)
174 // on FreeBSD and darwin libstdc++ is compiled with "generic" locale support
175 if (setlocale(LC_COLLATE, strLocale.c_str()) == NULL
176 || setlocale(LC_CTYPE, strLocale.c_str()) == NULL)
179 setlocale(LC_COLLATE, strLocale.c_str());
180 setlocale(LC_CTYPE, strLocale.c_str());
183 locale current_locale = locale::classic(); // C-Locale
186 locale lcl = locale(strLocale);
187 strLocale = lcl.name();
188 current_locale = current_locale.combine< collate<wchar_t> >(lcl);
189 current_locale = current_locale.combine< ctype<wchar_t> >(lcl);
191 assert(use_facet< numpunct<char> >(current_locale).decimal_point() == '.');
194 current_locale = locale::classic();
198 locale::global(current_locale);
200 g_charsetConverter.resetSystemCharset();
201 CLog::Log(LOGINFO, "global locale set to %s", strLocale.c_str());
204 CLangInfo::CLangInfo()
209 CLangInfo::~CLangInfo()
213 void CLangInfo::OnSettingChanged(const CSetting *setting)
218 const std::string &settingId = setting->GetId();
219 if (settingId == "locale.audiolanguage")
220 SetAudioLanguage(((CSettingString*)setting)->GetValue());
221 else if (settingId == "locale.subtitlelanguage")
222 SetSubtitleLanguage(((CSettingString*)setting)->GetValue());
223 else if (settingId == "locale.language")
225 if (!SetLanguage(((CSettingString*)setting)->GetValue()))
226 ((CSettingString*)CSettings::Get().GetSetting("locale.language"))->Reset();
228 else if (settingId == "locale.country")
230 g_langInfo.SetCurrentRegion(((CSettingString*)setting)->GetValue());
231 g_weatherManager.Refresh(); // need to reset our weather, as temperatures need re-translating.
235 bool CLangInfo::Load(const std::string& strFileName, bool onlyCheckLanguage /*= false*/)
240 if (!xmlDoc.LoadFile(strFileName))
242 CLog::Log(onlyCheckLanguage ? LOGDEBUG : LOGERROR, "unable to load %s: %s at line %d", strFileName.c_str(), xmlDoc.ErrorDesc(), xmlDoc.ErrorRow());
246 TiXmlElement* pRootElement = xmlDoc.RootElement();
247 if (pRootElement->ValueStr() != "language")
249 CLog::Log(onlyCheckLanguage ? LOGDEBUG : LOGERROR, "%s Doesn't contain <language>", strFileName.c_str());
253 if (pRootElement->Attribute("locale"))
254 m_defaultRegion.m_strLangLocaleName = pRootElement->Attribute("locale");
256 #ifdef TARGET_WINDOWS
257 // Windows need 3 chars isolang code
258 if (m_defaultRegion.m_strLangLocaleName.length() == 2)
260 if (! g_LangCodeExpander.ConvertTwoToThreeCharCode(m_defaultRegion.m_strLangLocaleName, m_defaultRegion.m_strLangLocaleName, true))
261 m_defaultRegion.m_strLangLocaleName = "";
264 if (!g_LangCodeExpander.ConvertWindowsToGeneralCharCode(m_defaultRegion.m_strLangLocaleName, m_languageCodeGeneral))
265 m_languageCodeGeneral = "";
267 if (m_defaultRegion.m_strLangLocaleName.length() != 3)
269 if (!g_LangCodeExpander.ConvertToThreeCharCode(m_languageCodeGeneral, m_defaultRegion.m_strLangLocaleName, !onlyCheckLanguage))
270 m_languageCodeGeneral = "";
273 m_languageCodeGeneral = m_defaultRegion.m_strLangLocaleName;
277 if (g_LangCodeExpander.ConvertToTwoCharCode(tmp, m_defaultRegion.m_strLangLocaleName))
278 m_defaultRegion.m_strLangLocaleCodeTwoChar = tmp;
280 const TiXmlNode *pCharSets = pRootElement->FirstChild("charsets");
281 if (pCharSets && !pCharSets->NoChildren())
283 const TiXmlNode *pGui = pCharSets->FirstChild("gui");
284 if (pGui && !pGui->NoChildren())
286 CStdString strForceUnicodeFont = ((TiXmlElement*) pGui)->Attribute("unicodefont");
288 if (strForceUnicodeFont.Equals("true"))
289 m_defaultRegion.m_forceUnicodeFont=true;
291 m_defaultRegion.m_strGuiCharSet=pGui->FirstChild()->Value();
294 const TiXmlNode *pSubtitle = pCharSets->FirstChild("subtitle");
295 if (pSubtitle && !pSubtitle->NoChildren())
296 m_defaultRegion.m_strSubtitleCharSet=pSubtitle->FirstChild()->Value();
299 const TiXmlNode *pDVD = pRootElement->FirstChild("dvd");
300 if (pDVD && !pDVD->NoChildren())
302 const TiXmlNode *pMenu = pDVD->FirstChild("menu");
303 if (pMenu && !pMenu->NoChildren())
304 m_defaultRegion.m_strDVDMenuLanguage=pMenu->FirstChild()->Value();
306 const TiXmlNode *pAudio = pDVD->FirstChild("audio");
307 if (pAudio && !pAudio->NoChildren())
308 m_defaultRegion.m_strDVDAudioLanguage=pAudio->FirstChild()->Value();
310 const TiXmlNode *pSubtitle = pDVD->FirstChild("subtitle");
311 if (pSubtitle && !pSubtitle->NoChildren())
312 m_defaultRegion.m_strDVDSubtitleLanguage=pSubtitle->FirstChild()->Value();
315 const TiXmlNode *pRegions = pRootElement->FirstChild("regions");
316 if (pRegions && !pRegions->NoChildren())
318 const TiXmlElement *pRegion=pRegions->FirstChildElement("region");
321 CRegion region(m_defaultRegion);
322 region.m_strName=pRegion->Attribute("name");
323 if (region.m_strName.empty())
324 region.m_strName="N/A";
326 if (pRegion->Attribute("locale"))
327 region.m_strRegionLocaleName = pRegion->Attribute("locale");
329 #ifdef TARGET_WINDOWS
330 // Windows need 3 chars regions code
331 if (region.m_strRegionLocaleName.length() == 2)
333 if (! g_LangCodeExpander.ConvertLinuxToWindowsRegionCodes(region.m_strRegionLocaleName, region.m_strRegionLocaleName))
334 region.m_strRegionLocaleName = "";
338 const TiXmlNode *pDateLong=pRegion->FirstChild("datelong");
339 if (pDateLong && !pDateLong->NoChildren())
340 region.m_strDateFormatLong=pDateLong->FirstChild()->Value();
342 const TiXmlNode *pDateShort=pRegion->FirstChild("dateshort");
343 if (pDateShort && !pDateShort->NoChildren())
344 region.m_strDateFormatShort=pDateShort->FirstChild()->Value();
346 const TiXmlElement *pTime=pRegion->FirstChildElement("time");
347 if (pTime && !pTime->NoChildren())
349 region.m_strTimeFormat=pTime->FirstChild()->Value();
350 region.m_strMeridiemSymbols[MERIDIEM_SYMBOL_AM]=pTime->Attribute("symbolAM");
351 region.m_strMeridiemSymbols[MERIDIEM_SYMBOL_PM]=pTime->Attribute("symbolPM");
354 const TiXmlNode *pTempUnit=pRegion->FirstChild("tempunit");
355 if (pTempUnit && !pTempUnit->NoChildren())
356 region.SetTempUnit(pTempUnit->FirstChild()->Value());
358 const TiXmlNode *pSpeedUnit=pRegion->FirstChild("speedunit");
359 if (pSpeedUnit && !pSpeedUnit->NoChildren())
360 region.SetSpeedUnit(pSpeedUnit->FirstChild()->Value());
362 const TiXmlNode *pTimeZone=pRegion->FirstChild("timezone");
363 if (pTimeZone && !pTimeZone->NoChildren())
364 region.SetTimeZone(pTimeZone->FirstChild()->Value());
366 m_regions.insert(PAIR_REGIONS(region.m_strName, region));
368 pRegion=pRegion->NextSiblingElement("region");
371 if (!onlyCheckLanguage)
373 const CStdString& strName = CSettings::Get().GetString("locale.country");
374 SetCurrentRegion(strName);
377 g_charsetConverter.reinitCharsetsFromSettings();
379 if (!onlyCheckLanguage)
380 LoadTokens(pRootElement->FirstChild("sorttokens"), g_advancedSettings.m_vecTokens);
385 bool CLangInfo::CheckLanguage(const std::string& language)
388 return li.Load("special://xbmc/language/" + language + "/langinfo.xml", true);
391 void CLangInfo::LoadTokens(const TiXmlNode* pTokens, vector<CStdString>& vecTokens)
393 if (pTokens && !pTokens->NoChildren())
395 const TiXmlElement *pToken = pTokens->FirstChildElement("token");
398 CStdString strSep= " ._";
399 if (pToken->Attribute("separators"))
400 strSep = pToken->Attribute("separators");
401 if (pToken->FirstChild() && pToken->FirstChild()->Value())
404 vecTokens.push_back(pToken->FirstChild()->Value());
406 for (unsigned int i=0;i<strSep.size();++i)
407 vecTokens.push_back(CStdString(pToken->FirstChild()->Value())+strSep[i]);
409 pToken = pToken->NextSiblingElement();
414 void CLangInfo::SetDefaults()
418 //Reset default region
419 m_defaultRegion.SetDefaults();
421 // Set the default region, we may be unable to load langinfo.xml
422 m_currentRegion=&m_defaultRegion;
424 m_languageCodeGeneral = "eng";
427 CStdString CLangInfo::GetGuiCharSet() const
429 CStdString strCharSet;
430 strCharSet=CSettings::Get().GetString("locale.charset");
431 if (strCharSet=="DEFAULT")
432 strCharSet=m_currentRegion->m_strGuiCharSet;
437 CStdString CLangInfo::GetSubtitleCharSet() const
439 CStdString strCharSet=CSettings::Get().GetString("subtitles.charset");
440 if (strCharSet=="DEFAULT")
441 strCharSet=m_currentRegion->m_strSubtitleCharSet;
446 bool CLangInfo::SetLanguage(const std::string &strLanguage)
448 string strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
449 if (!Load(strLangInfoPath))
452 if (ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
454 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
455 CStdString strFontSet;
456 if (!g_fontManager.GetFirstFontSetUnicode(strFontSet))
457 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
460 if (!g_localizeStrings.Load("special://xbmc/language/", strLanguage))
463 // also tell our weather and skin to reload as these are localized
464 g_weatherManager.Refresh();
465 g_PVRManager.LocalizationChanged();
466 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin", false);
471 bool CLangInfo::CheckLoadLanguage(const std::string &language)
473 return Load("special://xbmc/language/" + language + "/langinfo.xml", true);
476 // three char language code (not win32 specific)
477 const CStdString& CLangInfo::GetAudioLanguage() const
479 if (!m_audioLanguage.empty())
480 return m_audioLanguage;
482 return m_languageCodeGeneral;
485 void CLangInfo::SetAudioLanguage(const std::string& language)
488 || StringUtils::EqualsNoCase(language, "default")
489 || StringUtils::EqualsNoCase(language, "original")
490 || !g_LangCodeExpander.ConvertToThreeCharCode(m_audioLanguage, language))
491 m_audioLanguage.clear();
494 // three char language code (not win32 specific)
495 const CStdString& CLangInfo::GetSubtitleLanguage() const
497 if (!m_subtitleLanguage.empty())
498 return m_subtitleLanguage;
500 return m_languageCodeGeneral;
503 void CLangInfo::SetSubtitleLanguage(const std::string& language)
506 || StringUtils::EqualsNoCase(language, "default")
507 || StringUtils::EqualsNoCase(language, "original")
508 || !g_LangCodeExpander.ConvertToThreeCharCode(m_subtitleLanguage, language))
509 m_subtitleLanguage.clear();
512 // two character codes as defined in ISO639
513 const std::string CLangInfo::GetDVDMenuLanguage() const
516 if (!g_LangCodeExpander.ConvertToTwoCharCode(code, m_currentRegion->m_strLangLocaleName))
517 code = m_currentRegion->m_strDVDMenuLanguage;
522 // two character codes as defined in ISO639
523 const std::string CLangInfo::GetDVDAudioLanguage() const
526 if (!g_LangCodeExpander.ConvertToTwoCharCode(code, m_audioLanguage))
527 code = m_currentRegion->m_strDVDAudioLanguage;
532 // two character codes as defined in ISO639
533 const std::string CLangInfo::GetDVDSubtitleLanguage() const
536 if (!g_LangCodeExpander.ConvertToTwoCharCode(code, m_subtitleLanguage))
537 code = m_currentRegion->m_strDVDSubtitleLanguage;
542 const std::string CLangInfo::GetLanguageLocale(bool twochar /* = false */) const
545 return m_currentRegion->m_strLangLocaleCodeTwoChar;
547 return m_currentRegion->m_strLangLocaleName;
550 const CStdString& CLangInfo::GetRegionLocale() const
552 return m_currentRegion->m_strRegionLocaleName;
555 // Returns the format string for the date of the current language
556 const CStdString& CLangInfo::GetDateFormat(bool bLongDate/*=false*/) const
559 return m_currentRegion->m_strDateFormatLong;
561 return m_currentRegion->m_strDateFormatShort;
564 // Returns the format string for the time of the current language
565 const CStdString& CLangInfo::GetTimeFormat() const
567 return m_currentRegion->m_strTimeFormat;
570 const CStdString& CLangInfo::GetTimeZone() const
572 return m_currentRegion->m_strTimeZone;
575 // Returns the AM/PM symbol of the current language
576 const CStdString& CLangInfo::GetMeridiemSymbol(MERIDIEM_SYMBOL symbol) const
578 return m_currentRegion->m_strMeridiemSymbols[symbol];
581 // Fills the array with the region names available for this language
582 void CLangInfo::GetRegionNames(CStdStringArray& array)
584 for (ITMAPREGIONS it=m_regions.begin(); it!=m_regions.end(); ++it)
586 CStdString strName=it->first;
588 strName=g_localizeStrings.Get(416);
589 array.push_back(strName);
593 // Set the current region by its name, names from GetRegionNames() are valid.
594 // If the region is not found the first available region is set.
595 void CLangInfo::SetCurrentRegion(const CStdString& strName)
597 ITMAPREGIONS it=m_regions.find(strName);
598 if (it!=m_regions.end())
599 m_currentRegion=&it->second;
600 else if (!m_regions.empty())
601 m_currentRegion=&m_regions.begin()->second;
603 m_currentRegion=&m_defaultRegion;
605 m_currentRegion->SetGlobalLocale();
608 // Returns the current region set for this language
609 const CStdString& CLangInfo::GetCurrentRegion() const
611 return m_currentRegion->m_strName;
614 CLangInfo::TEMP_UNIT CLangInfo::GetTempUnit() const
616 return m_currentRegion->m_tempUnit;
619 // Returns the temperature unit string for the current language
620 const CStdString& CLangInfo::GetTempUnitString() const
622 return g_localizeStrings.Get(TEMP_UNIT_STRINGS+m_currentRegion->m_tempUnit);
625 CLangInfo::SPEED_UNIT CLangInfo::GetSpeedUnit() const
627 return m_currentRegion->m_speedUnit;
630 // Returns the speed unit string for the current language
631 const CStdString& CLangInfo::GetSpeedUnitString() const
633 return g_localizeStrings.Get(SPEED_UNIT_STRINGS+m_currentRegion->m_speedUnit);
636 void CLangInfo::SettingOptionsLanguagesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t)
640 XFILE::CDirectory::GetDirectory("special://xbmc/language/", items);
642 vector<string> vecLanguage;
643 for (int i = 0; i < items.Size(); ++i)
645 CFileItemPtr pItem = items[i];
646 if (pItem->m_bIsFolder)
648 if (StringUtils::EqualsNoCase(pItem->GetLabel(), ".svn") ||
649 StringUtils::EqualsNoCase(pItem->GetLabel(), "fonts") ||
650 StringUtils::EqualsNoCase(pItem->GetLabel(), "media"))
653 vecLanguage.push_back(pItem->GetLabel());
657 sort(vecLanguage.begin(), vecLanguage.end(), sortstringbyname());
659 for (unsigned int i = 0; i < vecLanguage.size(); ++i)
660 list.push_back(make_pair(vecLanguage[i], vecLanguage[i]));
663 void CLangInfo::SettingOptionsStreamLanguagesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t)
665 list.push_back(make_pair(g_localizeStrings.Get(308), "original"));
666 list.push_back(make_pair(g_localizeStrings.Get(309), "default"));
668 // get a list of language names
669 vector<string> languages = g_LangCodeExpander.GetLanguageNames();
670 sort(languages.begin(), languages.end(), sortstringbyname());
671 for (std::vector<std::string>::const_iterator language = languages.begin(); language != languages.end(); ++language)
672 list.push_back(make_pair(*language, *language));
675 void CLangInfo::SettingOptionsRegionsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t)
677 CStdStringArray regions;
678 g_langInfo.GetRegionNames(regions);
679 sort(regions.begin(), regions.end(), sortstringbyname());
682 for (unsigned int i = 0; i < regions.size(); ++i)
684 CStdString region = regions[i];
685 list.push_back(make_pair(region, region));
687 if (!match && region.Equals(((CSettingString*)setting)->GetValue().c_str()))
694 if (!match && regions.size() > 0)
695 current = regions[0];