Files
EVEngine/test/dialogue_localization.cpp
T

88 lines
3.8 KiB
C++

#include "dialogue/ConversationLocalization.h"
#include "dialogue/DialogueFlow.h"
#include "i18n/I18n.h"
#include "zeroerr/assert.h"
#include "zeroerr/unittest.h"
using namespace eve::dialogue;
TEST_CASE("dialogueLocalization.roundtripMissingAndVoiceManifest") {
ConversationAsset asset;
asset.id = "intro";
asset.entry = "welcome";
ConversationAsset::Node line;
line.id = "welcome";
line.kind = ConversationAsset::Node::Kind::Line;
line.text = "Welcome";
line.speaker = "Guide";
line.i18nKey = "intro.welcome";
line.voice = "voice/default";
line.next = "end";
asset.nodes = {line, {"end", ConversationAsset::Node::Kind::End}};
ConversationLocalizationCatalog catalog;
std::vector<ConversationDiagnostic> diagnostics;
const std::string csv =
"i18n_key,locale,translation,voice,status,duration\r\n"
"\"intro.welcome\",\"zh\",\"欢迎你,旅行者\",\"voice/zh/001\",\"recorded\",\"1.25\"\r\n";
CHECK(catalog.importCsv(csv, "", diagnostics) == 1);
CHECK(catalog.resolveText("intro.welcome", "zh-CN", "Welcome") == "欢迎你,旅行者");
CHECK(catalog.resolveVoice("intro.welcome", "zh-CN", "default") == "voice/zh/001");
CHECK(catalog.resolveStatus("intro.welcome", "zh-CN") == "recorded");
CHECK(catalog.resolveDuration("intro.welcome", "zh-CN") == 1.25);
CHECK(catalog.exportMissingCsv({asset}, "zh-CN").find("intro.welcome") == std::string::npos);
CHECK(catalog.exportMissingCsv({asset}, "ja").find("intro.welcome") != std::string::npos);
const std::string manifest = catalog.exportVoiceRecordingCsv({asset}, "zh-CN");
CHECK(manifest.find("recorded") != std::string::npos);
CHECK(manifest.find("voice/zh/001") != std::string::npos);
}
TEST_CASE("dialogueLocalization.rejectsPartialDuration") {
ConversationLocalizationCatalog catalog;
std::vector<ConversationDiagnostic> diagnostics;
const std::string csv =
"i18n_key,locale,translation,duration\n"
"intro.invalid,en,Hello,1.25seconds\n";
CHECK(catalog.importCsv(csv, "", diagnostics) == 1);
CHECK(catalog.resolveDuration("intro.invalid", "en") == 0.0);
REQUIRE(diagnostics.size() == 1);
CHECK(diagnostics.front().message == "invalid duration was ignored");
}
TEST_CASE("dialogueLocalization.validatesExactRuntimeLocaleCoverage") {
auto* localization = eve::i18n::I18n::create();
auto* flow = DialogueFlow::create();
REQUIRE(localization != nullptr);
REQUIRE(flow != nullptr);
localization->clear();
flow->clear();
auto bundle = localization->replaceBundleFromJson(R"({
"schema":"eve.i18n.bundle","version":1,"defaultLocale":"en",
"locales":{
"en":{"intro":{"welcome":"Welcome"}},
"zh-CN":{"intro":{"welcome":"欢迎"}}
}
})");
REQUIRE(bundle.ok());
REQUIRE_EQ(flow->loadFromDnut("conversation intro version=1 entry=welcome\n"
"node welcome line speaker=guide i18n=intro.welcome next=end\n"
"node end end\nendconversation\n",
"localized.dnut"),
1);
auto validated = flow->validateLocalization(*localization, "zh-CN");
REQUIRE(validated.ok());
CHECK_EQ(validated.value(), 1);
auto missingLocale = flow->validateLocalization(*localization, "fr");
CHECK(!missingLocale.ok());
REQUIRE_EQ(flow->loadFromDnut("conversation broken version=1 entry=line\n"
"node line line speaker=guide i18n=intro.missing next=end\n"
"node end end\nendconversation\n",
"missing.dnut"),
1);
auto missingKey = flow->validateLocalization(*localization, "en");
CHECK(!missingKey.ok());
flow->clear();
localization->clear();
}