Internationaliser un projet Delphi

| Eric SIBERT | Vincent CALLIES |

Cet article présente en cinq parties, de façon détaillée, les principes pour internationaliser un projet écrit avec Delphi.

- Titre : Internationaliser un projet Delphi

- Auteurs : Eric SIBERT, Vincent CALLIES

- Parution : 6 juillet 2002

- Mise à jour : 7 décembre 2019

- Licence : Ce document est issu de http://www.developpez.com et 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

- I. Préparer l'internationalisation

- I-A. Messages pour l'utilisateur

- I-B. Gestion des chaînes

- I-C. Utilisation des paramètres régionaux

- I-D. Conception de l'interface

- II. Traduction de projet en utilisant l'Expert DLL de ressources

- II-A. générer les DLL de ressources

- II-B. Traduire l'interface

- II-C. Traduire les chaînes de ressources

- II-D. Changer de langue à l'exécution

- II-E. conclusion

- III. Utiliser le référentiel de traduction de Delphi

- III-A. Le référentiel de traduction : la colonne vertébrale de l'ite

- III-A-1. Un outil pérennisant le travail de traduction

- III-A-2. Un outil souple

- III-B. Le module de traduction : l'environnement de travail de l'ite

- III-B-1. Un environnement puissant

- III-B-2. Un environnement ouvert

- III-C. Conclusion

- IV. Traduisez vos projets Delphi en russe

- IV-A. Introduction

- IV-B. Travail du traducteur

- IV-C. Tester le programme

- IV-D. Conclusion

- V. Internationalisez a posteriori vos projets Delphi

- V-A. Introduction

- V-B. Préparation

- V-C. Extraction du texte

- V-D. Travail du traducteur

- V-E. Traduction du projet

- V-F. Mise à jour

- V-G. Conclusion

I - Préparer l'internationalisation

L'internationalisation d'un projet Delphi doit être envisagée avant même de commencer le développement de l'application. Il y a en effet un certain de nombre de détails à prendre en compte aussi bien pendant l'écriture du code que durant la conception de l'interface et qui faciliteront la traduction. Les principaux points sont les suivants.

I-A - Messages pour l'utilisateur

Vous devez isoler les messages envoyés à l'utilisateur dans les ressources de votre projet afin de pouvoir les traduire sans modifier votre projet lui-même. Les resourcestring de Delphi permettent d'atteindre cet objectif. Vous devez simplement déclarer votre chaîne de caractères en resourcestring avant de l'utiliser :

// ancienne méthode
ShowMessage('Au revoir');
// nouvelle méthode
resourcestring
MessageFin = 'Au revoir';
...
ShowMessage(MessageFin); // bon

Et si votre message comporte plusieurs morceaux, regroupez-les en utilisant les chaînes de format :

// ancienne méthode
ShowMessage('Vous avez '+IntToStr(I)+' éléments');

// mauvaise nouvelle méthode
resourcestring
DebutMsg = 'Vous avez';
FinMsg = ' éléments';
...
ShowMessage(Debut+IntToStr(I)+FinMsg); // mauvais

// bonne nouvelle méthode
resourcestring
MonMessage = 'Vous avez %d éléments';
...

ShowMessage(Format(MonMessage,[i])); // bon

Vous aurez ainsi des phrases facilement compréhensibles par le traducteur plutôt que des bouts de texte disparates.
Il est conseillé, mais ce n'est pas une obligation, de les réunir dans une unité à part, unique pour l'ensemble du projet :

unit chaines;
interface

resourcestring
MonMessage = 'Bonjour monde';

implementation

end.

Pour conclure sur les resourcestring, si vous n'avez pas extrait les chaînes de texte au cours de la conception, j'ai développé ma propre méthode de traduction qui s'affranchit de ce problème.

I-B - Gestion des chaînes

La gestion des chaînes de caractères est un autre point important, surtout si vous envisagez d'utiliser des langues orientales dont tous les caractères ne peuvent pas être représentés par un jeu de 256 caractères. Dans ce cas, un caractère peut aussi bien être représenté par un seul ou par deux octets et la longueur d'un texte n'est alors pas toujours égale au nombre d'octets. On parle aussi de jeux de caractères MBCS (MultiByte Character Sets). À chaque fois que vous effectuez un traitement sur une chaîne, vous devez vous demander si celui-ci est compatible avec les jeux MBCS. Vous devez aussi vérifier dans l'aide de Delphi que les fonctions que vous appelez sont compatibles. Pour celles qui ne le sont pas, il existe dans de nombreux cas une fonction équivalente préfixée par Ansi :

