diff --git a/xbmc/utils/Locale.cpp b/xbmc/utils/Locale.cpp
new file mode 100644
index 0000000000000..a8cfefa94d284
--- /dev/null
+++ b/xbmc/utils/Locale.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2015 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * .
+ *
+ */
+
+#include "Locale.h"
+#include "utils/StringUtils.h"
+
+const CLocale CLocale::Empty;
+
+CLocale::CLocale()
+ : m_valid(false),
+ m_language(),
+ m_territory(),
+ m_codeset(),
+ m_modifier()
+{ }
+
+CLocale::CLocale(const std::string& language)
+ : m_valid(false),
+ m_language(),
+ m_territory(),
+ m_codeset(),
+ m_modifier()
+{
+ m_valid = ParseLocale(language, m_language, m_territory, m_codeset, m_modifier);
+}
+
+CLocale::CLocale(const std::string& language, const std::string& territory)
+ : m_valid(false),
+ m_language(language),
+ m_territory(territory),
+ m_codeset(),
+ m_modifier()
+{
+ Initialize();
+}
+
+CLocale::CLocale(const std::string& language, const std::string& territory, const std::string& codeset)
+ : m_valid(false),
+ m_language(language),
+ m_territory(territory),
+ m_codeset(codeset),
+ m_modifier()
+{
+ Initialize();
+}
+
+CLocale::CLocale(const std::string& language, const std::string& territory, const std::string& codeset, const std::string& modifier)
+ : m_valid(false),
+ m_language(language),
+ m_territory(territory),
+ m_codeset(codeset),
+ m_modifier(modifier)
+{
+ Initialize();
+}
+
+CLocale::~CLocale()
+{ }
+
+CLocale CLocale::FromString(const std::string& locale)
+{
+ return CLocale(locale);
+}
+
+bool CLocale::operator==(const CLocale& other) const
+{
+ if (!m_valid && !other.m_valid)
+ return true;
+
+ return m_valid == other.m_valid &&
+ StringUtils::EqualsNoCase(m_language, other.m_language) &&
+ StringUtils::EqualsNoCase(m_territory, other.m_territory) &&
+ StringUtils::EqualsNoCase(m_codeset, other.m_codeset) &&
+ StringUtils::EqualsNoCase(m_modifier, other.m_modifier);
+}
+
+std::string CLocale::ToString() const
+{
+ if (!m_valid)
+ return "";
+
+ std::string locale = ToShortString();
+
+ if (!m_codeset.empty())
+ locale += "." + m_codeset;
+
+ if (!m_modifier.empty())
+ locale += "@" + m_modifier;
+
+ return locale;
+}
+
+std::string CLocale::ToStringLC() const
+{
+ if (!m_valid)
+ return "";
+
+ std::string locale = ToString();
+ StringUtils::ToLower(locale);
+
+ return locale;
+}
+
+std::string CLocale::ToShortString() const
+{
+ if (!m_valid)
+ return "";
+
+ std::string locale = m_language;
+
+ if (!m_territory.empty())
+ locale += "_" + m_territory;
+
+ return locale;
+}
+
+std::string CLocale::ToShortStringLC() const
+{
+ if (!m_valid)
+ return "";
+
+ std::string locale = ToShortString();
+ StringUtils::ToLower(locale);
+
+ return locale;
+}
+
+bool CLocale::Equals(const std::string& locale) const
+{
+ CLocale other = FromString(locale);
+
+ return *this == other;
+}
+
+bool CLocale::Matches(const std::string& locale) const
+{
+ CLocale other = FromString(locale);
+
+ if (!m_valid && !other.m_valid)
+ return true;
+ if (!m_valid || !other.m_valid)
+ return false;
+
+ if (!StringUtils::EqualsNoCase(m_language, other.m_language))
+ return false;
+ if (!m_territory.empty() && !other.m_territory.empty() && !StringUtils::EqualsNoCase(m_territory, other.m_territory))
+ return false;
+ if (!m_codeset.empty() && !other.m_codeset.empty() && !StringUtils::EqualsNoCase(m_codeset, other.m_codeset))
+ return false;
+ if (!m_modifier.empty() && !other.m_modifier.empty() && !StringUtils::EqualsNoCase(m_modifier, other.m_modifier))
+ return false;
+
+ return true;
+}
+
+bool CLocale::CheckValidity(const std::string& language, const std::string& territory, const std::string& codeset, const std::string& modifier)
+{
+ static_cast(territory);
+ static_cast(codeset);
+ static_cast(modifier);
+
+ return !language.empty();
+}
+
+bool CLocale::ParseLocale(const std::string &locale, std::string &language, std::string &territory, std::string &codeset, std::string &modifier)
+{
+ if (locale.empty())
+ return false;
+
+ language.clear();
+ territory.clear();
+ codeset.clear();
+ modifier.clear();
+
+ // the format for a locale is [language[_territory][.codeset][@modifier]]
+ std::string tmp = locale;
+
+ // look for the modifier after @
+ size_t pos = tmp.find("@");
+ if (pos != std::string::npos)
+ {
+ modifier = tmp.substr(pos + 1);
+ tmp = tmp.substr(0, pos);
+ }
+
+ // look for the codeset after .
+ pos = tmp.find(".");
+ if (pos != std::string::npos)
+ {
+ codeset = tmp.substr(pos + 1);
+ tmp = tmp.substr(0, pos);
+ }
+
+ // look for the codeset after _
+ pos = tmp.find("_");
+ if (pos != std::string::npos)
+ {
+ territory = tmp.substr(pos + 1);
+ StringUtils::ToUpper(territory);
+ tmp = tmp.substr(0, pos);
+ }
+
+ // what remains is the language
+ language = tmp;
+ StringUtils::ToLower(language);
+
+ return CheckValidity(language, territory, codeset, modifier);
+}
+
+void CLocale::Initialize()
+{
+ m_valid = CheckValidity(m_language, m_territory, m_codeset, m_modifier);
+ if (m_valid)
+ {
+ StringUtils::ToLower(m_language);
+ StringUtils::ToUpper(m_territory);
+ }
+}
diff --git a/xbmc/utils/Locale.h b/xbmc/utils/Locale.h
new file mode 100644
index 0000000000000..b49cfaa6b115b
--- /dev/null
+++ b/xbmc/utils/Locale.h
@@ -0,0 +1,146 @@
+#pragma once
+/*
+ * Copyright (C) 2015 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * .
+ *
+ */
+
+#include
+
+/*!
+ \brief Class representing a full locale of the form [language[_territory][.codeset][@modifier]].
+ */
+class CLocale
+{
+public:
+ CLocale();
+ CLocale(const std::string& language);
+ CLocale(const std::string& language, const std::string& territory);
+ CLocale(const std::string& language, const std::string& territory, const std::string& codeset);
+ CLocale(const std::string& language, const std::string& territory, const std::string& codeset, const std::string& modifier);
+ ~CLocale();
+
+ /*!
+ \brief Empty (and invalid) CLocale instance.
+ */
+ static const CLocale Empty;
+
+ /*!
+ \brief Parses the given string representation and turns it into a locale.
+
+ \param locale String representation of a locale
+ */
+ static CLocale FromString(const std::string& locale);
+
+ bool operator==(const CLocale& other) const;
+ inline bool operator!=(const CLocale& other) const { return !(*this == other); }
+
+ /*!
+ \brief Whether the locale is valid or not.
+
+ \details A locale is considered valid if at least the language code is set.
+ */
+ bool IsValid() const { return m_valid; }
+
+ /*!
+ \brief Returns the (lower-case) ISO 639-1 language code of the locale.
+ */
+ const std::string& GetLanguageCode() const { return m_language; }
+ /*!
+ \brief Returns the (upper-case) ISO 3166-1 Alpha-2 territory code of the locale.
+ */
+ const std::string& GetTerritoryCode() const { return m_territory; }
+ /*!
+ \brief Returns the codeset of the locale.
+ */
+ const std::string& GetCodeset() const { return m_codeset; }
+ /*!
+ \brief Returns the modifier of the locale.
+ */
+ const std::string& GetModifier() const { return m_modifier; }
+
+ /*!
+ \brief Returns the full string representation of the locale.
+
+ \details The format of the string representation is
+ [language[_territory][.codeset][@modifier]] where the language is
+ represented as a (lower-case) two character ISO 639-1 code and the territory
+ is represented as a (upper-case) two character ISO 3166-1 Alpha-2 code.
+ */
+ std::string ToString() const;
+ /*!
+ \brief Returns the full string representation of the locale in lowercase.
+
+ \details The format of the string representation is
+ [language[_territory][.codeset][@modifier]] where the language is
+ represented as a two character ISO 639-1 code and the territory is
+ represented as a two character ISO 3166-1 Alpha-2 code.
+ */
+ std::string ToStringLC() const;
+ /*!
+ \brief Returns the short string representation of the locale.
+
+ \details The format of the short string representation is
+ [language[_territory] where the language is represented as a (lower-case)
+ two character ISO 639-1 code and the territory is represented as a
+ (upper-case) two character ISO 3166-1 Alpha-2 code.
+ */
+ std::string ToShortString() const;
+ /*!
+ \brief Returns the short string representation of the locale in lowercase.
+
+ \details The format of the short string representation is
+ [language[_territory] where the language is represented as a two character
+ ISO 639-1 code and the territory is represented as a two character
+ ISO 3166-1 Alpha-2 code.
+ */
+ std::string ToShortStringLC() const;
+
+ /*!
+ \brief Checks if the given string representation of a locale exactly matches
+ the locale.
+
+ \param locale String representation of a locale
+ \return True if the string representation matches the locale, false otherwise.
+ */
+ bool Equals(const std::string& locale) const;
+
+ /*!
+ \brief Checks if the given string representation of a locale partly matches
+ the locale.
+
+ \details Partial matching means that every available locale part needs to
+ match the same locale part of the other locale if present.
+
+ \param locale String representation of a locale
+ \return True if the string representation matches the locale, false otherwise.
+ */
+ bool Matches(const std::string& locale) const;
+
+private:
+ static bool CheckValidity(const std::string& language, const std::string& territory, const std::string& codeset, const std::string& modifier);
+ static bool ParseLocale(const std::string &locale, std::string &language, std::string &territory, std::string &codeset, std::string &modifier);
+
+ void Initialize();
+
+ bool m_valid;
+ std::string m_language;
+ std::string m_territory;
+ std::string m_codeset;
+ std::string m_modifier;
+};
+
diff --git a/xbmc/utils/Makefile.in b/xbmc/utils/Makefile.in
index 53e72084afb1d..abe863f8aeab4 100644
--- a/xbmc/utils/Makefile.in
+++ b/xbmc/utils/Makefile.in
@@ -39,6 +39,7 @@ SRCS += JSONVariantWriter.cpp
SRCS += LabelFormatter.cpp
SRCS += LangCodeExpander.cpp
SRCS += LegacyPathTranslation.cpp
+SRCS += Locale.cpp
SRCS += log.cpp
SRCS += md5.cpp
SRCS += Mime.cpp
diff --git a/xbmc/utils/test/Makefile b/xbmc/utils/test/Makefile
index aa84d3e386aa0..282f6eb88cf17 100644
--- a/xbmc/utils/test/Makefile
+++ b/xbmc/utils/test/Makefile
@@ -28,6 +28,7 @@ SRCS= \
TestJSONVariantWriter.cpp \
TestLabelFormatter.cpp \
TestLangCodeExpander.cpp \
+ TestLocale.cpp \
Testlog.cpp \
TestMathUtils.cpp \
Testmd5.cpp \
diff --git a/xbmc/utils/test/TestLocale.cpp b/xbmc/utils/test/TestLocale.cpp
new file mode 100644
index 0000000000000..e54477b6d588b
--- /dev/null
+++ b/xbmc/utils/test/TestLocale.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2015 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * .
+ *
+ */
+
+#include
+
+#include "utils/Locale.h"
+#include "utils/StringUtils.h"
+
+static const std::string TerritorySeparator = "_";
+static const std::string CodesetSeparator = ".";
+static const std::string ModifierSeparator = "@";
+
+static const std::string LanguageCodeEnglish = "en";
+static const std::string TerritoryCodeBritain = "GB";
+static const std::string CodesetUtf8 = "UTF-8";
+static const std::string ModifierLatin = "latin";
+
+TEST(TestLocale, DefaultLocale)
+{
+ CLocale locale;
+ ASSERT_FALSE(locale.IsValid());
+ ASSERT_STREQ("", locale.GetLanguageCode().c_str());
+ ASSERT_STREQ("", locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ("", locale.GetCodeset().c_str());
+ ASSERT_STREQ("", locale.GetModifier().c_str());
+ ASSERT_STREQ("", locale.ToString().c_str());
+}
+
+TEST(TestLocale, LanguageLocale)
+{
+ CLocale locale(LanguageCodeEnglish);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.GetLanguageCode().c_str());
+ ASSERT_STREQ("", locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ("", locale.GetCodeset().c_str());
+ ASSERT_STREQ("", locale.GetModifier().c_str());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.ToString().c_str());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.ToStringLC().c_str());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.ToShortString().c_str());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.ToShortStringLC().c_str());
+}
+
+TEST(TestLocale, LanguageTerritoryLocale)
+{
+ const std::string strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain;
+ std::string strLocaleLC = strLocale;
+ StringUtils::ToLower(strLocaleLC);
+
+ CLocale locale(LanguageCodeEnglish, TerritoryCodeBritain);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.GetLanguageCode().c_str());
+ ASSERT_STREQ(TerritoryCodeBritain.c_str(), locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ("", locale.GetCodeset().c_str());
+ ASSERT_STREQ("", locale.GetModifier().c_str());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+ ASSERT_STREQ(strLocaleLC.c_str(), locale.ToStringLC().c_str());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToShortString().c_str());
+ ASSERT_STREQ(strLocaleLC.c_str(), locale.ToShortStringLC().c_str());
+}
+
+TEST(TestLocale, LanguageCodesetLocale)
+{
+ const std::string strLocale = LanguageCodeEnglish + CodesetSeparator + CodesetUtf8;
+ std::string strLocaleLC = strLocale;
+ StringUtils::ToLower(strLocaleLC);
+
+ CLocale locale(LanguageCodeEnglish, "", CodesetUtf8);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.GetLanguageCode().c_str());
+ ASSERT_STREQ("", locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ(CodesetUtf8.c_str(), locale.GetCodeset().c_str());
+ ASSERT_STREQ("", locale.GetModifier().c_str());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+ ASSERT_STREQ(strLocaleLC.c_str(), locale.ToStringLC().c_str());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.ToShortString().c_str());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.ToShortStringLC().c_str());
+}
+
+TEST(TestLocale, LanguageModifierLocale)
+{
+ const std::string strLocale = LanguageCodeEnglish + ModifierSeparator + ModifierLatin;
+ std::string strLocaleLC = strLocale;
+ StringUtils::ToLower(strLocaleLC);
+
+ CLocale locale(LanguageCodeEnglish, "", "", ModifierLatin);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.GetLanguageCode().c_str());
+ ASSERT_STREQ("", locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ("", locale.GetCodeset().c_str());
+ ASSERT_STREQ(ModifierLatin.c_str(), locale.GetModifier().c_str());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+ ASSERT_STREQ(strLocaleLC.c_str(), locale.ToStringLC().c_str());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.ToShortString().c_str());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.ToShortStringLC().c_str());
+}
+
+TEST(TestLocale, LanguageTerritoryCodesetLocale)
+{
+ const std::string strLocaleShort = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain;
+ std::string strLocaleShortLC = strLocaleShort;
+ StringUtils::ToLower(strLocaleShortLC);
+ const std::string strLocale = strLocaleShort + CodesetSeparator + CodesetUtf8;
+ std::string strLocaleLC = strLocale;
+ StringUtils::ToLower(strLocaleLC);
+
+ CLocale locale(LanguageCodeEnglish, TerritoryCodeBritain, CodesetUtf8);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.GetLanguageCode().c_str());
+ ASSERT_STREQ(TerritoryCodeBritain.c_str(), locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ(CodesetUtf8.c_str(), locale.GetCodeset().c_str());
+ ASSERT_STREQ("", locale.GetModifier().c_str());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+ ASSERT_STREQ(strLocaleLC.c_str(), locale.ToStringLC().c_str());
+ ASSERT_STREQ(strLocaleShort.c_str(), locale.ToShortString().c_str());
+ ASSERT_STREQ(strLocaleShortLC.c_str(), locale.ToShortStringLC().c_str());
+}
+
+TEST(TestLocale, LanguageTerritoryModifierLocale)
+{
+ const std::string strLocaleShort = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain;
+ std::string strLocaleShortLC = strLocaleShort;
+ StringUtils::ToLower(strLocaleShortLC);
+ const std::string strLocale = strLocaleShort + ModifierSeparator + ModifierLatin;
+ std::string strLocaleLC = strLocale;
+ StringUtils::ToLower(strLocaleLC);
+
+ CLocale locale(LanguageCodeEnglish, TerritoryCodeBritain, "", ModifierLatin);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.GetLanguageCode().c_str());
+ ASSERT_STREQ(TerritoryCodeBritain.c_str(), locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ("", locale.GetCodeset().c_str());
+ ASSERT_STREQ(ModifierLatin.c_str(), locale.GetModifier().c_str());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+ ASSERT_STREQ(strLocaleLC.c_str(), locale.ToStringLC().c_str());
+ ASSERT_STREQ(strLocaleShort.c_str(), locale.ToShortString().c_str());
+ ASSERT_STREQ(strLocaleShortLC.c_str(), locale.ToShortStringLC().c_str());
+}
+
+TEST(TestLocale, LanguageTerritoryCodesetModifierLocale)
+{
+ const std::string strLocaleShort = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain;
+ std::string strLocaleShortLC = strLocaleShort;
+ StringUtils::ToLower(strLocaleShortLC);
+ const std::string strLocale = strLocaleShort + CodesetSeparator + CodesetUtf8 + ModifierSeparator + ModifierLatin;
+ std::string strLocaleLC = strLocale;
+ StringUtils::ToLower(strLocaleLC);
+
+ CLocale locale(LanguageCodeEnglish, TerritoryCodeBritain, CodesetUtf8, ModifierLatin);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.GetLanguageCode().c_str());
+ ASSERT_STREQ(TerritoryCodeBritain.c_str(), locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ(CodesetUtf8.c_str(), locale.GetCodeset().c_str());
+ ASSERT_STREQ(ModifierLatin.c_str(), locale.GetModifier().c_str());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+ ASSERT_STREQ(strLocaleLC.c_str(), locale.ToStringLC().c_str());
+ ASSERT_STREQ(strLocaleShort.c_str(), locale.ToShortString().c_str());
+ ASSERT_STREQ(strLocaleShortLC.c_str(), locale.ToShortStringLC().c_str());
+}
+
+TEST(TestLocale, FullStringLocale)
+{
+ const std::string strLocaleShort = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain;
+ std::string strLocaleShortLC = strLocaleShort;
+ StringUtils::ToLower(strLocaleShortLC);
+ const std::string strLocale = strLocaleShort + CodesetSeparator + CodesetUtf8 + ModifierSeparator + ModifierLatin;
+ std::string strLocaleLC = strLocale;
+ StringUtils::ToLower(strLocaleLC);
+
+ CLocale locale(strLocale);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(LanguageCodeEnglish.c_str(), locale.GetLanguageCode().c_str());
+ ASSERT_STREQ(TerritoryCodeBritain.c_str(), locale.GetTerritoryCode().c_str());
+ ASSERT_STREQ(CodesetUtf8.c_str(), locale.GetCodeset().c_str());
+ ASSERT_STREQ(ModifierLatin.c_str(), locale.GetModifier().c_str());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+ ASSERT_STREQ(strLocaleLC.c_str(), locale.ToStringLC().c_str());
+ ASSERT_STREQ(strLocaleShort.c_str(), locale.ToShortString().c_str());
+ ASSERT_STREQ(strLocaleShortLC.c_str(), locale.ToShortStringLC().c_str());
+}
+
+TEST(TestLocale, FromString)
+{
+ std::string strLocale = "";
+ CLocale locale = CLocale::FromString(strLocale);
+ ASSERT_FALSE(locale.IsValid());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+
+ strLocale = LanguageCodeEnglish;
+ locale = CLocale::FromString(strLocale);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+
+ strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain;
+ locale = CLocale::FromString(strLocale);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+
+ strLocale = LanguageCodeEnglish + CodesetSeparator + CodesetUtf8;
+ locale = CLocale::FromString(strLocale);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+
+ strLocale = LanguageCodeEnglish + ModifierSeparator + ModifierLatin;
+ locale = CLocale::FromString(strLocale);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+
+ strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain + CodesetSeparator + CodesetUtf8;
+ locale = CLocale::FromString(strLocale);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+
+ strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain + ModifierSeparator + ModifierLatin;
+ locale = CLocale::FromString(strLocale);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+
+ strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain + CodesetSeparator + CodesetUtf8 + ModifierSeparator + ModifierLatin;
+ locale = CLocale::FromString(strLocale);
+ ASSERT_TRUE(locale.IsValid());
+ ASSERT_STREQ(strLocale.c_str(), locale.ToString().c_str());
+}
+
+TEST(TestLocale, EmptyLocale)
+{
+ ASSERT_FALSE(CLocale::Empty.IsValid());
+ ASSERT_STREQ("", CLocale::Empty.GetLanguageCode().c_str());
+ ASSERT_STREQ("", CLocale::Empty.GetTerritoryCode().c_str());
+ ASSERT_STREQ("", CLocale::Empty.GetCodeset().c_str());
+ ASSERT_STREQ("", CLocale::Empty.GetModifier().c_str());
+ ASSERT_STREQ("", CLocale::Empty.ToString().c_str());
+}
+
+TEST(TestLocale, Equals)
+{
+ std::string strLocale = "";
+ CLocale locale;
+ ASSERT_TRUE(locale.Equals(strLocale));
+
+ locale = CLocale(LanguageCodeEnglish);
+ strLocale = LanguageCodeEnglish;
+ ASSERT_TRUE(locale.Equals(strLocale));
+
+ locale = CLocale(LanguageCodeEnglish, TerritoryCodeBritain);
+ strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain;
+ ASSERT_TRUE(locale.Equals(strLocale));
+
+ locale = CLocale(LanguageCodeEnglish, "", CodesetUtf8);
+ strLocale = LanguageCodeEnglish + CodesetSeparator + CodesetUtf8;
+ ASSERT_TRUE(locale.Equals(strLocale));
+
+ locale = CLocale(LanguageCodeEnglish, "", "", ModifierLatin);
+ strLocale = LanguageCodeEnglish + ModifierSeparator + ModifierLatin;
+ ASSERT_TRUE(locale.Equals(strLocale));
+
+ locale = CLocale(LanguageCodeEnglish, TerritoryCodeBritain, CodesetUtf8);
+ strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain + CodesetSeparator + CodesetUtf8;
+ ASSERT_TRUE(locale.Equals(strLocale));
+
+ locale = CLocale(LanguageCodeEnglish, TerritoryCodeBritain, "", ModifierLatin);
+ strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain + ModifierSeparator + ModifierLatin;
+ ASSERT_TRUE(locale.Equals(strLocale));
+
+ locale = CLocale(LanguageCodeEnglish, TerritoryCodeBritain, CodesetUtf8, ModifierLatin);
+ strLocale = LanguageCodeEnglish + TerritorySeparator + TerritoryCodeBritain + CodesetSeparator + CodesetUtf8 + ModifierSeparator + ModifierLatin;
+ ASSERT_TRUE(locale.Equals(strLocale));
+}