I've started using the WPF Localization Extension to localize my resources for WPF projects. I like the library because it can easily locate resource's out of the XAML-Code.
When I want to use the library to localize my resources in C# I have some problems. For a MessageBar (designed as UserControl in WPF) I want to set the displayed message in C# Code (ViewModel). The localized strings are stored in resource-files (the same which I used to localize strings in XAML).
Now my question, how can I localize my resources in C#-Code using the WPF Localization Extension? What is the best practice?
You can access your string values using this code.
public static string GetUIString(string key)
{
string uiString;
LocTextExtension locExtension = new LocTextExtension(key);
locExtension.ResolveLocalizedValue(out uiString);
return uiString;
}
Declare this method at a place where it is accessible to all the other classes. Then call it where ever you need the resource string and pass the resource key
Related
I have a C# .Net 4.5 WPF application.
The application have to be localizable. Which means I have to be able to change the labels/titles/button/text of everything visual in my application.
I have an existing model to take an id-String and return the text for the given language. Something like:
String localizedCancelText = Localize.Text("#Cancel"); //Cancel
String localizedMoneyLeftText = Localize.Text("#MoneyLeft",10); //$10 left
Where the Localize.Text(..) method is static.
This works all nicely.
The problem is with the labels/titles, thoses are set in WPF.
The idea is to have all labels(all visual) containing keywords insteed of english text. For example a WPF cancel button would be like:
<Button Content="#Cancel"/>
And then I have to take the "#Cancel" and lookup how cancel is written in the given language/location/department.
My question is:
How can I do this? I can set every label/button/text from codebehind, but that would be a ugly solution. I would much rather set it in WPF as shown above, and then "somehow" transelate the #Cancel using the Localize.Text(..) method to get the actual cancel text for the given language/location/department.
We use a software called Sisulizer that can parse the WPF and extract localizable strings. It can do that for all resources for that matter. We simply import all our resources into Sisulizer and the from there we export a csv file with required translations which we give our translators. Sisulizer builds satelite resource Dlls which we then use in our software.
it's better to use resource file .resx extension.you have to declare label and value in resx file.
My solution is based on this:
http://www.thomaslevesque.com/2009/07/28/wpf-a-markup-extension-that-can-update-its-target/
http://www.thomaslevesque.com/2009/08/23/wpf-markup-extensions-and-templates/
which allows me to use
<Button Content="{markUp:Localized Key=#BigButton}">
And still be able to change the language at runtime.
Is it possible to set localized resources from Code Behind to AppResources.resx File? I tried googling it didn't help much either. When I try to Access AppResources.(Key), I am getting error since there is no setter for the properties :-(
A localized string is concidered as a constant and should not be modified after its definition. So instead of trying to set your localized String from codebehind or from AppResources.Designer.cs, you might want to add a new one using AppResources.resx.
I am working on porting an iOS App to WP8. The iOS app is localized to 5 different languages. The localized strings are stored in different files. For example "app.strings" hold all strings unique for the app and "common.strings" hold strings that are used in other apps as well. Of course there are 5 versions of each .strings file (app.de.strings, app.en.strings, ....).
In the iOS code I can simple refere to "String_ID_123" and the system will automatically search for that string in all .strings files and display the correct value, no matter if this string can be found in app.strings, common.strings or elsewhere. Is this possible on WP8 as well?
VS automatically created two files to support localization:
AppResources.resx which holds the actual strings (with AppRessources.Designer.cs as code behind)
LocalizedStrings.cs which is a helper class to support binding
Of course I could add additional .resx files to the project and use them create the same structure as in the iOS project. But then I would have to add additional versions of LocalizedStrings.cs (e.g. LocalizedStrings_Common.cs) which refere to the correct .resx as well. Then I would have to explicitly use the correct Souce in XAML.
I would have to know where String_ID_123 is defines. Is there any way to let XAML/C# do that automatically?
I'm afraid VS isn't gonna help you with this. First, you cannot address String_ID_123 without specifying the resource file it resides in. Second, when you add additional resource files (e.g. CommonResources.resx) VS will not modify LocalizedStrings for you. You will have to do that yourself.
public class LocalizedStrings
{
private static AppResources _localizedResources = new AppResources();
private static CommonResources _locallizedCommonResources = new CommonResources();
public AppResources LocalizedResources { get { return _localizedResources; } }
public CommonResources LocalizedCommonResources { get { return _locallizedCommonResources; } }
And third, when you add new languages to your project, VS will generate AppResources.fr.resx for you but will not generate CommonResources.fr.resx. You'll have to add a copy your self.
I have a resource file in a Class Library project. I'm using this resource file to hold various messages the user may end up seeing.
For example, the name of the resource is "InvalidEmailAddress" and the value in the en-US resource file is "Invalid Email Address".
When I call the ResourceManager's GetString(string) method I am doing this:
return resourceManager.GetString("InvalidEmailAddress");
However, this seems really bad to me. What if somebody changes the name of the resource? Now my statement will return a null value.
Is there a way around this issue?
UPDATE: Localization is an important factor here. The resource manager is used in order to ensure I can change the culture and get appropriate string values.
You can instead use an automatically generated class - the magic string constants will be removed from the code and replaced with strongly typed access methods. VS names this file ResourceName.Designer.cs and updates it every time resx is modified in VS.
Sample of a generated method:
internal static string String1 {
get {
return ResourceManager.GetString("String1", resourceCulture);
}
Note: while creating this file is the default behavior when you add a new resource in VS, you may have disabled it or you may have tried to use the generated resource outside the assembly. In that case, make sure to set the "Custom Tool" property or resx file to "PublicResXFileCodeGenerator" or "ResXFileCodeGenerator" (later if you use resources only inside a single assembly). (Thanks #dbaseman for comment).
When you create a Resource, it will be generated strongly typed in the Resources namespace.
You can access it by Resources.ClassName.InvalidEmailAddress where ClassName is the name of your Resource (resx) file.
In asp.net I use like this:
gridView_Desti.Columns["CODE_DEST"].Caption = (string) HttpContext.GetGlobalResourceObject("Client", "Code_Dest");
How can I do the same thing on WinForm ?
Client is the resource name file --> Client.resx
Code_Dest is string on Client.resx --> string Code_Dest, value Code Destinataire
You should have an auto-generated class called Resources in the Properties namespace of your project. Each resource is exposed as a property in that class.
You can do :
Client.ResourceManager.GetString("Code_Dest");
Depending on the culture, it will look for the string in Client.en-US.resx (if en-US is your current culture) and if it fail, in Client.resx.
You can also acces like this (Code_Dest must be in Client.resx) :
Client.Code_Dest;
Add new item -> Resources i.e 'Resources1.resx'
Put necessary Resources Name & value ie string resources -> 'YourResourcesName' value whatever.
Access its value with Resources1.YourResourcesName
Hope this help,
If you don't have the namespace in, then prepend with "Properties" C# as so:
Properties.Resources1.YourResourcesName
Makes your code so much cleaner using the resx file. As an example, I have a DataGridViewImageColumn and assigned an image to it (from VS Image Library - the image is a .png file):
colAddNewItem.Image = Properties.Resource1.Add_16x;
FYI, in VB.Net it's
Resources.Resources1.YourResourcesName
There are many other ways, but this is the simplest, cleanest & preferred method.