Using SQL for localization instead of RESX files in ASP.NET - asp.net

I'm thinking of developing the following but wondering if it already exists out there:
I need a SQL based solution for assigning and managing localization text values for an asp.net site instead of using RESX files. This helps maintain text on the site without having to take it down for deployment whenever an update is required.
Thanks.

We actually went down that path, and ended up with a really really slow web site - ripping out the SQL-based translation mechanism and using the ASP.NET resources gave us a significant performance boost. So I can't really recommend you do that same thing.... (and yes - we were caching and optimizing for throughput and everything - and the SQL based stuff was still significantly slower).
You get what you pay for - the SQL based approach was more flexible in terms of being able to "translate" on the fly, and fix typos and stuff. But in the end, in our app (Webforms, .NET 2.0 at that time), using resources proved to be the only viable way to go.

We did this (SQL-Based Translation) and we are really happy with the result! We developed an interface for translation-agencies to perform the updates to the page online. As a side effect, the solution started to serve as content-management system. If you cache your data, performance is not an issue. The downside is, that we invested multiple hundreds of hours into our solution. (I would guess sth. arround 600 hours, but I could check.).

We ended up with a hybrid solution where users could edit content into a database but the application then created a .resx which was deployed manually.
You could also bypass the server translation altogether and do translation in jQuery on the client which is an approach I have used successfully.

I'm not sure about the website restart, but at least using .NET MVC is very convenient and I haven't noticed that restart problem, and, if occurs, how often you need to update the resx files? For bigger projects I use to create a solution with multiple projects, one for the localization, something like this:
MyApp.Localization
Model
Page
File1.resx
MyApp.Core
MyApp.Web
Then in the Web project I add a reference to the Localization project, and use it like
#MyApp.Localization.Model.Customer.CustomerName
#MyApp.Localization.Page.About.PageTitle
#MyApp.Localization.File1.Paragraph1
Everytime I change the translated text, I either upload an updated .dll or copy the .resx files.
NOTE: You need to set your resx files to PUBLIC, so can be accessed as strongly typed.

I created a SQL based translation scheme. But I only load the needed translations for a given page when it is requested, and just the ones for that particular page.
Those get loaded into a dictionary object when the page reloads and cached during the session. Then is just does text replacement based off a lookup on that.
Pretty much all of it is dynamically generated, and includes user defined content that must be translated, so the flexibility is key.
Performance is quite fast, the SQL queries to retrieve all the data take much longer (relatively speaking).

Related

Is there any .NET standard for dealing with localization yet allowing the users to customize the texts?

We're building an ASP.NET MVC application that is yet not localizable with a lot of Data Annotations DisplayAttribute with hard-coded strings and hard-coded message strings all over the code.
Now we have a requirement that the application must be localizable, but still, we need to allow the users to customize the field displays and the texts.
So far, I'm considering using RESX files with a custom IResourceProvider. Rick Strahl has written a good article about that. In this approach, the application is developed with standard RESX files, but in runtime, when the application need the strings, the custom provider will query the DB looking for customizations and will use them when found.
Even though it seems a good solution, it doesn't seem natural. I wonder if there's some better alternative.
Is there any standard for this?
What's not natural with using static values as defaults and checking database for localized ones? For me it's nice approach, because if someone will mess recources in db and, for example, remove one of them somehow, you'll always have a default text to display.
You can always do it in different way, by using only the db-based texts to not bother about changing defaults in your code and translations in database because it's easy to miss something when resources are in few places. When I was checking code of nopCommerce maybe 2 years ago, I've seen that when they do localization with resources from database only. I'm not sure how it's done now, but you can download source code and check it.
In WinForms app I developed a year ago I was using XML files for different languages because our customer wanted to be able to allow non-technical natives to create new language files. And I created localization tool built-in into app, but for websites it's best to use database, as you already have access to this and can easily manipulate data.
You can read more about this topic in this blog post.

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.

Localization (i18N) in ASP.Net Multi-tenant SaaS application

