/// <summary>
        /// Ivalidates app localisations cache
        /// </summary>
        /// <param name="appName"></param>
        public static void InvalidateAppLocalisationsCache(string appName, string className)
        {
            //app localisations cache first

            if (AppLocalisationsCache.ContainsKey(appName) && string.IsNullOrEmpty(className))
            {
                AppLocalisationsCache.Remove(appName);
            }
            else if (AppLocalisationsCache.ContainsKey(appName))
            {
                AppLocalisationsCache.Remove(appName);

                //FIXME - this requires better reading - need to read from db to 'top up' the cache

                //var localisations = AppLocalisationsCache[appName].ToList();

                //var toBeRemoved = localisations.FirstOrDefault(l => l.ClassName == className);
                //if(toBeRemoved != null)
                //    localisations.Remove(toBeRemoved);

                //AppLocalisationsCache[appName] = localisations;
            }

            //clients cache too...
            var keysToInvalidate = ClientLocalisationsCache.Keys.Where(k => k.IndexOf(appName) > -1).ToList();

            foreach (var key in keysToInvalidate)
            {
                ClientLocalisationsCache.Remove(key);
            }
        }
示例#2
0
        /// <summary>
        /// Gets localisations for specified lang codes and apps
        /// </summary>
        /// <typeparam name="TDbCtx"></typeparam>
        /// <param name="dbCtx"></param>
        /// <param name="langCodes"></param>
        /// <param name="appNames"></param>
        /// <returns></returns>
        public static async Task <Dictionary <string, Dictionary <string, Dictionary <string, string> > > > GetAppLocalisationsAsync <TDbCtx>(TDbCtx dbCtx, IEnumerable <string> langCodes, IEnumerable <string> appNames)
            where TDbCtx : DbContext, ILocalised
        {
            var ret = new Dictionary <string, Dictionary <string, Dictionary <string, string> > >();

            if (appNames == null || !appNames.Any())
            {
                return(ret);
            }

            //grab the default lng
            var defaultLang = await Lang.GetDefaultLangAsync(dbCtx);

            if (langCodes == null || !langCodes.Any())
            {
                if (defaultLang == null)
                {
                    return(ret);
                }

                //no langs provided, so the calling client may not be aware of the lang yet.
                //in this scenario just lookup the default lang and get the localisation fot the default lng
                langCodes = new[] { defaultLang.LangCode };
            }


            //see if there is cache for the current combination already
            var cacheKey = GetClientLocalisationsCacheKey(langCodes, appNames);

            if (ClientLocalisationsCache.ContainsKey(cacheKey))
            {
                return((Dictionary <string, Dictionary <string, Dictionary <string, string> > >)ClientLocalisationsCache[cacheKey]);
            }

            //fetch localisations if needed
            foreach (var appName in appNames)
            {
                if (!AppLocalisationsCache.ContainsKey(appName) || AppLocalisationsCache[appName] == null)
                {
                    //read all the Localisation classes for the given AppName
                    var localisationClasses = await
                                              dbCtx.LocalisationClasses.Where(lc => lc.ApplicationName == appName).ToListAsync();

                    //now grab the identifiers - need them in order to request translation keys. when using IQueryable, the range MUST BE static, simple types
                    //so even though compiler will not complain if a range is passes as localisationClasses.Select(lc => lc.Uuid) it will fail in the runtime
                    //saving this to a variable solves the issue!
                    var localisationClassesIdentifiers = localisationClasses.Select(lc => lc.Uuid);

                    var translationKeys = await
                                          dbCtx.TranslationKeys.Where(
                        tk => localisationClassesIdentifiers.Contains(tk.LocalisationClassUuid)).ToListAsync();

                    AppLocalisationsCache[appName] = localisationClasses.GroupJoin(
                        translationKeys,
                        lc => lc.Uuid,
                        tk => tk.LocalisationClassUuid,
                        (lc, tk) => new LocalisationClass()
                    {
                        ApplicationName    = lc.ApplicationName,
                        ClassName          = lc.ClassName,
                        InheritedClassName = lc.InheritedClassName,
                        TranslationKeys    = tk
                    }
                        );
                }

                var appLocalisations = AppLocalisationsCache[appName];

                foreach (var appL in appLocalisations)
                {
                    var key = $"{appL.ApplicationName}.{appL.ClassName}";
                    if (!ret.ContainsKey(key))
                    {
                        ret[key] = new Dictionary <string, Dictionary <string, string> >();
                    }
                    var classTranslations = ret[key];


                    foreach (var tk in appL.TranslationKeys)
                    {
                        if (!classTranslations.ContainsKey(tk.Key))
                        {
                            classTranslations[tk.Key] = new Dictionary <string, string>();
                        }

                        foreach (var translation in tk.Translations.Where(t => t.Key == defaultLang.LangCode || langCodes.Contains(t.Key)))
                        {
                            classTranslations[tk.Key].Add(translation.Key, translation.Value);
                        }
                    }
                }
            }

            //cahce the output
            ClientLocalisationsCache[cacheKey] = ret;

            return(ret);
        }