#include "l10n.hpp" #include #include #include namespace { struct L10nContext { std::shared_ptr mData; }; void getICUArgs(std::string_view messageId, const sol::table& table, std::vector& argNames, std::vector& args) { for (auto& [key, value] : table) { // Argument values if (value.is()) args.push_back(icu::Formattable(LuaUtil::cast(value).c_str())); // Note: While we pass all numbers as doubles, they still seem to be handled appropriately. // Numbers can be forced to be integers using the argType number and argStyle integer // E.g. {var, number, integer} else if (value.is()) args.push_back(icu::Formattable(LuaUtil::cast(value))); else { Log(Debug::Error) << "Unrecognized argument type for key \"" << LuaUtil::cast(key) << "\" when formatting message \"" << messageId << "\""; } // Argument names const auto str = LuaUtil::cast(key); argNames.push_back(icu::UnicodeString::fromUTF8(icu::StringPiece(str.data(), str.size()))); } } } namespace sol { template <> struct is_automagical : std::false_type { }; } namespace LuaUtil { sol::function initL10nLoader(lua_State* L, l10n::Manager* manager) { sol::state_view lua(L); sol::usertype ctxDef = lua.new_usertype("L10nContext"); ctxDef[sol::meta_function::call] = [](const L10nContext& ctx, std::string_view key, sol::optional args) { std::vector argValues; std::vector argNames; if (args) getICUArgs(key, *args, argNames, argValues); return ctx.mData->formatMessage(key, argNames, argValues); }; return sol::make_object( lua, [manager](const std::string& contextName, sol::optional fallbackLocale) { if (fallbackLocale) return L10nContext{ manager->getContext(contextName, *fallbackLocale) }; else return L10nContext{ manager->getContext(contextName) }; }); } }