From 2215fef883b33aadc320e34f1e48a7fdb3bf7759 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 19 Nov 2019 02:30:27 +0100 Subject: [PATCH] ZoneLoading: Dump localized strings as str files --- .../Dumping/Localize/StringFileDumper.cpp | 63 +++++++++++++ .../Dumping/Localize/StringFileDumper.h | 29 ++++++ .../AssetDumpers/AssetDumperLocalizeEntry.cpp | 89 ++++++++++++++++++- .../AssetDumpers/AssetDumperLocalizeEntry.h | 2 + src/ZoneLoading/Game/T6/ZoneDumperT6.cpp | 3 +- 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 src/ZoneLoading/Dumping/Localize/StringFileDumper.cpp create mode 100644 src/ZoneLoading/Dumping/Localize/StringFileDumper.h diff --git a/src/ZoneLoading/Dumping/Localize/StringFileDumper.cpp b/src/ZoneLoading/Dumping/Localize/StringFileDumper.cpp new file mode 100644 index 00000000..682f9118 --- /dev/null +++ b/src/ZoneLoading/Dumping/Localize/StringFileDumper.cpp @@ -0,0 +1,63 @@ +#include "StringFileDumper.h" +#include + +StringFileDumper::StringFileDumper(Zone* zone, FileAPI::File* file) +{ + m_zone = zone; + m_file = file; + + m_config_file = ""; + m_notes = ""; + m_language_caps = "ENGLISH"; + + m_wrote_header = false; +} + +void StringFileDumper::SetLanguageName(std::string language) +{ + m_language_caps = std::move(language); + for (auto& c : m_language_caps) c = toupper(c); +} + +void StringFileDumper::SetConfigFile(std::string configFile) +{ + m_config_file = std::move(configFile); +} + +void StringFileDumper::SetNotes(std::string notes) +{ + m_notes = std::move(notes); +} + +void StringFileDumper::WriteHeader() +{ + m_file->Printf("// Dumped from fastfile \"%s\".\n", m_zone->m_name.c_str()); + m_file->Printf("// In their original format the strings might have been separated in multiple files.\n"); + m_file->Printf("VERSION \"1\"\n"); + m_file->Printf("CONFIG \"%s\"\n", m_config_file.c_str()); + m_file->Printf("FILENOTES \"%s\"\n", m_notes.c_str()); + + m_wrote_header = true; +} + +void StringFileDumper::WriteLocalizeEntry(const std::string& reference, const std::string& value) +{ + if (!m_wrote_header) + WriteHeader(); + + m_file->Printf("\n"); + m_file->Printf("REFERENCE %s\n", reference.c_str()); + + const std::string escapedValue = std::regex_replace(value, std::regex("\n"), "\\n"); + + const std::string valueSpacing = std::string(15 - m_language_caps.length(), ' '); + m_file->Printf("LANG_%s%s\"%s\"\n", m_language_caps.c_str(), valueSpacing.c_str(), escapedValue.c_str()); +} + +void StringFileDumper::Finalize() +{ + if (!m_wrote_header) + WriteHeader(); + + m_file->Printf("\nENDMARKER"); +} \ No newline at end of file diff --git a/src/ZoneLoading/Dumping/Localize/StringFileDumper.h b/src/ZoneLoading/Dumping/Localize/StringFileDumper.h new file mode 100644 index 00000000..0e7315de --- /dev/null +++ b/src/ZoneLoading/Dumping/Localize/StringFileDumper.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Zone/Zone.h" +#include "Utils/FileAPI.h" + +class StringFileDumper +{ + Zone* m_zone; + FileAPI::File* m_file; + + std::string m_config_file; + std::string m_notes; + std::string m_language_caps; + + bool m_wrote_header; + + void WriteHeader(); + +public: + StringFileDumper(Zone* zone, FileAPI::File* file); + + void SetConfigFile(std::string configFile); + void SetNotes(std::string notes); + void SetLanguageName(std::string language); + + void WriteLocalizeEntry(const std::string& reference, const std::string& value); + + void Finalize(); +}; diff --git a/src/ZoneLoading/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ZoneLoading/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp index a459b094..c25a2db2 100644 --- a/src/ZoneLoading/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ b/src/ZoneLoading/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp @@ -1,8 +1,95 @@ #include "AssetDumperLocalizeEntry.h" +#include "Dumping/Localize/StringFileDumper.h" using namespace T6; std::string AssetDumperLocalizeEntry::GetNameOfLanguage(ZoneLanguage language) { - // TODO: Add a dumping method that dumps all localized strings to a .str file and not in separate files. + switch(language) + { + case ZoneLanguage::LANGUAGE_NONE: + case ZoneLanguage::LANGUAGE_ENGLISH: + default: + return "english"; + + case ZoneLanguage::LANGUAGE_FRENCH: + return "french"; + + case ZoneLanguage::LANGUAGE_GERMAN: + return "german"; + + case ZoneLanguage::LANGUAGE_ITALIAN: + return "italian"; + + case ZoneLanguage::LANGUAGE_SPANISH: + return "spanish"; + + case ZoneLanguage::LANGUAGE_BRITISH: + return "british"; + + case ZoneLanguage::LANGUAGE_RUSSIAN: + return "russian"; + + case ZoneLanguage::LANGUAGE_POLISH: + return "polish"; + + case ZoneLanguage::LANGUAGE_KOREAN: + return "korean"; + + case ZoneLanguage::LANGUAGE_JAPANESE: + return "japanese"; + + case ZoneLanguage::LANGUAGE_CZECH: + return "czech"; + + case ZoneLanguage::LANGUAGE_FRENCH_CAN: + return "frenchcan"; + + case ZoneLanguage::LANGUAGE_AUSTRIAN: + return "austrian"; + + case ZoneLanguage::LANGUAGE_PORTUGUESE: + return "portuguese"; + + case ZoneLanguage::LANGUAGE_MEXICAN_SPANISH: + return "mexicanspanish"; + + case ZoneLanguage::LANGUAGE_FULL_JAPANESE: + return "fulljapanese"; + } +} + +void AssetDumperLocalizeEntry::DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) +{ + const std::string language = GetNameOfLanguage(zone->m_language); + const std::string stringsPath = utils::Path::Combine(basePath, language + "/localizedstrings"); + + FileAPI::DirectoryCreate(stringsPath); + + FileAPI::File stringFile = FileAPI::Open(utils::Path::Combine(stringsPath, zone->m_name + ".str"), FileAPI::Mode::MODE_WRITE); + + if(stringFile.IsOpen()) + { + StringFileDumper stringFileDumper(zone, &stringFile); + + stringFileDumper.SetLanguageName(language); + + // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. + stringFileDumper.SetConfigFile(R"(C:\projects\cod\t6\bin\StringEd.cfg)"); + + stringFileDumper.SetNotes(""); + + for(auto localizeEntry : *pool) + { + stringFileDumper.WriteLocalizeEntry(localizeEntry->m_asset->name, localizeEntry->m_asset->value); + } + + stringFileDumper.Finalize(); + + stringFile.Close(); + } + else + { + printf("Could not create string file for dumping localized strings of zone '%s'\n", zone->m_name.c_str()); + } } \ No newline at end of file diff --git a/src/ZoneLoading/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h b/src/ZoneLoading/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h index 080ef068..e9ad3571 100644 --- a/src/ZoneLoading/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h +++ b/src/ZoneLoading/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h @@ -5,6 +5,8 @@ class AssetDumperLocalizeEntry final : public IAssetDumper { + static std::string GetNameOfLanguage(ZoneLanguage language); + public: void DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) override; }; \ No newline at end of file diff --git a/src/ZoneLoading/Game/T6/ZoneDumperT6.cpp b/src/ZoneLoading/Game/T6/ZoneDumperT6.cpp index 9b2fd3d7..71887efc 100644 --- a/src/ZoneLoading/Game/T6/ZoneDumperT6.cpp +++ b/src/ZoneLoading/Game/T6/ZoneDumperT6.cpp @@ -7,6 +7,7 @@ #include "AssetDumpers/AssetDumperQdb.h" #include "AssetDumpers/AssetDumperScriptParseTree.h" #include "AssetDumpers/AssetDumperStringTable.h" +#include "AssetDumpers/AssetDumperLocalizeEntry.h" bool ZoneDumperT6::CanHandleZone(Zone* zone) { @@ -45,7 +46,7 @@ bool ZoneDumperT6::DumpZone(Zone* zone, const std::string& basePath) // DUMP_ASSET_POOL(AssetDumperFontIcon, m_font_icon); // DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list); // DUMP_ASSET_POOL(AssetDumperMenuDef, m_menu_def); - // DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize); + DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize); // DUMP_ASSET_POOL(AssetDumperWeaponVariantDef, m_weapon); // DUMP_ASSET_POOL(AssetDumperWeaponAttachment, m_attachment); // DUMP_ASSET_POOL(AssetDumperWeaponAttachmentUnique, m_attachment_unique);