vbagettext

vbagettext is a collection of Visual Basic for Applications modules and classes that implement basic I18N and L10N capabilities for VBA projects. You can import these components into your own VBA project.

Since vbagettext uses the GNU gettext PO file format, translators can employ common localization tools, such as POedit.

The VBA components are written for and tested with an Excel VBA project (XL Toolbox).

Obtaining the vbagettext package

The vbagettext project consists of three components:

  1. A tool to extract translatable strings from your VBA code (XL Dev Tools).
  2. VBA modules and classes that you need to insert into your VBA project.
  3. A helper DLL (xltoolbox.dll) which provides fast code for some computations.

See below for information about a demo workbook.

XL Dev Tools

The XL Dev Tools add-in (developer.xla by the same author) is required to extract the translatable strings from your VBA project and generate a GNO PO file. You may obtain it here:

http://sourceforge.net/projects/vbatools

Code modules for your VBA project

You may download the source code at Sourceforge.net:

https://sourceforge.net/p/vbagettext/code/ci/master/tree

The Git command to clone the repository is:

git clone git://git.code.sf.net/p/vbagettext/code vbagettext-code

Once you have downloaded the modules, import them into your project from the Visual Basic IDE using the File-Import (CTRL+M) command. A more convenient alternative is to use the command from the XL Dev Tools menu (since you have installed this add-in to extract your strings, you can just as well use it for other tasks).

DLL

A compiled DLL can be downloaded at Sourceforge:

The source code for the DLL is included in the Git repository (see above). It is not trivial to compile the DLL from source code; I put together some instructions.

To make the DLL available at run-time, either place it into your Windows system32 folder (which requires administrative rights), or place it into the same folder that your VBA project file resides in. For addins on Windows XP, this is typically:

%appdata%\Microsoft\Addins

If Windows complains that it cannot find the DLL, you may need to register the path to the DLL with code like this:

#If VBA7 Then 
    Private Declare PtrSafe Function SetDllDirectory Lib "kernel32.dll" Alias "SetDllDirectoryA" ( _
        ByVal lpPathName As String) As Boolean
#Else
    Private Declare Function SetDllDirectory Lib "kernel32.dll" Alias "SetDllDirectoryA" ( _
        ByVal lpPathName As String) As Boolean
#End If

Function AddDLLPath(ByRef path As String) As Boolean
    Dim s As String
    s = path & Chr(0)
    AddDLLPath = SetDllDirectory(s)
End Function

Function RemoveDLLPath() As Boolean
    RemoveDLLPath = AddDLLPath("")
End Function

Then, make sure to call the AddDLLPath function with the appropriate parameter (i.e., the location of your DLL) before you use any of the vbagettext functions.

Instructions

Preparing your VBA project for translation comprises the following steps:

Preparing strings for extraction from your VBA project

In order to build a GNU Gettext PO file, you need to extract all of the translatable strings from your code. These strings can be:

You can use the XL Developer Tools addin to automatically extract all of these different kinds of strings and collect them in a GNU Gettext PO file.

To enable the XL Developer Tools to find the strings that you want to translate, you need to mark them in special ways.

Marking strings in functions and procedures

To mark translatable strings in functions and procedures, surround them with a function call to the vbagettext translate function t().

This function is defined in the Module_GetText module:

Function t(ByVal text As String, ParamArray params() As Variant) As String

All literal text that is used as the text parameter of this function will be identified and extracted from your project.

For example, if you have the code block as above:

MsgBox "Hello World."
Dim MyString = String
myString = "Hello World."

The marked version would be:

MsgBox t("Hello World.")
Dim MyString = String
myString = t("Hello World.")

As you can tell from the function declaration, the function accepts optional parameters if you want to include variables in the text:

MsgBox t("There are {} months in a year.", 12)

Of course, you can also use more than one parameter:

Dim Days_In_June as Long
Dim Months_In_Year as Long
Days_In_June = 30
Months_In_Year = 12
MsgBox t("There are {} days in June and {} months in a year.", _
    Days_In_June, Months_In_Year)

Line breaks

For your convenience, vbgagettext supports the C-style \n code to insert line breaks into strings. It is not recommended to use the usual vbNewLine constant, as this will break string extraction. Furthermore, Gettext translation software such as POedit can deal with \n, and you can also use \n to mark newlines in your translated strings.

Example:

MsgBox t("This is a string that\nspans two lines.")

Marking module-level constants

Marking string constants at the module level is done a bit differently:

Private Const MyConstant = "Hello World." ' < translate

It is the < translate part that turns the constant in to a translatable string. Important: In order to have the constant translated in the final code, you must enclose it in a t() function call:

MsgBox t(MyConstant)

Marking strings in form controls

Strings in form controls are automatically extracted as they are very easy to identify programmatically.

There may be some controls’ captions that you do not want to have extracted for translation. To prevent extraction of a control’s caption, add the tag noI18N to it’s properties:

Use the noI18N tag in a control’s properties to prevent its translation
Use the noI18N tag in a control’s properties to prevent its translation

Marking form captions

Form captions are automatically extracted.

Marking RibbonUI captions

To have your RibbonUI translated, you need to work with callback functions like this:

Public Sub MyProject_UI_getLabel(control as IRibbonControl, ByRef returnedVal)
    Select Case control.id
        Case "MyOwnID": returnedVal = t("My command")
    End Case