Problem scenario:
Implement ASP.Net localization in a SaaS based application.
Additional complexity: The tenant should be able to edit the localized content. Thus, if the hosted application has 10 tenants with each supporting 5 languages, we could end up with 50 units of translation content.
Please suggest on what would be an ideal approach given the above scenario.
Listed below, are approaches used in the past (for my other applications) and why they are not relevant now:
Option 1:
ASP.Net resource files
Problem:
Only one language file is created per localizable resource (.aspx page). Hence, it is not possible to have one Home.aspx.resx file for each of the tenant translations.
Though the resx keys can be modified to contain the TenantId (lblFirstName_44) and stored in the same resx file, but then this would be difficult to maintain and we could end up with large files.
Option 2:
Storing multilingual content in dedicated database tables (Labels, Messages, MenuItems)
Problem:
This has worked well in the past (in scenarios where the end user requires dynamic update of localizable content). The earlier solution relied heavily on cached data, in case of a multi-tenant solution the data would require extensive caching per page – per tenant. The caching could also be done per content type (Labels, Messages, MenuItems)
An alternate approach could be to implement a custom resource provider (by building on .Net’s existing provider)
Option 3:
Third party open source solutions like FairlyLocal
Problem:
Although very simple to implement, suffers from the same drawback as .resx files – not designed for allowing the end user to modify the content and to maintain multiple versions (tenant-wise) of same file.
Note: In case of not finding another solution, we would probably go with Option 2
I'd go for the second option. Especially since your resource entries are subject to modifications, resex files are not an option as you have said.
. You can easily find a good resource provider such as westwind one or write a custom provider.
The first option (storing translatable texts into resource files) is out. This would result in totally unmanageable mess.
The second option (using Database) is the most promising, just write your own Resource Provider, implement DB logic and you are done. In case of multi-tenancy, you would also need to provide valid context (based on URL?) and fall-back mechanism (so if the resource key is not found for this tenant, it would use default string) but these are minor annoyances.
As for third-party solutions I haven't heard of one that could be used in your context. You would probably have to implement almost the same amount of code as in case of DB solution (to support multi-tenancy) but you would end up with having a dependency on some vendor - this seems less flexible to me (just think how you would fix bugs...).
The only option that sounds scalable and maintainable is to store localized text in database. Resource type could be a bit complicated to map (such as images) but still a better solution than either of the other two.
It makes me wonder, how come Microsoft did not think of a solution to this challenge specially with their Azure initiative.

Single ASP.net site with Multiple Instances & web.configs

