Click here to Skip to main content
Click here to Skip to main content

WPF Runtime Localization

By , 14 Feb 2010
 

Update: This article has been rewritten after a helpful comment by Kingsley Moore below made the solution much, much simpler and easier to add to an application.

Design-time support in Expression Blend

Contents

Introduction

This article is yet another attempt to address the problem of localizing WPF applications in a simple and maintainable fashion.
In this case, I also wanted to be able to:

  • Switch cultures at runtime - automatically updating all localized elements
  • Use the existing Resource file structure (*.resx files), which can be maintained in Visual Studio
  • Keep design-time support for localized elements working in Expression Blend (and hopefully other XAML design applications)

The example application has a few localized strings to show it working, but since there's only so many ways to demonstrate localized strings, I've kept it brief.

The original implementation presented in this article required a wrapper class around the set of properties, which was a hassle to either manually or auto-generate. This update removes the need for this wrapper, making this much easier to use.

Background

There have been a number of other articles on this subject, including Localizing WPF Applications using Locbaml which covered different methods of localizing XAML files, each with their own advantages and disadvantages. The first approach in that article (Targeted Localization Without Using LocBaml.exe) got me thinking, but I had to diverge from that approach in order to trigger runtime auto-updating (for all elements, even on existing Windows).

Another earlier project is WPF Multi-Lingual at Runtime, which does provide a solution for runtime auto-updating, but to my mind introduces complexity in the management of the language resource files. By maintaining support for existing *.resx files in this article, we can still use existing applications to easily translate applications to new cultures.

I thoroughly recommend reading and understanding both these articles, there is a lot of information there, as well as useful tricks that have helped me a lot in other projects.

Using the Code

Automatic Updating with ObjectDataProvider

In order to get automatic updating when we change the current Culture, I am exploiting the characteristics of the ObjectDataProvider. The little gem of information from the MSDN page is:

"This class is also useful when you want to replace your current binding source object with another object and have all the associated bindings updated."

So all we need to do is replace (or refresh) the ObjectDataProvider object instance, and any bindings on the ODP properties will be updated automagically.

Here is where this solution has been improved. While it is possible to directly bind to the properties of the auto-generated RESX designer class (Resources.Designer.cs), we also need to get an instance of this class for the ODP. All ResXFileCodeGenerators (both default and custom) mark the Resources constructor as internal, meaning it can only be accessed from within the same assembly. (This also means the constructor cannot be accessed from XAML - i.e. using an ODP ObjectType.) To solve this, we can use the MethodName property on the ODP. (An alternative might be to extend an existing custom ResXFileCodeGenerator to mark the constructor public, but there is no need for that.)...

<ObjectDataProvider x:Key="Resources"
    ObjectType="{x:Type cultures:CultureResources}" 
    MethodName="GetResourceInstance"/>

... with the method:

public Properties.Resources GetResourceInstance()
{
  return new Properties.Resources();
}

Use of MethodName means that the ODP will become the object returned by the method, allowing us to bind an instance of the Resources class. We can create this instance because the call to the internal constructor above is coming from within the same assembly, not directly from XAML. Works like a charm.

One constraint for this to work is that the Resources class must be public, as we cannot return an instance of an internal class using a public method (this gives a lovely compiler error). This means we could use either the Extended Strongly Typed Resource Generator[^] which works in both Visual Studio 2005 & 2008, or the PublicResXFileCodeGenerator tool that ships with Visual Studio 2008. I like the Extended Code Generator as it generates super helpful string formatting methods as a bonus.

public static void ChangeCulture(CultureInfo culture)
{
  //remain on the current culture if the desired culture cannot be found
  // - otherwise it would revert to the default resources set,
  //   which may or may not be desired.
  if (pSupportedCultures.Contains(culture))
  {
    Properties.Resources.Culture = culture;
    ResourceProvider.Refresh();
  }
  else
    Debug.WriteLine("Culture [{0}] not available", culture);
}

Updating the current culture is quite simple, I have added a method to the CultureResources class that updates the current Resources Culture and triggers an update on the ObjectDataProvider, causing it to call the GetResourceInstance method, updating the ODP ObjectInstance, which refreshes any bindings on the ODP - which are updated to the new resource values.

