.resx vs database vs custom solution for providing Localization/Globalization - asp.net

At my office, we have had a long-standing debate about Localization/Globalization and how to handle it. One side pushes for the Resource (.resx) file route built in to ASP.NET, one side pushes for a database driven solution. A third group believes in rolling a custom solution.
Of course, each method has its own unique benefits and disadvantages - and we've discussed it over and over, without ever coming to a real consensus.
So, I pose it to the community: in your experience, which method provides the best mix of the following as the application grows:
Maintainability
Extensibility
Performance / Scalability
In addition to just advice, we'd also be interested in any open source projects which might help to simplify the question, as well. Thanks!

Rick Strahl (An MS MVP) has a great tool kit for managing localization via the DB - offer the ability to update and modify on demand through a controlled environment and does much of the heavy lifting for you. Histoolkit offer the following features:
Data Driven Localization Resource Provider
Database driven Localization lets you store resources in a SQL Server database.
Interactive Web based Resource Adminstration provides a live Web based adminstration for that can edit and update resources while the app is running
Resource Editing Control associates icons with each localizable control and allows jumping directly to the administration form with the current resource id and locale selected.
Resx Import and Export lets you import existing Resx resources, interactively edit them with the data driven provider, then export them back out as Resx resources.
Localization Utilities like a JavaScript Resource Handler, functions to embed localized script values and much more.
He also summarises the issues very well here (Ive pasted some good bits here - not my own work!)
To Resx or not to Resx
The default resource storage mechanism in .NET
uses Resx based resources. Resx refers to the file extension of XML
files that serve as the raw input for resources that are native to
.NET. Although XML is the input storage format that you see in Visual
Studio and the .Resx files, the final resource format is a binary
format (.Resources) that gets compiled into .NET assemblies by the
compiler. These compiled resources can be stored either alongside with
code in binary assemblies or on their own in resource satellite
assemblies whose sole purpose is to provide resources. Typically in
.NET the Invariant culture resources are embedded into the base
assembly with any other cultures housed in satellite assemblies stored
in culture specific sub-directories.
If you’re using Visual Studio
the resource compilation process is pretty much automatic – when you
add a .Resx file to a project VS.NET automatically compiles the
resources and embeds them into assemblies and creates the satellite
assemblies along with the required directory structure for each of the
supported locales. ASP.NET 2.0 expands on this base process by further
automating the resource servicing model and automatically compiling
Resx resources that are found App_GlobalResources and
App_LocalResources and making them available to the application with a
Resource Provider that’s specific to ASP.NET. The resource provider
makes resource access easier and more consistent from within ASP.NET
apps.
The .NET framework itself uses .Resx resources to serve
localized content so it seems only natural that the tools the
framework provides make resource creation tools available to serve
this same model.
Resx works well enough, but it’s not very flexible
when it comes to actually editing resources. The tool support in
Visual Studio is really quite inadequate to support localization
because VS doesn’t provide an easy way to cross reference resources
across multiple locales. And although ASP.NET’s design editor can help
with generating resources initially for all controls on a page – via
the Generate Local Resources Tool – it only works with data in the
default Invariant Culture Resx file.
Resx Resources are also static
– they are after all compiled into an assembly. If you want to make
changes to resources you will need to recompile to see those changes.
ASP.NET 2.0 introduces Global and Local Resources which can be stored
on the server and can be updated dynamically – the ASP.NET compiler
can actually compile them at runtime. However, if you use a
precompiled Web deployment model the resources still end up being
static and cannot be changed at runtime. So once you’re done with
compilation the resources are fixed.
Changing resources at runtime
may not seem like a big deal, but it can be quite handy during the
resource localization process. Wouldn’t it be nice if you could edit
resources at runtime, make a change and then actually see that change
in the UI immediately?
Using Database Resources
This brings me to storing resources in a
database. Databases are by nature more dynamic and you can make
changes to data in a database without having to recompile an
application. In addition, database data is more easily shared among
multiple developers and localizers so it’s easier to make changes to
resources in a team environment.
When you think about resource
editing it’s basically a data entry task – you need to look up
individual resource values, see all the different language variations
and then add and edit the values for each of the different locales.
While all of this could be done with the XML in the Resx files
directly it’s actually much easier to build a front end to a database
than XML files scattered all over the place. A database also gives you
much more flexibility to display the resource data in different views
and makes it easy to do things like batch updates and renames of keys
and values.
The good news is that the resource schemes in .NET are
not fixed and you can extend them. .NET and ASP.NET 2.0 allow you
create custom resource managers (core .NET runtime) and resource
providers (ASP.NET 2.0) to serve resources from anywhere including out
of a database.

