Difference between revisions of "Multi language C embedded"
m (Created page with "Different approaches of implementing multi language support in embedded C projects. (See links below). ==Design goals== *Should only exist in flash. (No copying to memory) *Logi...") |
m (→Simple Example) |
||
| (12 intermediate revisions by the same user not shown) | |||
| Line 2: | Line 2: | ||
==Design goals== | ==Design goals== | ||
| − | *Should only exist in flash. (No copying to | + | *Should only exist in flash. (No copying to RAM) |
*Logical for translators to translate from english to other language. | *Logical for translators to translate from english to other language. | ||
*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 13: | Line 13: | ||
"The format received is inconsistent with RFC 1024", | "The format received is inconsistent with RFC 1024", | ||
}; | }; | ||
| − | == Example == | + | </source> |
| + | |||
| + | == 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. | ||
<source lang=c> | <source lang=c> | ||
char const * const danish[] = { | char const * const danish[] = { | ||
| Line 36: | Line 40: | ||
} | } | ||
</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. | ||
| + | |||
| + | == Using array initialization with enum indices == | ||
| + | It is possible to initialize arrays – even const arrays – referencing members at compiletime. | ||
| + | |||
| + | <source lang=c> | ||
| + | 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! | ||
| + | } | ||
| + | </source> | ||
| + | [[Category:C]] | ||
Latest revision as of 08: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!
}