// exemple extrait de l'aide de Delphi
function LowerCase(const S: string): string;

Description
LowerCase renvoie une chaîne AnsiString contenant le même texte que celui de la chaîne transmis par S, l'ensemble des lettres ayant été converties en minuscules. La conversion n'affecte que les caractères ASCII sur 7 bits compris entre 'A' et 'Z'. Pour convertir les caractères internationaux sur 8 bits, utilisez AnsiLowerCase.

function AnsiLowerCase(const S: string): string;

Description
AnsiLowerCase renvoie une chaîne, qui est une copie de la chaîne donnée convertie en minuscules. La conversion fait appel au pilote de langue Windows actuellement installé. Cette fonction accepte les jeux de caractères MBCS (MultiByte Character Sets).

Nous constatons que non seulement AnsiLowerCase gère les caractères MCBS, mais s'occupe aussi de la conversion des caractères accentués, ce que ne fait pas LowerCase. Comme je n'ai pas vraiment de compétences concernant la traduction avec les caractères MCBS, je vous invite à consulter l'aide de Delphi qui fait le tour du problème.

I-C - Utilisation des paramètres régionaux

Après le respect de la langue de l'utilisateur, il est fortement conseillé de tenir correctement compte des paramètres régionaux (y compris pour les projets non internationalisés).

Si l'utilisateur a choisi la virgule comme séparateur décimal, il est de bon goût, lorsqu'il effectue une saisie avec le pavé numérique de remplacer la frappe du point par une virgule. Sauf qu'en Allemagne, par exemple, il y a une virgule sur le pavé numérique qu'il faut transformer en point si celui-ci est le séparateur décimal. Le code suivant doit résoudre ce problème dans toutes les situations :

Virgule : boolean;
procedure TForm1.EditXMinKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
Virgule:=(Key=VK_DECIMAL); // détection de l'appui de la touche séparateur décimal
// sur le pavé numérique
end;

procedure TForm1.EditXMinKeyPress(Sender: TObject; var Key: Char);
begin
if Virgule then
Key:=decimalseparator;  // on met le séparateur décimal de l'utilisateur à la place
end;

Dans le même genre, vous pouvez avoir des surprises avec la gestion de la date ou de l'heure. J'ai par exemple créé une application chronomètre qui m'indique le temps écoulé en hh:mm:ss en utilisant TimeToStr. J'amène ça au travail, sur un ordinateur en allemand, et surprise, j'obtiens 12:00:01 AM. Donc, n'hésitez pas à jouer avec les paramètres régionaux pour voir si votre application se comporte bien avec toutes les possibilités, sachant que je n'ai pas pu reproduire sur mon PC l'affichage AM/PM dans mon application même quand il était actif au niveau de l'horloge de Windows.

I-D - Conception de l'interface

Enfin, la préparation concerne l'interface graphique et consiste à prévenir les variations de longueur du texte affiché. Bien que cette adaptation puisse être réalisée après la traduction, la mise en œuvre des conseils suivants facilitera fortement le travail des personnes chargées de l'internationalisation. Vous devez donc réserver suffisamment d'espace au texte affiché dans les fenêtres pour qu'il puisse s'adapter à la nouvelle langue. Faites en particulier attention aux abréviations qui n'existent pas dans d'autres langues et qui exigeront beaucoup plus de place. L'aide de Delphi (recherchez le mot foisonnement) fournit des indications sur le pourcentage de place à prévoir en fonction de la taille du mot.

Petite astuce concernant les labels. Si un label est centré au-dessus d'un contrôle, mettez ses propriétés Autosize à false, Alignment à taCenter et augmentez sa largeur en prévision de la traduction. Ainsi, lorsque le texte changera de taille, il restera centré au-dessus de l'autre contrôle :

Pour un label situé devant un contrôle, faite le contraire avec Autosize à true et Alignment à taLeftJustify et prévoyez assez de place entre le label et le contrôle.

Pour terminer, je vous conseille fortement de consulter l'aide de Delphi sur le sujet, qui détaille certaines des remarques précédentes et fournit d'autres informations.

II - Traduction de projet en utilisant l'Expert DLL de ressources

Dans cette partie, je vais présenter la traduction d'un projet avec D5 Pro (ou supérieur). Je suppose que vous avez mis en œuvre les recommandations concernant la préparation d'un projet. En complément de cette partie, une page présente les apports de l'ITE (environnement de traduction intégré) dans le processus de traduction. Les points suivants sont abordés.

II-A - générer les DLL de ressources

