Monday, December 7, 2015

Localizing windows forms by Resgen.exe

Frequently isn't so easy to develop a localized widows forms application. For this reason I want to write this post based on my experience in localization. For localization you need  to use ResGen.exe this way:
  1. Create two txt files called (for example) resourceEN.txt and resourceIT.txt
  2. In langEN.txt create a list of items to localize this way (in this example we have two languages (for Italian and for English). On the left hand we have the name of the strings and on the right hand we have the contents.
Below are respectively langIT.txt and langEN.txt:  
langIT.txt:
str1=File non valido
str2=Selezionare una riga (cliccare sulla linguetta a sinistra)
str3=Selezionare una cartella (cliccare sulla linguetta a sinistra)
str4=Si desidera eliminare i records selezionati?
str5=Conferma eliminazione
str6=selezionare una riga
str7=I file icona sono visibili solo in modalità normale
str8=Hai selezionato una cartella. Seleziona un'immagine
str9=A questo percorso non corrisponde nessuna immagine o cartella. Modificare il record?
str10=Selezionare una cartella
str11=Salva
str12=Apri
str13=Carica cartella
str14=Questo titolo di immagine esiste già. Cambia il titolo
str15=Apri file
str16=Carica cartella
str17=Elimina
str18=Modifica
str19=Visualizza nell'album
str20=Anteprime

langEN.txt:
str1=Invalid file
str2=Select a row (click on left hand flap )
str3=Select a folder (click on flap left hand)
str4=Do you want to delete selected records?
str5=Delete confirmation
str6=Select a row
str7=Icon files are visible only in normal mode
str8=Selected folder. You have to select an image
str9=This path doesn't meet any folder or image. Do you want to modify this record?
str10=Select a folder
str11=Save
str12=Open
str13=Load folder
str14=This image title already exixts. Change title
str15=Open file
str16=Open folder
str17=Delete
str18=Edit
str19=View in album
str20=Thumbnails

First you have to check for ResGen.exe in your computer. Now we'll assume that resourceEN.txt and resourceIT.txt well be frequently edited before the first release. Assume also that your project folder is "Picture". Therefore for convenience we'll create a batch file this way:
C:\Programmi\Microsoft SDKs\Windows\v6.0A\bin\ResGen "C:\Users\gg\Documents\resources\Picture\resourceEN.txt" "C:\Users\gg\Documents\Visual Studio 2005\Projects\Picture\Picture\bin\Debug\language\langEN.resources" C:\Programmi\Microsoft SDKs\Windows\v6.0A\bin\ResGen "C:\Users\gg\Documents\resources\Picture\resourceIT.txt" "C:\Users\gg\Documents\Visual Studio 2005\Projects\Picture\Picture\bin\Debug\language\langIT.resources" 
In this batch file: C:\Programmi\Microsoft SDKs\Windows\v6.0A\bin\ is the directory where in my pc is located ResGen.exe C:\Users\gg\Documents\resources\Picture is the directory where I located my resourceEN.txt and resourceIT.txt. C:\Users\gg\Documents\Visual Studio 2005\Projects\Picture\Picture\bin\Debug\language is the target project directory where I want to locate resourceEN.resources and resourceIT.resources.
Example of application: As you ca see I can easily chose a directory where I want to locate .resources files. In my case this directory name is language, in the application directory. This way every time you edit the txt files you can execute the batch file and refresh .resources files Now we imagine to have a project to localize. In this project create a module file Module1. In Module1 we have to put the following code:

Imports System.Resources
Imports Microsoft.Reporting.WinForms

Private Declare Auto Function GetPrivateProfileString Lib "kernel32.dll" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer

Private Declare Auto Function WritePrivateProfileString Lib "kernel32.dll" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpString As String, ByVal lpFileName As String) As Integer

Friend Function IniRead(ByVal Filename As String, ByVal Section As String, ByVal Key As String, Optional ByVal lpDefault As String = "", Optional ByVal bRaiseError As Boolean = False) As String
Dim RetVal As String = New String(" ", 255)
Dim LenResult As Integer
Dim ErrString As String
LenResult = GetPrivateProfileString(Section, Key, lpDefault, RetVal, RetVal.Length, Filename)
If LenResult = 0 AndAlso bRaiseError Then
If Not (System.IO.File.Exists(Filename)) Then
ErrString = "Impossibile aprire il file INI" & Filename
Else
ErrString = "La sezione o la chiave sono errate oppure l’accesso al file non √® consentito"
End If
Throw New Exception(ErrString)
End If
Return RetVal.Substring(0, LenResult)
End Function

Friend Function IniWrite(ByVal Filename As String, ByVal Section As String, ByVal Key As String, ByVal Value As String, Optional ByVal bRaiseError As Boolean = False) As Boolean
Dim LenResult As Integer
Dim ErrString As String
LenResult = WritePrivateProfileString(Section, Key, Value, Filename)
If LenResult = 0 And bRaiseError Then
If Not (System.IO.File.Exists(Filename)) Then
ErrString = "Impossibile aprire il file INI" & Filename
Else
ErrString = "Accesso al file non consentito"
End If
Throw New Exception(ErrString)
End If
Return IIf(LenResult = 0, False, True)
End
End Function

This is a simple sample project. Now to call the language form insert in main form a new button to call language form. In click button event put language.show Now we can select one of two language by combobox1. Once selected a language we can execute the two msgboxes mentioned above and see the effect. In the msgboxes we'll read the same string meaning, but in two languages: English and Italiano 

1 comment:

  1. Thanks for sharing such a useful information.
    we a whole team from Nettech India Appreciates you

    ReplyDelete