End Sub

Extracting marked strings from your project

Use the XL Dev Tools addin to extract the strings that you marked and collect them in a GNU Gettext PO file.

Important: In order for this to work, you need to relax Excel’s security settings a little bit – see below.

Once you have installed the XL Dev Tools addin, start up Excel and open your project. Then, open the Visual Basic IDE by pressing Alt+F11. Make sure that your project is not running by pressing the ‘stop’ button or by choosing the “Reset” command from the “Run” menu.

Execute the “Internationalization…” command from the “XL Dev Tools” menu in the VBE.

The XL Dev Tools menu in the Visual Basic IDE.
The XL Dev Tools menu in the Visual Basic IDE.

Then, click on the radiobutton for “addins” or “workbooks”, as appropriate for your project.

The Collect Strings dialog of the XL Dev Tools addin.
The Collect Strings dialog of the XL Dev Tools addin.

When you click on “Create PO template”, you will be prompted for a file name for the PO template file. It has a .POT extension which causes Windows® to confuse it with a PowerPoint® template, so double-clicking this file will produce unexpected results.

You can distribute the newly generated PO template file to your translators to start translation.

Granting access to the Office VBA project

The default security settings of Microsoft® Excel® do not permit the XL Dev Tools addin read access to your own project’s code. Therefore, to extract strings from your project, you need to relax Excel’s security settings a little bit. Read more here:

http://support.microsoft.com/kb/282830

This is only needed for the extraction of strings.

To use the vbagettext library with a project that is distributed to end users, you do not need to relax the security settings.

Please note: You use the vbagettext library entirely at your own risk. No warranties, not even for merchantability or fitness for a particular purpose. The author does not assume any liability for any kind of damage that might result from installing or using the vbagettext library.

Translating the PO file

To translate the strings contained in the PO template file, use a suitable tool such as POedit, which is also free software.

If you have never translated your current VBA project before, start by generating a new PO file from the PO template file:

Choose the New catalog from template… command in POedit
Choose the “New catalog from template…” command in POedit

You will be prompted for information about the project and the team of translators – while informative, it is not really necessary to enter the information here, and you can dismiss the dialog.

Immediately after creating the new catalog, you will be prompted for a file name to save the .PO file. You must follow naming conventions, otherwise your file will not be found by the vbagettext functions.

Name your .PO file by appending an underscore followed by an international language code. Examples:

vbagettextdemo.pot
vbagettextdemo_de.po
vbagettextdemo_it.po
vbagettextdemo_en-US.po
vbagettextdemo_fr-FR.po

Then, start translating your strings.

Whenever you save your .PO file, a machine-readable .MO file will automatically be generated and saved in the same folder. It is this .MO file that you need to distribute with your project.

Updating translations

If you already have a translated .PO file and you obtain an updated .POT template file due to changes in your VBA project, open the .PO file in POedit and choose “Update from POT file…” from the “Catalog” menu.

Update your PO file with POEdit
Update your PO file with POEdit

Using the translation in your project

To use the translation in your VBA project, make sure you have imported all required vbagettext modules and classes (see “Obtaining vbagettext”).

In the Module_Gettext module, you must adjust two module-wide constants:

' Adjust the next two constants for use in your project
Private Const LOCALE_DIR = "resource"             ' where to locate the translation files
Private Const LOCALE_BASE_NAME = "vbagettextdemo" ' base name of the PO files

The LOCALE_DIR constant indicates a folder relative to your workbook or addin’s folder where the .MO files are stored. In the demo workbook, this is also the folder that contains the xltoolbox.dll and its 64-bit variant, xltoolbox-64.dll.

The LOCALE_BASE_NAME is the base name of the .MO files. It is advisable to make this the same name as the workbook or addin’s base file name, and it may be that a future version of vbagettext will always automatically use the current workbook or addin’s base file name.

To set a language in your project, use the SetLanguage() function. Example:

SetLanguage "de"

To retrieve the current language, use the GetLanguage() function. Example:

MsgBox t("Current language: {}", GetLanguage)

To obtain a string array with the available languages (based on the .MO files that are actually found in the LOCALE_DIR folder):

Dim astrLanguages() as String
dim lngCurrent as Long
astrLanguages = BuildLanguageList(lngCurrent)

The BuildLanguageList function sets the lngCurrent parameter to the index of the current language in the string array, which is useful if you want to fill a ListBox control and highlight the current language in it.

Demo workbook

Have a look at a little demo workbook to see vbagettext in action. The demo workbook and its supporting files can be downloaded from Sourceforge:

https://sf.net/projects/vbagettext/files

When you click on the “Start” button in this workbook, the following UserForm is displayed in English:

vbagettext demo UserForm in English
vbagettext demo UserForm in English

Clicking the “MsgBox” button brings up an English message:

vbagettext demo MsgBox in English
vbagettext demo MsgBox in English

When you choose “Deutsch (de)” (German) from the ListBox, some of the text (except where noted) will be translated at run-time to German:

vbagettext demo UserForm in German
vbagettext demo UserForm in German

Clicking the “MsgBox” button brings up the German translation of the message:

vbagettext demo MsgBox in German
vbagettext demo MsgBox in German

Contact

Contact the author, Daniel Kraus, at xltoolbox (at) gmx (dot) net.

License

This code is published unter the GPL v2 license.

vbagettext

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.