I recently had some C# code that that had to be made localizable. Most articles about localization/internationalization that you find on the web would talk about how nice Visual Studio is for code internationalization and would show nice examples of how many ways the forms-designer would extract code out into a resx file. I am perfectly ok with studio doing all the work for you. However there are very often, strings in your actual code that studio does not externalize to resx files.
Strings.rb is a ruby script that will parse your C# code base and identify literal string definitions in the code base and will move them to your resx file. The code was hacked up to fill out a personal need so your mileage on this may vary. The tool certainly isn’t fool proof and there are certain cases that it doesn’t handle too well. If you are however on the smart-scripter side of things then you may find it useful.
The script needs to be setup for your specific project. Once done you can run it several times on your code base and it can incrementally catch strings and externalize them for you. This is handy to have while your code is still undergoing changes so new strings can be identified as they pop up and can be moved out.
Getting Started
Downloads
1) First thing download the script (strings.rb) and put it in your project folder.
2) Download and install ruby from here – http://rubyforge.org/frs/?group_id=167, its about 12mb and the installation happens in a snap.
3) Download an install REXML library for XML handling in Ruby from here –
http://www.germane-software.com/archives/rexml_3.1.2.zip
http://www.germane-software.com/software/rexml/docs/tutorial.html
Patching Strings.rb for your project
1) You need to patch the script file to have the correct path to your resx file and the path to your wrapper class that will be used to read strings from your resx file.
Open the script file in a text editor. (If you have ruby installed you should find this editor called scite in the ruby installation folder – that’s a nice editor. Alternately you might want to try installing scite - http://scintilla.sourceforge.net/SciTEDownload.html - about 600k).
In your project identify your resx file. It will usually be in Properties\Resources.resx.
Change the following line the rb file to reflect the path path to your resx file.
strings.rb:4:$resx_fn = "properties/Resources.resx"
(The actual line number might change a bit)
2) Now create a new class in your project called Strings. VS should typically create an empty class definition file that looks like this.
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
#endregion
namespace <Some Namespace>
{
public class Strings
{
}
}
Patch the file with the following additions
- Add a using directive for your ‘Properties’ namespace.
- Add a comment that stays //start and one that says //stop. These ad as delimiters between with the script will generate the string definitions.
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
using <Some namespace>.Properties;
#endregion
namespace <Some Namespace>
{
public class Strings
{
//start
//stop
}
}
3) This is the wrapper class into which the script will generate string definitions. You need to patch the script with the path to this class file. Basically patch this line –
strings.rb:5:$stringsclass_fn = "helper/Strings.cs"
Done
If you have got this far then your installation is done and you are ready to go.
For sake of completeness let me just list out things again –
1) download the script and put it into the project folder
2) install ruby
3) install the REXML library for Ruby
4) patch the script with the path to the resx file of the project
5) create a empty Strings class and add the namespace directive and comment markers to it
6) patch the script to have the correct path to your Strings.cs file.
What does the script do?
The script does a few basic things.
1) it parses your *.cs files in all subdirectories and looks for strings.
2) when it finds a string a it prompts the user for an action
3) if it is a string that should be localized the user can provide a pseudonym for the string. On getting this name the script will -
1) add the string and the name to the resx file
2) add a property to the Strings class that will read the string from the rex file
3) replace the string literal in the code with a call to the property.
Running the script
To run the script after all the previous setup, simply go to the command line and type strings.rb
Here is a sample run of the Strings.rb script
Let me take up a simple project and show you how the internationalization script works.
Here is a project that has only one Program.cs file –
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
#endregion
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string a = "hello world";
string x = "skip this line";
string b = "escape sequences \n\r\t\\\"";
string c = @"cant handle this one";
}
}
}
The resx file looks like this –
<?xml version="1.0" encoding="utf-8"?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
(I have removed some unnecessary details from the original resx file here)
I created this Strings class –
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
using ConsoleApplication1.Properties;
#endregion
namespace ConsoleApplication1
{
public class Strings
{