Votre projet est prêt à être traduit. Et Delphi vous fournit l'assistant pour ceci, à savoir l'Expert DLL de ressources. Cet outil va réunir toutes vos ressources dans une DLL et générer autant de DLL que vous voulez de langues. Le programme n'aura alors plus qu'à charger la bonne DLL pour afficher la langue voulue.

Après avoir ouvert votre projet dans Delphi, vous accédez à cet assistant par le menu Nouveau… :

Vous avancez dans l'Expert en général sans rien changer et en appuyant uniquement sur le bouton Suivant. Vous arrivez au choix des langues :

Dans un premier temps, je vous déconseille de sélectionner la langue utilisée pour le développement, le français dans mon cas. Vous continuez ensuite jusqu'à la fin de l'assistant sans rien changer. À la question :

répondez Oui. Pour terminer, vous avez le droit à quelques statistiques.
De retour dans Delphi, vous voici avec une library (DLL) par langue :

En fait vos données sont organisées en groupe de projet. Avec Voir Gestionnaire de projet (Ctrl+Alt+F11), vous avez plus de détails :

II-B - Traduire l'interface

Vous devez maintenant traduire chaque projet en langue étrangère. Commencez par les Form et autres fenêtres. Avec la commande Ouvrir du menu contextuel, vous activez la forme dans l'EDI. Vous n'avez plus qu'à utiliser l'inspecteur d'objets pour modifier toutes les propriétés qui le nécessitent. La première à traduire est évidemment Caption, mais vous pouvez en modifier d'autres. Pour afficher la liste des propriétés que vous êtes autorisé à modifier, cliquez avec le bouton droit de la souris sur l'inspecteur d'objet et choisissez l'option Voir|Localisable comme suit :

Vous constatez alors que vous pouvez, par exemple, changer la largeur d'un composant qui serait trop étroit pour le texte qu'il doit contenir.

II-C - Traduire les chaînes de ressources

Ensuite passez au fichier ressource, toujours avec Ouvrir avec une surprise :

En plus de vos ressources à vous (vos resourcestring), il y a un tas d'autres chaînes qui peuvent apparaître dans vos applications. Nous voyons dans l'exemple ci-dessus les chaînes relatives aux fenêtres créées lors d'appels à la fonction MessageDlg. Pour un simple projet, il faut déjà compter 170 chaînes, nombre qui augmentera si vous utilisez le BDE par exemple. Pour un premier essai, je vous conseille de ne traduire que vos chaînes de ressources personnelles, mais à terme, il faudra traduire toutes les chaînes susceptibles d'être utilisées dans votre application.

Quand vous avez fini vos traductions, sauvegarder l'ensemble et recompilez-le avec la commande Compiler tous les projets :

II-D - Changer de langue à l'exécution

Avec le gestionnaire de projets, retournez sur le projet principal (sinon, vous restez sur la dernière langue de la liste) et exécutez votre projet. Vous constatez que rien n'a changé. D'ailleurs, nous n'avons jamais indiqué qu'il fallait changer quelque chose. En fait, au démarrage de l'application, celle-ci regarde la langue définie dans Windows et recherche s'il existe une DLL de ressources correspondantes. Si votre projet est en français avec Windows en français, votre application utilise le français. Par contre, si vous utilisez Windows en anglais, votre application doit utiliser l'anglais au démarrage. Vous avez donc détection et utilisation automatique de la langue de l'utilisateur. Ceci peut être gênant si l'utilisateur veut travailler avec une autre langue que celle de Windows. La méthode pour contourner ce problème est de changer dynamiquement de langue à l'exécution. Un exemple est présenté dans la démonstration de richedit fournie avec Delphi (dossier /demos/richedit). Pour mettre cette technique en œuvre dans votre projet, vous devez récupérer l'unité Reinit.pas de l'exemple de Delphi et l'inclure dans votre projet (ou mettre son chemin dans les options de recherche). Ensuite, pour passer en allemand standard, utilisez le code suivant :

uses
Reinit;
const
GERMAN  = (SUBLANG_GERMAN shl 10) or LANG_GERMAN;

procedure TForm1.Button1Click(Sender: TObject);
begin
if LoadNewResourceModule(GERMAN) <> 0 then
ReinitializeForms;
end;

Cette fois, l'essai est concluant et vous pouvez basculer votre application dans la langue que vous désirez. La première difficulté est de revenir en français si vous n'avez pas créé la DLL de ressources correspondantes (voir note). Le second problème est qu'il faut rajouter un bout de code à chaque fois que vous ajoutez une langue à votre projet. J'ai donc mis au point une autre technique qui liste automatiquement toutes les langues disponibles dans une ComboBox et vous n'avez plus qu'à faire votre choix : (1)

