From f1df08ef116e313e3481c0870452bddb9cf87656 Mon Sep 17 00:00:00 2001 From: Seweryn Presnal Date: Sat, 7 Sep 2024 15:59:14 +0200 Subject: [PATCH] Fix duplicate holy sites localization being outputted --- ImperatorToCK3/CK3/CK3LocDB.cs | 193 +++++------------- ImperatorToCK3/CK3/Characters/Character.cs | 13 +- ImperatorToCK3/CK3/Dynasties/Dynasty.cs | 2 +- .../CK3/Localization/CK3LocBlock.cs | 145 +++++++++++++ ImperatorToCK3/CK3/Localization/CK3LocType.cs | 7 + ImperatorToCK3/CK3/Titles/LandedTitles.cs | 15 +- ImperatorToCK3/CK3/Titles/Title.cs | 41 ++-- ImperatorToCK3/CK3/World.cs | 2 +- ImperatorToCK3/Outputter/BookmarkOutputter.cs | 4 +- .../Outputter/ReligionsOutputter.cs | 22 +- 10 files changed, 263 insertions(+), 181 deletions(-) create mode 100644 ImperatorToCK3/CK3/Localization/CK3LocBlock.cs create mode 100644 ImperatorToCK3/CK3/Localization/CK3LocType.cs diff --git a/ImperatorToCK3/CK3/CK3LocDB.cs b/ImperatorToCK3/CK3/CK3LocDB.cs index c22de163d..8d953e0a7 100644 --- a/ImperatorToCK3/CK3/CK3LocDB.cs +++ b/ImperatorToCK3/CK3/CK3LocDB.cs @@ -1,29 +1,39 @@ using commonItems; +using commonItems.Collections; using commonItems.Localization; using commonItems.Mods; -using System.Collections; +using ImperatorToCK3.CK3.Localization; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.IO; namespace ImperatorToCK3.CK3; -public class CK3LocDB : IEnumerable { - private LocDB ModFSLocDB { get; } = new LocDB(ConverterGlobals.PrimaryLanguage, ConverterGlobals.SecondaryLanguages); - private LocDB ConverterGeneratedLocDB { get; } = new LocDB(ConverterGlobals.PrimaryLanguage, ConverterGlobals.SecondaryLanguages); - private LocDB OptionalConverterLocDB { get; } = new LocDB(ConverterGlobals.PrimaryLanguage, ConverterGlobals.SecondaryLanguages); +public class CK3LocDB : IdObjectCollection { + public CK3LocDB() { } // For unit tests. - protected CK3LocDB() { } // Only for inheritance - public CK3LocDB(ModFilesystem ck3ModFS) { // Read loc from CK3 and selected CK3 mods. - ModFSLocDB.ScrapeLocalizations(ck3ModFS); + var modFSLocDB = new LocDB(ConverterGlobals.PrimaryLanguage, ConverterGlobals.SecondaryLanguages); + modFSLocDB.ScrapeLocalizations(ck3ModFS); + ImportLocFromLocDB(modFSLocDB); // Read loc from ImperatorToCK3 congifurables. // It will only be outputted for keys localized in neither ModFSLocDB nor ConverterGeneratedLocDB. LoadOptionalLoc(); } + private void ImportLocFromLocDB(LocDB locDB) { + foreach (var locBlock in locDB) { + var ck3LocBlock = GetOrCreateLocBlock(locBlock.Id); + foreach (var (language, loc) in locBlock) { + if (loc is null) { + continue; + } + ck3LocBlock.AddModFSLoc(language, loc); + } + } + } + private void LoadOptionalLoc() { const string optionalLocDir = "configurables/localization"; if (!Directory.Exists(optionalLocDir)) { @@ -31,64 +41,45 @@ private void LoadOptionalLoc() { return; } + var optionalConverterLocDB = new LocDB(ConverterGlobals.PrimaryLanguage, ConverterGlobals.SecondaryLanguages); var optionalLocFilePaths = Directory.GetFiles(optionalLocDir, "*.yml", SearchOption.AllDirectories); foreach (var outputtedLocFilePath in optionalLocFilePaths) { - OptionalConverterLocDB.ScrapeFile(outputtedLocFilePath); + optionalConverterLocDB.ScrapeFile(outputtedLocFilePath); + } + + foreach (var locBlock in optionalConverterLocDB) { + // Only add loc for the languages that are not already in the CK3LocDB. + var ck3LocBlock = GetOrCreateLocBlock(locBlock.Id); + foreach (var (language, loc) in locBlock) { + if (loc is null) { + continue; + } + if (!ck3LocBlock.HasLocForLanguage(language)) { + ck3LocBlock.AddOptionalLoc(language, loc); + } + } } } private readonly object insertionLock = new(); - public LocBlock AddLocBlock(string id) { + public CK3LocBlock GetOrCreateLocBlock(string id) { lock (insertionLock) { - return ConverterGeneratedLocDB.AddLocBlock(id); - } - } - - public bool ContainsKey(string key) { - if (ModFSLocDB.ContainsKey(key)) { - return true; - } - if (ConverterGeneratedLocDB.ContainsKey(key)) { - return true; - } - if (OptionalConverterLocDB.ContainsKey(key)) { - return true; - } - return false; - } - - public bool TryGetValue(string key, [MaybeNullWhen(false)] out LocBlock locBlock) { // TODO: return readonly locblock instead - bool found = false; - locBlock = null; - - // TODO: add unit test for combining loc from all the sources into one locblock - - if (OptionalConverterLocDB.TryGetValue(key, out var optionalLocBlock)) { - found = true; - locBlock = optionalLocBlock; - } - if (ConverterGeneratedLocDB.TryGetValue(key, out var converterGeneratedLocDBLocBlock)) { - found = true; - if (locBlock is null) { - locBlock = converterGeneratedLocDBLocBlock; - } else { - locBlock.CopyFrom(converterGeneratedLocDBLocBlock); - } - } - if (ModFSLocDB.TryGetValue(key, out var modFSLocBlock)) { - found = true; - if (locBlock is null) { - locBlock = modFSLocBlock; - } else { - locBlock.CopyFrom(modFSLocBlock); + if (TryGetValue(id, out var locBlock)) { + return locBlock; } + + // Create new loc block. + locBlock = new CK3LocBlock(id, ConverterGlobals.PrimaryLanguage); + Add(locBlock); + return locBlock; } - - return found; } - public LocBlock? GetLocBlockForKey(string key) { + // TODO: add unit test for combining loc from all the sources into one locblock + + + public CK3LocBlock? GetLocBlockForKey(string key) { if (TryGetValue(key, out var locBlock)) { return locBlock; } @@ -97,106 +88,35 @@ public bool ContainsKey(string key) { } public bool HasKeyLocForLanguage(string key, string language) { - if (ModFSLocDB.ContainsKey(key) && ModFSLocDB[key].HasLocForLanguage(language)) { - return true; - } - if (ConverterGeneratedLocDB.ContainsKey(key) && ConverterGeneratedLocDB[key].HasLocForLanguage(language)) { - return true; - } - if (OptionalConverterLocDB.ContainsKey(key) && OptionalConverterLocDB[key].HasLocForLanguage(language)) { - return true; + if (TryGetValue(key, out var locBlock)) { + return locBlock.HasLocForLanguage(language); } + return false; } public void AddLocForLanguage(string key, string language, string loc) { lock (insertionLock) { - ConverterGeneratedLocDB.AddLocForKeyAndLanguage(key, language, loc); + var locBlock = GetOrCreateLocBlock(key); + locBlock[language] = loc; } } public string? GetYmlLocLineForLanguage(string key, string language) { - if (ConverterGeneratedLocDB.TryGetValue(key, out var locBlock) && locBlock.HasLocForLanguage(language)) { - return locBlock.GetYmlLocLineForLanguage(language); - } - if (ModFSLocDB.TryGetValue(key, out locBlock) && locBlock.HasLocForLanguage(language)) { - return locBlock.GetYmlLocLineForLanguage(language); - } - if (OptionalConverterLocDB.TryGetValue(key, out locBlock) && locBlock.HasLocForLanguage(language)) { + if (TryGetValue(key, out var locBlock) && locBlock.HasLocForLanguage(language)) { return locBlock.GetYmlLocLineForLanguage(language); } return null; } - IEnumerator IEnumerable.GetEnumerator() { - return GetEnumerator(); - } - - public IEnumerator GetEnumerator() { - var alreadyOutputtedLocKeys = new HashSet(); - - foreach (var locBlock in ModFSLocDB) { - yield return locBlock; - alreadyOutputtedLocKeys.Add(locBlock.Id); - } - - foreach (var locBlock in ConverterGeneratedLocDB) { - if (alreadyOutputtedLocKeys.Contains(locBlock.Id)) { - continue; - } - - yield return locBlock; - alreadyOutputtedLocKeys.Add(locBlock.Id); - } - - foreach (var locBlock in OptionalConverterLocDB) { - if (alreadyOutputtedLocKeys.Contains(locBlock.Id)) { - continue; - } - - yield return locBlock; - alreadyOutputtedLocKeys.Add(locBlock.Id); - } - } - - private HashSet GetAlreadyOutputtedLocKeysForLanguage(string language) { - var keysPerLanguage = new HashSet(); - - foreach (var locBlock in ModFSLocDB) { - if (locBlock.HasLocForLanguage(language)) { - keysPerLanguage.Add(locBlock.Id); - } - } - - return keysPerLanguage; - } - public List GetLocLinesToOutputForLanguage(string language) { var locLinesToOutput = new List(); - - var alreadyWrittenLocForLanguage = GetAlreadyOutputtedLocKeysForLanguage(language); - - foreach (var locBlock in ConverterGeneratedLocDB) { - if (!locBlock.HasLocForLanguage(language)) { - continue; - } - - var loc = locBlock[language]; - if (loc is null) { - continue; - } - - locLinesToOutput.Add(locBlock.GetYmlLocLineForLanguage(language)); - alreadyWrittenLocForLanguage.Add(locBlock.Id); - } - - foreach (var locBlock in OptionalConverterLocDB) { - if (alreadyWrittenLocForLanguage.Contains(locBlock.Id)) { - continue; - } - if (!locBlock.HasLocForLanguage(language)) { + foreach (var locBlock in this) { + if (locBlock.GetLocTypeForLanguage(language) is null or CK3LocType.CK3ModFS) { + // If there's no loc for the language, the returned loc type is null. + // CK3ModFS locs are already present in the CK3/mod/blankMod files, we don't need to output them. continue; } @@ -206,7 +126,6 @@ public List GetLocLinesToOutputForLanguage(string language) { } locLinesToOutput.Add(locBlock.GetYmlLocLineForLanguage(language)); - alreadyWrittenLocForLanguage.Add(locBlock.Id); } return locLinesToOutput; diff --git a/ImperatorToCK3/CK3/Characters/Character.cs b/ImperatorToCK3/CK3/Characters/Character.cs index 5e02634e5..0d89a89ae 100644 --- a/ImperatorToCK3/CK3/Characters/Character.cs +++ b/ImperatorToCK3/CK3/Characters/Character.cs @@ -2,6 +2,7 @@ using commonItems.Collections; using commonItems.Localization; using ImperatorToCK3.CK3.Armies; +using ImperatorToCK3.CK3.Localization; using ImperatorToCK3.CommonUtils; using ImperatorToCK3.CommonUtils.Map; using ImperatorToCK3.Exceptions; @@ -279,7 +280,7 @@ Configuration config SetName(name, null); if (!string.IsNullOrEmpty(name)) { var impNameLoc = irLocDB.GetLocBlockForKey(name); - LocBlock ck3NameLoc = ck3LocDB.AddLocBlock(name); + CK3LocBlock ck3NameLoc = ck3LocDB.GetOrCreateLocBlock(name); if (impNameLoc is not null) { ck3NameLoc.CopyFrom(impNameLoc); } else { // fallback: use unlocalized name as displayed name @@ -360,7 +361,7 @@ ISet unlocalizedImperatorNames var name = $"IRTOCK3_CUSTOM_NAME_{locKey}"; SetName(name, null); - var ck3NameLocBlock = ck3LocDB.AddLocBlock(name); + var ck3NameLocBlock = ck3LocDB.GetOrCreateLocBlock(name); foreach (var language in ConverterGlobals.SupportedLanguages) { ck3NameLocBlock[language] = loc; } @@ -369,7 +370,7 @@ ISet unlocalizedImperatorNames var name = nameLoc.Replace(' ', '_'); SetName(name, null); if (!string.IsNullOrEmpty(name)) { - var ck3NameLocBlock = ck3LocDB.AddLocBlock(name); + var ck3NameLocBlock = ck3LocDB.GetOrCreateLocBlock(name); var matchedLocBlock = irLocDB.GetLocBlockForKey(name); if (matchedLocBlock is not null) { ck3NameLocBlock.CopyFrom(matchedLocBlock); @@ -694,7 +695,7 @@ public void ImportUnitsAsMenAtArms( CK3LocDB ck3LocDB ) { var locKey = $"IRToCK3_character_{Id}"; - var locBlock = ck3LocDB.AddLocBlock(locKey); + var locBlock = ck3LocDB.GetOrCreateLocBlock(locKey); locBlock[ConverterGlobals.PrimaryLanguage] = $"[GetPlayer.MakeScope.Var('IRToCK3_character_{Id}').Char.GetID]"; var menPerUnitType = new Dictionary(); @@ -714,7 +715,7 @@ CK3LocDB ck3LocDB menAtArmsTypes.Add(dedicatedType); MenAtArmsStacksPerType[dedicatedType.Id] = 1; - var maaTypeLocBlock = ck3LocDB.AddLocBlock(dedicatedType.Id); + var maaTypeLocBlock = ck3LocDB.GetOrCreateLocBlock(dedicatedType.Id); maaTypeLocBlock[ConverterGlobals.PrimaryLanguage] = $"${baseType.Id}$"; } @@ -748,7 +749,7 @@ CK3LocDB ck3LocDB if (unit.LocalizedName is not null) { var locKey = unit.LocalizedName.Id; sb.AppendLine($"\t\t\tname={locKey}"); - var unitLocBlock = ck3LocDB.AddLocBlock(locKey); + var unitLocBlock = ck3LocDB.GetOrCreateLocBlock(locKey); unitLocBlock.CopyFrom(unit.LocalizedName); } diff --git a/ImperatorToCK3/CK3/Dynasties/Dynasty.cs b/ImperatorToCK3/CK3/Dynasties/Dynasty.cs index 9f1b0d4de..b604afad1 100644 --- a/ImperatorToCK3/CK3/Dynasties/Dynasty.cs +++ b/ImperatorToCK3/CK3/Dynasties/Dynasty.cs @@ -117,7 +117,7 @@ private void SetCultureFromImperator(Family irFamily, IReadOnlyList i private void SetLocFromImperatorFamilyName(string irFamilyLocKey, LocDB irLocDB, CK3LocDB ck3LocDB) { var irFamilyLoc = irLocDB.GetLocBlockForKey(irFamilyLocKey); - var ck3NameLoc = ck3LocDB.AddLocBlock(Name); + var ck3NameLoc = ck3LocDB.GetOrCreateLocBlock(Name); if (irFamilyLoc is not null) { ck3NameLoc.CopyFrom(irFamilyLoc); ck3NameLoc.ModifyForEveryLanguage(irFamilyLoc, (orig, other, lang) => { diff --git a/ImperatorToCK3/CK3/Localization/CK3LocBlock.cs b/ImperatorToCK3/CK3/Localization/CK3LocBlock.cs new file mode 100644 index 000000000..3b140ff1e --- /dev/null +++ b/ImperatorToCK3/CK3/Localization/CK3LocBlock.cs @@ -0,0 +1,145 @@ +using commonItems.Collections; +using commonItems.Localization; +using System.Collections.Generic; + +namespace ImperatorToCK3.CK3.Localization; + +public class CK3LocBlock : IIdentifiable { // TODO: add ILocBlock interface that both this and commonItems' LocBlock would implement. + private readonly string baseLanguage; + private readonly Dictionary localizations = new(); + + public string Id { get; } + + public CK3LocBlock(string locKey, string baseLanguage) { + Id = locKey; + this.baseLanguage = baseLanguage; + } + + public CK3LocBlock(string locKey, string baseLanguage, LocBlock otherBlock) : this(locKey, baseLanguage) { + foreach (var (language, loc) in otherBlock) { + if (loc is null) { + continue; + } + localizations[language] = (loc, CK3LocType.ConverterGenerated); + } + } + + public void CopyFrom(LocBlock otherBlock) { + foreach (var (language, loc) in otherBlock) { + if (loc is null) { + continue; + } + localizations[language] = (loc, CK3LocType.ConverterGenerated); + } + } + + public void CopyFrom(CK3LocBlock otherBlock) { + foreach (var (language, loc) in otherBlock.localizations) { + localizations[language] = loc; + } + } + + public bool HasLocForLanguage(string language) { + return localizations.ContainsKey(language); + } + + public string? this[string language] { + get { + if (localizations.TryGetValue(language, out var toReturn)) { + return toReturn.Item1; + } + + // As fallback, try to use base language loc. + if (language != baseLanguage) { + if (localizations.TryGetValue(baseLanguage, out var baseLoc)) { + return baseLoc.Item1; + } + } + return null; + } + set { + if (value is null) { + localizations.Remove(language); + } else { + localizations[language] = (value, CK3LocType.ConverterGenerated); + } + } + } + + /// + /// Helps remove boilerplate by applying modifyingMethod to every language in the struct + /// For example: + /// + /// nameLocBlock["english"] = nameLocBlock["english"].Replace("$ADJ$", baseAdjLocBlock["english"]); + /// nameLocBlock["french"] = nameLocBlock["french"].Replace("$ADJ$", baseAdjLocBlock["french"]); + /// nameLocBlock["german"] = nameLocBlock["german"].Replace("$ADJ$", baseAdjLocBlock["german"]); + /// nameLocBlock["russian"] = nameLocBlock["russian"].Replace("$ADJ$", baseAdjLocBlock["russian"]); + /// nameLocBlock["simp_chinese"] = nameLocBlock["simp_chinese"].Replace("$ADJ$", baseAdjLocBlock["simp_chinese"]); + /// nameLocBlock["spanish"] = nameLocBlock["spanish"].Replace("$ADJ$", baseAdjLocBlock["spanish"]); + /// + /// + /// Can be replaced by: + /// + /// nameLocBlock.ModifyForEveryLanguage(baseAdjLocBlock, (string baseLoc, string modifyingLoc) => { + /// return baseLoc.Replace("$ADJ$", modifyingLoc); + /// }); + /// + /// + /// + /// + public void ModifyForEveryLanguage(LocBlock otherBlock, TwoArgLocDelegate modifyingFunction) { + var otherBlockAsCK3LocBlock = new CK3LocBlock(otherBlock.Id, baseLanguage, otherBlock); + ModifyForEveryLanguage(otherBlockAsCK3LocBlock, modifyingFunction); + } + + public void ModifyForEveryLanguage(CK3LocBlock otherBlock, TwoArgLocDelegate modifyingFunction) { + foreach (var language in localizations.Keys) { + var locValue = modifyingFunction(localizations[language].Item1, otherBlock[language], language); + if (locValue is null) { + localizations.Remove(language); + continue; + } + localizations[language] = (locValue, CK3LocType.ConverterGenerated); + } + if (!localizations.ContainsKey(baseLanguage)) { + var locValue = modifyingFunction(null, otherBlock[baseLanguage], baseLanguage); + if (locValue is not null) { + localizations[baseLanguage] = (locValue, CK3LocType.ConverterGenerated); + } + } + } + public void ModifyForEveryLanguage(LocDelegate modifyingFunction) { + foreach (var language in localizations.Keys) { + var locValue = modifyingFunction(localizations[language].Item1, language); + if (locValue is null) { + localizations.Remove(language); + continue; + } + localizations[language] = (locValue, CK3LocType.ConverterGenerated); + } + if (!localizations.ContainsKey(baseLanguage)) { + var locValue = modifyingFunction(null, baseLanguage); + if (locValue is not null) { + localizations[baseLanguage] = (locValue, CK3LocType.ConverterGenerated); + } + } + } + + public string GetYmlLocLineForLanguage(string language) { + return $" {Id}: \"{this[language]}\""; + } + + public CK3LocType? GetLocTypeForLanguage(string language) { + if (localizations.TryGetValue(language, out var loc)) { + return loc.Item2; + } + return null; + } + + public void AddModFSLoc(string language, string loc) { + localizations[language] = (loc, CK3LocType.CK3ModFS); + } + public void AddOptionalLoc(string language, string loc) { + localizations[language] = (loc, CK3LocType.Optional); + } +} \ No newline at end of file diff --git a/ImperatorToCK3/CK3/Localization/CK3LocType.cs b/ImperatorToCK3/CK3/Localization/CK3LocType.cs new file mode 100644 index 000000000..ab5cf63ea --- /dev/null +++ b/ImperatorToCK3/CK3/Localization/CK3LocType.cs @@ -0,0 +1,7 @@ +namespace ImperatorToCK3.CK3.Localization; + +public enum CK3LocType { + CK3ModFS, + Optional, + ConverterGenerated, +} \ No newline at end of file diff --git a/ImperatorToCK3/CK3/Titles/LandedTitles.cs b/ImperatorToCK3/CK3/Titles/LandedTitles.cs index 8465710ce..da66b60e7 100644 --- a/ImperatorToCK3/CK3/Titles/LandedTitles.cs +++ b/ImperatorToCK3/CK3/Titles/LandedTitles.cs @@ -55,8 +55,7 @@ public void LoadTitles(ModFilesystem ck3ModFS, CK3LocDB ck3LocDB) { string adjLocKey = county.Id + "_adj"; // Use the name loc as the adjective loc. - var nameLoc = ck3LocDB.GetLocBlockForKey(county.Id); - if (nameLoc is null) { + if (!ck3LocDB.TryGetValue(county.Id, out var nameLoc)) { continue; } foreach (var language in ConverterGlobals.SupportedLanguages) { @@ -739,12 +738,12 @@ private void SetDeJureKingdoms(CK3LocDB ck3LocDB, Date ck3BookmarkDate) { kingdom.Color1 = duchy.Color1; kingdom.CapitalCounty = duchy.CapitalCounty; - var kingdomNameLoc = ck3LocDB.AddLocBlock(kingdom.Id); + var kingdomNameLoc = ck3LocDB.GetOrCreateLocBlock(kingdom.Id); kingdomNameLoc.ModifyForEveryLanguage( (orig, language) => $"${duchy.Id}$" ); - var kingdomAdjLoc = ck3LocDB.AddLocBlock(kingdom.Id + "_adj"); + var kingdomAdjLoc = ck3LocDB.GetOrCreateLocBlock(kingdom.Id + "_adj"); kingdomAdjLoc.ModifyForEveryLanguage( (orig, language) => $"${duchy.Id}_adj$" ); @@ -952,9 +951,9 @@ private Dictionary GetHeritageIdToExistingTitleDict() { private Title CreateEmpireForHeritage(Pillar heritage, CultureCollection ck3Cultures, CK3LocDB ck3LocDB) { var newEmpireId = $"e_IRTOCK3_heritage_{heritage.Id}"; var newEmpire = Add(newEmpireId); - var nameLocBlock = ck3LocDB.AddLocBlock(newEmpire.Id); + var nameLocBlock = ck3LocDB.GetOrCreateLocBlock(newEmpire.Id); nameLocBlock[ConverterGlobals.PrimaryLanguage] = $"${heritage.Id}_name$ Empire"; - var adjectiveLocBlock = ck3LocDB.AddLocBlock($"{newEmpire.Id}_adj"); + var adjectiveLocBlock = ck3LocDB.GetOrCreateLocBlock($"{newEmpire.Id}_adj"); adjectiveLocBlock[ConverterGlobals.PrimaryLanguage] = $"${heritage.Id}_name$"; newEmpire.HasDefiniteForm = true; @@ -1080,12 +1079,12 @@ Date date newEmpire.CapitalCounty = mostDevelopedCounty; newEmpire.HasDefiniteForm = false; - var empireNameLoc = ck3LocDB.AddLocBlock(newEmpireId); + var empireNameLoc = ck3LocDB.GetOrCreateLocBlock(newEmpireId); empireNameLoc.ModifyForEveryLanguage( (orig, language) => $"${mostDevelopedCounty.Id}$" ); - var empireAdjLoc = ck3LocDB.AddLocBlock(newEmpireId + "_adj"); + var empireAdjLoc = ck3LocDB.GetOrCreateLocBlock(newEmpireId + "_adj"); empireAdjLoc.ModifyForEveryLanguage( (orig, language) => $"${mostDevelopedCounty.Id}_adj$" ); diff --git a/ImperatorToCK3/CK3/Titles/Title.cs b/ImperatorToCK3/CK3/Titles/Title.cs index 8d9c7319e..b8b9c96b0 100644 --- a/ImperatorToCK3/CK3/Titles/Title.cs +++ b/ImperatorToCK3/CK3/Titles/Title.cs @@ -6,6 +6,7 @@ using commonItems.Serialization; using commonItems.SourceGenerators; using ImperatorToCK3.CK3.Characters; +using ImperatorToCK3.CK3.Localization; using ImperatorToCK3.CK3.Provinces; using ImperatorToCK3.CK3.Religions; using ImperatorToCK3.CommonUtils; @@ -244,14 +245,14 @@ Configuration config // determine country name localization var nameSet = false; if (validatedName is not null) { - var nameLocBlock = ck3LocDB.AddLocBlock(Id); + var nameLocBlock = ck3LocDB.GetOrCreateLocBlock(Id); nameLocBlock.CopyFrom(validatedName); nameSet = true; } if (!nameSet) { var irTagLoc = irLocDB.GetLocBlockForKey(ImperatorCountry.Tag); if (irTagLoc is not null) { - var nameLocBlock = ck3LocDB.AddLocBlock(Id); + var nameLocBlock = ck3LocDB.GetOrCreateLocBlock(Id); nameLocBlock.CopyFrom(irTagLoc); nameSet = true; } @@ -261,7 +262,7 @@ Configuration config var name = ImperatorCountry.Name; if (!string.IsNullOrEmpty(name)) { Logger.Warn($"Using unlocalized Imperator name {name} as name for {Id}!"); - var nameLocBlock = ck3LocDB.AddLocBlock(Id); + var nameLocBlock = ck3LocDB.GetOrCreateLocBlock(Id); nameLocBlock[ConverterGlobals.PrimaryLanguage] = name; nameSet = true; } @@ -553,9 +554,15 @@ private void TrySetAdjectiveFromGovernorship(Governorship governorship, Country var adjSet = false; // Try to generate adjective from name. - var nameLocBlock = ck3LocDB.GetLocBlockForKey(Id) ?? irLocDB.GetLocBlockForKey(governorship.Region.Id); + CK3LocBlock? nameLocBlock = ck3LocDB.GetLocBlockForKey(Id); + if (nameLocBlock is null) { + var irRegionLoc = irLocDB.GetLocBlockForKey(governorship.Region.Id); + if (irRegionLoc is not null) { + nameLocBlock = new CK3LocBlock(irRegionLoc.Id, ConverterGlobals.PrimaryLanguage, irRegionLoc); + } + } if (!adjSet && nameLocBlock is not null) { - var adjLocBlock = ck3LocDB.AddLocBlock(adjKey); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock(adjKey); adjLocBlock.CopyFrom(nameLocBlock); var englishLoc = adjLocBlock["english"]; @@ -572,7 +579,7 @@ private void TrySetAdjectiveFromGovernorship(Governorship governorship, Country return; } if (ck3LocDB.TryGetValue($"{ck3Country.Id}_adj", out var countryAdjectiveLocBlock)) { - var adjLocBlock = ck3LocDB.AddLocBlock(adjKey); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock(adjKey); adjLocBlock.CopyFrom(countryAdjectiveLocBlock); adjSet = true; } @@ -623,11 +630,11 @@ CK3LocDB ck3LocDB if (potentialSourceArea is not null && irLocDB.TryGetValue(potentialSourceArea.Id, out var areaLocBlock)) { Logger.Debug($"Naming {Id} after I:R area {potentialSourceArea.Id} majorly ({biggestOwnershipPercentage:P}) controlled by {country.Tag}..."); - var nameLocBlock = ck3LocDB.AddLocBlock(Id); + var nameLocBlock = ck3LocDB.GetOrCreateLocBlock(Id); nameLocBlock.CopyFrom(areaLocBlock); nameSet = true; - var adjLocBlock = ck3LocDB.AddLocBlock($"{Id}_adj"); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock($"{Id}_adj"); adjLocBlock.CopyFrom(nameLocBlock); adjLocBlock.ModifyForEveryLanguage((loc, language) => language == "english" ? loc?.GetAdjective() : loc); } @@ -639,11 +646,11 @@ CK3LocDB ck3LocDB .MaxBy(p => p.CivilizationValue); if (sourceProvince is not null && irLocDB.TryGetValue(sourceProvince.Name, out var provinceLocBlock)) { Logger.Debug($"Naming {Id} after most developed I:R territory: {sourceProvince.Id}..."); - var nameLocBlock = ck3LocDB.AddLocBlock(Id); + var nameLocBlock = ck3LocDB.GetOrCreateLocBlock(Id); nameLocBlock.CopyFrom(provinceLocBlock); nameSet = true; - var adjLocBlock = ck3LocDB.AddLocBlock($"{Id}_adj"); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock($"{Id}_adj"); adjLocBlock.CopyFrom(nameLocBlock); adjLocBlock.ModifyForEveryLanguage((loc, language) => language == "english" ? loc?.GetAdjective() : loc); } @@ -654,7 +661,7 @@ CK3LocDB ck3LocDB var ck3Country = country.CK3Title; if (ck3Country is not null && ck3LocDB.TryGetValue($"{ck3Country.Id}_adj", out var countryAdjectiveLocBlock)) { Logger.Debug($"Naming {Id} after governorship with country adjective: {country.Tag} {governorship.Region.Id}..."); - var nameLocBlock = ck3LocDB.AddLocBlock(Id); + var nameLocBlock = ck3LocDB.GetOrCreateLocBlock(Id); nameLocBlock.CopyFrom(regionLocBlock); nameLocBlock.ModifyForEveryLanguage(countryAdjectiveLocBlock, (orig, adj, _) => $"{adj} {orig}" @@ -664,7 +671,7 @@ CK3LocDB ck3LocDB } if (!nameSet && regionLocBlock is not null) { Logger.Debug($"Naming {Id} after governorship: {governorship.Region.Id}..."); - var nameLocBlock = ck3LocDB.AddLocBlock(Id); + var nameLocBlock = ck3LocDB.GetOrCreateLocBlock(Id); nameLocBlock.CopyFrom(regionLocBlock); nameSet = true; } @@ -820,7 +827,7 @@ private void TrySetAdjectiveLoc(LocDB irLocDB, CountryCollection imperatorCountr } if (validatedAdj is not null) { - var adjLocBlock = ck3LocDB.AddLocBlock(locKey); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock(locKey); adjLocBlock.CopyFrom(validatedAdj); adjSet = true; } @@ -828,7 +835,7 @@ private void TrySetAdjectiveLoc(LocDB irLocDB, CountryCollection imperatorCountr if (!adjSet) { var adjOpt = ImperatorCountry.CountryName.GetAdjectiveLocBlock(irLocDB, imperatorCountries); if (adjOpt is not null) { - var adjLocBlock = ck3LocDB.AddLocBlock(locKey); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock(locKey); adjLocBlock.CopyFrom(adjOpt); adjSet = true; } @@ -836,7 +843,7 @@ private void TrySetAdjectiveLoc(LocDB irLocDB, CountryCollection imperatorCountr if (!adjSet) { var adjLocalizationMatch = irLocDB.GetLocBlockForKey(ImperatorCountry.Tag); if (adjLocalizationMatch is not null) { - var adjLocBlock = ck3LocDB.AddLocBlock(locKey); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock(locKey); adjLocBlock.CopyFrom(adjLocalizationMatch); adjSet = true; } @@ -851,7 +858,7 @@ private void TrySetAdjectiveLoc(LocDB irLocDB, CountryCollection imperatorCountr var generatedAdjective = name.GetAdjective(); Logger.Debug($"Generated adjective for country \"{name}\": \"{generatedAdjective}\""); - var adjLocBlock = ck3LocDB.AddLocBlock(locKey); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock(locKey); adjLocBlock["english"] = generatedAdjective; adjSet = true; } @@ -863,7 +870,7 @@ private void TrySetAdjectiveLoc(LocDB irLocDB, CountryCollection imperatorCountr var name = ImperatorCountry.Name; if (!string.IsNullOrEmpty(name)) { Logger.Warn($"Using unlocalized Imperator name {name} as adjective for {Id}!"); - var adjLocBlock = ck3LocDB.AddLocBlock(locKey); + var adjLocBlock = ck3LocDB.GetOrCreateLocBlock(locKey); adjLocBlock[ConverterGlobals.PrimaryLanguage] = name; adjSet = true; } diff --git a/ImperatorToCK3/CK3/World.cs b/ImperatorToCK3/CK3/World.cs index c9004f0df..3d4cf038e 100644 --- a/ImperatorToCK3/CK3/World.cs +++ b/ImperatorToCK3/CK3/World.cs @@ -379,7 +379,7 @@ private void ClearFeaturedCharactersDescriptions(Date ck3BookmarkDate) { } var holderId = title.GetHolderId(ck3BookmarkDate); if (holderId != "0" && Characters.TryGetValue(holderId, out var holder)) { - var locBlock = LocDB.AddLocBlock($"{holder.GetName(ck3BookmarkDate)}_desc"); + var locBlock = LocDB.GetOrCreateLocBlock($"{holder.GetName(ck3BookmarkDate)}_desc"); locBlock.ModifyForEveryLanguage((loc, language) => string.Empty); } } diff --git a/ImperatorToCK3/Outputter/BookmarkOutputter.cs b/ImperatorToCK3/Outputter/BookmarkOutputter.cs index cd753c5a4..63d71a8bc 100644 --- a/ImperatorToCK3/Outputter/BookmarkOutputter.cs +++ b/ImperatorToCK3/Outputter/BookmarkOutputter.cs @@ -75,13 +75,13 @@ Configuration config var holder = world.Characters[holderId]; // Add character localization for bookmark screen. - var holderLoc = ck3LocDB.AddLocBlock($"bm_converted_{holder.Id}"); + var holderLoc = ck3LocDB.GetOrCreateLocBlock($"bm_converted_{holder.Id}"); if (holder.GetName(config.CK3BookmarkDate) is {} holderName) { if (ck3LocDB.TryGetValue(holderName, out var holderNameLoc)) { holderLoc.CopyFrom(holderNameLoc); } } - var holderDescLoc = ck3LocDB.AddLocBlock($"bm_converted_{holder.Id}_desc"); + var holderDescLoc = ck3LocDB.GetOrCreateLocBlock($"bm_converted_{holder.Id}_desc"); foreach (var language in ConverterGlobals.SupportedLanguages) { holderDescLoc[language] = string.Empty; } diff --git a/ImperatorToCK3/Outputter/ReligionsOutputter.cs b/ImperatorToCK3/Outputter/ReligionsOutputter.cs index 2679f4e8b..927bb1fb0 100644 --- a/ImperatorToCK3/Outputter/ReligionsOutputter.cs +++ b/ImperatorToCK3/Outputter/ReligionsOutputter.cs @@ -37,20 +37,24 @@ private static async Task OutputHolySites(string outputModPath, ReligionCollecti // Add localization. foreach (var site in sitesToOutput) { // holy site name - var holySiteTitle = site.BaronyId ?? site.CountyId; - var siteNameLocBlock = ck3LocDB.AddLocBlock($"holy_site_{site.Id}_name"); + var siteNameLocBlock = ck3LocDB.GetOrCreateLocBlock($"holy_site_{site.Id}_name"); // holy site effect name - var siteEffectLocBlock = ck3LocDB.AddLocBlock($"holy_site_{site.Id}_effect_name"); + var siteEffectLocBlock = ck3LocDB.GetOrCreateLocBlock($"holy_site_{site.Id}_effect_name"); foreach (string language in ConverterGlobals.SupportedLanguages) { - if (holySiteTitle is not null) { - siteNameLocBlock[language] = $"${holySiteTitle}$"; - } else { - siteNameLocBlock[language] = "Holy site"; // fallback + if (!siteNameLocBlock.HasLocForLanguage(language)) { + var holySiteTitle = site.BaronyId ?? site.CountyId; + if (holySiteTitle is not null) { + siteNameLocBlock[language] = $"${holySiteTitle}$"; + } else { + siteNameLocBlock[language] = "Holy site"; // fallback + } + } + + if (!siteEffectLocBlock.HasLocForLanguage(language)) { + siteEffectLocBlock[language] = $"From [holy_site|E] #weak ($holy_site_{site.Id}_name$)#!"; } - - siteEffectLocBlock[language] = $"From [holy_site|E] #weak ($holy_site_{site.Id}_name$)#!"; } } }