PLM Software Multimedia Tools and Games

PLMLang

PLMLang, a multi-language tool

Description

The problem :
Any application uses static text data to display messages, labels, menu entries and all other interface elements. The applications are intended to be used by the greatest number of users, but the first step to be usable is to be understood. So, in this goal, an application has to handle multiple languages.

Question :
How an application can be written only once (code), but display all its texts in many languages ?

Answer :
By separating the data from the code, by moving any static text into a string table, and using only references (indices into the table) inside the code. A string provider object then loads a file containing the data, and returns strings to the application when it asks for them.

The solution is made of different components :

  • a header file with some #include, and a simple command to be used anywhere in the code where a string is needed.
  • a class used in the application to dynamically load the data file during execution, and get a list of all available languages (to choose which one to load).
  • a converter that takes a source text file using a specific syntax and converts it into a binary file, and generate a header file with all available indices used to compile the application.
  • a set of data files, sources files with a specific syntax.
  • a set of binary data files, directly usable by the application.

Now let's see how to use this system with an existing program :

  1. create a new empty source file, using your current language (the one currently used for the messages in your program). This file will become the reference file.
  2. open and check every file of your program source code to find all the static strings of text. Then with all of them, do the following :
    • decide if the text needs to be translated (some technical informations or meta-data does not need to, for example).
    • if you want to translate it, then choose a label name and add this label and the associated string to the message file.
      The label will be turned into an enum constant, so it must satisfy C/C++ naming conventions (something like STR_xxx is a usual solution).
    • remove the string from your code, and replace it by a call to the following inline function : _STR(<label>). This function must be used in any place where a static string is needed (const char *).
      You may have to make some other modifications to replace string arrays in your code. They are usually turned into index arrays.
    • include the header file called PLMLang.hpp (#include "") in each file that use a string.
  3. when all the strings are gathered, your source message-file is ready, and can be converted into a binary version. For this task, use the tool 'plmlang' with your message file as argument, and with the '-h' option to also generate a header file in the process.
    This header file will contain a big enum with all labels as entries. Those labels can then be used as index in the string table.
    This header file only need to be generated for the reference message file.
  4. modify your Makefile to compile and link PLMTranslator.cpp with your other files.
  5. add some code to your init function to initialise the translator object. Since this class is a singleton, you should first get an instance, then call the Init() method, and finally the Load() method to load the binary language file.
    Example :
    PLMTranslator *trans = PLMTranslator::Singleton();
    
    if (trans->Init ("/path/to/language/files") == 0)
      {
        cout << "No language file found, aborting !\n";
        exit(1);
      }
    
    // load the first language file found by Init()
    trans->Load (0);
    Note that you can also use this object to show a list of the language files found, and let the user choose one.
  6. now, the real translation can begin !
    Take your first message file as a reference, simply make a copy of it, and edit it. Change the language name, and translate all the strings.
    Never modify the labels, or remove one.
    Keep untranslated strings if you don't know how to translate them, but never remove them, this would create blanks in your program. The order is not important, a couple (label,string) defined in the beginning of your reference file can be placed at the end of another language file. It is not a problem since the label is the same.
    Do not forget to convert the translated source file into a binary version, and to place it with the other language files.
    No need to generate the header file in this case. It would generate the same one anyway.

Notes :

  • since labels are used within the code to retrieve the strings, their name is particularly important. In fact you have to realise that your code does not contain the strings anymore, so the label is the only information you have to guess the string contents.
  • labels usually start with "STR_" or "MSG_" followed by one or more words separated by '_', which reflect the meaning / content of the string.
  • it is a good idea to put general strings at the beginning, like STR_OK "Ok", STR_CANCEL "Cancel", STR_YES, ... then to group other strings by source code file. Add comments with the source-code file name, to easily find where the string is used in your code. This is helpfull when you need to add strings and when you translate, to better understand the context.
  • if you want to use this system for a new project, replace all static strings by calls to _STR(<label>) directly, and build your message file in parallel. In practice, it is a better solution to first use the strings while you develop your program, then to replace them when this part of your code is validated and should not change a lot.

The description of the source file format (syntax) is included in the package, with an example.

 Download

OSI certifiedOpen Source

Note that the following packages are released under the GNU LGPL license (Lesser General Public License).

Package Size Date Notes
Tools and source code 82.0 k 15 Oct 2004 ZIP, Linux/Windows binaries + sources + doc

Copyright 2001-2004 PLMSoft All rights reserved. (last mod.: 15 Oct 2004)