RickStrahl / Westwind.Globalization

Database driven resource localization for .NET applications
543 stars 135 forks source link

Multi-tenant support #126

Open Juanllb76 opened 6 years ago

Juanllb76 commented 6 years ago

Hello,

We have been using it on a project and it worked really good.

Now we are developing a multi-tenant application in asp.net core. This multi-tenant app created to just have one installation where all tenants access. Depending on the host it shows data from one database or another. This allows us to just maintain one installation and each tenant has a database.

We use the same localization resources (fixed texts) for all the clients. But they have to be able to change those texts. Ending with a client having different texts than others. Same resources keys always but different values.

We don’t know how can we address this with this library, since it creates a Resource.cs file with all the translations and it changes it every time a user changes a text.

Is there any approach to solve this using your library?

Juanllb76 commented 6 years ago

After reading about the new version of WestWind, would it be possible to maintain each tenant in a different resource set, so we load each resource set on the first access to the tenant associated host?

RickStrahl commented 6 years ago

There's nothing built-in to support multi-tenant directly and that's because we basically hook into the .NET native localization pipeline which has no concept or support for extensibility.

If you search issues here you can find a few discussions around this where people have basically added custom fields to the database and then created custom versions of DbRes.T() (or some other method) that takes the tenant into account as part of the operation. But that's a customization that has to be done explicitly and is application specific because again - that only works with the explicit calls to these methods, not with the internals of the .NET localization features.

Juanllb76 commented 6 years ago

Thanks for your answer Rick,

I think I figure out a way of doing this using the package as is. In case it works for someone else...

SInce in our multi-tenant app we have a master db and one db for each tenant, we are going to use the master db for the localizations. This way we are going to have localizations in just one db.

We are going to have a resource set for each tenant. This way we can pass the tenantId to the views and controllers and get the localized texts for the specific tenant. On each call to the localized text DbRes.T("ResourceId") we are going to include the resource set, like DbRes.T("ResourceId", "TenantId").

As I mentioned before, we are doing this because we need each tenant to be able to change its localization texts individually. They are going to have an administration page to look for the resources and edit them. Of course each tenant would see only the resources of the resorceset corresponding with the tenantId.

In our case, only a few resources would be editable, this way we avoid having a huge resources database. We have around 3K resources, so if multiply that by 200 tenants...There is no reason for us to have words like "Name", "Surname 1"...editable.

So, for the editable resources we'll use DbRes.T("ResourceId","TenantId") and for those not editable DbRes.T("ResourceId") or DbRes.T("ResourceId","Default") if we want to use a resource set. Is it ok not to use a resource set? Can we make DbRes.T to go to a default resource set when we don't indicate anything?

Thanks.

RickStrahl commented 5 years ago

Closing because while I agree it would be useful for some scenarios this is too app specific to provide natively. May rethink this in the future but it will require changes throughout the entire provider to make this happen.

Frankly though at that point this isn't about localization anymore, but really becomes a mechanism of application personalization almost to the point of being a mini CMS which is beyond the scope of this tooling.