Design-time Support

At design-time, Properties.Resources.Culture is initially set to the Neutral Language set in the project, or the Culture of the current thread if a Neutral Language has not been set. Either way, any bindings will default to the strings in the default Resources file (Resources.resx).

Adding Localized Strings

All strings that you want to localize need to be defined in all Resource files for localization to work, so it is generally easier to add more cultures after you have set everything up with the default Resources.resx file. Otherwise you would need to add each new string to all existing RESX files.

Add strings to resx files

We can then add a binding to the desired UI element:

<Label x:Name="labelCultureName"
    Content="{Binding Path=LabelCultureName, Source={StaticResource Resources}}"/>

And if we have added this resource string to the default Resources RESX file, after recompiling the project this default string value should now show up in the designer, and also of course when you run the application.

If you see the case that a string added for a Resources file other than the default seems to always show the default value, check that the resource string name in each RESX file is correct. If you have binding errors, then the Path set in the Binding does not match any strings in any of the RESX files, and it cannot even fall back to the default RESX value as in the previous case.

Adding More Cultures

Copy default Resource file to add new culture

A simple way to add another culture to your project is to Copy & Paste the default Resources.resx file in Visual Studio to create a new file. Select a suitable culture code from the list on the MSDN CultureInfo reference page. Add the culture code in the extension as in Resources.Fr-fr.resx, which Visual Studio will use to create the localized DLL when the application is built. Now that you have a new RESX file, you can change the resource values for the new culture and you're done.

Enumerating Available Cultures

Example using ComboBox to select from available cultures

With a number of cultures added to this project, the code used to enumerate those we have implemented can be demonstrated. I have made this dynamic to avoid any need to rebuild the application when a new culture is added. For an existing installed copy, you just need to create a folder with the new culture name and put the new correctly named resources DLL inside. Restart the application and it will be available (or if you are importing a culture from within the application, this method could be modified to search the install directory again).

Debug.WriteLine("Get Installed cultures:");
CultureInfo tCulture = new CultureInfo("");
foreach (string dir in Directory.GetDirectories(Application.StartupPath))
{
    try
    {
        //see if this directory corresponds to a valid culture name
        DirectoryInfo dirinfo = new DirectoryInfo(dir);
        tCulture = CultureInfo.GetCultureInfo(dirinfo.Name);

        //determine if a resources DLL exists in this directory that
        //matches the executable name
        if (dirinfo.GetFiles(Path.GetFileNameWithoutExtension
            (Application.ExecutablePath) + ".resources.dll").Length > 0)
        {
            pSupportedCultures.Add(tCulture);
            Debug.WriteLine(string.Format(" Found Culture: {0} [{1}]",
                tCulture.DisplayName, tCulture.Name));
        }
    }
     //ignore any ArgumentExceptions generated for non-culture
     //directories in the bin folder
    catch { }
}

The above is a relatively quick way of checking the applications bin directory for any folders that match Culture names. The CultureInfo.GetCultureInfo method will fail as desired if the string argument does not match any of the defined CultureInfo types.

Design-Time Solution for UserControls

A problem arose for me in the veiled form of the UserControl. If the properties that you want to localize are accessible external to the user control (added to the code-behind file as dependency properties), then there is no problem, you can localize them as described above. However, if the properties you want to localize are not externally accessible, such as a Label Content property, then the solution is a little trickier.

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="WPFLocalize.UserControl2"
    x:Name="UserControl">
    <Grid x:Name="LayoutRoot">
        <Label x:Name="labelUserControl2"
            Content="{Binding Path=LabelCultureName,
                    Source={StaticResource Resources}}"/>
    </Grid>
</UserControl>

When you add a binding to a label inside a UserControl as above, it will be rendered correctly at runtime, and also at design-time (e.g. in Blend) when it is loaded up by itself. Unfortunately it will fail to render correctly when you load up a window that contains the UserControl. (This seems to only be a problem in Expression Blend, the Visual Studio 2008 Designer will render correctly in this situation.)

