Activities of "thomas.blotiere@abraxas.ch"

Hello,

We are working on a Multi-tenant application (ASP.NET core + Angular).

It appears that translations( table abplanguagetexts ) takes the tenant into account which would lead to different translations for different tenants (for a same language).

I would like to know how to achieve one translation for all tenant in a language. For example for ABPUI:ADDROLE, I want to add only a row in French with "Ajouter rôle" as a value instead of 1 row per tenant for this ABPUI:ADDROLE key.

To say it differently I would like the translation engine NOT to check the tenant when looking for a translation.

Is there a way to do this ?

Thanks

Thomas

  • ABP Framework version: 4.3
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): yes
  • Exception message and stack trace:
  • Steps to reproduce the issue:

Hello Maliming,

Thank you for your quick reply, your solution works very nicely !

( I just had to replace the resource.ResourceName with the name of the resource I want to target, for exampel AbpIdentity)

Best Regards

Thomas

Hello,

I have followed the solution that has been suggested as an answer of my initial question here : https://support.abp.io/QA/Questions/1642/Is-there-a-way-to-bypass-Tenant-for-Translations

Technically, this is working fine but what happens is that my code now loads up to 33 ressources and the impact on performance is significant when the user changes of tenant or of language.

I had to disregard this solution because of this performance issue.

Sure I am sure I can remove a few ressources from loading but a few less will not change much of the performance issue.

Can this code be improved ? Or is there a better way to do achieve the same result, that is to access translations independently of the tenant ?

Thank you

Thomas

ABP Framework version: 4.3 UI type: Angular DB provider: EF Core Tiered (MVC) or Identity Server Separated (Angular): yes

`
using Volo.Abp.Caching;
using Volo.Abp.LanguageManagement;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

namespace AbxEps.Fines
{
    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IDynamicResourceLocalizer))]
    public class TenantIndependentResourceLocalizer : DynamicResourceLocalizer
    {
        public TenantIndependentResourceLocalizer(
            IServiceScopeFactory serviceScopeFactory,
            IDistributedCache<LanguageTextCacheItem> cache)
            : base(serviceScopeFactory, cache)
        {
        }

        protected override LanguageTextCacheItem CreateCacheItem(LocalizationResource resource, string cultureName)
        {
            var cacheItem = new LanguageTextCacheItem();

            using (var scope = ServiceScopeFactory.CreateScope())
            {
                var currentTenant = scope.ServiceProvider.GetRequiredService<ICurrentTenant>();

                if (currentTenant == null || !currentTenant.IsAvailable)
                    return base.CreateCacheItem(resource, cultureName);

                using (currentTenant.Change(null))
                {
                    var service = scope.ServiceProvider.GetRequiredService<ILanguageTextRepository>();

                    AddToLanguageDictionary("AbpIdentity", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpAccount", cultureName, cacheItem, service);
                    AddToLanguageDictionary("LanguageManagement", cultureName, cacheItem, service);
                    AddToLanguageDictionary("TextTemplateManagement", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpSettingManagement", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpIdentityServer", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpAuditLogging", cultureName, cacheItem, service);
                    AddToLanguageDictionary("CentralTools", cultureName, cacheItem, service);
                    AddToLanguageDictionary("CentralTools:CommonUI", cultureName, cacheItem, service);
                    AddToLanguageDictionary("Fines", cultureName, cacheItem, service);
                    AddToLanguageDictionary("Batches", cultureName, cacheItem, service);
                    AddToLanguageDictionary("ListSpool", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpUi", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpLocalization", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpTiming", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpAuthorization", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpValidation", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpExceptionHandling", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpFeatureManagement", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpFeature", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpPermissionManagement", cultureName, cacheItem, service);
                    AddToLanguageDictionary("Saas", cultureName, cacheItem, service);
                    AddToLanguageDictionary("TextTemplateManagement", cultureName, cacheItem, service);
                    AddToLanguageDictionary("EpsilonThemeManagement", cultureName, cacheItem, service);
                    AddToLanguageDictionary("BlobStoringDatabase", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AuditLog", cultureName, cacheItem, service);
                    AddToLanguageDictionary("Core", cultureName, cacheItem, service);
                    AddToLanguageDictionary("Fines:CommonUI", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpDddApplicationContracts", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpGlobalFeature", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpLdap", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpEmailing", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpUiNavigation", cultureName, cacheItem, service);
                    AddToLanguageDictionary("AbpUiMultiTenancy", cultureName, cacheItem, service);
                }
            }

            return cacheItem;
        }

        private void AddToLanguageDictionary(string resourceName, string cultureName, LanguageTextCacheItem cacheItem, ILanguageTextRepository service)
        {
            var texts = service.GetList(resourceName, cultureName);

            foreach (var text in texts)
            {
                cacheItem.Dictionary[text.Name] = text.Value;
            }
        }
    }
}`

At first, I only added a few needed ressources.

But then I found out that many translations were missing.

It is not always clear to me what resource abp uses to get translations but after adding resources one by one, I ended up adding all ABP resources, just in case as there was always one ressource missing each time I tested.

Concerning the resources on our side, I can remove 2 at most.

After digging more with how ressources are loaded and when, I understand my mistake.

The CreateCacheItem method is already called for every resource ; by adding those dictionaries, I was making many unnecessarily calls.

For some reason, the exact code https://support.abp.io/QA/Questions/1642/Is-there-a-way-to-bypass-Tenant-for-Translations#answer-eea69656-8bb0-af79-e8fb-39fe16c17820 did not work when I first tried it 2 months ago ( bad copy paste ?) but now it is working.

Thank you

  • ABP Framework version: v5.1.2
  • UI type: Angular and MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): yes
  • Exception message and stack trace:
  • Steps to reproduce the issue:"
  • Log in
  • When on the Home page or any other page, try to switch the language -> some elements are updated in the target language but most don't

As you can see in the screen shot, there are 2 cookies .AspNetCore.Culture : one with path /CentralTools/Dev/masterdata and another with path /

After login, both of them have the same value, for example French.

When I change the language to English, only the one with the /CentralTools/Dev/masterdata path gets updated.

If I delete the other one (with path /) then everything works well ; I can change language any time, it is ok. But obviously we are not going to ask users to delete manually the cookie each time they log in...

What would you suggest to address this issue ?

Thanks,

Thomas

PS : This issue doe not happen locally or if the website is deployed at the root with IIS.

I have tried in incognito mode, no luck, same behavior.

You woud not have access to our integration server for security reasons ; I have tried from home, it does not work.

The culture (with / path) can be already set by other domain before you navigate to sub-domain.

This is probably true. The cookie with path '/' is set up at login. The cookie with the path /Centraltools/masterdata is set up at login and updated when I use the switch language feature.

Still I have no clue on how to advance from here. I was thinking maybe, I have to override the switch language cookie creation mechanism or on the contrary block the creation of the cookie with root '/'.

Any suggestion is welcome.

Thanks

Thomas

We can do a Teams or TeamViewer session if that helps. Just send me an email.

Thanks

Hello Albert,

Thank you for the answer. I'll test it asap.

Thomas

Hello Albert,

I am sorry but I could not test as we have a blocking issue with the build since thursday . I will test what you have suggested as soon as I can.

Thomas

Showing 1 to 10 of 13 entries
Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11