Displaying all the resources strings in a resx file - c#

I have a "GUI Strings" .resx file in my application that holds all the strings that I display. I can obviously access each string directly via
Resources.Resource_GUI_Strings.CameraSettings_BrightnessLabel
But how do I list all the settings in the .resx file, as their (name, value) pair, is my only option using reflection?
I want to list all the pairs (i.e. CameraSettings_BrightnessLabel & "Brightness") so that the user can edit the string for each item. This is so they can localise the GUI. I don't want to fully internationalise the app, the requirements are only for the user to be able to do it themselves.
So I need to be able to read the pairs of values from the .resx file and then write them back if the users edits them.
Just to add I want to do this at runtime inside the application itself, so I can't parse the .resx file on disk.

Normally I'd use the ResXResourceReader and ResXResourceWriter classes, but my guess is that your resx files will be locked at runtime. You may be better off storing the text in a database instead of resource files to get around this.
This answer shows how to make a custom resource provider / resource manager to store/edit resources in the database. Alternatively you could forgo the resource model altogether and roll your own solution.

Related

How I can programatically create another Column in resx file

Description:
I am working on a Dictionary for a MultiLingual,MultiOrganization CMS.
Currently we are using Database solution (Sql Server), but due to massive database traffic we are looking for an alternative solution and I have found .resx files.
Here we will be creating .resx file programatically and one .resx file/Language.
On every .resx file we want to add an organizationId.You can see the .resx file for English Language below.
We want this structure in .resx
Name Value Comment OrganizationId
About About this file is for english 1
Login Login this file is for english 2
The scenario is that when in my cms a lang is added i will be creating a resource file with it which will contain the dictionary(English key , that language value) for the language.
Now everything would have gone as planned if one word would have one meaning but there is a requirement that Two organization can one have different meaning for a single word.
for example word hello will have meaning abc for organization1 and it will have meaning abc2 for organization2.
My Question:
1.How can I do this using .resx file and if its not possible using .resx file then what is the most efficient (speed,maintainance,flexibility) alternate for this scenario.
My Code:
Currently I am trying this sample:
// Define a resource file named CarResources.resx.
using (ResXResourceWriter resx = new ResXResourceWriter(#"D:\VSProjects\CreateResourceFile\CreateResourceFile\CarResources.resx"))
{
resx.AddResource(new ResXDataNode("About", "About"){ Comment = "this file is for english" });
resx.AddResource("Login", "Login");
resx.AddResource("News", "News");
resx.AddResource("Headline", "Headline");
resx.AddResource("Information", SystemIcons.Information);
}
Resx files have strict schema and it does not include additional field you want. So even if you manage to add the filed (i.e. with regular XML API) standard .Net resource methods will likely fail to process such modified files.
Depending on your needs you may either use completely custom XML (LINQ-to-XML provides an easy way to create/read XML documents) or if you really want to use resx files - partition files by organization (in addition to language) like
text.org1.en-us.resx
text.org2.en-us.resx
text.org1.fr.rest

Can we skip ResourceManager?

I've working on a project where I'm using ResourceManager extensively and this question just crossed my mind.
Can we read from .resx files without using ResourceManager? I mean, is there another way?
ResourceManager is a convenience class, it works very well with the way the build system supports .resx files. No, it is not a strict necessity.
A .NET assembly has the generic capability of embedding arbitrary data into the manifest of the assembly. Just a blob of bytes, it can be anything you want. Directly supported by the build system as well, just add a file to your project and set its Build Action to "Embedded Resource". At runtime, you retrieve the data in that file with Assembly.GetManifestResourceStream().
You can stop right there, but that's just a single file, it doesn't scale very well if you have many small resources you want to embed. Which is where a .resx file starts, it is an XML file that contains resources in a friendly format. One that gives you a fighting chance to recover the source again when the original got lost.
But an XML format is not a very good format for resource data, it is bulky and it is expensive to find data back. So .NET has resgen.exe, a build tool that turns the XML file into a binary file, a .resources file. Compact and easy to find stuff back. And fit to be embedded directly as a single manifest resource.
What you don't want to do is having to read the .resources data yourself. You'll want to use a helper class that can find specific resources back from the blob of bytes. You want use the ResourceReader class, its GetResourceData() lets you specify the resource name and it will spit the resource type and data back out.
You can stop right there, but an app often has a need for different sets of resources. A very common localization need. Which is what satellite assemblies are all about, different assemblies that contain nothing but resources, each for a specific culture. They are separate so you don't pay for the virtual memory that's required to store all the localized resources when you need only one set of them. What's needed here is a helper class that automatically locates and loads the correct satellite assembly and retrieves the resource for you, based on the current culture.
That helper class is ResourceManager.
If you choose to skip the use of the ResourceManager you can let Visual Studio handle code generation for you. Ultimately the generated code uses a ResourceManager, but you're no longer writing that code manually. Additionally, you get compile-time checking since you're referencing a generated static class.
If you add a resource file to your project and double click it from the Solution Explorer, Visual Studio presents you with a dialog where you can enter a name for a resource, and its value. The dialog presents you with options to add resources as strings, images, audio, etc. (look at the dropdowns at the top of the dialog). Next, to get the code generation bit, you need to set the Access Modifier to either "Public" or "Internal". The third option is "No code generation."
For example, add a resource file called "MyResources", then add a string resource with the name Greeting and a value of Hello! With one of the former two options selected for code generation (start off with public to test it, restrict the access as needed), you should now be able to reference the resources from your code via MyResources.Greeting. If you don't see it right away, make sure you've saved the file and try compiling.
string greeting = MyResources.Greeting; // "Hello!"
If you add other resource types (image, audio, etc.) then the return types will differ, of course.
At this point you could inspect the generated .cs file and see that the generated code is using a ResourceManager. The other use for resource files is localization. Let's say you wanted a Spanish version of MyResources. You would add a new file called MyResources.es.resx, where es corresponds to the language code desired (Spanish in this case). Now add the same resource name of Greeting with a Spanish value of Hola!.
If you change the thread culture to Spanish, referencing the resource will now return the Spanish version:
string defaultGreeting = MyResources.Greeting; // "Hello!"
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("es");
string spanishGreeting = MyResources.Greeting; // "Hola!"
Note that you only really need to set the access modifier to one of the code generation options for your default resource file (i.e., MyResources.resx), not for all the other localized versions you add. There's no harm in doing so, but in my opinion it's cleaner to have the main file generated while the others just have the resource values desired without code generation.
Well, Resources are compiled into the assembly. You could try to read the assembly by reading the bytes (or the IL), and extract the resources from there.
ResourceManager does this all for you, so I could not think of any reason you want to do this... Maybe one, if you don't want to load the assembly in memory, you could do it without ResourceManager.
Ref Microsoft: Represents a resource manager that provides convenient access to culture-specific resources at run time.
I expect, I'd you use multi Lang, you will get a more consistent result and better compatibility.
IMHO

box with files, which cannot be seen from Windows

Good day, is there any option how to create a box, which cannot be seen from Windows? I would like to insert some files into this box. These files should be accessible only through my application, not from Windows. Thank you in advance.
How many files and how do you need to access them? If they are only for reading and you don't have too many, you always have the option to store them as a resource in your project. Have a look at this link on MSDN on how to store various file types directly inside your assembly.
NOTE: If you are planning on storing passwords or security-sensitive data, you shouldn't use this approach.
Another alternative would be to store you files inside a database. If you were to use something such as SQLite (here is the .Net data provider), Windows would have access to the database file, but not to the files contained within the database (which could be encrypted). Depending on your data, you'd have to store the file information as a binary large object (blob). See here for an example of how to do this.
It depends on the layer of abstraction you want. All files created by an application are at some level accessible by windows, however, you can mask the content of these files (i.e. encrypt them).
Generally speaking, you could still store the files in a folder, and apply encryption. Here's the msdn article on the point. The other issue is where do you store the key used for encryption.
A simple solution is to hard-code the key in some variable. However, if the assembly is decompiled, the key will become apparent. On the other hand, if you want the user that created the files to begin with, to be the only one to access the files, then you can use the Data Protection API.
If your question is how to the hide the box then you can set the "Visible" attribute to false no matter what control you are using for this "box".
if your box does not include a lot of files or not large file, you can try save it in a compress file like .zip and add a password for it. also add the hidden attribute on that box.

Localization Resources .NET - how to keep them synchronized?

When we follow localization guidelines we endup with at least a couple of resource files.
Resource.resx and Resource.CI.resx which is a specific CultureInfo resource.
Lets say we add a hundred string pairs in Resource.resx and want to translate those keys in another resource. we can copy paste them right now and translate them and it might work the first time.
However after we translate strings it becomes hard to keep files synchronized - it reorders strings automatically and I currently don't understand what is the supposed way to make sure each string is localized.
Since resource strings are supposed to be kind of linked with each other and with extra job that is done to make sure satellite assemblies are built correctly I was hoping theres a function like 'make sure each resource string is present in localized resource file' but I am afraid that one is missing..
RESX Synchroniser might do you what you are looking for
When you edit the .NET Resource files
in Visual Studio, either manually and
using the "Generate Local Resources"
command, the IDE updates only the
culture-invariant resources: if you
have a resource file called
Messages.aspx, the files in other
languages, say Messages.it-IT.resx,
are not updated, and you have to do
that manually. RESX Synchronizer will
help you keep the resource files
synchronized, adding the new keys to
the localized files, and removing the
deleted ones. Comments are preserved
during the process.
I just found http://zetaresourceeditor.codeplex.com/ as well seems like a similar idea to the others
may be UnitTest can help you? you know, which text each control should have, once you create them, after just add new strings to list and compare the values. after once hard working you can test your localization works right.
a little old this discussion, but still interesting. have a look at ResXManager
I know this has already been given traditional answers, but I would also like to put forward something completely original we tried (and succeeded) doing ourselves for more efficient localisation of Silverlight:
Localisation of Silverlight projects after completion
(Resx is so "last century")
I suggest you create culture specific resource files programmatically using the Resx file for that Winform.
You can create a small app which you could run time to time.
Create XML kind of file for each culture like fr.XML, fill that with the Union of all the strings in your project.And provide the translations there itself like, for example that file in french might look like the following..
< wordTranslation>
< Word>Hello< /Word>
< Translation>Bonjour< /Translation>
< /wordTranslation>
Create a hashtable or some data structure which would best act as dictionary for each culture, fill it with data from the culture specific XMl files like frDictionary.
For Each Resx file in your project for example wind1.resx , create a culture specific file like wind1.fr.resx.
Read words from wind1.resx, find the translation of the word from the frDictionayry.
Write it to wind1.fr.resx.
You can keep updating your translations in the XML file.
So its a one time effort.
This way you can keep it synchornised and easily maintainable.
You mean synchronize translations between those files? Use http://www.getlocalization.com and upload both as master files, when they are translated the translations are populated to all your files.
I think you can try Amanuens. It's developed by the same author of RESX Synchronizer and besides help keeping resource files synchronized (even automatically into your repository if you set it), can be used to give your translators access to strings to be translated in a very powerful and easy to use web editor.

adding different language strings to a single resource file

I have a small application, which includes a resource (.resx) file.
This file contains an icon, and a string, which is used by another application. The icon will be displayed on a button, and the string is the mouseover text.
What I want is in some way, to add strings in multiple languages, without having to crate additional .resx files.
Is there any way to do this?
I am writing my application in C#, and I would like to keep it in the .Net environment, and keep the resource managed.
Any help is appreciated - thanks in advance.
This would be an abuse of the way localization works in .net. It is meant to work like that - you create a resource file AND localized resource files containing .languageid. in the middle.
Of course, you can code your own "reader" method which appends some prefix to the resource name and then save several values in your file (for instance lv-formtitle, en-formtitle, ru-formtitle etc) , but - why?
If the problem is you do not want to copy the icon to several resource files - make 2 resources, one for icons, other for strings. Localize only the one containing strings.
Of course you can add more strings to your resource file, but they will have to have a different name and managed in your application that way (for example - "title" and "title-he") .
Doing this however, defeats the point of resource files.
You should use additional resource files, one per locale, even though you don't want to...

Categories