I understand that the problem when loading a UserControl as a child of a Window is that the designer creates an instance of the control and then adds it to the Window. The Resources that would be available at runtime are not present because the instance is not created from within the window, and so the above binding fails and the control cannot be rendered. After many failures trying to work around this situation, I eventually came up with the following:

public UserControl2()
{
#if DEBUG
    //only perform the following fix if we are in the designer
    // - the default ctor is not executed when editing the usercontrol,
    //   but is executed when usercontrol has been added to a window/page
    // NB. The Visual Studio designer might return null for Application.Current
    //     http://msdn.microsoft.com/en-us/library/bb546934.aspx
    if (DesignerProperties.GetIsInDesignMode(this) && Application.Current != null)
    {
        Uri resourceLocater =
            new System.Uri("/WPFLocalize;component/ResourceDictionary1.xaml",
                UriKind.Relative);
        ResourceDictionary dictionary =
            (ResourceDictionary)Application.LoadComponent(resourceLocater);
        //add the resourcedictionary containing our Resources ODP to
        //App.Current (which is the Designer / Blend)
        if (!Application.Current.Resources.MergedDictionaries.Contains(dictionary))
            Application.Current.Resources.MergedDictionaries.Add(dictionary);
    }
#endif
    this.InitializeComponent();
}

Using the DesignerProperties.GetIsInDesignMode() means this code is only executed at design-time, and all it's doing is adding the ResourceDictionary that contains our Resources ObjectDataProvider to the designer itself, so that they will be available when the UserControl is initialized. This will actually be a second instance of the ODP, which would be bad at runtime (as only the first one included in App.xaml would be updated), but fine at design-time as we will not be updating the culture. Problem solved.

Limitations

In this example I am using WPF Bindings, which require Dependency Properties to bind to. There are other cases where you might want to access these properties, but adding a binding is not appropriate or easy to accomplish. An example of this is when you want to access a localized value direct from code. In order to keep auto-updating working in this case, you can hook an eventhandler on the ObjectDataProvider DataChanged event, which is triggered after we update the ODP. So, when values are re-fetched in the eventhandler the updated resource values are available. Alternatively you can just make sure you re-fetch the localized value after you know the ODP has been updated, there is little difference.

ResourceCultureProvider.DataChanged +=
    new EventHandler(ResourceCultureProvider_DataChanged);

void ResourceCultureProvider_DataChanged(object sender, EventArgs e)
{
    Debug.WriteLine
        ("ObjectDataProvider.DataChanged event. New culture [{0}]",
        CurrentResourceCulture.LabelCultureName));
}

History

  • January 2008 - Initial release
  • May 2008 - Rewritten, removing need for wrapper class
  • February 2010 - Updated links

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Andrew Wood
Software Developer siliconcoach ltd
New Zealand New Zealand
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionNot working with MergeDictionaries for me [modified]memberSonia Molina7 Feb '13 - 0:38 
Ok, that was sooo stupid from me. Code works sooo fine. It's really fast and I really say: 5/5!! Really good. But I have a little problem. Andrew, if you could help I would be so thanked.
 
The problem is, when I add my ResourceDictionary.xaml to my App.xaml and remove it from my design windows, I can't see styles at design time. Any idea on why?
 
Have to say too: really clear and well explained example for a so needed topic.

modified 7 Feb '13 - 12:25.

AnswerRe: Not working with MergeDictionaries for mememberAndrew Wood7 Feb '13 - 9:34 
Hi,
 
If I remember correctly, the Visual Studio designer doesn't load resources from App.xaml at design time, only at runtime. So when you eg. load up a Window xaml file, you only see resources that the window can loads directly - either included in the window resources or in resources included by custom/user controls on the window.
 
Perhaps some code can be put in the window constructor to include the resources from App.xaml, but only to run at design time - similar to the code in the article for handling User controls at design time?
 
At runtime resources in App.xaml are loaded first, so it should all be working correctly already?
 
regards,
Andrew
GeneralRe: Not working with MergeDictionaries for me [modified]memberSonia Molina22 Feb '13 - 1:05 
Hello Andrew,
 
