diff --git a/src/Lang.cpp b/src/Lang.cpp index eebd1ea68c3..a3076f9b3cc 100644 --- a/src/Lang.cpp +++ b/src/Lang.cpp @@ -104,23 +104,27 @@ namespace Lang { return true; } - const std::string &Resource::Get(const std::string &token) const + static const std::string _empty = ""; + const std::string &Resource::Get(std::string_view token) const { std::map::const_iterator i = m_strings.find(token); if (i == m_strings.end()) { - static const std::string empty; - return empty; + return _empty; } return (*i).second; } - std::vector Resource::GetAvailableLanguages(const std::string &resourceName) + std::vector Resource::GetAvailableLanguages(std::string_view resourceName) { std::vector languages; - for (FileSystem::FileEnumerator files(FileSystem::gameDataFiles, "lang/" + resourceName); !files.Finished(); files.Next()) { + std::string searchPath = "lang/"; + searchPath.append(resourceName); + + for (FileSystem::FileEnumerator files(FileSystem::gameDataFiles, searchPath); !files.Finished(); files.Next()) { assert(files.Current().IsFile()); const std::string &path = files.Current().GetPath(); + if (ends_with_ci(path, ".json")) { const std::string name = files.Current().GetName(); languages.push_back(name.substr(0, name.size() - 5)); @@ -175,21 +179,21 @@ namespace Lang { for (token_map::iterator i = s_token_map.begin(); i != s_token_map.end(); ++i) { const std::string &token = i->first; - std::string text = res.Get(token); + std::string_view text = res.Get(token); if (text.empty()) { - Log::Info("{}/{}: token '{}' not found\n", res.GetName().c_str(), res.GetLangCode().c_str(), token.c_str()); + Log::Info("{}/{}: token '{}' not found\n", res.GetName(), res.GetLangCode(), token); text = token; } if (text.size() > size_t(STRING_RECORD_SIZE)) { - Log::Info("{}/{}: text for token '{}' is too long and will be truncated\n", res.GetName().c_str(), res.GetLangCode().c_str(), token.c_str()); - text.resize(STRING_RECORD_SIZE); + Log::Info("{}/{}: text for token '{}' is too long and will be truncated\n", res.GetName(), res.GetLangCode(), token); + text = text.substr(0, STRING_RECORD_SIZE); } // const_cast so we can set the string, see above char *record = const_cast(i->second); - copy_string(record, text.c_str(), text.size(), STRING_RECORD_SIZE); + copy_string(record, text.data(), text.size(), STRING_RECORD_SIZE); } s_coreResource = res; @@ -202,9 +206,9 @@ namespace Lang { static std::map m_cachedResources; - Resource GetResource(const std::string &name, const std::string &langCode) + Resource &GetResource(std::string_view name, std::string_view langCode) { - auto key = name + ":" + langCode; + std::string key = fmt::format("{}:{}", name, langCode); auto i = m_cachedResources.find(key); if (i != m_cachedResources.end()) @@ -214,19 +218,18 @@ namespace Lang { bool loaded = res.Load(); if (!loaded) { if (langCode != "en") { - Log::Warning("couldn't load language resource {}/{}, trying {}/en\n", name.c_str(), langCode.c_str(), name.c_str()); + Log::Warning("couldn't load language resource {}/{}, trying {}/en\n", name, langCode, name); res = Lang::Resource(name, "en"); loaded = res.Load(); - key = name + ":" + "en"; + key.replace(key.size() - langCode.size(), langCode.size(), "en"); } if (!loaded) - Log::Warning("couldn't load language resource {}/en\n", name.c_str()); + Log::Warning("couldn't load language resource {}/en\n", name); } - if (loaded) - m_cachedResources.insert(std::make_pair(key, res)); + m_cachedResources.insert(std::make_pair(key, std::move(res))); - return res; + return m_cachedResources.at(key); } } // namespace Lang diff --git a/src/Lang.h b/src/Lang.h index a054ea2006c..ab7fd920f08 100644 --- a/src/Lang.h +++ b/src/Lang.h @@ -8,30 +8,33 @@ #include #include #include +#include #include namespace Lang { class Resource { public: - Resource(const std::string &name, const std::string &langCode) : + using StringMap = std::map>; + + Resource(std::string_view name, std::string_view langCode) : m_name(name), m_langCode(langCode), m_loaded(false) {} - const std::string &GetName() const { return m_name; } - const std::string &GetLangCode() const { return m_langCode; } + std::string_view GetName() const { return m_name; } + std::string_view GetLangCode() const { return m_langCode; } bool Load(); Uint32 GetNumStrings() const { return static_cast(m_strings.size()); } - const std::string &Get(const std::string &token) const; + const std::string &Get(std::string_view token) const; - static std::vector GetAvailableLanguages(const std::string &resourceName); + static std::vector GetAvailableLanguages(std::string_view resourceName); - IterationProxy> GetStrings() { return MakeIterationProxy(m_strings); } - const IterationProxy> GetStrings() const { return MakeIterationProxy(m_strings); } + IterationProxy GetStrings() { return MakeIterationProxy(m_strings); } + const IterationProxy GetStrings() const { return MakeIterationProxy(m_strings); } private: std::string m_name; @@ -39,7 +42,7 @@ namespace Lang { bool m_loaded; - std::map m_strings; + StringMap m_strings; }; // declare all strings @@ -50,7 +53,7 @@ namespace Lang { void MakeCore(Resource &res); const Resource &GetCore(); - Resource GetResource(const std::string &name, const std::string &langCode); + Resource &GetResource(std::string_view name, std::string_view langCode); } // namespace Lang diff --git a/src/LangStrings.inc.h b/src/LangStrings.inc.h index cba03935e9b..8c91e7a4a4d 100644 --- a/src/LangStrings.inc.h +++ b/src/LangStrings.inc.h @@ -1,6 +1,10 @@ // Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt +#ifndef DECLARE_STRING +#define DECLARE_STRING(_) +#endif + DECLARE_STRING(LANG_NAME) DECLARE_STRING(SUGGESTED_RESPONSES) DECLARE_STRING(SHIP) diff --git a/src/Pi.cpp b/src/Pi.cpp index ab1b755acc5..71ef17dc611 100644 --- a/src/Pi.cpp +++ b/src/Pi.cpp @@ -342,7 +342,7 @@ void Pi::App::Startup() ModManager::Init(); - Lang::Resource res(Lang::GetResource("core", config->String("Lang"))); + Lang::Resource &res(Lang::GetResource("core", config->String("Lang"))); Lang::MakeCore(res); // FIXME: move these out of the Pi namespace diff --git a/src/lua/LuaLang.cpp b/src/lua/LuaLang.cpp index 8780a4d7472..01c4d64f5fa 100644 --- a/src/lua/LuaLang.cpp +++ b/src/lua/LuaLang.cpp @@ -66,7 +66,7 @@ static int l_lang_get_resource(lua_State *l) lua_pop(l, 1); lua_newtable(l); - Lang::Resource res = Lang::GetResource(resourceName, langCode); + Lang::Resource &res = Lang::GetResource(resourceName, langCode); if (res.Load()) { for (auto i : res.GetStrings()) { const std::string token(i.first);