Development/Tutorials/Localization/i18n (fr)
Série de tutoriels | Localization |
Prérequis | Lire l'introduction à l'Unicode est recommandé, mais ce n'est pas obligatoire |
Suite | Éviter les pièges de traduction les plus courants |
Aller plus loin | n/a |
Théorie
Avoir un grand nombre d'utilisateur et de développeurs requiert que votre logiciel puisse être traduit, ou tout au moins qu'il soit linguistiquement et culturellement (formats d'écriture (date, heure, ...), alphabets, sens d'écriture, ...) adapté à l'utilisateur de votre application. C'est le travail de la traduction (ou localisation) et ce tutoriel vous guidera sur les voies de la création d'applications facilement traduisibles.
Que sont l'internationalisation et la traduction ?
L'internationalisation, ou i18n ('i', suivit de 18 lettres, puis d'un 'n'), est le processus d'écriture d'applications qui peuvent être facilement localisables. Cela signifie prendre en compte des choses telles que :
- les messages textuels qui sont affichés à l'utilisateur
- les données envoyées ou écrites par l'utilisateur ; les fichiers par exemple
- les formats de dates, nombres, monnaie, etc.
La localisation, ou l10n ('l', suivit de 10 lettres, puis d'un 'n'), est le fait de "prendre" une application internationalisée et l'adapter à un pays ou à une langue.
D'une façon générale, les programmeurs internationalisent leurs applications, et les équipes de traduction les localisent.
Pourquoi est-ce si important ?
Le développement de KDE se fait principalement en Anglais, ce qui permet d'avoir de plus grandes communautés de développement et de traduction. Cependant, l'Anglais n'est pas le langage majoritaire dans le monde. En réalité, moins de 8% de l'Humanité par Anglais, et cette langue n'est la langue maternelle que de 5% des personnes. Mais, si actuellement 35% des personnes allant sur Internet parlent cette langue, ce chiffre diminue. De plus, un grand nombre de langues (9 par mis les 10 majoritaires) utilisent des caractères non-ASCII. Il est donc facile de comprendre le besoin de fournir un logiciel localisé.
En tant que projet international, une telle localisation est une des valeurs fondamentales de KDE. En fait, pendant que de nombreux développeurs de KDE écrivent leurs logiciels e Anglais, ils utilisent sur leur ordinateur leur langue native (qui n'est pas forcément l'Anglais).
Avoir du code traduisible avec i18n()
Pour vous assurer que votre application est prête à être localisée, vous devez suivres quelques règles de base. Toutes les chaînes de caractères visibles dans votre application peuvent être traduites avant d'être affichées sur l'écran de l'utilisateur, exception fait des messages de déboguage, de la configuration des touches, et des types similaires aux données textuelles
KDE fourni la classe KLocale dans la bibliothèque libkdecore, dans le but de faciliter la locasation. KLocale permet aux développeurs de créer plus facilement du code i18n, mais il y a tout de même certaines choses à faire avant de pouvoir rendre les applications utilisables dans d'autres langues ou pays.
L'accès à l'objet global KLocale est fourni via KGlobal::locale(). Cet objet KLocale est créé automatiquement par KInstance et veille à toutes les préférences i18n de l'utilisateur. Il est automatiquement détruit à la fermeture de l'application.
Les traductions sont rendues possibles par la méthode QString i18n(const char*) définie dans klocalizedstring.h, dans lequel vous devez mettre toutes les chaînes de caractères susceptibles d'être affichées. L'objet QString retourné par i18n() est la chaîne traduite (si nécessaire). Cela rend la création de widgets aussi simpel que cet exemple :
#include <klocalizedstring.h>
[...]
QPushButton* myButton = new QPushButton(i18n("Translate this!"));
L'utilisation native de l'Unicode dans QString permet d'être sûr que toutes les traductions sont correctement effectées, sans problème d'encodage. Pour cette raison, toutes les chaînes de caractères manipulées par votre application doivent utiliser QString.
ki18n
La méthode i18n() requiert qu'une KInstance (par exemple KApplication) ait été créée. Pour toutes les chaînes créées antérieurement, il existe une autre méthode : ki18n(). Elle permet de "marquer" les chaînes qui devront être traduites dès que possible. ki18n() retourne une KLocalizedString, qui est peut être transformée en QString (par exemple quand elle est traduite pour de bon) après que la KInstance ait été créée, en utilisant sa méthode toString().
ki18n() est typiquement utilisée pour les chaînes données à KAboutData, car il est construite avant la KApplication et vous ne pouvez utiliser i18n() seulement après la constructution de cet objet. Dans les autres cas, il est conseillé d'utiliser i18n() si vous êtes sûr(e) que le code sera exécuté après la création de la KApplication ou de toute autre KInstance.
Préciser le contexte avec i18nc()
Il existe une méthode additionelle, i18nc(), qui prend pour paramètres deux const char*. Le premier argument est une information supplémentaire quant au contexte de la deuxième chaîne, qui sera traduite. Ce contexte permet aux traducteurs d'avoir plus d'infomration sur l'utilisation de la chaîne, ce qui leur permet d'effectuer des traductions plus appropriées, au contexte justement.
Utilisez i18nc() dès que le sens du texte risque d'être ambigüe. Par exemple, dans le cas où un menu contextuel appellé "View" dans un gestionnaire de fichiers sert à ouvrir une vue du fichier sélectionné. Dans ce contexte, "View" est un verbe. Mais, cette même application est susceptible d'avoir un autre menu appellé "View", qui, lui, serait un nom. Or, la traduction n'est pas forcément la même si s'agit d'un verbe ou d'un nom (exemple en Français, où la traduction peut être "Voir" ou "Vue").
De plus, les traducteurs ont parfois besoin d'informations pour les aider à comprendre à quoi se réfère le texte qu'ils sont en train de traduire.
Dans l'exemple précédent du gestionnaire de fichier, on peut écrire l'une des deux lignes suivantes :
contextMenu->addAction(i18nc("verb, to view something", "View"));
viewMenu->addAction(i18nc("noun, the view", "View"));
Maintenant, les deux chaînes peuvent être correctement traduites, à la fois par les traducteurs et à l'exécution, par KLocale.
Utilisez cette forme de i18n dès que la chaîne à traduire est courte ou que le sens n'est pas évident. Par exemple :
QString up = i18nc("Go one directory up in the hierarchy", "Up");
QString relation = i18nc("A person's name and their familial relationship to you.", "%1 is your %2", name, relationship);
Les contextes peuvent également être ajoutés lors de la création des fenêtres avec Qt Designer. Chaque label de widget, y compris les infobulles et les textes "whatsthis", a un attribut "disambiguation" (appelé "comment" avat Qt 4.5), qui sert à la même chose que le premier argument de i18nc().
Contexte standard pour les phrases courantes
Ci-dessous est présenté une liste des mots et phrases les plus courants en Anglais et le contexte qui doit être utilisé pour être sûr qu'ils soient correctement traduits dans les autres langues
Phrase | Context | i18nc Call | Example |
---|---|---|---|
Busy | Referring to a person | i18nc("A person is busy", "Busy") | |
Busy | Referring to a thing | i18nc("A thing is busy", "Busy") | |
Color | Color mode, as opposed to Grayscale | i18nc("Not Grayscale", "Color") | |
Creator | Referring to a person | i18nc("A person who creates", "Creator") | |
Creator | Referring to software | i18nc("Software", "Creator") | |
Display | Referring to hardware | i18nc("Hardware display", "Display") | |
Editor | Referring to a person | i18nc("A person who edits", "Editor") | |
Editor | Referring to software | i18nc("Software", "Editor") | |
Line | Referring to drawing | i18nc("Draw a line", "Line") | |
Line | Referring to text | i18nc("Line of text", "Line") | |
Name | Referring to a name of thing | i18nc("A thing's name", "Name") | In theme change dialog: i18nc("Theme name", "Name") |
Name | Referring to first name and last name of person | i18nc("Person's first and last name", "Name") | In KAddessbook contact edit dialog: i18nc("Person's first and last name", "Name") |
New | Create something | i18nc("Action", "New") | |
New | Status | i18nc("New mail message", "New") | |
No | Answer to a question | i18nc("Answer to a question", "No") | |
No | Availability of a thing | i18nc("Availability", "No") | |
(Re)load | (Re)load a document, medium etc. | i18nc("(Re)load a document", "(Re)load") | |
(Re)load | (Re)start a program, daemon etc. | i18nc("(Re)start a program", "(Re)load") | |
Title | Referring to a person | i18nc("A person's title", "Title") | |
Title | Referring to a thing | i18nc("A thing's title", "Title") | |
Trash | Referring to the action of emptying | i18nc("The trash is not empty. Empty it", "Empty") | |
Trash | Referring to the state of being empty | i18nc("The trash is empty. This is not an action, but a state", "Empty") | |
Volume | Referring to sound | i18nc("Sound volume", "Volume") | |
Volume | Referring to a filesystem | i18nc("Filesystem volume", "Volume") | |
Volume | Referring to books | i18nc("Book volume", "Volume") | |
Yes | Answer to a question | i18nc("Answer to a question", "Yes") | |
Yes | Availability of a thing | i18nc("Availability", "Yes") |
Pluriels
Les pluriels sont "gérés" différemment d'une langue à une autre. Certaines langues ont même des pluriels différents selon le nombre (2, 10, 20, 100, etc). Quand la chaîne que vous voulez traduire de réfère à plus d'un élément, vous devez utiliser la troisième forme de i18n : i18np(). Il prend les singulier et pluriel Anglais comme premiers paramètres, suivis par les éléments susceptibles de varier, mais au moins un d'eux doit être une valeur entière. Par exemple :
msgStr = i18np("1 image in album %2", "%1 images in album %2", numImages, albumName);
msgStr = i18np("Delete Group", "Delete Groups", numGroups);
i18np() s'étend dans les nombreux cas qui peuvent être requis par la langue de l'utilisateur. En Anglais, il ne s'agit que de deux formes, mais il peut y en avoir plus selon les langues, en fonction du premier argument qui est une valeur entière. Exemple :
Le code suivant :
i18n("%1 files were deleted", numFilesDeleted);
est incorrect, car il faut utiliser :
i18np("1 file was deleted",
"%1 files were deleted",
numFilesDeleted);
La meilleure solution reste cependant d'avoir dans ce cas la plus petite chaîne possible :
i18ncp("Personal file", "1 file", "%1 files", numFiles);
Format des dates et des nombres
Lors de l'affichage d'un nombre à l'utilisation, votre programme doit faire attention au séparateur décimal (par exemple le point an Anglais ou la virgule en Français), si il y a la possibilité qu'il en soit affiché un.
Voici une liste des fonctions susceptibles de vous aider à afficher les nombres et autres données au bon format.
Formats a.. | Paramètre(s) a.. | Function Prototype |
---|---|---|
Number | String | QString formatNumber( const QString & numStr ) |
Number | Integer, double | formatNumber( double num, int precision = -1 ) |
Money | String | formatMoney( const QString & numStr ) |
Money | Number | formatMoney( double num, const QString & currency, int digits = -1 ) |
Date | String | formatDate( const QDate & pDate, bool shortFormat=false ) |
Time | QTime | formatTime( const QTime & pTime, bool includeSecs=false) |
Date and time | QDateTime | formatDateTime( const QDateTime &pDateTime, bool shortFormat = true, bool includeSecs = false ) |
Des fonctions similaires existent pour lire les informations fournies par l'utilisateur à l'exécution dans leur format d'écriture, par exemple : readNumber() ou readMoney().
Gestion du temps et des dates
Développer des applications gérant le temps et les dates, comme des calendriers, est très complexe. Non seulement les chaines affichées contenant une date ou une heure doivent être localisées, mais il faut aussi faire attention à :
- quel calendrier est utilisé
- quel jour de la semaine est le premier (ex : Lundi en France et Dimanche en Angleterre)
- au nombre de mois dans l'année
- "era"-based calendars
- au système d'heures dans la journée (12 ou 24)
QDate implémente uniquement un calendrier de type Julien/Grégorien (celui utilisé aux USA et en Europe de l'Ouest), si le calendrier utilisé par l'utilisateur est un autre calendrier, alors les dates et les calculs de dates effectués avec QDate afficheront des données erronées.Tous les calculs de dates doivent être effectués au travers des méthodes de KLocale et de KCalendarSystem, qui fournissent des données compatibles avec QDate. Le calendrier courant peut être connu via KGlobal::locale()->calendar(). Le format de date de KLocale pointe toujours vers le calendrier système courant.
KLocale fourni, entre autres, les méthodes suivantes :
Formats a.. | From a.. | Function Prototype |
---|---|---|
Date | QDate | formatDate( const QDate & pDate, bool shortFormat=false ) |
Time | QTime | formatTime( const QTime & pTime, bool includeSecs=false ) |
Date and time | QDateTime | formatDateTime( const QDateTime &pDateTime, bool shortFormat=true, bool includeSecs=false ) |
cleanup confusing sections and fix sections which contain a todo
provide more info on the different calendar systems
Eviter les erreurs les plus communes
Il existe des erreurs assez communes, qui empêchent une application d'^tre correctement localisée. Lisez comment éviter les erreurs courantes de localisation pour les connaître et les éviter.