As you perhaps know, default method (which is actually industry best practice) for Localizing .Net Applications is using resource files (.resx in this case). If you want to use database, you would have to write your own ResourceManager.
From this, the answer should be obvious: use standard and do not reinvent the wheel.
You might be wondering why Localization via resource files became industry-wide standard. Well, there are many reasons (too many to mention here), most of them regard to Localization process. The key one is, it is painfully hard to update (i.e. fix or install) translations for database driven Localization. Just think of what you need to install it - some SQL script. You know what will happen if you send out this for translation? Or even mistakenly update it? These kind of files are not very safe to work with (and they tend to be very large), so either you would need to create some kind of generator (with resource-like file as an input, which totally bits the purpose...) or you would need to be very careful (and pray that a translator won't break the file).
That is to say, database-driven Localization is sometimes the only sensible way of doing things - this is when you need to implement so-called dynamic Localization, that is allow users to translate things or add their contents in multiple languages.
For static Localization (typical scenario) use resource files.

Localizing user interface should not be stored in database, it is preferable to use the standard resx method because this will give you the flexibility to customize the user interface of front end for each client/deployment, without the need to change the back end or store much data about each client customization in database.
Regarding data (bi-lingual data or multi-lingual data) store them in database and use whatever technique suitable for the context (table per language, or duplicate columns for each language).

using resx is the best approach for some static values that needs not to be manipulated via UI of the app but if your values needs to be updated DB driven would be the best for it. For me its still a case to case basis. But one of the blogs I have seen in the internet made the resx files updateable via user interface.. http://sandblogaspnet.blogspot.com/2009/11/updating-resource-file.html.. hope this would help you.

As all the above are true, I want to add some additional insights.
I tend to use .resx based localisation, when working on "static" projects/websites like Dashboards or other small websites, which are focused on a specific usergroup.
When working on larger and more "dynamic" projects like shops, service-offerings, etc. (esp. when content is localized - not only labels) I like to use database localisation.
When you are developing on larger projects each language is maintained by another person, who is not necessarily in your project (especially in community-projects). Thus maintenance of different languages becomes a real hassle.
On the other side providing users some good/easy UI to update their language is time-consuming as well. So try to find a good path for your project.

Related

Implicit localization, strongly typed resources, App_LocalResources and embedded resources

tl;dr Does strongly typed resource code generation work with normal (non-embedded) resources in App_LocalResources?
If not then why, and does the alternative of using embedded resources in satellite assemblies work with implicit localization?
The rest of this post just explains where I currently am in solving these questions, feel free to ignore it if you know the answers.
When using implicit localization (meta:resourceKey="Foo" syntax), I understand that one would need to write their own resource provider if one wants to embed the resources in satellite assemblies. The reason would be that ASP.NET always uses the default provider for these, and that this provider expects resx files in App_LocalResources that can be retrieved at runtime. Also see this question, which has no answer at the time of this writing.
If that assumption is correct, then it doesn't seem possible to use strongly typed generated classes (using ResXFileCodeGenerator) without writing such a provider (which we'd like to avoid doing), as enabling code generation requires the use of embedded resources.
Because the use of generated types appears to work perfectly fine for global resources, I want to question that second assumption:
If I can generate strongly typed classes for global resources (in App_GlobalResources using GlobalResourceProxyGenerator) without embedding them in a satellite assembly (Build Action set to Content as opposed to Embedded), then why can't I do the same for local resources? Why can't the generated code find and use the resx files in App_LocalResources?
Note that the exception thrown when attempting to do this is a System.Resources.MissingManifestResourceException containing the following message:
Could not find any resources appropriate for the specified culture or
the neutral culture. Make sure
"PROJECT.App_LocalResources.PAGE.aspx.resources" was
correctly embedded or linked into assembly "PROJECT" at
compile time, or that all the satellite assemblies required are
loadable and fully signed.
I know that this message is misleading, as it clearly looks up satellite assemblies instead of trying the resx files (or whatever they're compiled to by the runtime, App_LocalResources.dll I guess).
If there is a good reason why this is not allowed (and we are thus forced to use embedded resources in satellite assemblies), is there a good implementation of a resource provider that can look up resources in satellite assemblies when doing implicit localization? Surely somebody has tried to do this before, and it doesn't sound like the application developer's job to tackle this kind of plumbing problem.
As a sub-question to the previous one, I also assume that when using embedded resources in satellite assemblies, one wouldn't put the resx files in the App_* directories, as these are special directories used by the runtime. Indeed, the resx files aren't even deployed, so the directories would be empty. Is that correct, and are there what would pass as best practices regarding this?
I suppose another way of formulating the question is: Can I make ResXFileCodeGenerator behave like GlobalResourceProxyGenerator when it comes to generating code that can load assemblies compiled by the runtime, as opposed to satellite assemblies compiled at build time?
Embedded resources can co-exist with ASP.NET Resource provider resources that live in the App_LocalResources/App_GlobalResources folder. But all the intrinsic WebForms localization features only work with the resources that are fed by the ASP.NET Resource Provider, which means the resources by default come out of the App_ folders only - not from embedded resources.
Embedded strongly typed resources do not use the ASP.NET Resource Provider - they use a stock .NET Resource Manager and when you use them you lose some of the optimizations that the ASP.NET ResourceProvider system uses vis a vis caching and loading of resources. It's more efficient in the ASP.NET scenario.
As you correctly point out it's possible to do this by creating a custom resource provider that reads embedded resources (or resources from another source such as a database), but you have to create this resource provider and hook it up. I wrote about this in an article some time ago (using a SQL database provider): http://www.west-wind.com/presentations/wwDbResourceProvider/
I wouldn't recommend mixing App_ folder resources from the Resource Provider with strongly typed resources because you'll end up with two different sets of resources loaded using different mechanisms. It works and can be done but it's just not very inconsistent. Pick one approach or the other. For Web Forms the resource provider model works better simply because it's the only way you'll be able to use implicit resources.
Note that ASP.NET MVC doesn't use the ASP.NET Resource Provider typically (although it could) and rather relies on strongly typed resources embedded into the code. If your WebForms code is mainly script based then using embedded resources might work well, but if you need to bind control properties the Resource Provider is the only way to go.

.net localization messages in xml configuration file instead of resources

I am wandering if I use xml configuration files(like castle.windsors component xmls) to store my localization strings and messages instead of resources file for the sake of flexibility. I may need to change messages frequently and getting frequent builds freaks me out. As the size of document I can say that I will have a couple of thousands strings stored in multiple xml files according to the languages. Is it a good practice to do this that way?
You could implement this Globalisation system provided by MVP RIck Strahl should suit your needs nicely and provide a lovely interface at the same time - also uses a DB as backing storage rather than XML files which should be easier to generally keep track of with regard to backing up and such forth.
On NuGet here
https://nuget.org/packages/Westwind.Globalization
Here's the project page and a summary direct from it (See the Data Driven Localization Resource Provider section).
http://www.west-wind.com/westwindwebtoolkit/

The "correct" way of using multilingual support

I just began working with ASP.NET and I'm trying to bring with me some coding standards I find healthy. Among such standards there is the multilingual support and the use of resources for easily handling future changes.
Back when I used to code desktop applications, every text had to be translated, so it was a common practice to have the language files for every languages I would want to offer to the customers. In those files I would map every single text, from button labels to error messages. In ASP.NET, with the help of Visual Studio, I have the resort of using the IDE to generate such Resource Files (from Tools -> Generate Local Resource), but then I would have to fill my webpages with labels - at least that is what I've learned from articles and tutorials. However, such approach looks a bit odd and I'm tempted to guess it doesn't smell that good as well. Now to the question:
Should I keep every single text in my website as labels and manage its contents in the resource files? It looks/feels odd especially when considering a text with several paragraphs.
Whenever I add/remove something, e.g.: a button, to an aspx file I would have to add it to the resource file as well, because generating the resource file again would simply override all my previous changes to it. That doesn't feel like a reusable code at all for me.
Perhaps I got it all wrong from tutorials as it doesn't seem like a standardized matter - specially if it required recompiling the entire application whenever some change has to be done.
Best practices for ASP.NET Web Forms localization have not really changed much over the years. If you don't have much dynamic content then you can get away with implicit localization and bind web forms controls (form elements and yes, even labels) to resource files. Explicit localization is useful if you want a bit more control over where localized text is rendered in a control with multiple captions or something you've created yourself. You don't need to look very far for instructional steps from MS on how to do either of these.
Walkthrough: Using Resources for Localization with ASP.NET
If your localization requirements are more dynamic, for example, you want to easily provision new languages, centralize resources, or you need to provision new string captions on a new dimension (like per client), then you need to get a bit more creative. .NET allows you to extend the
the resource provider and you can implement a database backend that allows for easy administration of localized resources.
Extending the ASP.NET 2.0 Resource-Provider Model, Building a Database Resource Provider
Extending Resource-Provider for storing resources in the database * A more recent implementation
Or you could just roll your own!
I've also dug up a duplicate SO post. It's a few years old, but speaking from experience I believe the advice found on the referenced code project page are still true (for Web Forms): Globalization and localization demystified in ASP.NET 2.0
I hope that helps! If you have any more specific questions regarding localization please add them to your Questions or comments.

Global resource vs. Local resource in ASP.NET

We use resx files to localize our web applications. We usually create local resx files (that map to a specific page) when only one page uses a certain phrase, and a global resx file when more than one page needs the phrase.
But the good thing about global resx files is that they are a class, and you can call the phrases like you call properties of a class:
Resource.UI.iNotFound
So I was thinking - why have local resx files at all? why not use one global resx file for the whole application, and that way avoid runtime errors from calling non-existent phrases?
I'm sure there's a good answer for that, I just don't know what it is....
I kept on looking for guidelines, and found this in MSDN:
Choosing Between Global and Local Resource Files
You can use any combination of global
and local resource files in the Web
application. Generally, you add
resources to a global resource file
when you want to share the resources
between pages. Resources in global
resource files are also strongly typed
for when you want to access the files
programmatically.
However, global resource files can
become large, if you store all
localized resources in them. Global
resource files can also be more
difficult to manage, if more than one
developer is working on different
pages but in a single resource file.
Local resource files make it easier to
manage resources for a single ASP.NET
Web page. But you cannot share
resources between pages. Additionally,
you might create lots of local
resource files, if you have many pages
that must be localized into many
languages. If sites are large with
many folders and languages, local
resources can quickly expand the
number of assemblies in the
application domain.
When you make a change to a default resource file,
either local or global, ASP.NET
recompiles the resources and restarts
the ASP.NET application. This can
affect the overall performance of your
site. If you add satellite resource
files, it does not cause a
recompilation of resources, but the
ASP.NET application will restart.
So it seems that it's really up to the programming team to weigh the pros and cons of each method and choose what's good for them.
Joe90 - I have to say that in my experience, I can't agree that managing lots of local resource files scattered throughout your whole project is easier than managing one, global resource file. There is nothing to stop repetition of the same translations again and again and they are very difficult to track down. Access to the Global resource file is very easy to co-ordinate within a team and multiple users can see at a glance whether their required translation has already been done.
I started off with exactly the same policy as Lea - i.e. start with a local resource file and then move this to a global resource file if it was referenced more than once. This soon became loads of hassle to manage and I've since moved to using global resource files every time now.
There don't seem to be any clear guidelines by Microsoft as to what the best practice is, or even, how the two methods are implemented so that we can hazard a guess!
I'm guessing the comparison/payoff is that local resource files only require a recompile of the file they relate to, whereas changing a global resource file seems to require a recompile of the whole web site - with an inherent loss of session state etc. so requires taking the site offline during the update to be safe.
I have a development team of at least 10 developers on a single product and we are using one global resx for each site.
The problem with merging this big resx file should in my opinion not be a problem.
If you have 10 developers who themselves set the language on the site, how do you get a uniform way to express themselves on the site? Developers often tend to be good at code and not the grammatical expression. (I am a developer myself.)
A language expert should edit resx file and lock it for the developers!
A Global Resource file is the best method for translation. The key is use a naming convention, like page name abbreviations for the first few letters of a string name so that you can locate resources per web page basis easily. Trying to reuse many phrases across multiple pages will cause more confusion for the translators.
You can define resuable phrases as much or as little as you want, like Yes, No, BTN_OK, BTN_Cancel, QTN_AreYouSure, etc by using a lack of page naming convention (no page name abbreviations for the first few letters). The majority of your lines of RESX will be specific to each page and you should not focus on trying to reuse as much as possible. Changing one phrase across the entire file can be carefully done in minutes using text find/replace when needed.

Localization CMS - Admin functionality to edit the localization files for Content Editors?

Are there solutions/tutorials/open source solutions to providing the functionality of having Content Editors edit ASP.net Localization files?
For example,
With Labels.resx and Labels.fr.resx, it would be great if theres an editor out there that allows End Users to end the content of the file.
I would suggest a database solution with caching. I found this article which might help. It has a complete provider along with a very good write up.
Creating a Data Driven ASP.NET Localization
Resource Provider and Editor
http://www.west-wind.com/presentations/wwDbResourceProvider/
ASP.NET 2.0 introduces a provider
model for creating custom Resource
Providers that can store localization
data in stores other than Resx files.
Resx resources are all fine and good
but putting data in a more flexible
resource store gives you many more
options for editing and administering
resources interactively and even at
runtime. In this article I'll
demonstrate how to create a new
Resource Provider that stores resource
information in a database and show a
resource editing tool that makes it
much easier to edit resources
interactively in the context of your
live ASP.NET applications.
Particular bit to note:
Resx Resources are also static – they
are after all compiled into an
assembly. If you want to make changes
to resources you will need to
recompile to see those changes.
ASP.NET 2.0 introduces Global and
Local Resources which can be stored on
the server and can be updated
dynamically – the ASP.NET compiler can
actually compile them at runtime.
However, if you use a precompiled Web
deployment model the resources still
end up being static and cannot be
changed at runtime. So once you’re
done with compilation the resources
are fixed.
I just wrote an application like that because I could not find a free soft that does resx editing:
Reads the content of all the resx files from a folder
Displays the values from different cultures but same resx besides each other
Generates/saves the resx files back
You might consider using structured XML files. Seems like this would be a more elegant solution than hacking .resx files to work in an unconventional way. You could use a LINQ query to get to the XML in a strongly typed manner similar to the resx file. Additionally, XML files could be edited by the user through the presentation layer since they aren't compiled into the application.

Resources