Support links to GMST in l10n files

depth-refraction
Petr Mikheev 2 years ago
parent efebb8efd8
commit 58fdd687a8

@ -777,6 +777,18 @@ void OMW::Engine::prepareEngine()
mEnvironment.setWorldModel(mWorld->getWorldModel());
mEnvironment.setWorldScene(mWorld->getWorldScene());
const MWWorld::Store<ESM::GameSetting>* gmst = &mWorld->getStore().get<ESM::GameSetting>();
mL10nManager->setGmstLoader([gmst](std::string_view gmstName) {
const ESM::GameSetting* res = gmst->search(gmstName);
if (res && res->mValue.getType() == ESM::VT_String)
return res->mValue.getString();
else
{
Log(Debug::Error) << "GMST " << gmstName << " not found";
return std::string("GMST:") + std::string(gmstName);
}
});
mWindowManager->setStore(mWorld->getStore());
mWindowManager->initUI();

@ -87,7 +87,7 @@ you_have_arrows: "Arrows count: {count}"
internal::CaptureStdout();
l10n::Manager l10nManager(mVFS.get());
l10nManager.setPreferredLocales({ "de", "en" });
EXPECT_THAT(internal::GetCapturedStdout(), "Preferred locales: de en\n");
EXPECT_THAT(internal::GetCapturedStdout(), "Preferred locales: gmst de en\n");
l["l10n"] = LuaUtil::initL10nLoader(l, &l10nManager);
@ -114,7 +114,7 @@ you_have_arrows: "Arrows count: {count}"
internal::CaptureStdout();
l10nManager.setPreferredLocales({ "en", "de" });
EXPECT_THAT(internal::GetCapturedStdout(),
"Preferred locales: en de\n"
"Preferred locales: gmst en de\n"
"Language file \"l10n/Test1/en.yaml\" is enabled\n"
"Language file \"l10n/Test1/de.yaml\" is enabled\n"
"Language file \"l10n/Test2/en.yaml\" is enabled\n");
@ -152,7 +152,7 @@ you_have_arrows: "Arrows count: {count}"
internal::CaptureStdout();
l10nManager.setPreferredLocales({ "en-GB-oed", "de" });
EXPECT_THAT(internal::GetCapturedStdout(),
"Preferred locales: en_GB_OED de\n"
"Preferred locales: gmst en_GB_OED de\n"
"Language file \"l10n/Test1/en.yaml\" is enabled\n"
"Language file \"l10n/Test1/de.yaml\" is enabled\n"
"Language file \"l10n/Test2/en.yaml\" is enabled\n");

@ -12,6 +12,7 @@ namespace l10n
void Manager::setPreferredLocales(const std::vector<std::string>& langs)
{
mPreferredLocales.clear();
mPreferredLocales.push_back(icu::Locale("gmst"));
std::set<std::string> langSet;
for (const auto& lang : langs)
{
@ -90,6 +91,7 @@ namespace l10n
throw std::runtime_error(std::string("Invalid l10n context name: ") + contextName);
icu::Locale fallbackLocale(fallbackLocaleName.c_str());
std::shared_ptr<MessageBundles> ctx = std::make_shared<MessageBundles>(mPreferredLocales, fallbackLocale);
ctx->setGmstLoader(mGmstLoader);
updateContext(contextName, *ctx);
mCache.emplace(key, ctx);
return ctx;

@ -24,6 +24,7 @@ namespace l10n
void dropCache() { mCache.clear(); }
void setPreferredLocales(const std::vector<std::string>& locales);
const std::vector<icu::Locale>& getPreferredLocales() const { return mPreferredLocales; }
void setGmstLoader(std::function<std::string(std::string_view)> fn) { mGmstLoader = std::move(fn); }
std::shared_ptr<const MessageBundles> getContext(
const std::string& contextName, const std::string& fallbackLocale = "en");
@ -35,6 +36,7 @@ namespace l10n
const VFS::Manager* mVFS;
std::vector<icu::Locale> mPreferredLocales;
std::map<std::pair<std::string, std::string>, std::shared_ptr<MessageBundles>> mCache;
std::function<std::string(std::string_view)> mGmstLoader;
};
}

@ -72,6 +72,7 @@ namespace l10n
{
YAML::Node data = YAML::Load(input);
std::string localeName = lang.getName();
const icu::Locale& langOrEn = localeName == "gmst" ? icu::Locale::getEnglish() : lang;
for (const auto& it : data)
{
const auto key = it.first.as<std::string>();
@ -79,7 +80,7 @@ namespace l10n
icu::UnicodeString pattern = icu::UnicodeString::fromUTF8(icu::StringPiece(value.data(), value.size()));
icu::ErrorCode status;
UParseError parseError;
icu::MessageFormat message(pattern, lang, parseError, status);
icu::MessageFormat message(pattern, langOrEn, parseError, status);
if (checkSuccess(status,
std::string("Failed to create message ") + key + " for locale " + lang.getName(), parseError))
{
@ -120,6 +121,20 @@ namespace l10n
return formatMessage(key, argNames, argValues);
}
static std::string loadGmst(
const std::function<std::string(std::string_view)> gmstLoader, const icu::MessageFormat* message)
{
icu::UnicodeString gmstNameUnicode;
std::string gmstName;
icu::ErrorCode success;
message->format(nullptr, nullptr, 0, gmstNameUnicode, success);
gmstNameUnicode.toUTF8String(gmstName);
if (gmstLoader)
return gmstLoader(gmstName);
else
return "GMST:" + gmstName;
}
std::string MessageBundles::formatMessage(std::string_view key, const std::vector<icu::UnicodeString>& argNames,
const std::vector<icu::Formattable>& args) const
{
@ -132,7 +147,11 @@ namespace l10n
{
message = findMessage(key, loc);
if (message)
{
if (loc == "gmst")
return loadGmst(mGmstLoader, message);
break;
}
}
// If no requested locales included the message, try the fallback locale
if (!message)

@ -1,6 +1,7 @@
#ifndef COMPONENTS_L10N_MESSAGEBUNDLES_H
#define COMPONENTS_L10N_MESSAGEBUNDLES_H
#include <functional>
#include <map>
#include <string_view>
#include <unordered_map>
@ -42,6 +43,7 @@ namespace l10n
void load(std::istream& input, const icu::Locale& lang, const std::string& path);
bool isLoaded(const icu::Locale& loc) const { return mBundles.find(loc.getName()) != mBundles.end(); }
const icu::Locale& getFallbackLocale() const { return mFallbackLocale; }
void setGmstLoader(std::function<std::string(std::string_view)> fn) { mGmstLoader = std::move(fn); }
private:
// icu::Locale isn't hashable (or comparable), so we use the string form instead, which is canonicalized
@ -49,6 +51,7 @@ namespace l10n
const icu::Locale mFallbackLocale;
std::vector<std::string> mPreferredLocaleStrings;
std::vector<icu::Locale> mPreferredLocales;
std::function<std::string(std::string_view)> mGmstLoader;
const icu::MessageFormat* findMessage(std::string_view key, const std::string& localeName) const;
};

Loading…
Cancel
Save