Yes, at runtime it's working perfect. The problem comes with the design mode, but I also read that if I load a ResourceDictionary from App.xaml, for Visual Studio 2010 it's not solved yet to show styles on design time.
 
My real problem comes:
 
My UserControls, at runtime, don't change language... If I'm debugging at Debug or Release mode, it works fine. But if I execute the App, the UserControls I created ignore the language I chose. Any idea on why?
 
EDIT: Maybe some extra info will help:
I'm creating my UserControls programatically (not shown at MainWindow at first).

modified 22 Feb '13 - 7:59.

SuggestionRe: Not working with MergeDictionaries for mememberAndrew Wood22 Feb '13 - 20:27 
Hi Sonia,
 
As mentioned, for design-time to work with usercontrols you would need to add code similar to section in the article under "Design-time solution for usercontrols". This uses GetIsInDesignMode so that the code only runs at design-time, then loads the Resource Dictionaries needed for the usercontrol manually.
 
I'm not sure if it's practical to try to build something that does this automatically (eg. perhaps at design-time, before InitializeCompoent is called, try to automatically load all resource dictionaries from App.xaml), I'm sure there would be cases where this still wouldn't work. Might have a play with this sometime, but not sure when that would be.
 
As for not working when you run the app outside visual studio - are you running the same exe from the VS output folder, or are you copying the exe somewhere else? If you are copying the exe somewhere else, make sure you copy all the resources folders as well (eg. "fr-FR" for french, the resources dlls are inside these folders). If these do not exist in the same location as the exe when you run it, the culturew ould not change as you are seeing.
 
One idea to check if this doesn't help - does it work when you run the exe directly from the Debug/Release output folder?
GeneralRe: Not working with MergeDictionaries for mememberSonia Molina27 Feb '13 - 4:09 
Actually it only works when running from Visual Studio (doesn't make any difference between Debug/Release). But it fails from the .exe directly. And no, I don't copy it out from my folder Frown | :(
 
I think I'm gonna investigate a bit further... For the moment I load a specific language and don't allow to change it at runtime. If I finally find a solution I will post it Wink | ;)
 
Thanks Andrew Smile | :)
GeneralRe: Not working with MergeDictionaries for mememberAndrew Wood27 Feb '13 - 11:38 
Some ideas:
- Try disabling the Visual Studio Hosting process - exe project settings, debug tab. Am curious whether this would lead to the same behaviour in the debugger as when running exe directly.
- Are you using Debugger.IsAttached anywhere? Could be leading to the behaviour you are seeing.
SuggestionHow to change language at run-time in WPF with loadable Resource Dictionaries and DynamicResource Bindingmemberrhyous27 Jan '12 - 9:59 
Andrew,
 
If you have time, It would be great to get your feed back on this method I wrote for WPF localization.
 
How to change language at run-time in WPF with loadable Resource Dictionaries and DynamicResource Binding
 
Thanks!
QuestionhelpfulmemberCIDev30 Aug '11 - 3:44 
A very helpful article; thanks for the update. Smile | :)
Just because the code works, it doesn't mean that it is good code.

GeneralMy vote of 5members0h028 Jun '11 - 9:54 
Great solution for lokalization... thanks a lot.
NewsWorking in WPF, VS2010 and Windows 7memberismamad21 Jun '11 - 4:24 
Hi,
 
First of all thank you for a great post even after three years (more or less).
 
This has shed some light over me since I was not managing to get it to work. I ended up doing some changes and some points where not very clear like:
- Changing the resources file to a custom folder but leaving the namespace pointing to Properties
- The necessity of the ComboBox handler being added on the begining before setting the default values (allows values to filled in first, without it, no values will be found)
 
Anyway I will set the code straight and I can send it to you for an update.
 
Thanks once again,
GeneralRe: Working in WPF, VS2010 and Windows 7memberAndrew Wood21 Jun '11 - 12:00 
Hi,
 
Thank you for your kind words.
 
You are right, it really doesn't clearly explain what to do if you move the resource files to a different folder. As you have probably found you need to set the Custom Tool Namespace on the resources files to correct this. The sample code I does show an example of this though, where the resource files are all in the Cultures folder.
 
