1. Introduction▲
Certaines bases de données orientées vers l'international nécessitent d'être déployées avec des langues étrangères (anglais, italien, allemand, etc.) et sur des systèmes d'exploitation différents.
Il existe des commandes 4e Dimension qui permettent de retourner différentes informations liées à l'environnement système, mais nous n'avons pas de commandes qui permettent de connaître la langue Système de façon précise en respectant le code ISO 639-1.
2. Informations liées à l’environnement système que nous pouvons récupérer▲
Les commandes 4e Dimension liées à l'environnement système sont :
Hauteur ecran
{(*)
->
Num
ériqueLargeur ecran
{(*)
}->
Num
ériqueNombre e
crans->
Ent
ier longCOORDONNEES ECRAN
(
gauche;
haut;
droite;
bas{;
écran})
PROFONDEUR ECRAN
(
profondeur;
couleurs{;
écran})
FIXER PROFONDEUR ECRAN
(
profondeur{;
couleurs{;
écran}})
Ecran principal
->
Ent
ier longHauteur barre de menus
->
Ent
ier longLISTE DES POLICES
(
polices)
- Nom de police
(
numéro)
->
Alpha Num
ero de police(
nomPolice)
->
Ent
ier long- PROPRIETES PLATE FORME
(
plateForme{;
système{;
machine}})
Dossier systeme
{(
type)
} AlphaDossier temporaire
->
AlphaNom de la machine
->
Alpha- Nom du possesseur
->
Alpha - Gestalt
(
sélecteur;
valeur)
->
Num
érique ENREGISTRER EVENEMENT
(
message{;
importance})
FIXER VARIABLE ENVIRONNEMENT
(
nomVar;
valeurVar)
LANCER PROCESS EXTERNE
(
nomFichier{;
fluxEntrée{;
fluxSortie{;
fluxErreur}}})
Pour plus d'informations se reporter à l'adresse suivante :
https://4d.developpez.com/documentation/4DDoc2004/V6F/V6F00018.HTM
Nous avons aussi la commande Gestalt qui retourne dans valeur un numérique représentant les caractéristiques de la configuration matérielle et logicielle de votre système, en fonction du sélecteur que vous avez passé dans le paramètre sélecteur. Si l'information demandée est obtenue, la fonction Gestalt retourne 0, sinon elle retourne l'erreur -5550. Si le sélecteur est inconnu, Gestalt retourne l'erreur -5551.
Important :
Le Gestalt Manager est spécifique à MacOS. Certains des sélecteurs sont également implémentés sous Windows, mais l'utilité de cette fonction reste limitée sur cette plate-forme.
Pour plus d'informations sur les sélecteurs que vous pouvez passer dans Gestalt, reportez-vous à la documentation technique Apple relative au Gestalt Manager, consultable en ligne à l'adresse suivante :
http://developer.apple.com/documentation/Carbon/Reference/Gestalt_Manager/index.
Mais nous n'avons pas de commandes qui nous renseignent sur la langue système utilisée par la machine.
3. Détermination de la langue système sous Macintosh et Windows▲
On peut faire par exemple la différence entre le système français et le système américain grâce à la date système qui se règle dans les « paramètres régionaux », car l'emplacement du mois et du jour est inversé si l'on passe d'un système à l'autre.
Exemple : le mercredi 17 novembre 2004-11-17
Pour le système français, nous aurons 17/11/2004
Pour le système américain, nous aurons 11/17/2004
Il y a donc possibilité d'envisager une solution par programmation autour de la commande Date du langage 4e Dimension.
Par contre, pour tous les autres systèmes étrangers, il n'existe pas de commandes pour déterminer la langue système sous Macintosh et Windows.
Pour résoudre ce problème, nous allons utiliser un nouveau Plug-In compilé sous Windows, Carbon et Macho. Le Plug-In est appelé « InfoSysteme » et il contient 2 commandes pour Windows et une commande pour Macintosh
3-1. Le Plug-in InfoSysteme sous Windows▲
3-1-a. Explication du Code 4e Dimension utilisé▲
Les commandes utilisées sous Windows sont GetLanguage et GetidLanguage.
GetLanguage ne prend pas de paramètres et retourne une chaîne alphanumérique.
La chaîne retournée correspond à la langue système, pour le système français nous aurons :
Français (France)
GetidLanguage ne prend pas de paramètres et retourne une chaîne alphanumérique.
La chaîne retournée correspond au code ISO 639-x, elle donnera « fr » pour « Français » par exemple.
Vous trouverez tous les codes ISO 639-1 à l'adresse suivante :
http://www.loc.gov/standards/iso639-2/englangn.html
Le code utilisé dans la base est le suivant :
2.
3.
4.
Si
(
Evenement formulaire
=
Sur chargement
)
Idlanguage:=
0
Nom_Langue:=
""
Fin de si
Le code utilisé dans le bouton « GetLanguage » est :
2.
Nom_Langue:=
GetLanguage
idlanguage:=
GetidLanguage
Comment utiliser la base exemple sous Windows ?
À partir du menu « Fichier », sélectionnez la ligne « Démonstration », cliquez ensuite « GetLanguage » :
3-1-b. Explication des principales fonctions utilisées dans le Plug-in▲
Les principales fonctions utilisées dans le source en C sont :
- GetSystemDirectory
- GetFileVersionInfoSize
- VerLanguageName
GetSystemDirectory
La fonction GetSystemDirectory renvoie le chemin du répertoire système. Ce répertoire contient des fichiers tels que dll, drivers, polices, etc.
Cette fonction sert en premier lieu à assurer la compatibilité. Les applications doivent sauvegarder le code dans le dossier ProgramFiles et les données dans le dossier Data du profile de l'utilisateur.
UINT GetSystemDirectory
(
LPTSTR lpBuffer,
UINT uSize
);
GetFileVersionInfoSize
La fonction GetFileVersionInfoSize détermine si le système est en mesure de renvoyer l'information de version pour un dossier donné. Lorsque la chose est possible, cette fonction renvoie la taille (en bytes ou octets) de cette info.
DWORD GetFileVersionInfoSize
(
LPTSTR lptstrFilename,
LPDWORD lpdwHandle
);
VerLanguageName
La fonction VerLanguageName renvoie une chaîne descriptive afférente à la langue liée à un MLI binaire spécifique.
DWORD VerLanguageName
(
DWORD wLang,
LPTSTR szLang,
DWORD nSize
);
3-2. Le Plug-in InfoSysteme sur Macintosh▲
3-2-a. Explication du Code 4e Dimension utilisé▲
La commande utilisée sous Macintosh est GetidLanguage.
GetidLanguage ne prend pas de paramètres et retourne une chaîne alphanumérique.
La chaîne retournée correspond au code ISO 639-1 ; elle donnera « fr » pour « Français » par exemple.
La commande GetLanguage n'existe pas, mais peut être implémentée facilement dans 4e Dimension à partir de la commande GetidLanguage.
Exemple
2.
3.
4.
Au cas ou
: (
idLanguage=
"fr"
)
Nom_Langue:=
"french"
Fin de cas
Le paramètre idLanguage a été implémenté dans les ressources du Plug-in pour éviter tout problème de compilation cross-plateforme.
Le code utilisé dans la base est le suivant :
2.
3.
Si
(
Evenement formulaire
=
Sur chargement
)
Idlanguage:=
""
Fin de si
Comment utiliser la base exemple sous Macintosh ?
À partir du menu « Fichier », sélectionnez la ligne « Démonstration », cliquez ensuite « GetLanguage ».
3-2-b. Explication des principales fonctions utilisées dans le Plug-in▲
Les principales fonctions utilisées dans le source en C sont :
- CFPreferencesCopyValue
- CFStringGetCString
- LocaleRefFromLocaleString
- LocaleRefGetPartString
CFPreferencesCopyValue
Cette fonction permet de rechercher des clefs de préférence et d'obtenir une valeur préférence pour un domaine spécifié.
CFPropertyListRef CFPreferencesCopyValue (
CFStringRef key,
CFStringRef applicationID,
CFStringRef userName,
CFStringRef hostName);
Les clés de préférences pour notre Plug-in sont :
- CFSTR(« AppleLanguages ») ;
- kCFPreferencesAnyApplication ;
- kCFPreferencesCurrentUser ;
- kCFPreferencesAnyHost.
lgArray =
(
CFArrayRef) CFPreferencesCopyValue
(
CFSTR
(
"
AppleLanguages
"
),
kCFPreferencesAnyApplication, kCFPreferencesCurrentUser,
kCFPreferencesAnyHost);
CFStringGetCString
Permet de copier les caractères contenus dans un objet CFString vers un buffer chaîne C local après conversion des caractères de l'encodage donné.
Boolean CFStringGetCString (
CFStringRef theString,
char *buffer,
CFIndex bufferSize,
CFStringEncoding encoding
);
LocaleRefFromLocaleString
Permet de convertir une chaîne contenant des données locales en une référence locale
OSStatus LocaleRefFromLocaleString (
const char localeString[],
LocaleRef * locale
);
LocaleRefGetPartString
Permet de convertir une référence de locale en une chaîne contenant des données locales.
2.
3.
4.
5.
6.
OSStatus LocaleRefGetPartString (
LocaleRef locale,
LocalePartMask partMask,
ByteCount maxStringLen,
char
partString[]
);
Pour certaines langues (German, Spanish et Dutch), nous avons été obligés de faire un cas spécial :
Si le code retourné est « German » on recopie « de » dans le code
Si le code retourné est « Spanish » on recopie « spa » dans le code
Si le code retourné est « Dutch » on recopie « dut » dans le code
Pour les langues (French et English), si l'on prend les deux caractères et qu'on passe en minuscules, on obtient directement les codes ISO 639-1 « fr » et « en ».
4. Conclusion▲
Le Plug-in infoSysteme est compilé pour :
- Windows ;
- Macho ;
- Carbon.
Après compilation le Plug-in se situe dans le dossier « Debug » ou dans le dossier « Release ».
Une base de démonstration est fournie pour Macintosh et Windows.
Grâce à ce plug-in, nous pouvons connaître la langue Système de façon précise en respectant le code ISO 639-1. Cette information est très utile pour les bases de données déployées avec des langues étrangères différentes.
Elle peut servir par exemple à ouvrir un fichier de ressources lié à une langue ou lancer un traitement en relation avec une autre langue.
Ce Plug-in fourni en note technique est libre de droits et vous pouvez donc l'intégrer à vos applicatifs. La société 4D ne s'engage à aucune obligation d'évolution de ce plug-in.
4-1. Les codes sources en C▲
4-1-a. Code en C Windows▲
/* --------------------------------------------------------------------------------
# 4DPlugin.c
# Project : InfoSysteme
# author : Aziz Elghomari
# --------------------------------------------------------------------------------*/
#include "4DPluginAPI.h"
#include "4DPlugin.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#if VERSIONWIN
#include <Windows.h>
#endif
//#include "AsiPort.h"
#define NUM_TCHARS_NEEDED_FOR_BACKSLASH (1)
#define NUM_TCHARS_NEEDED_FOR_NULL_TERM (1)
#define BACKSLASH (TEXT("\\"))
//long AnsiToMac( unsigned char *AnsiStr, unsigned char *MacStr, short AnsiLen );
char
*
conversion
(
char
*
ptr);
void
PluginMain
(
long
selector, PA_PluginParameters params )
{
switch
(
selector )
{
case
kInitPlugin :
InitPlugin
(
);
break
;
case
kDeinitPlugin :
DeinitPlugin
(
);
break
;
// --- InfoSysteme
case
eCMD_GetLanguage :
GetLanguage
(
params );
break
;
case
eCMD_GetidLanguage :
GetidLanguage
(
params );
break
;
}
}
void
InitPlugin
(
)
{
// write initialisation code here...
}
void
DeinitPlugin
(
)
{
// write deinitialisation code here...
}
// ---------------------------------- InfoSysteme ---------------------------------
void
GetLanguage
(
PA_PluginParameters params )
{
char
*
maval;
char
returnValue[256
];
long
IDLanguage;
UINT nLenOfSysDirPath =
0
;
LPTSTR lpszSysDir =
NULL
;
//char lpdwTrans[256],cbTrans[256];
LPVOID *
lpdwTrans; // address of buffer for version value pointer
PUINT cbTrans; // address of length buffer
LPTSTR lpszSysFile =
NULL
;
UINT nLen =
0
;
DWORD dwUseless =
0
;
LPVOID lpVersionData =
NULL
;
DWORD dwSize =
0
;
LCID lcidUSER;
TCHAR szUserLangName [64
];
long
lenr, taille;
char
t1[255
] =
"
çéèà
"
;
char
t2[255
] =
""
;
unsigned
char
*
src =
(
unsigned
char
*
)t1;
unsigned
char
*
dest =
(
unsigned
char
*
)t2;
nLen =
GetSystemDirectory
(
NULL
, 0
);
nLenOfSysDirPath =
nLen +
NUM_TCHARS_NEEDED_FOR_BACKSLASH;
lpszSysDir =
(
LPTSTR) LocalAlloc
(
LPTR, nLenOfSysDirPath *
sizeof
(
TCHAR ) );
lpszSysFile =
(
LPTSTR) LocalAlloc
(
LPTR, (
nLenOfSysDirPath+
8
) *
sizeof
(
TCHAR ) );
GetSystemDirectory
(
lpszSysDir, nLen );
if
(
lstrcmp
(
(
LPCTSTR) lpszSysDir[ lstrlen
(
lpszSysDir ) ], (
LPCTSTR) BACKSLASH ) )
lstrcat
(
lpszSysDir, (
LPCTSTR) BACKSLASH );
//lstrcpy( lpszSysFile, (LPCTSTR) lpszSysDir );
lstrcpy
(
lpszSysFile,(
LPCTSTR)lpszSysDir );
lstrcat
(
lpszSysFile, (
LPCTSTR) TEXT
(
"
USER.EXE
"
));
dwSize =
GetFileVersionInfoSize
(
lpszSysFile,&
dwUseless);
if
(
dwSize)
{
lpVersionData =
LocalAlloc
(
LPTR,(
UINT)dwSize);
if
(
GetFileVersionInfo
(
lpszSysFile,dwUseless,dwSize,lpVersionData))
{
if
(
VerQueryValue
(
lpVersionData,TEXT
(
"
\\
VarFileInfo
\\
Translation
"
),(
VOID**
)&
lpdwTrans,&
cbTrans))
{
lcidUSER =
LOWORD
(
lpdwTrans[0
]);
}
}
// end we got version data
LocalFree
((
HLOCAL)lpVersionData);
}
// --- write the code of GetLanguage here...
VerLanguageName (
lcidUSER,szUserLangName,sizeof
(
szUserLangName));
PA_ReturnString
(
params, szUserLangName );
LocalFree
(
lpszSysDir);
LocalFree
(
lpszSysFile);
}
void
GetidLanguage
(
PA_PluginParameters params )
{
char
*
maval;
char
returnValue[256
];
long
IDLanguage;
UINT nLenOfSysDirPath =
0
;
LPTSTR lpszSysDir =
NULL
;
//char lpdwTrans[256],cbTrans[256];
LPVOID *
lpdwTrans; // address of buffer for version value pointer
PUINT cbTrans; // address of length buffer
LPTSTR lpszSysFile =
NULL
;
UINT nLen =
0
;
DWORD dwUseless =
0
;
LPVOID lpVersionData =
NULL
;
DWORD dwSize =
0
;
LCID lcidUSER;
TCHAR szUserLangName [64
];
long
lenr, taille;
char
t1[255
] =
"
çéèà
"
;
char
t2[255
] =
""
;
unsigned
char
*
src =
(
unsigned
char
*
)t1;
unsigned
char
*
dest =
(
unsigned
char
*
)t2;
unsigned
char
*
dest2 =
(
unsigned
char
*
)t2;
nLen =
GetSystemDirectory
(
NULL
, 0
);
nLenOfSysDirPath =
nLen +
NUM_TCHARS_NEEDED_FOR_BACKSLASH;
lpszSysDir =
(
LPTSTR) LocalAlloc
(
LPTR, nLenOfSysDirPath *
sizeof
(
TCHAR ) );
lpszSysFile =
(
LPTSTR) LocalAlloc
(
LPTR, (
nLenOfSysDirPath+
8
) *
sizeof
(
TCHAR ) );
GetSystemDirectory
(
lpszSysDir, nLen );
if
(
lstrcmp
(
(
LPCTSTR) lpszSysDir[ lstrlen
(
lpszSysDir ) ], (
LPCTSTR) BACKSLASH ) )
lstrcat
(
lpszSysDir, (
LPCTSTR) BACKSLASH );
//lstrcpy( lpszSysFile, (LPCTSTR) lpszSysDir );
lstrcpy
(
lpszSysFile,(
LPCTSTR)lpszSysDir );
lstrcat
(
lpszSysFile, (
LPCTSTR) TEXT
(
"
USER.EXE
"
));
dwSize =
GetFileVersionInfoSize
(
lpszSysFile,&
dwUseless);
if
(
dwSize)
{
lpVersionData =
LocalAlloc
(
LPTR,(
UINT)dwSize);
if
(
GetFileVersionInfo
(
lpszSysFile,dwUseless,dwSize,lpVersionData))
{
if
(
VerQueryValue
(
lpVersionData,TEXT
(
"
\\
VarFileInfo
\\
Translation
"
),(
VOID**
)&
lpdwTrans, &
cbTrans))
{
lcidUSER =
LOWORD
(
lpdwTrans[0
]);
}
}
// end we got version data
LocalFree
((
HLOCAL)lpVersionData);
}
// --- write the code of GetLanguage here...
VerLanguageName (
lcidUSER,szUserLangName,sizeof
(
szUserLangName));
strncpy
(
dest,szUserLangName,2
);
PA_ReturnString
(
params, dest );
LocalFree
(
lpszSysDir);
LocalFree
(
lpszSysFile);
}
4-1-b. Code en C Macintosh▲
/* ------------------------------------------------------------------------
#
# 4DPlugin.c
# source generated by 4D Plugin Wizard
# Project : InfoSysteme
# author : azizelghomari
# 10/11/04
#
# --------------------------------------------------------------------------------*/
#include "4DPluginAPI.h"
#include "4DPlugin.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <extras_string.h>
#if VERSIONWIN
#include <Windows.h>
#endif
void
PluginMain
(
long
selector, PA_PluginParameters params )
{
switch
(
selector )
{
case
kInitPlugin :
InitPlugin
(
);
break
;
case
kDeinitPlugin :
DeinitPlugin
(
);
break
;
// --- InfoSysteme
case
1
:
GetLanguage
(
params );
break
;
}
}
void
InitPlugin
(
)
{
// write initialisation code here...
}
void
DeinitPlugin
(
)
{
// write deinitialisation code here...
}
// ---------------------------------- InfoSysteme ---------------------------------
void
GetLanguage
(
PA_PluginParameters params )
{
CFArrayRef lgArray;
char
lgCode[4
];
char
code[256
];
CFStringRef strRef;
Boolean result;
OSStatus status;
LocaleRef locale;
lgCode[0
] =
0
;
lgArray =
(
CFArrayRef) CFPreferencesCopyValue
(
CFSTR
(
"
AppleLanguages
"
),
kCFPreferencesAnyApplication, kCFPreferencesCurrentUser,
kCFPreferencesAnyHost);
if
(
lgArray !=
NULL
) {
strRef =
(
CFStringRef) CFArrayGetValueAtIndex
(
lgArray, 0
);
if
(
strRef !=
NULL
) {
result =
CFStringGetCString
(
strRef, code, 256
, kCFStringEncodingASCII);
if
(
result ==
true
) {
status =
LocaleRefFromLocaleString
(
code, &
locale);
if
(
status ==
noErr) {
char
lcode[256
];
status =
LocaleRefGetPartString
(
locale, kLocaleLanguageMask, 256
, lcode);
if
(
status ==
noErr) {
strcpy
(
code, lcode);
}
}
if
(
strlen
(
code) >
2
) {
if
(
strcmp
(
code, "
german
"
) ==
0
) strcpy
(
code, "
de
"
);
//allemand
else
if
(
strcmp
(
code, "
spanish
"
) ==
0
) strcpy
(
code, "
es
"
);
//espagnol
else
if
(
strcmp
(
code, "
dutch
"
) ==
0
) strcpy
(
code, "
nl
"
);
//neerlandais
else
code[2
] =
0
;
}
tolower
(
code[0
]);
tolower
(
code[1
]);
strcpy
(
lgCode, code);
}
}
}
PA_ReturnString
(
params, lgCode );
}
5. Bases exemples▲
Téléchargez les bases exemples :
Base exemple Win
Base exemple Mac