Déterminer la langue système sous Macintosh et Windows

Aziz ELGHOMARI

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. Nous vous proposons un plug-in permettant cela (Windows, MachO, Carbon). ♪

- Titre : Déterminer la langue système sous Macintosh et Windows

- Auteur : Aziz ELGHOMARI

- Parution : 1 février 2005

- Licence : Ce document est issu de https://www.developpez.comet reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- 1. Introduction

- 2. Informations liées à l’environnement système que nous pouvons récupérer

- 3. Détermination de la langue système sous Macintosh et Windows

- 3-1. Le Plug-in InfoSysteme sous Windows

- 3-1-a. Explication du Code 4e Dimension utilisé

- 3-1-b. Explication des principales fonctions utilisées dans le Plug-in

- 3-2. Le Plug-in InfoSysteme sur Macintosh

- 3-2-a. Explication du Code 4e Dimension utilisé

- 3-2-b. Explication des principales fonctions utilisées dans le Plug-in

- 4. Conclusion

- 4-1. Les codes sources en C

- 4-1-a. Code en C Windows

- 4-1-b. Code en C Macintosh

- 5. Bases exemples

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érique

- Largeur ecran {(*)}->Numérique

- Nombre ecrans -> Entier long

- COORDONNEES ECRAN (gauche; haut; droite; bas{; écran})

- PROFONDEUR ECRAN (profondeur; couleurs{; écran})

- FIXER PROFONDEUR ECRAN (profondeur{; couleurs{; écran}})

- Ecran principal -> Entier long

- Hauteur barre de menus -> Entier long

- LISTE DES POLICES (polices)

- Nom de police (numéro) -> Alpha

- Numero de police (nomPolice) -> Entier long

- PROPRIETES PLATE FORME (plateForme{; système{; machine}})

- Dossier systeme {(type)} Alpha

- Dossier temporaire -> Alpha

- Nom 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 :

1. Si (Evenement formulaire=Sur chargement)

2. Idlanguage:=0

3. Nom_Langue:=""

4. Fin de si

Le code utilisé dans le bouton « GetLanguage » est :

1. Nom_Langue:= GetLanguage

2. 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.

Syntaxe :

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.

Syntaxe :

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.

Syntaxe :

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

1. Au cas ou

2. : (idLanguage="fr")

3. Nom_Langue:="french"

4. 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 :

1. Si (Evenement formulaire=Sur chargement)

2. Idlanguage:=""

3. 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.

Syntaxe :

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.

1. OSStatus LocaleRefGetPartString (

2. LocaleRef locale,

3. LocalePartMask partMask,

4. ByteCount maxStringLen,

5. char partString[]

6. );

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