I am developing a Windows application and I want to store all the text for labels, radio buttons, buttons, check boxes and column headers of grids at one place. I have tried using a class file, an xml file, a database table and a resource file.
I found that a class file is the best way to store all these texts, but I want to know is there any alternative way? If I am using a class file then I will have to recompile the project if any text changes.
Will a resource file work properly for large amounts data? What about a dictionary or storing data in variables?
10
In short: It sounds to me like a localization of resources (different types like static labels, text, etc..). Generally speaking, changes in resource file content should not require a re-build of the application.
The dis-advantage to store resources in classes, is that each change/modification will require a re-build of the win-form application.
Will a resource file work properly for large amounts data?
I think the limitation is the file-size limitation of the operating system and that is 4 GB on 32 Bit systems, if I remember correctly. For 64 bit it should be even bigger. Anyway, for the purpose to store the static text, it should be more than enough.
Thus, in my opinion, this should not be done anywhere else if the text will be static.
An alternative approach would be creating a class to control access to your resource files. This class might be used to store the keys to access your resource files and a have strongly typed way to retrieve available resources of the project.
Some references on SE answers on localization and resources:
- Resource string location
- Globalize an existing Windows Forms application
- Using .resx files for global application messages
References from MSDN :
- Walkthrough: Localizing Windows Forms
- Resource Files (Visual Studio)
6
Portable Object (.po) is very popular and pretty much a standard outside of the .NET world. I saw it used in a few C# projects (e.g. https://github.com/OrchardCMS/OrchardCore/tree/d729a2048a4390380d99e7be9f7968ff8f8e9271/src/OrchardCore/OrchardCore.Localization.Core). There’s no official support for it, but the format is not that complex and there are some libraries for it: https://github.com/neris/NGettext
The format is definitely simpler than .resx as it’s not based on XML. You have many tools for it as well e.g. pootle, poedit and more…
Another option is to use some simple (or custom) format like JSON/YAML/TOML, or even something as simple as Key=Value
in plaintext with some file naming convention like Locale.{languagecode2-country/regioncode2}
. You could then embed it as a resource in your assembly 🙂 But then you have to come up with your own translation tooling, or some converter to/from po/resx to work with the existing tooling.
Other than that, .resx is the official way and first choice to go with. Tooling is decent too: https://github.com/dotnet/ResXResourceManager
I think you pretty much mentioned it all.
If you want something flexible, where you don’t need to recompile, then the DB might be your best option.
But otherwise I would go with .resx, as this is the standard.
Saving text inside class files is a rather bad idea.
Besides the .resx format, you can also use .txt or .restext files, which are in a simpler (and easier to read and edit) format.
Creating Resource Files for Desktop Apps (see the “Resources in Text Files” section)
The format is essentially name = value
, with the ability to have comments and conditional compilation.
Another option is to use whatever source or text file you want, and build the binary .resources file either manually or as part of a build step. (see “Resources in .resrouces Files” from the link above).
Either way, there is a little more work to get these into your project and compiling, but they both have the benefit of having support for multiple languages, just like the .resx file.
In C#, you’re almost certainly better off using a Resource file (which is an XML file). This gives you the following benefits:
- Removes need to re-compile entire solution for changes of text.
- Allows management of strings to be done by someone other than the coder (coders aren’t necessarily the best people to be writing user error/informational messages).
- Allows fairly trivial localisation.
2
I had a similar requirement before and I stored resources in a .resx file but I have decided to use classes for storing the keys.
For example, say I have resources for banking withdrawal screen.
I have created a simple class on the lines of
public class BankingWithdrawalResource
{
public string WithdrawFunds { get; set; }
}
I then implemented a class for retrieving resources. My aim was to have a strongly typed way of pulling out resources. I also wanted to make resource retrieval unit testable. I’ve extracted an interface for retrieving resources: IResource
.
Each time I wanted to use resources, I would get an implementation through IoC container.
var resource = Dependency.Resolve<IResource>();
Finally, when it came to using the resource, I would have something on the lines of:
resource.For<BankingWithdrawalResource>(p => p.WithdrawFunds)
In above line, I used lambda expression that allowed me to view all available resources through intellisense.
When it came to unit testing, I would mock IResource
and set expectations on it.
For example:
resourceMock.Expect(a => a.For<BankingWithdrawalResource>(p => p.WithdrawFunds)).Repeat.Once();
Also notice that we have extracted an interface for resource retrieval. Because of this, we are now able to store resources anywhere we want. For example:
public class DatabaseResource : IResource
{
// Logic to retrieve resources from database
// Won't cause recompilation
}
public class XmlResource : IResource
{
// Logic to retrieve resources from xml files
}
public class DefaultResource : IResource
{
// Will cause recompilation as resources are stored in .resx
}
I wrote above from top of my head in notepad, so if you have any problems let me know and I’ll add implementation later.
8
I have just done something similar following this CodeProject walkthrough: link
It is for making multiple easily updateable text files into resource files which you can add to your project in order to have different languages (in my case, a combo box allows me to change between as many languages as I create resource files for)
The advantage of this over .resx files is that you can have only 1 per language per project, instead of having to have 1 per language per form
Just something else to think about