unit uchoix; // unité de la fenêtre de choix de langue
...
procedure TChoix_langue.FormShow(Sender: TObject);
var
Les_Langues : TLanguages;
I : integer;
Racine : TFileName;
begin
inherited;
ComboBox.Items.Clear;
Racine:=Application.ExeName;
// récupération de toutes les langues installées sur Windows
Les_Langues:=Languages;

for I:=0 to Les_Langues.Count-1 do
begin
// on regarde si la DLL correspondant à une langue existe
if FileExists(ChangeFileExt(Racine,'.'+Les_Langues.Ext[I])) then
// si oui, on l'ajoute à la liste des langues disponibles
ComboBox.Items.AddObject(Les_Langues.Name[I],TObject(StrToInt(Les_Langues.ID[I])));
end;
ComboBox.ItemIndex:=0;
end;

procedure TForm1.Choisir1Click(Sender: TObject);
var
I : integer;
begin
if Choix_Langue.ShowModal=mrOk then
begin
I:=integer(Choix_Langue.ComboBox.Items.Objects[Choix_Langue.ComboBox.ItemIndex]);
if LoadNewResourceModule(I) <> 0 then
ReinitializeForms;
end;
end;

On remarque au passage que l'ID de la langue est stocké dans le champ Objects des Items de la ComBox. Nous avons ainsi un moyen rapide, élégant et qui s'adapte aux évolutions de votre projet :

II-E - conclusion

Je vous mets le code source (101 ko) d'un projet illustrant la traduction d'un projet avec changement dynamique de la langue.

Dans cette partie, nous avons vu la manière de traduire dans Delphi une application dans plusieurs langues et la méthode pour changer dynamiquement de langue à l'affichage. Parmi les inconvénients, il est nécessaire de disposer de Delphi pour réaliser la traduction et il faut à chaque projet traduire l'ensemble des mots, y compris les plus courants, comme ceux qui sont présents dans les ressources par défaut. Dans la partie suivante, nous allons voir l'utilité de l'ITE qui permet réellement de gérer la traduction.

III - Utiliser le référentiel de traduction de Delphi

Nous allons ici apprendre à utiliser un puissant outil, l'environnement de traduction intégré (ITE) de Delphi. Cet outil s'inscrit dans le processus de traduction, dans le cadre de l'utilisation de l'expert de DLL ressources. L'ITE n'est disponible que dans les versions ENTREPRISE de Delphi 5 et 6.

III-A - Le référentiel de traduction : la colonne vertébrale de l'ite

La puissance de l'ITE repose sur le référentiel de traduction. Le référentiel de traduction est une sorte de dictionnaire établissant des correspondances entre les chaînes de caractères traduites en plusieurs langues. Vous y trouverez toutes les chaînes utilisées par les composants visibles ou invisibles de Delphi (dont les messages d'erreur) en français, en anglais et en allemand. Il vous appartient d'enrichir ce référentiel avec vos propres correspondances ou d'autres langues. Pour ce faire la démarche est simple. Le référentiel de traduction peut s'exporter ou s'importer au format XML.

III-A-1 - Un outil pérennisant le travail de traduction

La nécessité d'enrichir le référentiel de traduction est la meilleure façon de s'assurer une maintenance aisée de la localisation. Le projet traduit va évoluer : les chaînes de caractères à traduire ne seront pas au même endroit, il y en aura moins ou, plus probablement, plus. La photographie de l'état actuel du projet, c'est-à-dire le projet de DLL que vous aurez créé, ne servira à rien : il ne coïncidera plus avec le nouveau projet. Il faudra créer un nouveau projet de DLL.

Si vous n'avez pas pris la précaution de faire remonter votre travail de traduction vers le référentiel, le nouveau projet de traduction sera un recommencement du travail de traduction déjà fait. En effet, pour créer le projet de DLL, Delphi s'appuiera sur le référentiel et non sur le travail fait dans votre précédent projet.

III-A-2 - Un outil souple

L'avantage du référentiel de traduction est qu'il peut être enrichi partiellement. Vous pouvez importer dans votre référentiel en cours des données qui viendront le compléter.

Par exemple, dans le cadre d'un logiciel de cartographie vectorielle, vous pouvez enrichir votre référentiel de termes, menus, options, propres au jargon technique utilisé. Il vous suffit de créer un fichier XML contenant ces informations et de l'importer dans votre référentiel de traduction. C'est le choix fait par le projet open source en Delphi AutoREALM pour sa localisation en français.