I'm not totally sure what you mean about the Combobox handler - do you mean that the binding needs to have been added before setting the default selected value? I would be interested to see an example of this, a code snippet here would be fine.
 
Regards,
 
Andrew
GeneralMy vote of 4memberismamad21 Jun '11 - 4:20 
Just to say that I managed to make it work on WPF with VS2010 SP1 and Windows 7. There where some tricky parts though like having to set the resources namespace and using the event handler to detect changes and doing nothing with the handler. Great help and thank you for a great post (even after three years) Wink | ;)
GeneralRe: My vote of 4memberMember 827596512 Mar '12 - 2:24 
I have runtime errors with the binding. May you send me your solution?
GeneralRe: My vote of 4memberAndrew Wood12 Mar '12 - 10:43 
I am not sure what sort of problem you seem to be having. Does the sample code work ok? If so then there might be a typo - make sure the Binding matches the string you are trying to bind to, it must match exactly (uppercase characters too). Visual Studio should give you a pointer as to which Binding is affected.
 
If you are still having problems perhaps you could post some code snippets here - the Binding string, the resource name and any other description about how you are using this code would be helpful.
GeneralRe: My vote of 4memberMember 827596512 Mar '12 - 21:08 
Hi, thanks for your answer. The sample works great.
App.Xaml
<Application x:Class="MultiLangTestNeu.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml"
             xmlns:culture="clr-namespace:MultiLangTestNeu.Cultures"
             xmlns:local="clr-namespace:MultiLangTestNeu"
             >
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ResourceDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>
ResourceDictionary.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:cultures="clr-namespace:MultiLangTestNeu.Cultures"
                    xmlns:properties="clr-namespace:MultiLangTestNeu.Properties">
 
    <ObjectDataProvider x:Key="res" ObjectType="{x:Type cultures:CultureResources}" MethodName="GetResourceInstance"/>
    
    <!-- CultureResources ODP provides access to list of currently available cultures -->
    <ObjectDataProvider x:Key="CultureResourcesDS" ObjectType="{x:Type cultures:CultureResources}"/>
    
</ResourceDictionary>
MainWindow.xaml
<Window x:Class="MultiLangTestNeu.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:properties="clr-namespace:MultiLangTestNeu.Properties"
        xmlns:cultures="clr-namespace:MultiLangTestNeu.Cultures"
        xmlns:projekt="clr-namespace:MultiLangTestNeu"
        Title="MainWindow" Height="350" Width="525">
        
    <Grid>
        <ComboBox Name="cbLanguages" Height="25" Width="100">
            <ComboBoxItem Content="Deutsch" IsSelected="True" />
            <ComboBoxItem Content="Englisch" />
        </ComboBox>
        <Label x:Name="labelCultureName" Content="{Binding Path=land, Source={StaticResource res}}"/>
    </Grid>
</Window>
The Error is here (I think):
CultureResources.cs
private static ObjectDataProvider m_provider;
public static ObjectDataProvider ResourceProvider
{
    get
    {
        if (m_provider == null)
            m_provider = (ObjectDataProvider)App.Current.FindResource("res");
                
        return m_provider;
    }
}
If I debug the code "App.Current" has no resource element at this time.
GeneralRe: My vote of 4memberMember 827596513 Mar '12 - 5:10 
I got it Cool | :cool:
My Error was in the CultureInfo. I have added "en-EN" instead of "en-GB" and nothing worked.
GeneralRe: My vote of 4memberAndrew Wood13 Mar '12 - 10:51 
Good thinking, that would have confused me too.
 
The full list of culture names is available at msdn[^] but you've probably already seen it.
GeneralMy vote of 4membermacabre13@o2.pl20 Dec '10 - 23:12 
Works like a charm. Thanks
QuestionProject is not updated?memberMember 474288812 May '10 - 0:23 
Hi Andrew,
 
Thanks for publishing this solution, I really need it. Just 1 question, I read in this article that there's no need to change from "internal" to "public" what's inside of Resources.Designer.cs. But the solution I downloaded has them all "public" and has a comment that says that it was generated with "ResXFileCodeGeneratorEx".
 
