Difference between revisions of "GTRANS"

From uGFX Wiki
Jump to: navigation, search
(Example)
(API reference)
 
(13 intermediate revisions by 2 users not shown)
Line 1: Line 1:
The GTRANS module allows to manage language translations. The language of an application can be changed dynamically during run-time using the GTRANS module.
+
The GTRANS module allows to manage language translations. The language of an application can be changed dynamically during runtime using the GTRANS module.
  
 
== API reference ==
 
== API reference ==
The API reference of the GTRANS module can be found [http://api.ugfx.org/group___g_t_r_a_n_s.html here].
+
The API reference of the GTRANS module can be found [http://api.ugfx.io/group___g_t_r_a_n_s.html here].
  
 
== Intended usage ==
 
== Intended usage ==
Line 20: Line 20:
 
#define gt(str) gtransString(str)
 
#define gt(str) gtransString(str)
 
</source>
 
</source>
 +
 +
== Optimization ==
 +
Calling <code>gt()</code> (or <code>gtransString()</code> directly) uses the <code>strcmp()</code> function of the standard C library to compare strings. This operation can take a lot of time. For performance critical applications or low-resource systems the application translation speed can be optimized by using <code>gtransIndex()</code> (instead of <code>gtransString()</code>) which directly takes the index of the string in the translation table. However, this introduces the limitation that each string in each of the translation tables need to be at the same position (the same index). Using <code>gtransString()</code> allows to have translation tables of unequal sizes due to the nature of the translation being based on string comparison rather than index accessing of the table.
  
 
== Example ==
 
== Example ==
 +
Complete examples can be found under ''/demos/modules/gtrans/'' in the uGFX library directory.
 +
 +
=== Basic Example ===
 +
The following code is a very simple usage example showing how the GTRANS module is used. This is a very minimalistic example with no dependencies other than the [[GDISP]] module to interface a display.
 
<source lang="c">
 
<source lang="c">
 +
#include <stdio.h>
 
#include "gfx.h"
 
#include "gfx.h"
  
 +
#define COLOR_BACKGROUND    Silver
 +
#define COLOR_TEXT          Black
 +
 +
gFont font;
 +
 +
// English Translation
 
static const char* EnglishStrings[] = {
 
static const char* EnglishStrings[] = {
 
     "Welcome",
 
     "Welcome",
     "The number %s has the value %d",
+
     "The temperature is %d degrees",
     "Goodbye"
+
     "Goodbye",
 +
    "This is a translated uGFX application"
 
};
 
};
 
static const transTable EnglishTranslation = { sizeof(EnglishStrings)/sizeof(EnglishStrings[0]), EnglishStrings };
 
static const transTable EnglishTranslation = { sizeof(EnglishStrings)/sizeof(EnglishStrings[0]), EnglishStrings };
  
 +
// German translation
 
static const char* GermanStrings[] = {
 
static const char* GermanStrings[] = {
 
     "Herzlich Willkommen",
 
     "Herzlich Willkommen",
     "Die Zahl %s hat den Wert %d",
+
     "Die Temperatur beträgt %d Grad",
     "Auf Wiedersehen"
+
     "Auf Wiedersehen",
 +
    "Das ist eine übersetzte uGFX Anwendung"
 
};
 
};
 
static const transTable GermanTranslation = { sizeof(GermanStrings)/sizeof(GermanStrings[0]), GermanStrings };
 
static const transTable GermanTranslation = { sizeof(GermanStrings)/sizeof(GermanStrings[0]), GermanStrings };
  
int main(void)
+
// French translation
 +
static const char* FrenchStrings[] = {
 +
    "Bienvenue",
 +
    "La température est de %d degrés",
 +
    "Au revoir",
 +
    "Ceci est une application traduit uGFX"
 +
};
 +
static const transTable FrenchTranslation = { sizeof(FrenchStrings)/sizeof(FrenchStrings[0]), FrenchStrings };
 +
 
 +
void updateText()
 
{
 
{
     size_t i, j;
+
     coord_t width = 400;
     font_t font;
+
     coord_t height = 30;
  
 +
    // Translate some basic strings
 +
    gdispFillStringBox(20,  20, width, height, gt("Welcome"), font, COLOR_TEXT, COLOR_BACKGROUND, justifyLeft);
 +
    gdispFillStringBox(20,  60, width, height, gt("This is a translated uGFX application"), font, COLOR_TEXT, COLOR_BACKGROUND, justifyLeft);
 +
    gdispFillStringBox(20, 100, width, height, gt("Goodbye"), font, COLOR_TEXT, COLOR_BACKGROUND, justifyLeft);
 +
 +
    // A more complex example using string formatting
 +
    char buffer[128];
 +
    sprintf(buffer, gt("The temperature is %d degrees"), 18);
 +
    gdispFillStringBox(20, 140, width, height, buffer, font, COLOR_TEXT, COLOR_BACKGROUND, justifyLeft);
 +
}
 +
 +
int main(void)
 +
{
 +
    // Initialize the uGFX library
 
     gfxInit();
 
     gfxInit();
     gdispClear(Silver);
+
     gdispClear(COLOR_BACKGROUND);
  
 +
    // Take the first font we find
 
     font = gdispOpenFont("*");
 
     font = gdispOpenFont("*");
  
 +
    // Set the base language of the application
 
     gtransSetBaseLanguage(&EnglishTranslation);
 
     gtransSetBaseLanguage(&EnglishTranslation);
    gtransSetLanguage(&GermanTranslation);
 
  
     gtransSetLanguage(&EnglishTranslation);
+
     // Loop through the languages
    i = 0;
+
    while (TRUE) {
    for (j = 0; j < EnglishTranslation.numEntries; j++) {
+
        // English
         gdispFillStringBox(20+300*i, 35*j, 300, 35, gtransIndex(j), font, Black, Silver, justifyLeft);
+
        gtransSetLanguage(&EnglishTranslation);
    }
+
        updateText();
 +
        gfxSleepMilliseconds(3000);
 +
 
 +
        // German
 +
        gtransSetLanguage(&GermanTranslation);
 +
         updateText();
 +
        gfxSleepMilliseconds(3000);
  
    gtransSetLanguage(&GermanTranslation);
+
        // French
    i = 1;
+
        gtransSetLanguage(&FrenchTranslation);
    for (j = 0; j < EnglishTranslation.numEntries; j++) {
+
        updateText();
         gdispFillStringBox(20+300*i, 35*j, 300, 35, gtransIndex(j), font, Black, Silver, justifyLeft);
+
         gfxSleepMilliseconds(3000);
 
     }
 
     }
  
     gdispFillStringBox(20, 300, 300, 25, gt("Welcome"), font, Black, Silver, justifyLeft);
+
     return 0;
 +
}
 +
</source>
  
while (TRUE) {
+
=== Example with widgets ===
gfxSleepMilliseconds(500);
+
The GTRANS module can also be used to translate widget texts. GWIN doesn't do anything with the text set by <code>gwinSetText()</code> except displaying it. Therefore, the <code>gtransString()</code> (or <code>gt()</code> respectively) function can be used directly inside of the <code>gwinSetText()</code> call. When the current language changes, the <code>gwinSetText()</code> function must be re-called manually. There's currently no way to tell GWIN to automatically use the string for the currently active language as this would add a lot of overhead to both the GWIN core module as well as to each widget rendering function in order to support parameter substitution.
}
+
  
return 0;
+
Example:
}
+
<source lang="c">
 +
gwinSetText(ghMyButton, gt("The temperature is %d degrees"));
 
</source>
 
</source>

Latest revision as of 17:25, 23 August 2021

The GTRANS module allows to manage language translations. The language of an application can be changed dynamically during runtime using the GTRANS module.

API reference

The API reference of the GTRANS module can be found here.

Intended usage

Each translation is specified by a transTable struct which is essentially a table of strings:

typedef struct transTable {
    unsigned numEntries;     // The number of strings that this table contains
    const char** strings;    // The translated strings
} transTable;

A translatable application needs to have a base language. All translations happen relative to that base language. The base language is specified using gtransSetBaseLanguage(). The current language of the application is set using gtransSetLanguage(). The actual translations take place by calling gtransString(). A string contained in the translation table of the base language is passed to gtransString(). The function returns the corresponding string of the current language that was set using gtransSetLanguage() or the passed string if none was found.

A wrapper macro named gt() around gtransString() is available to make writing and reading translatable applications easier:

#define gt(str) gtransString(str)

Optimization

Calling gt() (or gtransString() directly) uses the strcmp() function of the standard C library to compare strings. This operation can take a lot of time. For performance critical applications or low-resource systems the application translation speed can be optimized by using gtransIndex() (instead of gtransString()) which directly takes the index of the string in the translation table. However, this introduces the limitation that each string in each of the translation tables need to be at the same position (the same index). Using gtransString() allows to have translation tables of unequal sizes due to the nature of the translation being based on string comparison rather than index accessing of the table.

Example

Complete examples can be found under /demos/modules/gtrans/ in the uGFX library directory.

Basic Example

The following code is a very simple usage example showing how the GTRANS module is used. This is a very minimalistic example with no dependencies other than the GDISP module to interface a display.

#include <stdio.h>
#include "gfx.h"
 
#define COLOR_BACKGROUND    Silver
#define COLOR_TEXT          Black
 
gFont font;
 
// English Translation
static const char* EnglishStrings[] = {
    "Welcome",
    "The temperature is %d degrees",
    "Goodbye",
    "This is a translated uGFX application"
};
static const transTable EnglishTranslation = { sizeof(EnglishStrings)/sizeof(EnglishStrings[0]), EnglishStrings };
 
// German translation
static const char* GermanStrings[] = {
    "Herzlich Willkommen",
    "Die Temperatur beträgt %d Grad",
    "Auf Wiedersehen",
    "Das ist eine übersetzte uGFX Anwendung"
};
static const transTable GermanTranslation = { sizeof(GermanStrings)/sizeof(GermanStrings[0]), GermanStrings };
 
// French translation
static const char* FrenchStrings[] = {
    "Bienvenue",
    "La température est de %d degrés",
    "Au revoir",
    "Ceci est une application traduit uGFX"
};
static const transTable FrenchTranslation = { sizeof(FrenchStrings)/sizeof(FrenchStrings[0]), FrenchStrings };
 
void updateText()
{
    coord_t width = 400;
    coord_t height = 30;
 
    // Translate some basic strings
    gdispFillStringBox(20,  20, width, height, gt("Welcome"), font, COLOR_TEXT, COLOR_BACKGROUND, justifyLeft);
    gdispFillStringBox(20,  60, width, height, gt("This is a translated uGFX application"), font, COLOR_TEXT, COLOR_BACKGROUND, justifyLeft);
    gdispFillStringBox(20, 100, width, height, gt("Goodbye"), font, COLOR_TEXT, COLOR_BACKGROUND, justifyLeft);
 
    // A more complex example using string formatting
    char buffer[128];
    sprintf(buffer, gt("The temperature is %d degrees"), 18);
    gdispFillStringBox(20, 140, width, height, buffer, font, COLOR_TEXT, COLOR_BACKGROUND, justifyLeft);
}
 
int main(void)
{
    // Initialize the uGFX library
    gfxInit();
    gdispClear(COLOR_BACKGROUND);
 
    // Take the first font we find
    font = gdispOpenFont("*");
 
    // Set the base language of the application
    gtransSetBaseLanguage(&EnglishTranslation);
 
    // Loop through the languages
    while (TRUE) {
        // English
        gtransSetLanguage(&EnglishTranslation);
        updateText();
        gfxSleepMilliseconds(3000);
 
        // German
        gtransSetLanguage(&GermanTranslation);
        updateText();
        gfxSleepMilliseconds(3000);
 
        // French
        gtransSetLanguage(&FrenchTranslation);
        updateText();
        gfxSleepMilliseconds(3000);
    }
 
    return 0;
}

Example with widgets

The GTRANS module can also be used to translate widget texts. GWIN doesn't do anything with the text set by gwinSetText() except displaying it. Therefore, the gtransString() (or gt() respectively) function can be used directly inside of the gwinSetText() call. When the current language changes, the gwinSetText() function must be re-called manually. There's currently no way to tell GWIN to automatically use the string for the currently active language as this would add a lot of overhead to both the GWIN core module as well as to each widget rendering function in order to support parameter substitution.

Example:

gwinSetText(ghMyButton, gt("The temperature is %d degrees"));