/// <summary> /// Obtains inherited translations /// </summary> /// <param name="dbCtx"></param> /// <returns></returns> protected internal static async Task ObtainInheritedTranslations(DbContext dbCtx, TranslationKey tk) { var localizedDbCtx = dbCtx as ILocalizedDbContext; var localizationClass = await localizedDbCtx.LocalizationClasses.AsNoTracking() .FirstOrDefaultAsync(x => x.Uuid == tk.LocalizationClassUuid); //drill one level down as assuming that it should be actual if (localizationClass != null && !string.IsNullOrWhiteSpace(localizationClass.InheritedClassName)) { var inheritedLocalizationClass = await localizedDbCtx.LocalizationClasses.AsNoTracking() .FirstOrDefaultAsync(x => x.ApplicationName + x.ClassName + "Localization" == localizationClass.InheritedClassName); if (inheritedLocalizationClass == null) { return; } var inheritedTk = await localizedDbCtx.TranslationKeys.FirstOrDefaultAsync(x => x.LocalizationClassUuid == inheritedLocalizationClass.Uuid && x.Key == tk.Key); if (inheritedTk == null) { return; } tk.Translations = inheritedTk.Translations; await tk.SilentUpdateAsync <TranslationKey>(dbCtx); } }
public static async Task SaveLocalizationsAsync(DbContext dbCtx, IEnumerable <LocalizationClass> localizations, bool?overwrite, bool?upsert, IEnumerable <string> langsToImport) { var localisedDbCtx = (ILocalizedDbContext)dbCtx; var appNames = new List <string>(); foreach (var incomingLc in localizations) { if (!appNames.Contains(incomingLc.ApplicationName)) { appNames.Add(incomingLc.ApplicationName); } var lc = await localisedDbCtx.LocalizationClasses.FirstOrDefaultAsync( x => x.ApplicationName == incomingLc.ApplicationName && x.ClassName == incomingLc.ClassName); if (overwrite == true) { if (lc != null) { //this should nicely cleanup the translation keys too await lc.DestroyAsync <LocalizationClass>(dbCtx, lc.Uuid); } lc = new LocalizationClass { ApplicationName = incomingLc.ApplicationName, ClassName = incomingLc.ClassName, InheritedClassName = incomingLc.InheritedClassName }; await lc.CreateAsync(dbCtx); foreach (var translationKey in incomingLc.TranslationKeys) { //filter out translations that are about to be saved var translations = new Translations(); foreach (var lng in translationKey.Translations.Keys) { if (langsToImport == null || langsToImport.Contains(lng)) { translations.Add(lng, translationKey.Translations[lng]); } } var tk = new TranslationKey { LocalizationClassUuid = lc.Uuid, Key = translationKey.Key, Inherited = translationKey.Inherited, Overwrites = translationKey.Overwrites, Translations = translations ?? new Translations() }; await tk.CreateAsync(dbCtx); } } else { //this is a non-overwrite, so it applies to both - localization and translation keys; whatever is in the db must be maintained //only the missing bits and pieces are added //take care of the translation key - if not there it must be created if (lc == null) { lc = new LocalizationClass { ApplicationName = incomingLc.ApplicationName, ClassName = incomingLc.ClassName, InheritedClassName = incomingLc.InheritedClassName }; await lc.CreateAsync(dbCtx); } //review the translations now foreach (var translationKey in incomingLc.TranslationKeys) { //check if the translation key is already there var tk = await localisedDbCtx.TranslationKeys.FirstOrDefaultAsync( x => x.LocalizationClassUuid == lc.Uuid && x.Key == translationKey.Key); //create key if not there if (tk == null) { tk = new TranslationKey { LocalizationClassUuid = lc.Uuid, Key = translationKey.Key, Translations = new Translations() }; await tk.CreateAsync(dbCtx); } tk.Inherited = translationKey.Inherited; tk.Overwrites = translationKey.Overwrites; //filter out translations that are about to be saved var translations = new Translations(); foreach (var lng in translationKey.Translations.Keys) { if (langsToImport == null || langsToImport.Contains(lng)) { translations.Add(lng, translationKey.Translations[lng]); } } //check translations foreach (var lng in translations.Keys) { if (upsert == true || !tk.Translations.ContainsKey(lng)) { tk.Translations[lng] = translations[lng]; } } await tk.SilentUpdateAsync <TranslationKey>(dbCtx); } } } //need to wipe out cache too... foreach (var appName in appNames) { InvalidateAppLocalizationsCache(appName); } }
/// <summary> /// Propagates change up the inheritance stack, so translations in inheriting classes are updated; /// propagation stops when an inheriting translation overwrites inherited value /// </summary> /// <param name="dbCtx"></param> /// <param name="tk"></param> /// <returns></returns> protected internal static async Task PropagateChangeUpTheInheritanceStack(DbContext dbCtx, TranslationKey tk) { var appName = await GetLocalizationClassAppNameAsync(dbCtx, tk.LocalizationClassUuid); var className = await GetLocalizationClassClassNameAsync(dbCtx, tk.LocalizationClassUuid); var localizedDbCtx = dbCtx as ILocalizedDbContext; var inheritingClasses = await(localizedDbCtx).LocalizationClasses.AsNoTracking() .Where(lc => lc.InheritedClassName == $"{appName}.{className}Localization").ToListAsync(); foreach (var inheritingClass in inheritingClasses) { //get inheriting tk var inheritingTk = await localizedDbCtx.TranslationKeys.FirstOrDefaultAsync(x => x.LocalizationClassUuid == inheritingClass.Uuid && x.Key == tk.Key); //no key, or key overwrites - stop, as no point, as this breaks inheritance chain if (inheritingTk == null || inheritingTk.Overwrites == true) { continue; } inheritingTk.Translations = tk.Translations; await inheritingTk.SilentUpdateAsync <TranslationKey>(dbCtx); await PropagateChangeUpTheInheritanceStack(dbCtx, inheritingTk); } }