I have a C# app that needs to be localized. I can use the RESX .NET MUI strategy to do that. Now, I have a separate team that is providing additional localized resources (XML files) post build/compile time. I'd like to take advantage of .NETs MUI strategy which provides a nice fallback mechanism, but I can't seem to find a way to make that happen.
Note, I have thought about adding the localized file names (which I know) in my App's string resources file. However, if at runtime the file doesn't exist, then I'll have problems (and no way to automatically fallback).
So, is there a way to utilize the .NET MUI strategy in this scenario?
Option 1:
You can store the XML files in a resource, and then get a stream object to read it, which uses the same approach as is done with strings, etc. See http://msdn.microsoft.com/en-us/library/zxee5096.aspx for that.
Option 2:
You can also apply the same basic approach as that used by resources yourself. I've found it convenient with web applications which are often based on a lot of files (.aspx, .html, .css, .js, .png, etc) anyway. Say you've got a bunch of directories like:
localised/en/SomeFile1.xml (and etc....)
localised/en-US/SomeFile1.xml (and etc....)
localised/en-GB/SomeFile.xml
localised/fr/SomeFile.xml
I come along with my en-IE prefernces, and you don't match that, but you do match en and that's good enough (okay ideally you should pick up that en-IE is closer to en-GB than en-US, but that's totally into the bonus-credit territory and much better than .NET will do with resources).
Your matching algorithm should be:
Try to find a match for the locale sought, return if found.
Drop off the end of the locale, so en-GB-OED becomes en-GB, en-GB becomes en- and so on. If that doesn't remove the whole thing, go back to step 1 with this new locale.
Try zxx (zxx isn't used by .NET afaik, but it is used with BCP 47/RFC 4647 and ISO 639 for items with no lingual content - e.g. a passport photo of you is locale zxx because it's just as appropriate to go with a French document as a Yoruba or Welsh one).
Try a "default" locale as defined by you (or error if your application promises to make a good match).
At that point, you'll be doing slightly better than what resource files do. Still, mostly option 1 is a lot simpler and is far more self-contained.
Related
I have an localizeable c# application.
There is a file Localization.resx and a file Localization.de.resx.
The Localization.resx contains the invariant language - it is english.
The user should be able to select his preferred language. I found the first answer of this question Programmatic way to get all the available languages (in satellite assemblies) to determine which cultures are available. I see that there is de and InvariantCulture available.
But I can't offer InvariantCulture. An user wont know what this is. Instead I should offer en.
I can't rename Localization.resx to Localization.en.resx, since this file is needed to create the Class holding the resources.
I could copy Localization.resx to Localization.en.resx, but then I would always have to keep those files consistent and also need to remove InvariantCulture from the available cultures.
I could write a converter that visualizes the the InvariantCulture as en. But this, I think, is an ugly hack.
Any help please?
You can use the NeutralResourcesLanguageAttribute assembly attribute to set the neutral language.
[assembly: NeutralResourcesLanguageAttribute("en-US", UltimateResourceFallbackLocation.Satellite)]
This also makes it "fallback" to other satellites if a key is not found in one resource (if you ask for a key which is not defined in resource.en-US.resx, it'll search in resource.en.resx and finally in resource.resx)
I'm not sure how you are listing the language names, but in case this still gives InvariantCulture, you could have an empty Localization.en.resx, and with this method it'll find all missing resources in Localization.resx, so no need to have them in sync.
In the UI we let user know what "By Default" application has English localization. And offer to change it by showing all available options except Invariant. Also it won't be an ugly hack to write a converter that visualizes the the InvariantCulture as en.
I am about to start a localization project for my employer. It concerns a pre-existing project with many windows forms and an established code base, programmed in C# and ASP.NET. I have done research into how to localize an application in visual studio and found resources.
While these are an adequate solution to the problem, I am not entirely happy with the down sides of using resources. This is to say, it has a rather large footprint, requiring changes in each of the form files. Furthermore, the resource files are only editable from within Visual Studio. I would prefer enabling external translators without programming knowledge to do the translation.
So I came up with an alternative solution:
Build a static localization utility class with an extension method on String:
public static String Localize(this String s)
The utility class loads localization strings from file on startup. When the program needs a string somewhere, it is called as
"foo".Localize();
And the program would use the string itself as the key in the table to find the translation.
It seems a safe and effective solution, and I'm happy with the small footprint that it leaves on the existing codebase.
Basically I want to ask:
Are there downsides to my solution that I've missed?
Which file formats for the localization data should I look into (I've already encountered the .po file format)?
Is it a good enough reason to deviate from the resource files solution?
Any advice and/or considerations you may have will be appreciated.
You are trying to reinvent the wheel that MS invented long ago. You can use plenty of tools available for resources or even write your own Resources provider.
Some tools available: What tools are available for adding Localization to an ASP.NET project?
If you want to use a database for translators: Data Driven Resource provider from Rick Strahl
Are there downsides to my solution that I've missed?
I can point out some, what about the texts in the aspx files. Are you going to make your extension method available to them as well? That would be tough I guess.
e.g. <asp:Label Text="Title"> - how are you going to translate that?
Further, some of your claims are not entirely true.
the resource files are only editable from within Visual Studio
They are xml files , so you can use any editor to edit them or write a custom utility to do that.
Are there downsides to my solution that I've missed?
The standard resource files go beyond changing the text.
You might need to resize certain elements to fit the new text (if you don't use the existing layout management mechanism). And for some languages you will need to change the fonts/fonts sizes (think Chinese, Japanese, Korean) or alignment (think right-to-left languages like Arabic and Hebrew).
Also, translating standard files means that using an editor that is aware of the format one can see the dialog "as is", so it gives more context than stand-alone strings, which results in better translation quality.
We have a program that is used in one specific industry and has strings that are specific to that industry. We now have the situation where it can be used in another industry and we want to customise the strings for that industry without duplicating our code base.
The problem space appears very similar to localisation. Are we going to have a separate resource assembly for each industry? If so when would we choose which assembly to use, could we do this at install time or would it need to be at compile time?. How do we keep the separate resource assemblies synchronised, so that the same keys to messages appear in each one?
What is the best way to do this?
Let me re-phrase it: you have an industrial application which could be used in various industries and the only things that are different are resources (that is strings, layout, maybe images and sounds). The other code stays the same.
In such case your problem is not just similar it is actually identical to Localization. And as such you can use Satellite Assemblies.
Now, it is up to you if you want to package such created applications separately or distribute one application with both problem spaces.
The first seem more realistic scenario to me - you would need to decide on which .resx file to include at compile time (i.e. during project preparation you would overwrite existing resources with problem-space resources and then proceed with compilation, that should give you different flavors of your application; I would also modify their names in such case).
The latter would require you to manually instantiate ResourceManager at runtime to read from valid satellite assembly - it could be based on some configuration file. It means more work (you would need to actually modify your code) and you will end up distributing both flavors of your application at once, that is you won't have control over how your customers will use it. From the business perspective it could be a little dangerous.
EDIT (Note to self: read whole question carefully)
Somehow I managed to miss install time vs. compile time. I believe compile time is the answer because of the same reason I gave in config-driven switch section: you would package the resources and you won't have any control on how customers use it. Some clever guy would figure it out, that is for sure.
I would recommend having a properties file with key value pairs. Where you currently have industry specific strings, replace them with calls to the properties file. Obviously you would cache these strings in some container. I don't know the C# container - Java would use java.util.Properties.
aerospace.props:
INDUSTRY_NAME=aerospace
INDUSTRY_START_YEAR=1903
manufacturing.props:
INDUSTRY_NAME=manufacturing
INDUSTRY_START_YEAR=1600
If I would want to create a c# application that support multiple languages, how should I store them?
I'd probably use constants in the application as value holders.
Such as:
Console.Write(FILE_NOT_FOUND);
When compiled, it would change into the string determined by the language.
I'll probably stick to 3 languages (Danish, English, Deutsch), not that I think it matters though.
It seems to be a waste to have a class file for each language, which all is processed when the application is compiled. It would also mean that you'd have to re-compile and re-distribute the whole program every time you want to change a string.
As far as I know, hardcoded strings is a bad thing.
Maybe a text file?
English.txt
Line1: FILE_NOT_FOUND=File Not Found. Try Again
Line2
Line3
etc.
Danish.txt
Line1: FILE_NOT_FOUND=Filen blev ikke fundet. Prøv igen
Line2
Line3
etc.
and so on.
If the user selects English, it reads the text file and set the different constant values.
The last one I can think of is placing it in a SQL database.
Could you give me some input? :)
Also, I tried writing FILE _ NOT _ FOUND (without spaces, but the text editor wouldn't let me
Use a resource file. That's the standard way to handle localization.
For details, see this tutorial.
--- EDIT ---
An alternative tutorial is available here. This one uses much better naming, so it may be more clear how it works.
I think your best option is to use the built in localization resources of the .NET Framework. You can read more about the mechanics of that here.
As for using a database to store your localised elements (text, images and the like) this is certainly a common option, but I think it's mostely because developers understand getting data from a database, more than working with satellite assemblies and the like. There a number of problems with using a database, so I'll name only a few: 1) added complexity of deployment of the application 2) addtional load on the database server, 3) where do you store the localized messages to say that the database is down :)
Using some sort of text file (likely XML) also carries with it some deployment issues, but more importanly the percieved flexibility of making text changes 'on the fly' is somewhat over rated. Apart of spelling mistakes and awkward wording you'll almost always be shipping a new build as the text of your app changes.
Check out the Localization/Internationalization samples here:
http://msdn.microsoft.com/en-us/goglobal/bb688096.aspx
I've also heard good things about this book.
This topic is far too large for a reply.
The process of making a program ready for new languages is normally called "internationalization" or "i18n", and the process of taking that and actually making it run is "localization" or "l10n".
Briefly, you want to have hardcoded strings replaced by string resources, as you say, and then typically create different resource files for different languages. Assuming you're working in .NET (a fairly good assumption for C#), there's a lot of stuff Microsoft does to make it easier.
Remember that there are other localization issues than language. For example, the Danish currency symbol is probably not '$', but rather the Euro symbol, dates are almost certainly abbreviated differently, and many places use ',' for the decimal point and '.' for the thousands separator, opposite from the English practice.
I'm using Visual Studio (2005 and up). I am looking into trying out making an application where the user can change language for all menues, input formats and such. How would I go on doing this, as I suppose that there is some complete feature within .Net that can help me with this?
I need to take the following into account (and fill me in if I miss some obvious stuff)
Strings (menues, texts)
Input data (parsing floats, dates, etc..)
Should be easy to add support for another language
I'm not an expert with .NET by any means but Localization is never just as simple as "swapping out String values" or "changing date formats". There is much more to be taken into consideration such as layout, proper text placement.
Take Chinese for example. The way you read is top to bottom not left to right. If properly localized the app should take that into account.
http://msdn.microsoft.com/en-us/library/y99d1cd3(VS.80).aspx seems to be a good start though if you're dealing with Windows Forms.
The classic recipe is: design the app with no native language but a localization facility, and develop an initialization into one language (e.g., English). So you build the app and localize it into English every night; without the localization step it would not be usable. Do that well, and the resources for the initial sample localization can be replaced with those for any other language. Take into account non-roman scripts from the beginning. It's much cleaner to have a no-language app that always requires localization rather than a language-specific app that needs to have its native language subtracted and a replacement added.
For strings you should just separate your strings from your code (having an XML/DLL that will transform string IDs to real strings is one way to go). However you do need to make sure that you are supporting double byte characters for some languages (this is relevant if you use C/C++).
For input data what you want is to have different locale's. In Java this is relatively easy, and if you use C# it probably is quite easy also. In C/C++ I don't really know. The basic idea is that the input parsers should be different based on the locale selected at that time. So each field (textfield, textbox, etc.) must have an abstract parser that is then implemented by a different class depending on the locale (right to left, double byte, etc.).
Check the Java implementation for details on how they did it. It is quite functional.
You definitely need to be using the .NET ResourceManager and the resx file xml format, however there are a number of approaches to using this.
It really depends on what you are wanting to achieve. For me I wanted a single xml resource file (for each supported language) that could be modified by anyone. I created a helper class that loaded the global resource file into ResourceManager (once only) and I had a helper function that gives me the required resource for a given name. The only disadvantage in this approach was that I could not leverage dynamic binding of resources to properties.
I found this better and easier to manage than multiple or embedded resource files for every form. Additionally exactly the same approach can used in an ASP.NET application. I also found this approach means that outsourcing translation of resources and shipping language packs to customers much more manageable.
Microsoft's recommended approach is to use satellite assemblies, as described in Packaging and Deploying Resources. If you're using a ResourceManager to load resources, .NET will load the correct resources for the CurrentUICulture. This defaults to the user's current UI language setting in Windows.
It is possible to localize Windows Forms either through Visual Studio or an external tool, WinRes.exe. This article describes WinRes and how to use Visual Studio to localize the form.