III-B - Le module de traduction : l'environnement de travail de l'ite

Le gestionnaire de traduction est un environnement de travail très agréable pour procéder à la localisation d'un projet. Il est beaucoup plus spécialisé que celui du simple gestionnaire de projets : les objets ne sont pas présentés comme tels, mais sous la forme d'une liste dans un tableau de chaînes de caractères où seules celles qui sont pertinentes à traduire sont présentes.

III-B-1 - Un environnement puissant

L'affichage disponible au travers du module de traduction va au-delà de celui dont on pourrait disposer dans le traditionnel gestionnaire de projets. L'affichage est optimisé en ce que seules les chaînes pertinentes à localiser sont affichées sous forme d'un tableau. Ce tableau est dynamique : l'utilisateur peut afficher les chaînes traduites, les chaînes traduites automatiquement, les chaînes restant à traduire.

Il est à noter que la localisation permise par l'ITE concerne tout à la fois les chaînes de caractères, mais aussi leur positionnement.

III-B-2 - Un environnement ouvert

La souplesse du référentiel de traduction vous permet de l'utiliser non pas seulement dans le cadre du processus automatisé de production de DLL locale, mais aussi lors de la retouche des DLL. D'un simple clic du bouton droit de votre souris, vous pouvez faire appel au référentiel dans le cadre même du gestionnaire de traduction.

III-C - Conclusion

L'ITE permet de pérenniser votre travail de traduction en adaptant cette dernière aux évolutions de votre projet. D'autres outils comme celui d'Eric SIBERT, permettent d'inscrire dans le temps votre travail de traduction, mais sans offrir toute la souplesse de l'ITE. En effet, le référentiel de traduction vous permet de centraliser l'ensemble du texte à traduire que vous ferez ensuite redescendre sur votre nouveau projet de DLL afin de ne pas perdre le bénéfice du travail déjà opéré. Cela ne vous prendra que quelques secondes. On comprend la puissance d'un tel environnement de traduction : il est unique à Delphi.

IV - Traduisez vos projets Delphi en russe

IV-A - Introduction

Dans cette partie, nous allons étudier comment réaliser une traduction entre deux langues utilisant des alphabets différents en nous appuyant sur l'exemple du russe qui s'écrit en cyrillique. Même si cette partie concerne plutôt la traduction avec mon utilitaire, la plupart des idées sont générales, à l'exception du paragraphe Travail du traducteur, et pourront aussi être lues par ceux qui utilisent les outils de traduction de Delphi.

Mais d'abord, regardons comment Windows gère le cyrillique. La norme ASCII définit un ensemble de caractères numérotés de 0 à 127. Ces caractères permettent d'écrire du texte en anglais, guère plus. Pour les autres langues, les fabricants se sont rabattus sur les caractères de 128 à 255, voire codent sur deux octets. Pour l'Europe de l'Ouest, nous pouvons voir le résultat dans la table de caractères de Windows 95

Nous constatons que tous nos caractères spéciaux ou accentués sont présents, ainsi que ceux de certains de nos voisins. Ce jeu de caractères est appelé Latin ou Western.

Pour le cyrillique, ils ont utilisé le même principe, les caractères ASCII de 0 à 127 et le cyrillique de 128 à 255 :

Il y a de cette façon presque autant de tables de caractères que de langues. Lorsque vous utilisez Windows, celui-ci emploie une table de caractères par défaut. Et les applications que vous développez avec Delphi font de même. Mais Windows peut gérer plusieurs tables à la fois. Pour ceci, vous devez activer la prise en charge multilingue. Commencez par aller dans le Panneau de configuration, Ajout/Suppression de programmes, onglet Installation de Windows :

Je vous conseille de tout installer, mais vous pouvez vous contenter des langues qui vous intéressent. Après cette installation, vous aurez le support pour le bulgare, le biélorusse, le russe, le serbo-croate, l’ukrainien, le grec, le turc, l’estonien, le letton, le lithuanien, l’albanais, le tchèque, le croate, le hongrois, le polonais, le slovaque et le slovène :-)).

IV-B - Travail du traducteur

Étudions maintenant ce qui change dans la traduction d'une application avec mon utilitaire. La création de la liste de mots à traduire ne change pas. Par contre, le travail du traducteur change. En effet, il va devoir visualiser côte à côte le texte en français et celui dans sa langue. Dans la suite, je supposerai que le traducteur utilise une version de Windows en français, mais, dans le cas contraire, il y a juste quelques opérations à inverser.

