mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
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:
@@ -37,7 +37,7 @@ class MessageContent {
|
||||
public:
|
||||
/**
|
||||
* The code for the default language assumed for message content, which is
|
||||
* English.
|
||||
* "en" (English).
|
||||
*/
|
||||
LOOT_API static const std::string defaultLanguage;
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
/**
|
||||
* A less-than operator implemented with no semantics so that MessageContent
|
||||
* objects can be stored in sets.
|
||||
* @returns True if this MessageContent is less than the given
|
||||
* @returns True if this MessageContent is less than the given
|
||||
* MessageContent, false otherwise.
|
||||
*/
|
||||
LOOT_API bool operator<(const MessageContent& rhs) const;
|
||||
@@ -89,11 +89,26 @@ public:
|
||||
* @param content
|
||||
* The MessageContent objects to choose between.
|
||||
* @param language
|
||||
* The language code for the preferred language to select. If no
|
||||
* message in the preferred language is present, the English
|
||||
* MessageContent will be returned.
|
||||
* @return A MessageContent object. If the given vector is empty, a
|
||||
* default-constructed MessageContent is returned.
|
||||
* The locale or language code for the preferred language to select.
|
||||
* Locale codes are of the form <language code>_<country code>.
|
||||
* @return A MessageContent object.
|
||||
*
|
||||
* If the vector only contains a single element, that element is
|
||||
* returned.
|
||||
*
|
||||
* If content with a language that exactly matches the given locale
|
||||
* or language code is present, that content is returned.
|
||||
*
|
||||
* If a locale code is given and there is no exact match but content
|
||||
* for that locale's language is present, that content is returned.
|
||||
*
|
||||
* If a language code is given and there is no exact match but content
|
||||
* for a locale in that langauge is present, that content is returned.
|
||||
*
|
||||
* If no locale or language code matches are found and content in the
|
||||
* default language is present, that content is returned.
|
||||
*
|
||||
* Otherwise, a default-constructed MessageContent is returned.
|
||||
*/
|
||||
LOOT_API static MessageContent Choose(
|
||||
const std::vector<MessageContent> content,
|
||||
@@ -111,9 +126,9 @@ private:
|
||||
LOOT_API bool operator!=(const MessageContent& lhs, const MessageContent& rhs);
|
||||
|
||||
/**
|
||||
* Check if the first MessageContent object is greater than the second
|
||||
* Check if the first MessageContent object is greater than the second
|
||||
* MessageContent object.
|
||||
* @returns True if the second MessageContent object is less than the first
|
||||
* @returns True if the second MessageContent object is less than the first
|
||||
* MessageContent object, false otherwise.
|
||||
*/
|
||||
LOOT_API bool operator>(const MessageContent& lhs, const MessageContent& rhs);
|
||||
@@ -121,13 +136,13 @@ LOOT_API bool operator>(const MessageContent& lhs, const MessageContent& rhs);
|
||||
/**
|
||||
* Check if the first MessageContent object is less than or equal to the second
|
||||
* MessageContent object.
|
||||
* @returns True if the first MessageContent object is not greater than the
|
||||
* @returns True if the first MessageContent object is not greater than the
|
||||
* second MessageContent object, false otherwise.
|
||||
*/
|
||||
LOOT_API bool operator<=(const MessageContent& lhs, const MessageContent& rhs);
|
||||
|
||||
/**
|
||||
* Check if the first MessageContent object is greater than or equal to the
|
||||
* Check if the first MessageContent object is greater than or equal to the
|
||||
* second MessageContent object.
|
||||
* @returns True if the first MessageContent object is not less than the second
|
||||
* MessageContent object, false otherwise.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user