Click here to Skip to main content
15,891,951 members
Articles / Programming Languages / C#
Article

RESX to XLS conversion for multi-language support

Rate me:
Please Sign up or sign in to vote.
4.72/5 (24 votes)
25 Jul 20072 min read 189.6K   12.2K   61   39
Easily convert your RESX projects files to Excel and back to localized RESX

Resx2Xls ScreenShot

Introduction

Do you need to localize your RESX files and don't want to open them one file at a time, clean them of unused keys, localize them etc., etc.? Then Resx2Xls is for you.

  1. Open Resx2xls. Click on "Create new Excel document...," select your Project Root and follow the wizard. Done!!
  2. Fill your Excel file with your localized key values or just send it to your translator.
  3. Now, do you want to create the localized RESX files from the filled Excel workbook? Open Resx2xls, click on "Generate resx files...," select your Excel file, click Next and then click Finish. Done!!
  4. Have you updated your project after your resource files were modified/added/removed/updated? No problem. Open Resx2xls, click on "Update your Excel document...," click Next, select your Project Root and Excel document and click Finish. Done!!

Thanks go to Manish Ranjan Kumar and his WizardBase control. It has helped me to give the application a more decent style.

Background

I was frustrated with copying my project resource files created in VS 2005, cleaning them of unused keys and then localizing them one file at a time. This tool should help you to just point and click at your project and obtain an Excel file filled with all of the strings of ALL of your resource files. After compiling the XLS with the translations, I wanted to convert all of the keys back into localized RESX files. I hope this helps!

Points of interest

I've had some problems loading resources with the ResxResourceReader class. I've noticed that if you have an image resource stored in the resource file, the path of the image in the XML document is relative to the document itself, not the project. Opening from another directory, i.e. Resx2xls bin, I get a "cannot parse" path exception. This was solved by setting the BasePath property of the resource reader with the path to the RESX file.

History

  • 25-7-2007: Article edited and posted to the main CodeProject article base
  • 5-7-2007: Added wizard
  • 4-7-2007: First release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Italy Italy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: License Pin
matmat19823516-Sep-10 13:16
matmat19823516-Sep-10 13:16 
GeneralIt works great but... Pin
patokike8-Oct-09 3:27
patokike8-Oct-09 3:27 
GeneralIdentifying unused string keys Pin
trinity7917-Sep-09 6:56
trinity7917-Sep-09 6:56 
Generalexisting translations Pin
Patrick Mortara11-Aug-09 22:29
Patrick Mortara11-Aug-09 22:29 
GeneralRe: existing translations Pin
jaxwax16-Oct-09 9:58
jaxwax16-Oct-09 9:58 
GeneralRe: existing translations Pin
Patrick Mortara16-Oct-09 11:06
Patrick Mortara16-Oct-09 11:06 
Questionno comments? Pin
kevin.floyd17-Dec-08 12:15
kevin.floyd17-Dec-08 12:15 
GeneralProblem with App_LocalResources - extra files Pin
uswebpro230-Sep-08 21:38
uswebpro230-Sep-08 21:38 
Hello,
I found this program works great with the GlobalResources, however with the App_LocalResources, it creates duplicated files for each language. If you have the same problem, check out the script below. I put it on the web form + wire it to a button click, and it deletes the extra files and keeps the ones you need. - Yes I know this is a cheap "band aid solution" but its quick and worked 4 me.

public partial class Temp_RemoveBadLocalFiles : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}
protected void Button1_Click(object sender, EventArgs e)
{
string folder = @"C:\Users\aron\Documents\Visual Studio 2008\WebSites\TheaterSalesCorporate\App_LocalResources\";
Label1.Text = TraverseTree(folder);

}

public string TraverseTree(string root)
{
StringBuilder sb = new StringBuilder();

// Data structure to hold names of subfolders to be
// examined for files.
Stack<string> dirs = new Stack<string>(20);

if (!System.IO.Directory.Exists(root))
{
throw new ArgumentException();
}
dirs.Push(root);

while (dirs.Count > 0)
{
string currentDir = dirs.Pop();
string[] subDirs;
try
{
subDirs = System.IO.Directory.GetDirectories(currentDir);
}
// An UnauthorizedAccessException exception will be thrown if we do not have
// discovery permission on a folder or file. It may or may not be acceptable
// to ignore the exception and continue enumerating the remaining files and
// folders. It is also possible (but unlikely) that a DirectoryNotFound exception
// will be raised. This will happen if currentDir has been deleted by
// another application or thread after our call to Directory.Exists. The
// choice of which exceptions to catch depends entirely on the specific task
// you are intending to perform and also on how much you know with certainty
// about the systems on which this code will run.
catch (UnauthorizedAccessException e)
{
sb.Append(e.Message);
continue;
}
catch (System.IO.DirectoryNotFoundException e)
{
sb.Append(e.Message);
continue;
}

string[] files = null;
try
{
files = System.IO.Directory.GetFiles(currentDir);
}

catch (UnauthorizedAccessException e)
{

sb.Append(e.Message);
continue;
}

catch (System.IO.DirectoryNotFoundException e)
{
sb.Append(e.Message);
continue;
}
// Perform the required action on each file here.
// Modify this block to perform your required task.
foreach (string file in files)
{
try
{
// Perform whatever action is required in your scenario.
System.IO.FileInfo fi = new System.IO.FileInfo(file);
if ((fi.Name.Substring(2, 1).Equals(".")) || ((fi.Name.Substring(0, 6).Equals("zh-CHS"))))
{
sb.AppendFormat("DELETED FILE: {0}: {1}, {2}
", fi.Name, fi.Length, fi.CreationTime);
fi.Delete();
}
else
{
sb.AppendFormat("GOOD FILE: {0}: {1}, {2}
", fi.Name, fi.Length, fi.CreationTime);
}
}
catch (System.IO.FileNotFoundException e)
{
// If file was deleted by a separate application
// or thread since the call to TraverseTree()
// then just continue.
sb.Append(e.Message);
continue;
}
}

// Push the subdirectories onto the stack for traversal.
// This could also be done before handing the files.
foreach (string str in subDirs)
dirs.Push(str);
}

return sb.ToString();
}

}

- aron

GeneralFantastic! Pin
uswebpro218-Aug-08 2:50
uswebpro218-Aug-08 2:50 
GeneralOttimo lavoro... Pin
Nicola Costantini21-Jan-08 4:59
Nicola Costantini21-Jan-08 4:59 
GeneralExcellent work Pin
Ethan Huang19-Sep-07 23:13
Ethan Huang19-Sep-07 23:13 
GeneralRe: Excellent work Pin
umurlu1-Dec-08 21:05
umurlu1-Dec-08 21:05 
GeneralCOMException: Old format or invalid type library Pin
marco vervoort10-Jul-07 21:18
marco vervoort10-Jul-07 21:18 
GeneralRe: COMException: Old format or invalid type library Pin
Kerdal17-Jul-07 7:18
Kerdal17-Jul-07 7:18 
GeneralRe: COMException: Old format or invalid type library Pin
marco vervoort17-Jul-07 21:16
marco vervoort17-Jul-07 21:16 
GeneralRe: COMException: Old format or invalid type library Pin
uswebpro218-Aug-08 2:09
uswebpro218-Aug-08 2:09 
Generalresource editor with multi language support Pin
edwin_vermeer10-Jul-07 2:39
edwin_vermeer10-Jul-07 2:39 
GeneralRe: resource editor with multi language support Pin
Marco Roello22-Jul-07 21:36
Marco Roello22-Jul-07 21:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.