Première méthode, il peut utiliser Wordpad. Il ouvre donc dans Wordpad d'une part le texte français qui s'affiche correctement. D'autre part, il crée dans une nouvelle fenêtre de Wordpad un nouveau document au format Texte seulement :

Ensuite, dans Format|Police, il doit indiquer en bas à droite de la fenêtre qu'il faut travailler en cyrillique :

Si la police proposée ne dispose pas du cyrillique, il faut en prendre une autre, genre Arial.
Il n'y a plus qu'à faire la saisie de la traduction en cyrillique :

Deuxième méthode, vous envoyez au traducteur mon utilitaire de traduction. Il ouvre le texte français comme d'habitude. Par contre, pour la Langue étrangère, il doit modifier la Police et choisir le cyrillique :

Ensuite, il traduit, enregistre et vous renvoie le tout.

IV-C - Tester le programme

Vous n'avez plus qu'à traduire le projet suivant la méthode habituelle. Sauf que vous aimeriez bien pouvoir tester le résultat. Sur votre PC en français, ce n'est pas brillant :

Inutile d'essayer de bricoler les fonts dans votre projet. Le menu, entre autres, utilise les paramètres de Windows pour s'afficher. Il vous faut un PC en russe pour tester votre application. Comme c'est assez peu courant chez nous et qu'en plus, il faudrait un PC par langue, il y une autre méthode. Cette technique ne fonctionne qu'avec NT4 ou W2000 et pas du tout sous 95/98/Me. Le principe est qu'il est possible de basculer Windows de façon réversible en russe. En fait, il existe deux installations de Windows, l'installation d'origine en anglais US et les installations localisées. Vous pouvez facilement passer de la version US à une version localisée, les versions localisées utilisant une extension de l'ASCII. Nous voyons d'ailleurs ici bien le problème. Si vous basculez entre deux versions localisées qui n'utilisent pas la même extension de l'ASCII, les caractères spéciaux comme les accents ne pourront suivre la transformation et les noms de fichier et répertoire les utilisant seront endommagés.

Je vais donc vous présenter la méthode pour passer NT4 (SP5) en russe. La méthode pour W2000 ainsi que beaucoup d'autres informations sur la russification peuvent être trouvées sur cette page. Vous démarrez donc IMPÉRATIVEMENT avec une version de NT4 US. Allez dans le Panneau de configuration et activez les Paramètres régionaux :

Vous sélectionnez le russe et vous cochez la case Set as system default locale. Puis suivez les instructions de Windows (insérer le CD de Windows et redémarrer). Après le redémarrage, vous êtes aussi censés réinstaller le dernier Service Pack (c'est signalé à l'installation du SP !). Personnellement, je ne le fais qu'après le retour en anglais. Après le redémarrage, vous constatez que la police a changé, d'ailleurs pas très lisible (beaucoup plus lisible si vous réinstallez le SP !).

Il est temps de tester votre projet en démarrant simplement l'exe :

Ça va beaucoup mieux. Le test est concluant.
Une fois le test terminé, vous n'avez plus qu'à remettre Windows en anglais suivant le chemin inverse. Et, pendant que vous êtes en russe, évitez de créer des fichiers ou des dossiers utilisant des caractères cyrilliques.

IV-D - Conclusion

Pour clore, nous avons vu que la traduction en russe n'est guère plus difficile que la traduction simple. De la même manière, vous pouvez accéder à l'ensemble des langues est-européennes. L'arabe et l'hébreu doivent aussi être envisageables (l'arabe est alphabétique, pour l'hébreu, je ne sais pas) sauf qu'ils ne sont pas proposés par défaut dans W95. Quant aux langues orientales, qui ne sont pas vraiment alphabétiques, je n'ai aucune idée sur la manière de procéder.

Je tiens à remercier Sergueï (alias Serge Arbiol) pour son aide et ses conseils concernant l'utilisation du Russe dans Delphi et Windows, ainsi que pour la traduction en russe de mon utilitaire de traduction.

V - Internationalisez a posteriori vos projets Delphi

V-A - Introduction

Vous avez développé votre application à l'aide de Delphi. Vous êtes content du résultat et vous voudriez en faire profiter un maximum de monde. Aussi, vous aimeriez bien traduire votre projet dans d'autres langues que le français.