We have a legacy ASP.net powered site running on a IIS server, the site was developed by a central team and is used by multiple customers. Each customer however has their own copy of the site's aspx files plus a web.config file. This is causing problems as changes made by well meaning support engineers to the copies of the source aspx files are not being folded back into the central source, so our code base is diverging. Our current folder structure looks something like:
OurApp/Source aspx & default web.config
Customer1/Source aspx & web.config
Customer2/Source aspx & web.config
Customer3/Source aspx & web.config
Customer4/Source aspx & web.config
...
This is something I'd like to change to each customer having just a customised web.config file and all the customers sharing a common set of source files. So something like:
OurApp/Source aspx & default web.config
Customer1/web.config
Customer2/web.config
Customer3/web.config
Customer4/web.config
...
So my question is, how do I set this up? I'm new to ASP.net and IIS as I usually use php and apache at home but we use ASP.net and ISS here at work.
Source control is used and I intend to retrain the support engineers but is there any way to avoid having multiple copies of the source aspx files? I hate that sort of duplication!
If you're dead-set on the single app instance, you can accomplish what you're after using a custom ConfigurationSection in your single web.config. For the basics, see:
http://haacked.com/archive/2007/03/12/custom-configuration-sections-in-3-easy-steps.aspx
http://msdn.microsoft.com/en-us/library/2tw134k3.aspx
Example XML might be:
<YourCustomConfigSection>
<Customers>
<Customer Name="Customer1" SomeSetting="A" Another="1" />
<Customer Name="Customer2" SomeSetting="B" Another="2" />
<Customer Name="Customer3" SomeSetting="C" Another="3" />
</Customers>
</YourCustomConfigSection>
Now in your ConfigSection Properties, expose Name, SomeSetting, and Another. When the Property is accessed or set, use a condition (request domain or something else that uniquely identifies the Customer) to decide which to use.
With the proper implementation, the app developers don't need to be aware of what's going on behind the scenes. They just use CustomSettings.Settings.SomeSetting and don't worry about which Customer is accessing the app.
I know it might seem annoying, but the duplication is actually a good thing. The problem here is with your process, not with the way the systems are setup.
Keeping the sites separate is actually a good thing. Whilst it looks like "duplication" it's actually not. It's separation. Making changes in the production code by your support engineers should be actively discouraged.
You should be looking at changing your process to change once deploy everywhere. This will make everything a lot easier for you in the long run.
To actually answer your question, the answer is no, you can't do it. The reason is that web.config isn't designed to store user level settings, it's designed to store per application instance settings. In your case, you need an application instance per user which means separate config files.
For your system to work, you need to be able to preemptively tell the application which config file to use, which isn't possible without some sort of input from the user.
Use an external source control application and keep rolling out updates as required.
It isn't really a good idea to let your live site be updated by support engineers in real time anyway.
Depending on what is actually in the web config, and what settings differ between customers, you could opt to use a single web config, and store other customer specific configuration options in a database or some other custom xml/text file. As long as the specific customer settings in the web.config don't have to do anything with how IIS operates, and you are just using it to store values, then this solution might work out well for you.
Thank you all again for your answers. After reading through them and having a think what I think I will do is leave the multiple instances alone for now and I will try to improve our update process first. then I will develop a new version of the application that has the user configuration information in the database layer and then pick the user based on the request domain or URL as someone suggested. That way I can have a single application instance supporting multiple different client configurations cleanly.
As most of the client configuration data is really presentation or data source related, nothing complicated. I think we ended up with multiple application instances mostly because the original programmer hadn't been expecting multiple customers and didn't design for that so when someone came along later and added a second customer they just duplicated the application which is wasteful as each instance is about 99.99% identical to the original.
I am implementing this as we speak.
In the main web.config, I have 1 item per installation. It points me toward the custom config file I built for each client (and toward the custom masterpage, css, images, etc).
Using WebConfigurationManager.OpenWebConfiguration, I open the new webconfigs in their subdirectories. I determine which one to use by using System.Web.HttpContext.Current.Request.Url.OriginalString, and determining the uRL that called me. Based on that URL, I know which web.config to use.
From that point forward the clients all use the same codebase. They have their own databases too.
The idea of having to update 30-40 installations when we make an update scares the death out of me. We do not want to support 30-40 codebases, so there won't be customization beyond the master page, css, and images.
I wrote a custom class lib that knows how to switch to the proper webconfig, and read the custom section I built with all our settings.
The only issue I have now is the FormsAuthentication Cookie. I need to be able to switch that as well. Unfortunately, the property for the name is read only
If I understand correctly, it sounds like you have multiple deployments (one for each client) where the only difference is the web.config, right?
First off, although I don't know your unique situation, I would generally urge you to stay with separate installs. It usually allows much more flexibility. Off the top of my head: are you ever going to have customizations, or different clients running different versions? Are you sure? The easiest way to stay flexible here is to keep going with separate installs.
In my opinion, it isn't ugly at all if your practices are aligned properly. Based on some things you mentioned, you have trouble in that area - obviously, possible source control buy-in/training issues. But you are aware of that. I would also take a hard look at your deployment procedures and so on. I have a feeling you might have further issues in that area, and I mean absolutely no offense.
That said, let's say you want to move forward with this.
You didn't say whether all the clients share a single common database, but I'm thinking no, since designing that type of system is often not worth the extra complexity (which can be severe in systems of any size) so people often opt to keep them separate.
What that means is that you have store your connection string somewhere. Usually that would be web.config... So that seems to break our plan.
Really, the apparent elegance of this situation is almost always wildly offset by the challenges it introduces. If I thought about it hard enough, I could maybe find a way around this by introducing another database that intelligently manages connection strings or maybe delving into keeping all your login info directly in web.config (which is possible but... not ideal), however my gut says the work will be wasted because some day you will end up going back to how you're doing it now.
Also: changing code directly in production is obviously not the best practice here. But you if you are on a monolithic shared platform with any amount of traffic, that can never ever ever happen. Food for thought.
Let me know if I'm missing something!

ASP.NET XML ObjectDataSource Wrapper Class Examples

I want to use XML instead of SQLServer for a simple website.
Are their any good tutorials, code examples, and/or tools available to make a (prefer VB.NET) wrapper class to handle the basic list, insert, edit, and delete (CRUD) code?
The closest one I found was on a Telerik Trainer video/code for their Scheduler component where they used XML to handle the scheduling data in the demo. They created an ObjectDataSource class. Here is a LINK to that demo if anyone is interested.
[Reply to Esteban]
it would make deployment easier for clients that use godaddy where the database isn't in the app_data folder. also backing up those websites would be as simple as FTP the entire thing.
i have concerns about possible collisions on saving. especially if I add something as simple as a click counter to say a list of mp3 files visitors to the site can access.
In these days of SQL Server Express, I'd say there's really no reason for you not to use a database.
I know this doesn't really answer your question, but I'd hate to see you roll out code that will be a nightmare to maintain and scale.
Maybe you could tell us why you want to use XML files instead of a proper database.
It would make deployment easier for clients that use go-daddy where the database isn't in the app_data folder. also backing up those websites would be as simple as FTP the entire thing.
I have concerns about possible collisions on saving. especially if I add something as simple as a click counter to say a list of mp3 files visitors to the site can access.

Resources