LocalizedStringManager.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <ILocalizationManager.h>
  10. #include <ISystem.h>
  11. #include <StlUtils.h>
  12. #include <VectorMap.h>
  13. #include <AzCore/std/containers/map.h>
  14. #include "Huffman.h"
  15. //////////////////////////////////////////////////////////////////////////
  16. /*
  17. Manage Localization Data
  18. */
  19. class CLocalizedStringsManager
  20. : public ILocalizationManager
  21. , public ISystemEventListener
  22. {
  23. public:
  24. using TLocalizationTagVec = std::vector<AZStd::string>;
  25. constexpr const static size_t LOADING_FIXED_STRING_LENGTH = 2048;
  26. constexpr const static size_t COMPRESSION_FIXED_BUFFER_LENGTH = 6144;
  27. CLocalizedStringsManager(ISystem* pSystem);
  28. virtual ~CLocalizedStringsManager();
  29. // ILocalizationManager
  30. const char* LangNameFromPILID(const ILocalizationManager::EPlatformIndependentLanguageID id) override;
  31. ILocalizationManager::EPlatformIndependentLanguageID PILIDFromLangName(AZStd::string langName) override;
  32. ILocalizationManager::EPlatformIndependentLanguageID GetSystemLanguage() override;
  33. ILocalizationManager::TLocalizationBitfield MaskSystemLanguagesFromSupportedLocalizations(const ILocalizationManager::TLocalizationBitfield systemLanguages) override;
  34. ILocalizationManager::TLocalizationBitfield IsLanguageSupported(const ILocalizationManager::EPlatformIndependentLanguageID id) override;
  35. const char* GetLanguage() override;
  36. bool SetLanguage(const char* sLanguage) override;
  37. int GetLocalizationFormat() const override;
  38. AZStd::string GetLocalizedSubtitleFilePath(const AZStd::string& localVideoPath, const AZStd::string& subtitleFileExtension) const override;
  39. AZStd::string GetLocalizedLocXMLFilePath(const AZStd::string& localXmlPath) const override;
  40. bool InitLocalizationData(const char* sFileName, bool bReload = false) override;
  41. bool RequestLoadLocalizationDataByTag(const char* sTag) override;
  42. bool LoadLocalizationDataByTag(const char* sTag, bool bReload = false) override;
  43. bool ReleaseLocalizationDataByTag(const char* sTag) override;
  44. bool LoadAllLocalizationData(bool bReload = false) override;
  45. bool LoadExcelXmlSpreadsheet(const char* sFileName, bool bReload = false) override;
  46. void ReloadData() override;
  47. void FreeData() override;
  48. bool LocalizeString_s(const AZStd::string& sString, AZStd::string& outLocalizedString, bool bEnglish = false) override;
  49. bool LocalizeString_ch(const char* sString, AZStd::string& outLocalizedString, bool bEnglish = false) override;
  50. void LocalizeAndSubstituteInternal(AZStd::string& locString, const AZStd::vector<AZStd::string>& keys, const AZStd::vector<AZStd::string>& values) override;
  51. bool LocalizeLabel(const char* sLabel, AZStd::string& outLocalizedString, bool bEnglish = false) override;
  52. bool IsLocalizedInfoFound(const char* sKey) override;
  53. bool GetLocalizedInfoByKey(const char* sKey, SLocalizedInfoGame& outGameInfo) override;
  54. bool GetLocalizedInfoByKey(const char* sKey, SLocalizedSoundInfoGame* pOutSoundInfoGame) override;
  55. int GetLocalizedStringCount() override;
  56. bool GetLocalizedInfoByIndex(int nIndex, SLocalizedInfoGame& outGameInfo) override;
  57. bool GetLocalizedInfoByIndex(int nIndex, SLocalizedInfoEditor& outEditorInfo) override;
  58. bool GetEnglishString(const char* sKey, AZStd::string& sLocalizedString) override;
  59. bool GetSubtitle(const char* sKeyOrLabel, AZStd::string& outSubtitle, bool bForceSubtitle = false) override;
  60. void FormatStringMessage_List(AZStd::string& outString, const AZStd::string& sString, const char** sParams, int nParams) override;
  61. void FormatStringMessage(AZStd::string& outString, const AZStd::string& sString, const char* param1, const char* param2 = nullptr, const char* param3 = nullptr, const char* param4 = nullptr) override;
  62. void LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, AZStd::string& outTimeString) override;
  63. void LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, AZStd::string& outDateString) override;
  64. void LocalizeDuration(int seconds, AZStd::string& outDurationString) override;
  65. void LocalizeNumber(int number, AZStd::string& outNumberString) override;
  66. void LocalizeNumber_Decimal(float number, int decimals, AZStd::string& outNumberString) override;
  67. bool ProjectUsesLocalization() const override;
  68. // ~ILocalizationManager
  69. // ISystemEventManager
  70. void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) override;
  71. // ~ISystemEventManager
  72. void GetLoadedTags(TLocalizationTagVec& tagVec);
  73. void FreeLocalizationData();
  74. private:
  75. void SetAvailableLocalizationsBitfield(const ILocalizationManager::TLocalizationBitfield availableLocalizations);
  76. bool LocalizeStringInternal(const char* pStr, size_t len, AZStd::string& outLocalizedString, bool bEnglish);
  77. bool DoLoadExcelXmlSpreadsheet(const char* sFileName, uint8 tagID, bool bReload);
  78. using LoadFunc = bool(CLocalizedStringsManager::*)(const char*, uint8, bool);
  79. bool DoLoadAGSXmlDocument(const char* sFileName, uint8 tagID, bool bReload);
  80. LoadFunc GetLoadFunction() const;
  81. struct SLocalizedStringEntryEditorExtension
  82. {
  83. AZStd::string sKey; // Map key text equivalent (without @)
  84. AZStd::string sOriginalActorLine; // english text
  85. AZStd::string sUtf8TranslatedActorLine; // localized text
  86. AZStd::string sOriginalText; // subtitle. if empty, uses English text
  87. AZStd::string sOriginalCharacterName; // english character name speaking via XML asset
  88. unsigned int nRow; // Number of row in XML file
  89. };
  90. struct SLanguage;
  91. //#define LOG_DECOMP_TIMES //If defined, will log decompression times to a file
  92. struct SLocalizedStringEntry
  93. {
  94. //Flags
  95. enum
  96. {
  97. USE_SUBTITLE = BIT(0), //should a subtitle displayed for this key?
  98. IS_DIRECTED_RADIO = BIT(1), //should the radio receiving hud be displayed?
  99. IS_INTERCEPTED = BIT(2), //should the radio receiving hud show the interception display?
  100. IS_COMPRESSED = BIT(3), //Translated text is compressed
  101. };
  102. union trans_text
  103. {
  104. AZStd::string* psUtf8Uncompressed;
  105. uint8* szCompressed; // Note that no size information is stored. This is for struct size optimization and unfortunately renders the size info inaccurate.
  106. };
  107. AZStd::string sCharacterName; // character name speaking via XML asset
  108. trans_text TranslatedText; // Subtitle of this line
  109. // audio specific part
  110. AZStd::string sPrototypeSoundEvent; // associated sound event prototype (radio, ...)
  111. CryHalf fVolume;
  112. CryHalf fRadioRatio;
  113. // SoundMoods
  114. AZStd::vector<SLocalizedAdvancesSoundEntry> SoundMoods;
  115. // EventParameters
  116. AZStd::vector<SLocalizedAdvancesSoundEntry> EventParameters;
  117. // ~audio specific part
  118. // subtitle & radio flags
  119. uint8 flags;
  120. // Index of Huffman tree for translated text. -1 = no tree assigned (error)
  121. int8 huffmanTreeIndex;
  122. uint8 nTagID;
  123. // bool bDependentTranslation; // if the english/localized text contains other localization labels
  124. //Additional information for Sandbox. Null in game
  125. SLocalizedStringEntryEditorExtension* pEditorExtension;
  126. SLocalizedStringEntry()
  127. : flags(0)
  128. , huffmanTreeIndex(-1)
  129. , pEditorExtension(nullptr)
  130. {
  131. TranslatedText.psUtf8Uncompressed = nullptr;
  132. };
  133. ~SLocalizedStringEntry()
  134. {
  135. SAFE_DELETE(pEditorExtension);
  136. if ((flags & IS_COMPRESSED) == 0)
  137. {
  138. SAFE_DELETE(TranslatedText.psUtf8Uncompressed);
  139. }
  140. else
  141. {
  142. SAFE_DELETE_ARRAY(TranslatedText.szCompressed);
  143. }
  144. };
  145. AZStd::string GetTranslatedText(const SLanguage* pLanguage) const;
  146. };
  147. //Keys as CRC32. Strings previously, but these proved too large
  148. using StringsKeyMap = VectorMap<uint32, SLocalizedStringEntry*>;
  149. struct SLanguage
  150. {
  151. using TLocalizedStringEntries = std::vector<SLocalizedStringEntry*>;
  152. using THuffmanCoders = std::vector<HuffmanCoder*>;
  153. AZStd::string sLanguage;
  154. StringsKeyMap m_keysMap;
  155. TLocalizedStringEntries m_vLocalizedStrings;
  156. THuffmanCoders m_vEncoders;
  157. };
  158. struct SFileInfo
  159. {
  160. bool bDataStripping;
  161. uint8 nTagID;
  162. };
  163. #ifndef _RELEASE
  164. std::map<AZStd::string, bool> m_warnedAboutLabels;
  165. bool m_haveWarnedAboutAtLeastOneLabel;
  166. void LocalizedStringsManagerWarning(const char* label, const char* message);
  167. void ListAndClearProblemLabels();
  168. #else
  169. inline void LocalizedStringsManagerWarning(...) {};
  170. inline void ListAndClearProblemLabels() {};
  171. #endif
  172. void AddLocalizedString(SLanguage* pLanguage, SLocalizedStringEntry* pEntry, const uint32 keyCRC32);
  173. void AddControl(int nKey);
  174. //////////////////////////////////////////////////////////////////////////
  175. void ParseFirstLine(IXmlTableReader* pXmlTableReader, char* nCellIndexToType, std::map<int, AZStd::string>& SoundMoodIndex, std::map<int, AZStd::string>& EventParameterIndex);
  176. void InternalSetCurrentLanguage(SLanguage* pLanguage);
  177. ISystem* m_pSystem;
  178. // Pointer to the current language.
  179. SLanguage* m_pLanguage;
  180. // all loaded Localization Files
  181. using pairFileName = std::pair<AZStd::string, SFileInfo>;
  182. using tmapFilenames = std::map<AZStd::string, SFileInfo>;
  183. tmapFilenames m_loadedTables;
  184. // filenames per tag
  185. using TStringVec = std::vector<AZStd::string>;
  186. struct STag
  187. {
  188. TStringVec filenames;
  189. uint8 id;
  190. bool loaded;
  191. };
  192. using TTagFileNames = std::map<AZStd::string, STag>;
  193. TTagFileNames m_tagFileNames;
  194. TStringVec m_tagLoadRequests;
  195. // Array of loaded languages.
  196. std::vector<SLanguage*> m_languages;
  197. using PrototypeSoundEvents = std::set<AZStd::string>;
  198. PrototypeSoundEvents m_prototypeEvents; // this set is purely used for clever string/string assigning to save memory
  199. struct less_strcmp
  200. {
  201. bool operator()(const AZStd::string& left, const AZStd::string& right) const
  202. {
  203. return strcmp(left.c_str(), right.c_str()) < 0;
  204. }
  205. };
  206. using CharacterNameSet = std::set<AZStd::string, less_strcmp>;
  207. CharacterNameSet m_characterNameSet; // this set is purely used for clever string/string assigning to save memory
  208. // CVARs
  209. int m_cvarLocalizationDebug;
  210. int m_cvarLocalizationEncode; //Encode/Compress translated text to save memory
  211. //The localizations that are available for this SKU. Used for determining what to show on a language select screen or whether to show one at all
  212. TLocalizationBitfield m_availableLocalizations;
  213. //Lock for
  214. mutable AZStd::mutex m_cs;
  215. using AutoLock = AZStd::lock_guard<AZStd::mutex>;
  216. };