Confronté à ce problème, j'ai commencé par lire la documentation de Delphi sur le sujet. Je suis tombé sur un écueil, à savoir que pour préparer mon projet à la traduction, je devais isoler toutes les chaînes de caractères à traduire en tant que resourcestring (plus de détails). N'ayant pas envie de faire ce travail, j'ai préféré développer ma propre solution logicielle de traduction a posteriori, qui ne nécessite pas cette préparation. Cette méthode fonctionne avec toutes les versions de Delphi (de 1 à 6, Standard, Pro, Ent.), pas encore avec Kylix. Il est à noter que si vous savez avant de commencer un projet qu'il devra être traduit en plusieurs langues, il existe d'autres méthodes plus adaptées fournies avec Delphi.

Le principe de mon utilitaire est de récupérer toutes les chaînes de texte d'un projet, y compris celles présentes dans le code source, puis de réaliser un nouveau projet avec les chaînes traduites. Vous aurez alors un projet et un exécutable distincts pour chaque langue.

V-B - Préparation

Les méthodes générales de préparation d'un projet sont présentées par ailleurs. Concernant mon utilitaire, même s'il n'est pas nécessaire d'extraire en resourcestring toutes les chaînes de caractères du code source, une certaine préparation du projet s'impose.
Il faut en particulier formater correctement les chaînes pour qu'un même message ne soit pas fractionné en plusieurs morceaux :

ShowMessage('Vous avez '+IntToStr(I)+' éléments'); // mauvais
ShowMessage(Format('Vous avez %d éléments',[i])); // bon

Dans le premier cas, vous aurez deux textes à traduire qui pourront éventuellement être séparés dans la liste à traduire. Au contraire, dans le second cas, avec la chaîne de format, vous n'avez qu'un seul texte plus compréhensible à traduire.

V-C - Extraction du texte

Nous pouvons maintenant rentrer dans le vif du sujet. Commencez par récupérer mon utilitaire (440 ko) et installez-le sur le même ordinateur que la version de Delphi qui a servi à développer votre projet. Vous devez maintenant extraire l'ensemble des mots et expressions utilisés dans votre projet. Ensuite, copiez les fichiers utiles (pas, dfm, xfm, dpr et res) de votre projet dans un nouveau dossier. NE TRAVAILLEZ JAMAIS SUR VOTRE PROJET ORIGINAL. Un autre programme personnel (ou un .bat:) peut vous aider pour cette tâche. En général, j'utilise la structure suivante pour traduire un projet en mettant la copie dans « traduction » :

Ensuite, démarrez l'utilitaire de traduction et choisissez votre projet avec la commande Projet|Ouvrir :

Commencez l'analyse de suite avec Projet|Analyser. L'utilitaire vous demande au passage la version de Delphi utilisée pour écrire le projet :

Vous devez disposer de la version correspondante à votre projet installée sur votre PC. Si vous indiquez une version trop vieille, vous risquez le plantage. Avec une version plus récente, vous ne pourrez relire votre projet qu'avec cette nouvelle version.
Vous avez alors dans la colonne de gauche une liste de mots ou expression :

Vous constatez qu'en plus des expressions qui vous intéressent, il y a du texte purement technique comme les noms des unités ou des polices. Ce texte se trouve principalement en début de liste, mais il y en a aussi un peu dispersé tout au long de la liste. Vous devez éliminer ce texte. Pour ceci, un simple clic droit sur les lignes correspondantes et vous choisissez l'option (unique) Exclure du menu contextuel. À la fin, vous devez obtenir une liste épurée :

Enregistrez cette liste avec Langue Source|Enregistrer ainsi que la liste des mots exclus avec Exclusion|Enregistrer :

À partir de maintenant, vous disposez d'un fichier texte contenant l'ensemble des mots et expressions à traduire.

V-D - Travail du traducteur

Il est temps de prendre contact avec le traducteur. Vous lui envoyez le fichier texte précédemment créé et vous lui demandez de le traduire en respectant les & des raccourcis et les %d des chaînes de format. Deux possibilités : soit il travaille avec le bloc-note de Windows :

Avantage, le bloc-note est disponible partout, en contrepartie, il y a risque de décalage entre les deux listes.
Soit vous lui envoyez mon utilitaire de traduction pour avoir les deux listes côte à côte :

Il ouvre la liste française avec Langue source|Ouvrir et il enregistre le résultat avec Langue étrangère|Enregistrer. Inconvénient, il faut aussi lui envoyer l'utilitaire de traduction.

À la fin, le traducteur vous renvoie la liste des mots traduits.

Vous pouvez préparer le travail du traducteur en traduisant au préalable les mots standards de Windows. Les listes correspondantes sont disponibles sur mon site. Vous devez, dans l'ordre, charger (ou générer) la liste des mots de la langue source, indiquez la liste des mots standards (Langue source|Mots standards), charger les mots standards de la langue étrangère (Langue étrangère|Mots standards) et réaliser la mise en correspondance avec Traduction|Mots standards. Et n'oubliez pas d'enregistrer la liste des mots étrangers ainsi générés :

V-E - Traduction du projet

Une fois que vous avez récupéré la liste des mots traduits, il vous faut traduire le projet lui-même. Vous reprenez l'utilitaire de traduction. Vous ouvrez la liste de mots locale (Langue source|Ouvrir), la liste de mots étrangère (Langue étrangère|Ouvrir) et le projet (Projet|Ouvrir). Vous n'avez plus qu'à réaliser la traduction avec Traduction|Réaliser… :

Vous devez dans un premier temps indiquer un nouveau répertoire où enregistrer le projet traduit, sans changer de nom. Ensuite, indiquez de nouveau la version de Delphi à utiliser. La traduction démarre :

Quand la fenêtre de progression disparaît, la traduction est terminée. Vous n'avez plus qu'à quitter l'utilitaire, ouvrir le nouveau projet dans Delphi et le recompiler. Voici le résultat :

C'est ti pas beau ? Comme vous pouvez le voir, je l'ai appliqué sur un projet relativement important (pour moi) avec 40 000 lignes de code et 35 fiches.

Il reste quelques détails à régler. Certains éléments n'ont pas été traduits comme les boutons Oui/Non dans les fenêtres MessageDlg. En effet, ces textes ne font pas partie de votre code, mais se trouvent dans une série de fichiers source de la VCL (ou la CLX) de Delphi. Ces fichiers sont consts.pas, bdeconst.pas, dbconsts.pas et oleconsts.pas. Ils sont systématiquement fournis avec Delphi, y compris en version Standard, au moins depuis D3. Vous devez traduire le ou les fichiers qui concernent votre projet (pas besoin de traduire bdeconst.pas si vous n'utilisez pas le BDE :)). La méthode est la même que pour un projet sauf que dans Projet|Ouvrir, vous sélectionnez Unités Delphi à la place de Projet Delphi. Et dans la liste des mots à traduire, ne traitez que ceux qui peuvent concerner votre projet. Le travail est déjà fait ici pour le français, l'allemand et l'anglais. Le contenu de certains boutons (obtenus par appel direct de l'API Windows) ne changera toujours pas. Il ne changera que lorsque vous utiliserez le projet avec Windows dans la langue visée. Enfin, mon utilitaire ne traduit pas les messages d'erreur correspondant aux exceptions non gérées par votre code. Alors, autant que possible, interceptez les exceptions avant. En plus, les messages abscons correspondants affolent généralement les utilisateurs.

Et si vous utilisez des InfoVersions, pensez à changer la Langue :

V-F - Mise à jour

Vous avez donc traduit votre projet dans une ou plusieurs langues, mais celui-ci continue d'évoluer. Vous devez mettre à jour les traductions. Le processus est similaire, mais commencez par charger l'ancienne liste de mots français et la liste des mots exclus. Ouvrez votre projet et analysez-le de nouveau. Les nouveaux mots sont ajoutés en bas de la liste :

La suite comme pour la première traduction.

V-G - Conclusion

En guise de conclusion, nous avons vu comment traduire un projet Delphi. Nous ne nous sommes pour le moment pas préoccupé de changement de police. Je vous invite à voir sur cette page la méthode pour traduire et tester une application en russe. Le principal inconvénient de mon utilitaire est qu'il génère un exe par langue. Il en découle deux inconvénients. D'une part, vous ne pouvez pas changer de langue durant l'exécution. D'autre part, vous devez faire autant de programmes d'installation que de langues, et quand vous apportez des modifications à votre projet, ça devient assez vite lourd à gérer. Pour terminer, vous pouvez retrouver l'ensemble des fichiers relatifs à la traduction, y compris les sources de l'utilitaire, sur mon site. Les marchés à l'export s'ouvrent en grand devant vous :)))

(1)Note concernant la génération de DLL de ressource en français : si vous générez cette DLL, alors elle sera automatiquement utilisée lorsque vous démarrez votre projet à la place des ressources par défaut. Et si vous modifiez l'interface de votre projet, vous êtes obligé de régénérer cette DLL pour voir apparaître les modifications à l'exécution. À l'opposé, si vous ne créez pas cette DLL, vous ne pourrez pas revenir vers le français en changeant dynamiquement de langue. Je conseille de ne générer la DLL en français qu'une fois le projet terminé ou pour réaliser des essais spécifiques à cette DLL. Dans le second cas, je suggère de retirer le français de la liste des langues et de supprimer la DLL une fois les essais terminés. S