/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 * * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ #include "StringTable.h" #include "../core/IStream.hpp" #include "../core/Json.hpp" #include "../core/String.hpp" #include "../localisation/Language.h" #include "../localisation/LanguagePack.h" #include "../localisation/LocalisationService.h" #include "Object.h" #include static constexpr const uint8_t RCT2ToOpenRCT2LanguageId[] = { LANGUAGE_ENGLISH_UK, LANGUAGE_ENGLISH_US, LANGUAGE_FRENCH, LANGUAGE_GERMAN, LANGUAGE_SPANISH, LANGUAGE_ITALIAN, LANGUAGE_DUTCH, LANGUAGE_SWEDISH, LANGUAGE_JAPANESE, LANGUAGE_KOREAN, LANGUAGE_CHINESE_SIMPLIFIED, LANGUAGE_CHINESE_TRADITIONAL, LANGUAGE_UNDEFINED, LANGUAGE_PORTUGUESE_BR, }; static bool StringIsBlank(const utf8* str) { for (auto ch = str; *ch != '\0'; ch++) { if (!isblank(static_cast(*ch))) { return false; } } return true; } void StringTable::Read(IReadObjectContext* context, OpenRCT2::IStream* stream, ObjectStringID id) { try { RCT2LanguageId rct2LanguageId; while ((rct2LanguageId = static_cast(stream->ReadValue())) != RCT2LanguageId::End) { uint8_t languageId = (EnumValue(rct2LanguageId) <= EnumValue(RCT2LanguageId::Portuguese)) ? RCT2ToOpenRCT2LanguageId[EnumValue(rct2LanguageId)] : static_cast(LANGUAGE_UNDEFINED); std::string stringAsWin1252 = stream->ReadStdString(); auto stringAsUtf8 = rct2_to_utf8(stringAsWin1252, rct2LanguageId); if (!StringIsBlank(stringAsUtf8.data())) { stringAsUtf8 = String::Trim(stringAsUtf8); StringTableEntry entry{}; entry.Id = id; entry.LanguageId = languageId; entry.Text = stringAsUtf8; _strings.push_back(std::move(entry)); } } } catch (const std::exception&) { context->LogError(ObjectError::BadStringTable, "Bad string table."); throw; } Sort(); } ObjectStringID StringTable::ParseStringId(const std::string& s) { if (s == "name") return ObjectStringID::NAME; if (s == "description") return ObjectStringID::DESCRIPTION; if (s == "capacity") return ObjectStringID::CAPACITY; if (s == "vehicleName") return ObjectStringID::VEHICLE_NAME; return ObjectStringID::UNKNOWN; } void StringTable::ReadJson(json_t& root) { Guard::Assert(root.is_object(), "StringTable::ReadJson expects parameter root to be object"); // We trust the JSON type of root is object auto jsonStrings = root["strings"]; for (auto& [key, jsonLanguages] : jsonStrings.items()) { auto stringId = ParseStringId(key); if (stringId != ObjectStringID::UNKNOWN) { for (auto& [locale, jsonString] : jsonLanguages.items()) { auto langId = language_get_id_from_locale(locale.c_str()); if (langId != LANGUAGE_UNDEFINED) { auto string = Json::GetString(jsonString); SetString(stringId, langId, string); } } } } Sort(); } std::string StringTable::GetString(ObjectStringID id) const { for (auto& string : _strings) { if (string.Id == id) { return string.Text; } } return std::string(); } std::string StringTable::GetString(uint8_t language, ObjectStringID id) const { for (auto& string : _strings) { if (string.LanguageId == language && string.Id == id) { return string.Text; } } return std::string(); } void StringTable::SetString(ObjectStringID id, uint8_t language, const std::string& text) { StringTableEntry entry; entry.Id = id; entry.LanguageId = language; entry.Text = text; _strings.push_back(std::move(entry)); } void StringTable::Sort() { auto targetLanguage = LocalisationService_GetCurrentLanguage(); std::sort(_strings.begin(), _strings.end(), [targetLanguage](const StringTableEntry& a, const StringTableEntry& b) -> bool { if (a.Id == b.Id) { if (a.LanguageId == b.LanguageId) { return String::Compare(a.Text, b.Text, true) < 0; } if (a.LanguageId == targetLanguage) { return true; } if (b.LanguageId == targetLanguage) { return false; } if (a.LanguageId == LANGUAGE_ENGLISH_UK) { return true; } if (b.LanguageId == LANGUAGE_ENGLISH_UK) { return false; } return a.LanguageId < b.LanguageId; } return a.Id < b.Id; }); }