Compare language codes in MessageContent::Choose()

If there is no exact match, compare language codes so that a more
generic match is preferred over just returning the English content.

This means that if a locale code is given, Choose() will also look for
the locale's language code (but will not match another locale with the
same language code), and if a language code is given, Choose() will also
look for a locale with that language code.
This commit is contained in:
Oliver Hamlet
2021-03-28 22:31:14 +01:00
parent 12ed2de739
commit cd978bb215
3 changed files with 151 additions and 18 deletions
+32 -5
View File
@@ -24,6 +24,8 @@
#include "loot/metadata/message_content.h"
#include <optional>
#include <boost/algorithm/string.hpp>
namespace loot {
@@ -33,8 +35,7 @@ MessageContent::MessageContent() : language_(MessageContent::defaultLanguage) {}
MessageContent::MessageContent(const std::string& text,
const std::string& language) :
text_(text),
language_(language) {}
text_(text), language_(language) {}
std::string MessageContent::GetText() const { return text_; }
@@ -63,13 +64,39 @@ MessageContent MessageContent::Choose(const std::vector<MessageContent> content,
else if (content.size() == 1)
return content[0];
else {
auto languageCode = language.substr(0, language.find("_"));
auto isCountryCodeGiven = languageCode.length() != language.length();
std::optional<MessageContent> matchedLanguage;
MessageContent english;
for (const auto& mc : content) {
if (mc.GetLanguage() == language) {
auto contentLanguage = mc.GetLanguage();
if (contentLanguage == language) {
return mc;
} else if (mc.GetLanguage() == MessageContent::defaultLanguage)
english = mc;
} else if (!matchedLanguage.has_value()) {
if (isCountryCodeGiven && contentLanguage == languageCode) {
matchedLanguage = mc;
} else if (!isCountryCodeGiven) {
auto underscorePos = contentLanguage.find("_");
if (underscorePos != std::string::npos) {
auto contentLanguageCode = contentLanguage.substr(0, underscorePos);
if (contentLanguageCode == language) {
matchedLanguage = mc;
}
}
}
if (contentLanguage == MessageContent::defaultLanguage) {
english = mc;
}
}
}
if (matchedLanguage.has_value()) {
return matchedLanguage.value();
}
return english;
}
}
@@ -25,11 +25,10 @@ along with LOOT. If not, see
#ifndef LOOT_TESTS_API_INTERNALS_METADATA_MESSAGE_CONTENT_TEST
#define LOOT_TESTS_API_INTERNALS_METADATA_MESSAGE_CONTENT_TEST
#include "loot/metadata/message_content.h"
#include <gtest/gtest.h>
#include "api/metadata/yaml/message_content.h"
#include "loot/metadata/message_content.h"
namespace loot {
namespace test {
@@ -240,6 +239,98 @@ TEST(
EXPECT_TRUE(content1 >= content2);
}
TEST(MessageContent,
chooseShouldReturnAnEmptyEnglishMessageIfTheVectorIsEmpty) {
auto content = MessageContent::Choose(std::vector<MessageContent>(), "fr");
EXPECT_EQ("en", content.GetLanguage());
EXPECT_EQ("", content.GetText());
}
TEST(MessageContent, chooseShouldReturnTheOnlyElementOfASingleElementVector) {
MessageContent content("test", "de");
auto chosen = MessageContent::Choose({MessageContent("test", "de")}, "fr");
EXPECT_EQ(content, chosen);
}
TEST(
MessageContent,
chooseShouldReturnAnEmptyEnglishMessageIfTheVectorHasNoEnglishOrMatchingLanguageContentWithTwoOrMoreElements) {
auto contents = {MessageContent("test1", "de"),
MessageContent("test2", "fr")};
auto content = MessageContent::Choose(contents, "pt");
EXPECT_EQ("en", content.GetLanguage());
EXPECT_EQ("", content.GetText());
}
TEST(MessageContent,
chooseShouldReturnElementWithExactlyMatchingLocaleCodeIfPresent) {
auto contents = {MessageContent("test1", "en"),
MessageContent("test2", "de"),
MessageContent("test3", "pt"),
MessageContent("test4", "pt_PT"),
MessageContent("test5", "pt_BR")};
auto content = MessageContent::Choose(contents, "pt_BR");
EXPECT_EQ("pt_BR", content.GetLanguage());
EXPECT_EQ("test5", content.GetText());
}
TEST(
MessageContent,
chooseShouldReturnElementWithMatchingLanguageCodeIfExactlyMatchingLocaleCodeIsNotPresent) {
auto contents = {MessageContent("test1", "en"),
MessageContent("test2", "de"),
MessageContent("test3", "pt_PT"),
MessageContent("test4", "pt")};
auto content = MessageContent::Choose(contents, "pt_BR");
EXPECT_EQ("pt", content.GetLanguage());
EXPECT_EQ("test4", content.GetText());
}
TEST(
MessageContent,
chooseShouldReturnElementWithEnLanguageCodeIfNoMatchingLanguageCodeIsPresent) {
auto contents = {MessageContent("test1", "en"),
MessageContent("test2", "de"),
MessageContent("test3", "pt_PT")};
auto content = MessageContent::Choose(contents, "pt_BR");
EXPECT_EQ("en", content.GetLanguage());
EXPECT_EQ("test1", content.GetText());
}
TEST(
MessageContent,
chooseShouldReturnElementWithExactlyMatchingLanguageCodeIfLanguageCodeIsGiven) {
auto contents = {
MessageContent("test1", "en"),
MessageContent("test2", "de"),
MessageContent("test3", "pt_BR"),
MessageContent("test4", "pt"),
};
auto content = MessageContent::Choose(contents, "pt");
EXPECT_EQ("pt", content.GetLanguage());
EXPECT_EQ("test4", content.GetText());
}
TEST(
MessageContent,
chooseShouldReturnFirstElementWithMatchingLanguageCodeIfLanguageCodeIsGivenAndNoExactMatchIsPresent) {
auto contents = {MessageContent("test1", "en"),
MessageContent("test2", "de"),
MessageContent("test3", "pt_PT"),
MessageContent("test4", "pt_BR")};
auto content = MessageContent::Choose(contents, "pt");
EXPECT_EQ("pt_PT", content.GetLanguage());
EXPECT_EQ("test3", content.GetText());
}
TEST(MessageContent, emittingAsYamlShouldOutputDataCorrectly) {
MessageContent content("content", french);
YAML::Emitter emitter;