Hemme's Blog

Stories from behind the keyboard

  • RSS
  • Twitter
  • Linkedin

One straightforward way to localize a Windows Phone 7 application you are writing is the following:

  • Create and edit a .resx file (for instance LocalizedStrings.resx).
  • Build your project, so that Visual Studio (well, the PublicResXFileCodeGenerator tool) generates the .Designer.cs file. This way your assembly is having a nice LocalizedStrings static class that you can use in your XAML.
  • Register the static class as an application resource, in your App.xaml:
<Application ... 
 xmlns:my="clr-namespace:{your default namespace}">
<!-- .... -->

<Application.Resources>
  <!-- .... -->
  <my:LocalizedStrings x:Key="Loc"/>
</Application.Resources>
  • Feel free to bind to any localized string in your XAML using the built-in Managed Resource Editor. For instance, if you have a string resource called MyLocalizedString, image you can write somewhere in your XAML’s:
<!-- .... -->

<TextBox Text="{Binding MyLocalizedString, Source={StaticResource Loc}}" ../>

<!-- .... -->

At this point you build and run your project….

image

...and sudden notice that your program gives a creepy "AG_E_PARSER_UNKNOWN_TYPE" error. (“WTF!?”): image

This error says that the runtime parser doesn't know a type, but stays absolutely silent about the type’s name! The unknown type is just the LocalizedStrings class and it is unknown to the parser because the PublicResXFileCodeGenerator tool made its constructor internal.

image

Editing by-hand the code behind is pointless, since every time you edit or add a resource in the Managed Resource Designer, the PublicResXFileCodeGenerator tool rebuilds the LocalizedStrings.Designer.cs and (re-)sets the constructor to “internal”.

At this point you can take one of the following steps:

  • Commit to Android development
  • Change your mind about binding to resources
  • Use an IL weaving technique and make the constructor’s access modifier public
  • Follow KISS and YAGNI principles (kind of..) and just replace “internal” with “public” before building your project.

The latter is the path I followed, after a little struggle with NuGet (I couldn’t find any proper NuGet Fody add-on, precisely).

To put it shortly, I wrote a tiny REPLACE.EXE console utility. It takes 3 input parameters: a full filename, a text to find and a text to replace. Then I set the following pre-build action for my WP7 application project - $(ProjectDir) is a Visual Studio macro; you can find it and more on  MSDN’s “Pre-build Event/Post-build Event Command Line Dialog Box” page).

image

image

This way, anytime I build my project, REPLACE.EXE resets the LocalizedStrings contructor to public.

All’s well what ends well; happy programming!

P.S: Here’s the RESET.EXE’s Main()…

image

2 comments:

Anonymous said...

Why have you not set the Access Modifier of the resource file to public?

In the project file change

ResXFileCodeGenerator

to

PublicResXFileCodeGenerator

Marco Mariotti said...

I did used PublicResXFileCodeGenerator, as you can read in my post. The problem is that the generator makes the dictionary's .ctor "internal" so the Windows Phone infrastructure is unable to invoke it, as you can see in the above code fragment picture. Don't get me wrong: this issue is typical of WP7 and the PublicResXFileCOdeGenerator does a good job in WPF.