So, I would like to know if this is the most updated solution and I understood something wrong, or if this is an old solution. If that's the case, could you please let me download the most recent one that matches your article and doesn't need to change the "internal" in that Designer file?
 
Thank you very much.
AnswerRe: Project is not updated?memberAndrew Wood12 May '10 - 0:52 
Hi,
 
When I was talking about the need to change internal to public it is talking about the class itself - the default ResXFileCodeGenerator creates an internal class in Resources.designer.cs. This solution would not work if the resources class was marked internal. Using the ResXFileCodeGeneratorEx is what fixes this, it makes sure the designer class that is generated is public like we need. Sorry if it is a little confusing in the article, what the solution does is change the default behaviour so that the resources can now be used.
 
You could test this if you like, on one of the resx files change the property with ResXFileCodeGeneratorEx in it to ResXFileCodeGenerator and right click on the resx file, choosing "Run Custom Tool". This will rebuild the designer class, and you would see that it is now internal instead of public. If you went and ran the solution now it would not work, can't remember the error exactly off the top of my head. Change back to ResXFileCodeGeneratorEx and it will work again after a rebuild.
 
Does that make a little more sense?
GeneralRe: Project is not updated?memberMember 474288812 May '10 - 3:34 
Thanks for your quick answer! Yes, I understood. You helped me a lot! Thanks!
QuestionHow to access images in the resource file with this method [modified]memberMember 27122018 Apr '10 - 19:58 
Hi,
 
When accessed an image from the resource file using this method, it always shows blank!
<Image Source="{Binding Path=New, Source={StaticResource Resources}}" Height="100" Width="100"></Image>
 

is there anything I'm doing wrong?
 
PS: the images are embedded in the resource file.
 
thanks
modified on Friday, April 9, 2010 2:30 AM

AnswerRe: How to access images in the resource file with this methodmemberAndrew Wood9 Apr '10 - 2:52 
Hi,
 
The problem here is that you can't set a System.Drawing.Bitmap as the source of a WPF Image. You should see binding errors in the debug output when you try this that look something like the following:
 
System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.;
Value='System.Drawing.Bitmap' BindingExpression:Path=TestImage; DataItem='Resources' (HashCode=50833863);
 target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource')
 
Most of what that is telling you is that the target property (Source) is expecting an ImageSource and you gave it a Bitmap.
 
When using images usually you set the Source property to a Uri, and if I remember correctly behind the scenes wpf is loading that up as a BitmapSource for you.
 
My quick way around getting localized images working is to localize the image path, as I did in my sample. If you want to be able to embed the image in the resx file, then you need to convert the bitmap to load it as a bitmapsource.
 
I think this can be done with an IValueConverter on the binding, which will take the bitmap object and load it as a bitmap source. A likely way of doing this would be to use System.Windows.Interop.CreateBitmapSourceFromHBitmap() in the Convert method.
 
hth
 
Andrew
QuestionCannot get it to work in new projectmemberMember 27122018 Apr '10 - 1:33 
Hi,
 
Thanks for the great solution,. I can get your downloaded project to work.
But, I cannot get this working in a new project I created.
 
I have uploaded the solution at http://rapidshare.com/files/373411683/LocalizationTest.zip.html[^]
 
I would be grateful if you could solve my problem
 
Thanks Smile | :)
AnswerRe: Cannot get it to work in new projectmemberAndrew Wood9 Apr '10 - 2:40 
Hi,
 
I'm not sure why, but the text format of the resx files was somehow incorrect. Didn't look too much into why exactly, but deleting & recreating the resx files worked fine. I think the text format had been changed in some way that resulted in a compiled resources dll that then didn't work correctly, and it always resulted in the default value when doing resource lookups. Maybe you copied the base resx file using windows explorer to created the finnish resx file? I have always created and copied my resx files from within the visual studio solution explorer, and that works in this case too.
 
hth
 
Andrew

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 14 Feb 2010
Article Copyright 2008 by Andrew Wood
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid