For context, I am trying to do some simplistic localization, as a first step into that "ocean", with limited language options. I want to be more "inclusive" than just limited to itemizing all instances of the type (three options for values of Bash environment variable LANGUAGE).
#define SPANISH 'es_MX:es'
#define FRENCH 'fr_CA:fr'
#define ENGLISH 'en_CA:en'
In AWK, I can do
MYLANG = sprintf("%2s", LANG)
I want to do something that simple, so I can do
// AWK syntax for sprintf
#define MYLANG {simple}
to obtain only the first two characters of the string LANG.
Is there something that I can use for that?
The full working script, all behaving as expected except for not having access to the environment variable LANGUAGE is the following:
#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#define SPANISH 'es'
#define FRENCH 'fr'
#define ENGLISH 'en'
#ifndef LANGUAGE
#include "CIMIfrecN_MessagesTable_fr.h"
#else
#define MYLANG LANGUAGE[0],LANGUAGE[1] // Not valid
#if MYLANG == SPANISH
//#include "_cimifrecn_messagestable_es_h"
#include "CIMIfrecN_MessagesTable_es.h"
#elif MYLANG == FRENCH
//#include "_cimifrecn_messagestable_fr_h"
#include "CIMIfrecN_MessagesTable_fr.h"
#else
//#include "_cimifrecn_messagestable_en_h"
#include "CIMIfrecN_MessagesTable_en.h"
#endif
#endif
//==================================================================================================
// START OF MAIN PROGRAM
//==================================================================================================
int main() {
char yellowON[12] = "\e[93;1m";
char yellowOFF[12] = "\e[0m";
char redON[12] = "\e[91;1m";
char redOFF[12] = "\e[0m";
char blueON[12] = "\e[94;1m";
char blueOFF[12] = "\e[0m";
char ThisLOCALE[30];
sprintf(ThisLOCALE, "%s", setlocale(LC_ALL, ""));
printf("\n\t %s\n\n", ThisLOCALE);
printf("\n == %s%s%s ==\n", blueON, ScenarioSetUp, blueOFF);
return 0;
}
The outputs are displayed as follows:
That shows that the proposed method using two single-position references to LANGUAGE does not work. :-(
<Addendum 1>
So, I tried a revised version of that script, where I do compare to the full value of the LANGUAGE variable, thinking that it demonstrated that it was accessible during the pre-processing. Unfortunately, I did not realize I had English as the default fallback case, so my conclusion was incorrect. I had received a false-positive. :-(
...(deleted)...
<Addendum 2>
I revised my program again, setting English for a specific value match, and added specific strings to identify which of the invalid conditions are encountered:
#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#define SPANISH 'es_MX:es' // Format reported by bash environment variable LANGUAGE
#define FRENCH 'fr_CA:fr'
#define ENGLISH 'en_CA:en'
//#define SPANISH 'es'
//#define FRENCH 'fr'
//#define ENGLISH 'en'
//#define TESTOR LANGUAGE[0],LANGUAGE[1] // Not valid
#define TESTOR LANGUAGE
//#ifndef LANG
#ifndef TESTOR
char ScenarioSetUp[30] = "TESTOR was not defined";
//#include "_cimifrecn_messagestable_es_h"
#include "CIMIfrecN_MessagesTable_es.h"
#else
#if TESTOR == NULL
char ScenarioSetUp[50] = "LANGUAGE was not obtained from the environment";
#elif TESTOR == SPANISH
//#include "_cimifrecn_messagestable_es_h"
#include "CIMIfrecN_MessagesTable_es.h"
#elif TESTOR == ENGLISH
//#include "_cimifrecn_messagestable_en_h"
#include "CIMIfrecN_MessagesTable_en.h"
#else
//#include "_cimifrecn_messagestable_fr_h"
#include "CIMIfrecN_MessagesTable_fr.h"
#endif
#endif
//==================================================================================================
// START OF MAIN PROGRAM
//==================================================================================================
//int setProgramLOCALE() {
int main() {
char yellowON[12] = "\e[93;1m";
char yellowOFF[12] = "\e[0m";
char redON[12] = "\e[91;1m";
char redOFF[12] = "\e[0m";
char blueON[12] = "\e[94;1m";
char blueOFF[12] = "\e[0m";
char ThisLOCALE[30];
sprintf(ThisLOCALE, "%s", setlocale(LC_ALL, ""));
printf("\n\t %s\n\n", ThisLOCALE);
printf("\n == %s%s%s ==\n", blueON, ScenarioSetUp, blueOFF);
return 0;
}
This time, it definitely shows specifically failure to detect LANGUAGE for the assignment to TESTOR for compiler directives, as can be seen by the message reported:
So I am still looking for a way to get at LANGUAGE during compiler directives. :-(
Please help.
Sample include file:
//==================================================================================================
// FILE: CIMIfrecN_MessagesTable_fr.h
// Header initializing context-based messages for the program
//==================================================================================================
#ifndef _cimifrecn_messagestable_fr_h
#define _cimifrecn_messagestable_fr_h
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
char ScenarioSetUp[91] = "configuration du scénario";
char EnterDesiredFrequency[91] = "Veuillez entrer la fréquence désirée";
char DesiredFrequency[91] = "Fréquence désirée";
char NumberLevelsImplied[91] = "Nombre de niveaux impliqués";
char NumberStrutsRequired[91] = "Nombre de poutres nécessaires";
char EvaluationPointRelevance[91] = "Évaluation des point du grillage pour identifier leur pertinence";
char Considering[91] = "Examinons";
char Horizontals[91] = "Horizontales";
char NoneMetCriteria[91] = "(aucunes comblait les critères)";
char Diagnonals[91] = "Diagonales";
char VerticesMinimalSet[91] = "Intersections identifiées pour un ensemble minimal contraignant entièrement la grille";
char ThereAre[91] = "Il y a";
char Vertices[91] = "Intersections";
char VerteIndexMatrix[91] = "Matrice des indices pour Intersections";
char VerticesProjectedSphere[91] = "Liste des intersections du polyhèdre projetés sur la sphère";
char EvalStrutelevance[91] = "Évaluation des poutres pour déterminer leur pertinence";
char HorizontalStruts[91] = "Poutres Horizontales";
char DiagonalStruts[91] = "Poutres Diagonales";
char PreOptimizationStruts[91] = "Groupe maximal de poutres requis à être optimisés pour l'ensemble minimum";
char StrutsAndTheirLengthsAre[91] = "poutres et leur longeurs sont";
#endif /* _cimifrecn_messagestable_fr_h */
//==================================================================================================
Script to generate language specific header file from comprehensive master message file:
#!/bin/sh
lang="${1}"
MESSAGE_TABLE="CIMIfrecN_MessagesTable_ALL.h"
MESSAGE_HEADER="CIMIfrecN_MessagesTable_${lang}.h"
Module="_"`echo "${MESSAGE_HEADER}" | tr '[A-Z]' '[a-z]' `
Module=`basename "${Module}" ".h" `"_h"
maxVar=`grep '^V|' "${MESSAGE_TABLE}" | cut -f2- -d\| |
while read msg
do
echo "${msg}" | wc -c
done | sort -r | head -1 `
maxStr=`grep '^'${lang}'|' "${MESSAGE_TABLE}" | cut -f2- -d\| |
while read msg
do
echo "${msg}" | wc -c
done | sort -r | head -1 `
#echo ${maxStr}
awk -v maxV="${maxVar}" -v maxS="${maxStr}" -v local="${lang}" -v file="${MESSAGE_HEADER}" -v module="${Module}" 'BEGIN{
var="" ;
msg=""
printf("\t local = %s\n", local ) | "cat 1>&2" ;
printf("//==================================================================================================\n") ;
printf("// FILE: %s\n", file ) ;
printf("// Header initializing context-based messages for the program\n") ;
printf("//==================================================================================================\n") ;
printf("\n") ;
printf("#ifndef %s\n", module ) ; ### Insert "header guard" to avoid double referencing by compiler
printf("#define %s\n", module ) ;
printf("\n") ;
printf("//#include <stdio.h>\n") ;
printf("//#include <stdlib.h>\n") ;
printf("//#include <string.h>\n") ;
printf("\n") ;
}{
switch( $0 ){
case /\|/ :
#printf("\n %s\n", $1 ) ;
gsub( "\015", "", $0 );
split( $0, dat, "|" ) ;
if( dat[1] == "V" ){
var=dat[2] ;
#printf("\n\t %s\n", var ) ;
}else{
#printf("\n %s\n", $1 ) ;
if( dat[1] ~ local ){
msg=dat[2] ;
#printf("\n\t %s\n", msg ) ;
} ;
} ;
if( var != "" && msg != "" ){
#printf("\n\t\t var = %s\n", var ) ;
#printf("\t\t msg = %s\n", msg ) ;
offset=maxV-length(var)+3 ;
printf("\tchar %s\133%d\135%"offset"s= %s ;\n", var, maxS, "", msg ) ;
var=""
msg=""
} ;
break ;
default :
break ;
} ;
}END{
printf("\n#endif /* %s */\n", module ) ;
printf("//==================================================================================================\n") ;
}' "${MESSAGE_TABLE}" > "${MESSAGE_HEADER}"
gvim "${MESSAGE_HEADER}"
echo "\n\t Done.\n"
#//3456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+
Updated answer...
Try to use this code...
#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
// Define preprocessor macros for each language
#ifdef SPANISH
#define MYLANG "es_MX:es"
#include "CIMIfrecN_MessagesTable_es.h"
#endif
#ifdef FRENCH
#define MYLANG "fr_CA:fr"
#include "CIMIfrecN_MessagesTable_fr.h"
#endif
#ifdef ENGLISH
#define MYLANG "en_CA:en"
#include "CIMIfrecN_MessagesTable_en.h"
#endif
//==================================================================================================
// START OF MAIN PROGRAM
//==================================================================================================
int main() {
char yellowON[12] = "\e[93;1m";
char yellowOFF[12] = "\e[0m";
char redON[12] = "\e[91;1m";
char redOFF[12] = "\e[0m";
char blueON[12] = "\e[94;1m";
char blueOFF[12] = "\e[0m";
char ThisLOCALE[30];
sprintf(ThisLOCALE, "%s", setlocale(LC_ALL, ""));
printf("\n\t %s\n\n", ThisLOCALE);
printf("Selected language: %s\n", MYLANG);
printf("\n == %s%s%s ==\n", blueON, ScenarioSetUp, blueOFF);
return 0;
}
Now, you should be able to compile your program with the right language preprocessor macro.
Here are examples of how you’d do this.
Spanish:
gcc -DSPANISH -o my_program my_program.c
French:
gcc -DFRENCH -o my_program my_program.c
English:
gcc -DENGLISH -o my_program my_program.c
The individual compilation should now include the language-specific header file and set MYLANG
macro accordingly. Then you should be able to switch between languages at compile.
I don't believe you need to make any changes to your "Script to generate language specific header file from comprehensive master message file"
Your Include file seems to be fine... Just remember that each language-specific file should be structured the same but translated in the respective language so your program can use the correct translation.
Assuming you've made similar changes to each of the other language-specific message files (e.g., CIMIfrecN_MessagesTable_es.h, CIMIfrecN_MessagesTable_en.h), I'd think the structure should work correctly.