Search code examples
c#resourcesinternationalizationmonodevelopglobalization

C#, Localization, Resources, and MonoDevelop


My problem is this: Using MonoDevelop (which is the preferred environment for a number of projects I'm working on) I'm trying to figure out how to use resource files for localized messages and how to properly include them in the project as an embedded resource.

My goal is to have a resources file with simple name-value pairs for message keys and their values, and have separate files for their localized strings e.g.

Messages.resources

Hello.World = Hello World
Goodbye.Cruel.World = Goodbye, Cruel World

Messages.de.resources

Hello.World = Hallo Welt
Goodbye.Cruel.World = Auf Wiedersehen, grausame Welt

I'm having a couple of issues.

First, what is the difference (if any) between MonoDevelop's .resources file and Visual Studio's concept of resources. From what I understand, MonoDevelop (and SharpDevelop) allow you to create .resources files, whereas Visual Studio utilizes .resx files and compiles them into .resources files (a binary file type) through the resgen utility. When using resources in MonoDevelop do I need to compile my resources (e.g. Messages.resources) using resgen? When I try to use just the straight .resources files that MonoDevelop allows me to create through their wizard I get the following error:

"Stream is not a valid resource file."

Second, once I have an appropriately generated resource file, I can embed them to my project, which if I understand it correctly, makes the resources a part of the assembly. If I have two files though, Messages.resources and Messages.de.resources, MonoDevelop (at least) assigns them the same ID value when I embed them. Do I need to have my default localization included in the project and then a separate project for each supported locale? Following up on this, how does C# distinguish between my Messages.resources and Messages.de.resources files (or whatever files they are)?

I'm currently trying to resolve my message resources with the following code:

...
public string Translate(string messageKey, CultureInfo cultureInfo) {
    ResourceManager resourceManager = new ResourceManager("My.Project.Messages", Assembly.GetExecutingAssembly());
    string message = resourceManager.GetString(messageKey, cultureInfo);
    return message;
}
...

I feel like I'm missing some fundamental points in the effort of internationalization/localization/globalization etc. with C#. I have worked on internationalized projects in Java before, but for some reason I can't quite wrap my head around it in C#.

Also, as an aside--what is the "preferred" directory structure for resources in an internationalized project?


Solution

  • I'm not familiar with .NET localization (I use gettext), but as I understand it, .resources files are a binary format that's actually embedded into your dll. You can compile resx (XML) or text resources into the binary format using resgen. Text files are more readable but can only be used for string resources. XML is more verbose but can represent everything that binary resources can.

    The usual thing is to store your resources in .resx form in the project, and MonoDevelop will automatically compile them into .resources files when building your project (you'd have to compile .txt files manually). Unfortunately MD doesn't have special editing tools for resx files, so you'd have to edit the XML directly.

    MD does have nice localization tools for gettext, but these aren't currently supported on Windows.