Difference between revisions of "Multi language C embedded"

From Teknologisk videncenter
Jump to: navigation, search
m
m (Simple Example)
 
(3 intermediate revisions by the same user not shown)
Line 6: Line 6:
 
*Easy to change language on-the-fly
 
*Easy to change language on-the-fly
 
*No padding of strings to max length in arrays
 
*No padding of strings to max length in arrays
**In the example below the text strings '''yes''' and '''no''' use the same amount of memory as the long message.
+
**In the example below the text strings '''yes''' and '''no''' use the same amount of memory as the long message and will be copied to RAM on a system with firmware.
 
<source lang=c>
 
<source lang=c>
 
char txt[3][] = {
 
char txt[3][] = {
Line 18: Line 18:
 
In this small example both languages are in the same file. In a project, you should have a file called english.h where all your english messages should reside. When the project is internationalized send a copy of english.h to the translator with a new name. For example german.h  
 
In this small example both languages are in the same file. In a project, you should have a file called english.h where all your english messages should reside. When the project is internationalized send a copy of english.h to the translator with a new name. For example german.h  
  
'''Remember:''' The translator must keep the variables as indicated by %<TYPE> in all messages.
+
'''Remember:''' The translator must keep the variables as indicated by %<TYPE> in all messages, in the same order.
 
<source lang=c>
 
<source lang=c>
 
char const * const danish[] = {
 
char const * const danish[] = {
Line 41: Line 41:
 
</source>
 
</source>
 
The drawback of this method is that the array-members need to come in this exact order and if you delete one of the members, it’s necessary to leave an empty (“”) string as the array-member number is the reference to the string when used. For example textmes(2) references the battery warning.
 
The drawback of this method is that the array-members need to come in this exact order and if you delete one of the members, it’s necessary to leave an empty (“”) string as the array-member number is the reference to the string when used. For example textmes(2) references the battery warning.
 +
 
== Using array initialization with enum indices ==
 
== Using array initialization with enum indices ==
 
It is possible to initialize arrays – even const arrays – referencing members at compiletime.
 
It is possible to initialize arrays – even const arrays – referencing members at compiletime.
  
 
<source lang=c>
 
<source lang=c>
enum Errors {
+
enum texts {
 
     ERR_NONEXCOM = 0,
 
     ERR_NONEXCOM = 0,
 
     ERR_INVDATE,
 
     ERR_INVDATE,
 
     ERR_LOWBAT,
 
     ERR_LOWBAT,
  } err;
+
  } ;
  
 
char const * const danish[] = {
 
char const * const danish[] = {
 
     [ERR_NONEXCOM]  = "FEJL: Kommando eksisterer ikke: %s",
 
     [ERR_NONEXCOM]  = "FEJL: Kommando eksisterer ikke: %s",
     [ERR_INVDATE]       = "FEJL: Dato %s ugyldig",
+
     [ERR_INVDATE]   = "FEJL: Dato %s ugyldig",
     [ERR_LOWBAT]       = "Advarsel: Der er kun %u%% batteri tilbage!"
+
     [ERR_LOWBAT]   = "Advarsel: Der er kun %u%% batteri tilbage!"
 
  };
 
  };
  
 
char const * const english[] = {
 
char const * const english[] = {
     [ERR_NONEXCOM]   = "ERROR: Non-existing command: %s",
+
     [ERR_NONEXCOM] = "ERROR: Non-existing command: %s",
     [ERR_INVDATE]         = "ERROR: Invalid Date %s",
+
     [ERR_INVDATE]   = "ERROR: Invalid Date %s",
     [ERR_LOWBAT]         = "Warning: Only %u%% battery left!"
+
     [ERR_LOWBAT]   = "Warning: Only %u%% battery left!"
 
};
 
};
  

Latest revision as of 07:43, 27 March 2021

Different approaches of implementing multi language support in embedded C projects. (See links below).

Design goals

  • Should only exist in flash. (No copying to RAM)
  • Logical for translators to translate from english to other language.
  • Easy to change language on-the-fly
  • No padding of strings to max length in arrays
    • In the example below the text strings yes and no use the same amount of memory as the long message and will be copied to RAM on a system with firmware.
char txt[3][] = {
  "Yes",
  "No",
  "The format received is inconsistent with RFC 1024",
};

Simple Example

In this small example both languages are in the same file. In a project, you should have a file called english.h where all your english messages should reside. When the project is internationalized send a copy of english.h to the translator with a new name. For example german.h

Remember: The translator must keep the variables as indicated by %<TYPE> in all messages, in the same order.

char const * const danish[] = {
  "FEJL: Kommando eksisterer ikke: %s",
  "FEJL: Dato %s ugyldig",
  "Advarsel: Der er kun %u%% batteri tilbage!"
};
char const * const english[] = {
  "ERROR: Non-existing command: %s",
  "ERROR: Invalid Date %s",
  "Warning: Only %u%% battery left!"
};
void example(void) {
  char **textmes;
  
  textmes = (char **) &danish;  // Set danish language
  printf( textmes[2], 17);      // Outputs: Advarsel: Der er kun 17% batteri tilbage!
  textmes = (char **) &english; // Set english language
  printf( textmes[2], 17);      // Outputs: Warning: Only 17% battery left!

}

The drawback of this method is that the array-members need to come in this exact order and if you delete one of the members, it’s necessary to leave an empty (“”) string as the array-member number is the reference to the string when used. For example textmes(2) references the battery warning.

Using array initialization with enum indices

It is possible to initialize arrays – even const arrays – referencing members at compiletime.

enum texts {
     ERR_NONEXCOM = 0,
     ERR_INVDATE,
     ERR_LOWBAT,
 } ;

char const * const danish[] = {
    [ERR_NONEXCOM]  = "FEJL: Kommando eksisterer ikke: %s",
    [ERR_INVDATE]   = "FEJL: Dato %s ugyldig",
    [ERR_LOWBAT]    = "Advarsel: Der er kun %u%% batteri tilbage!"
 };

char const * const english[] = {
    [ERR_NONEXCOM]  = "ERROR: Non-existing command: %s",
    [ERR_INVDATE]   = "ERROR: Invalid Date %s",
    [ERR_LOWBAT]    = "Warning: Only %u%% battery left!"
};

void example(void) {
  char **textmes;
        int i;
 
      textmes = (char **) &english; // Set english language
      printf( textmes[ERR_LOWBAT], 17);      // Outputs: Warning: Only 17% battery left!
      textmes = (char **) &danish;  // Set danish language
      printf( textmes[ERR_LOWBAT], 17);      // Outputs: Advarsel: Der er kun 17% batteri tilbage!
}