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.
Related
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.
At the moment I can think of three cases:
assemblies that don't contain any resources
control libraries that only contain images (ie. ToolBoxBitmaps) within their resource files
libraries that contain only text used for throwing exceptions (we don't want the user to see those anyway, do we? ;-) )
Am I right with these cases or not, and are there others I don't see right now?
Just because the a library contains only non-text resources does not mean that it doesn't need to be localized. Images may need to be localized too, either because they contain text, or because they are significantly influenced by cultural biases (granted, I know of no major applications that currently localize images for only that reason). There may also be language/culture-specific sound files.
Also, just because the only text in the library is exception text also does not mean that the library does not need to be localized. Even though you may not want the user to ever see your exception text, your developers will still see it; and not all developers speak the same language. All exception text in the BCL is localized for this reason.
I don't really see any advantage to ever using the invariant culture as the neutral language for an assembly. If you have resources in the assembly, you should use the native culture for those resources. If you don't, it doesn't really matter, so you might as well use the native culture in which the assembly is developed (or most likely to be used), so you don't have to change anything if you add resources in the future.
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
Given that (at least on NTFS) the filesystem on Windows is case insensitive, I would like to compare String fileA to String fileB as such:
fileA.Equals(fileB, StringComparison.CurrentCultureIgnoreCase)
The question then becomes which culture I should use, does the default current (ui?) culture suffice? I can't seem to find any BCL methods for this purpose.
You should use StringComparison.OrdinalIgnoreCase, according to Best Practices for Using Strings in the .NET Framework.
The string behavior of the file system, registry keys and values, and environment variables is best represented by StringComparison.OrdinalIgnoreCase.
If you use a culture for matching the strings, you may get in a sitation where for example the names "häl.gif" and "hal.gif" would be considered a match.
This is not possible to do reliably.
Yes, the case conversion for the file system is case-insensitive.
But the case conversion table is stored on the file system itself (for NTFS), and it does change between versions (for instance the Vista case conversion table was brought to the Unicode 5 level, so Vista NTFS and XP NTFS have different case conversion rules).
And the thing that matters is the OS that formatted the file system, not the current OS.
Then you can run into all kind of problems with other file systems (Mac OS does some kind of Unicode normalization (not the standard one)), Linux does not do anything, but Samba (implementing the Windows file sharing protocol) does. And has other tables than Windows.
So what happens if I map a letter to a network disk shared by Linux or Mac OS?
In general you should never try to compare file names. If you want to know if it is there, try to access it.
Marcus,
You might want to at look at the answer for another StackOverflow question, which is very similar: Win32 File Name Comparison , which in turn mentions http://www.siao2.com/2005/10/17/481600.aspx .
Following a link in another answer to the same question and digging further, I came across the following MSDN article http://msdn.microsoft.com/en-us/library/ms973919.aspx . It is worth a read in general, but when it comes to file name comparison it recommends using StringComparison.OrdinalIgnoreCase. See Table 1 in the article, which contains file paths as one of the data types handled or the following the quote:
So, when interpreting file names, cookies, or anything else where something like the å combination can appear, ordinal comparisons still offer the most transparent and fitting behavior.
Hopes this helps,
Boaz
Maybe you could try this:
http://msdn.microsoft.com/en-us/library/zkcaxw5y.aspx
You could use InvariantCulture (look at http://msdn.microsoft.com/en-us/library/4c5zdc6a.aspx).
In your example:
FileA.Equals(FileB,StringComparison.InvariantCultureIgnoreCase )
I tried this.
Path.GetFullPath(path1).Equals(Path.GetFullPath(path2))
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.