/// <summary> /// Helper method /// </summary> /// <param name="name"></param> /// <returns></returns> private string Localize(string name) { // Just in case 2 threads with 2 different cultures invoked the same localizer concurrently // (It probably never happens, but I have seen signs that some MVC libraries might do that) lock (_translationsLock) { // This is to workaround the behavior of certain MVC libraries // which seem to re-use the same IStringLocalizer across multiple requests, // even though the current UI culture is a scoped value and the localizer is transient if (_translations == null || (_culture ?? CultureInfo.CurrentUICulture).Name != _translations.CultureName) { _translations = _factory.GetTranslations(_culture); } // Go over the dictionaries one by one and return the first hit foreach (var translationDictionary in _translations.InDescendingOrderOfPrecedence()) { if (translationDictionary != null && translationDictionary.ContainsKey(name)) { return(translationDictionary[name]); } } // If all is a miss, return the name as is, forgiveness here is a virtue. return(name); } }
public CascadingTranslations GetTranslations(CultureInfo culture = null) { culture = culture ?? CultureInfo.CurrentUICulture; // Current UI culture by default string defaultUICulture = _config["DefaultUICulture"]; string specificUICulture = culture.Name; string neutralUICulture = culture.IsNeutralCulture ? specificUICulture : culture.Parent.Name; // We refresh the cache once per request, and we track this using a flag in the HTTP Context object string flag = specificUICulture; var isUpdated = (bool?)(_httpContextAccessor.HttpContext == null ? false : _httpContextAccessor.HttpContext.Items[flag]); if (!(isUpdated ?? false)) { // The list of cultures to update; List <string> culturesToFreshenUp = new List <string> { // Update localization cache for the default application culture defaultUICulture }; // Update localization cache for the current request culture, if different if (specificUICulture != defaultUICulture) { culturesToFreshenUp.Add(specificUICulture); } // Update localization cache for the neutral request culture, if not already neutral if (neutralUICulture != specificUICulture) { culturesToFreshenUp.Add(neutralUICulture); } // Update the local cache, or distributed cache timestamp if need be EnsureFreshnessOfCaches(culturesToFreshenUp.ToArray()); // Set the flag, to prevent another cache refresh within the same scope // Note: this is thread safe, since only one thread at a time will get // a copy of the HTTP context, since it is scoped per request if (_httpContextAccessor.HttpContext != null) { _httpContextAccessor.HttpContext.Items[flag] = true; } } _localCache.TryGetValue(CacheKey(specificUICulture), out LocalCacheItem specificCache); _localCache.TryGetValue(CacheKey(neutralUICulture), out LocalCacheItem neutralCache); _localCache.TryGetValue(CacheKey(defaultUICulture), out LocalCacheItem defaultCache); var result = new CascadingTranslations { CultureName = specificUICulture, SpecificTranslations = specificCache?.Translations, NeutralTranslations = neutralCache?.Translations, DefaultTranslations = defaultCache?.Translations, }; // Return the translations return(result); }