I have status tables in my database, and ‘localised’ tables that contain language-specific versions of those statuses. The point of the main status table is to define the status ID values, and other meta-data about the status. The ‘localised’ table is to display the text representation in a UI, according to the users’ preferred language. Here is an example schema:
create table [Language] ( ID smallint primary key, ISOName varchar(12) ) create table EmployeeStatus ( ID smallint primary key, Code varchar(50) ) create table EmployeeStatusLocalised ( EmployeeStatusID smallint, LanguageID smallint, Description varchar(50), constraint PK_EmployeeStatusLocalised primary key (EmployeeStatusID, LanguageID), constraint FK_EmployeeStatusLocalised_EmployeeStatus foreign key (EmployeeStatusID) references EmployeeStatus (ID), constraint FK_EmployeeStatusLocalised_Language foreign key (LanguageID) references [Language] (ID) ) create table Employee ( ID int identity(1,1) primary key, EmployeeName varchar(50) not null, EmployeeStatusID smallint not null, constraint FK_Employee_EmployeeStatus foreign key (EmployeeStatusID) references EmployeeStatus (ID) )
This is how I’d typically access that data:
select e.EmployeeName, esl.Description as EmployeeStatus from Employee e inner join EmployeeStatusLocalised esl on e.EmployeeStatusID = esl.EmployeeStatusID and esl.LanguageID = 1
I’m not really happy that my LINQ to SQL is doing things in the most efficient way, though. Here’s an example:
using (var context = new MyDbDataContext()) { var item = (from record in context.Employees select record).Take(1).SingleOrDefault(); Console.WriteLine('{0}: {1}', item.EmployeeName, item.EmployeeStatus.EmployeeStatusLocaliseds. Where(esl => esl.LanguageID == 1).Single().Description); }
Personally, I’d probably leave the EmployeeStatus codes in the DB and move all localization logic into the client. If this is a web app (ASP.NET or ASP.NET MVC) then you’d use the the EmployeeStatus code as a key into a resource file, and then use UICulture=’Auto’ and Culture=’Auto’ to tell ASP.NET to pick up the right resources based upon the ‘Accept-Language’ HTTP Header.
You’d provide default (culture insensitive) resources embedded in your app, and allow satalite assemblies to override the defaults where they needed.
The problem, for me, with adding localization into the DB is that you firstly end up with much more complicated queries, you have to keep pumping the locale into each of these queries, and you can’t cache the outputs of the queries so widely. Secondly, you have a mixure of tables that hold entities and tables that hold localization. Finally, a DBA is required to do the localization.
Ideally you want someone who understands how to translate text to do the localization, and for them to use some tool that they’re comfortable with. There are plenty of .resx tools out there, and apps that allow language experts to ‘do their thing’.
If you’re stuck with DB tables for localization because ‘that’s how it is’ then perhaps you should query the lookups seperately to the real data, and join the two at the UI. This would at least give you an ‘upgrade path’ to .RESX in the future.
You should check out Guy Smith-Ferrier’s book on i18n if you’re interested in this area:
http://www.amazon.co.uk/NET-Internationalization-Developers-Guide-Building/dp/0321341384/ref=sr_1_1?ie=UTF8&s=books&qid=1239106912&sr=8-1