Tester douze langues sans douze appareils
Les bugs de localisation ont une signature : ils sont trouvés par les utilisateurs, pas par la QA, et ils sont trouvés dans les langues que personne dans l'équipe ne parle.
La raison tient à la procédure plutôt qu'à la technique. Vérifier un écran dans une langue de plus suppose d'ouvrir les Réglages, de changer la langue du système, de naviguer dans une application de réglages que vous ne savez plus lire, de relancer l'application, de retrouver le chemin jusqu'à l'écran, puis de tout défaire. Personne ne fait cela douze fois. Résultat : le build allemand part avec un bouton qui dit Zahlungsm... et le build arabe avec une flèche de retour dans le mauvais sens.
Le correctif n'est pas plus de discipline. C'est la suppression de la boucle en vingt étapes.
Ce qui casse réellement, à peu près par ordre de fréquence
L'expansion du texte. L'allemand est en moyenne environ 30 % plus long que l'anglais, et les chaînes courtes sont bien pires que cela — un libellé de 5 à 10 caractères peut doubler ou tripler. « Save » devient Speichern. « Settings » devient Einstellungen. Le finnois, le russe et le polonais sont tout aussi peu cléments. Votre bouton avait été dimensionné pour la chaîne anglaise : il tronque, il passe sur deux lignes qui débordent, ou il pousse son voisin hors de l'écran.
Les écrans qui cassent sont toujours les mêmes : barres d'onglets, contrôles segmentés, boutons sur une ligne à largeur fixe, cellules de tableau avec un libellé et une valeur sur la même ligne, et tout ce qui se trouve dans une barre de navigation.
Les mises en page RTL. L'arabe, l'hébreu, le persan et l'ourdou reflètent toute la mise en
page — pas seulement l'alignement du texte. Les flèches de retour pointent à droite. Les barres de
progression se remplissent de droite à gauche. Les chevrons s'inversent. Les panneaux latéraux
s'ouvrent de l'autre côté. Les icônes qui suggèrent une direction doivent être reflétées ; celles
qui n'en suggèrent pas (un bouton lecture, un logo) ne doivent surtout pas l'être. Les marges
left/right codées en dur au lieu de leading/trailing sont l'origine du problème, et elles
restent invisibles tant que vous ne regardez pas réellement le build RTL.
Les règles de pluriel. L'anglais a deux formes. Le russe en a trois, l'arabe six, et beaucoup
de langues une seule. Toute chaîne construite en concaténant un nombre avec un suffixe codé en dur
est fausse dans la majeure partie du monde — "$count items" ne peut pas être localisée
correctement, quelle que soit la qualité du traducteur. C'est l'un des rares bugs de localisation
qui relève vraiment du code plutôt que de la mise en page, et il exige des ressources de chaînes
gérant les pluriels, pas un fichier de traduction plus long.
Les formats. Séparateurs décimaux (1,234.56 contre 1.234,56), ordre des dates, horloges
sur 12 ou 24 heures, premier jour de la semaine, position du symbole monétaire. Le bug qui fait
vraiment mal ici concerne l'analyse : une application qui formate correctement à l'affichage
mais analyse la saisie utilisateur avec une locale fixe rejettera des montants parfaitement
valides saisis par les utilisateurs de la moitié de l'Europe.
Les opérations sur chaînes sensibles à la locale. Le cas célèbre est le turc : passer "i" en
majuscule dans une locale turque produit "İ", pas "I". Tout code qui met une chaîne en
majuscules ou en minuscules pour la comparer — un nom d'en-tête, une vérification de schéma, une
clé de cache — se comporte différemment sur un appareil turc. C'est le bug archétypal, impossible
à trouver en lisant le code et trivial à trouver en exécutant l'application en tr-TR.
Le rendu du texte. Le thaï et le khmer n'ont pas d'espaces entre les mots et se coupent selon des règles que votre mise en page n'implémente peut-être pas. Le japonais et le chinois coupent les lignes au milieu d'un « mot » par nature. Les diacritiques du vietnamien et du tchèque se font rogner par des hauteurs de ligne calibrées pour l'anglais. La devanagari combine les glyphes d'une façon qui rend absurde toute troncature fondée sur un nombre de caractères.
Les chaînes non traduites. Le point ennuyeux, et le plus fréquent en valeur absolue. Une chaîne ajoutée tard, codée en dur dans un fichier de mise en page, ou livrée avant le retour de la traduction. Chaque version en introduit quelques-unes.
Les pseudo-locales : trouver l'essentiel avant même la traduction
Vous n'avez pas besoin de traductions finalisées pour trouver la moitié « mise en page » de cette liste. Les deux plateformes fournissent des pseudo-locales exactement pour cela, et c'est l'élément de cet article au meilleur rapport valeur/effort.
Android propose en-XA — de l'anglais avec des accents et du rembourrage, par exemple
[Ŝéţţîñĝŝ one two] — et ar-XB, une pseudo-locale de droite à gauche qui reflète votre mise en
page tout en gardant le texte lisible. Les deux s'activent dans les options développeur à partir
d'Android 7.
iOS offre l'équivalent sous forme d'options de schéma dans Xcode : Double-Length Pseudolanguage, Accented Pseudolanguage et Right-to-Left Pseudolanguage.
Trois choses ressortent quand vous exécutez votre application ainsi :
- Tout ce qui n'est pas en texte accentué est une chaîne codée en dur, non traduite. C'est de loin le moyen le plus rapide de les trouver — aucun traducteur, aucun diff, il suffit de chercher l'anglais en clair.
- Tout ce qui tronque ou se chevauche en double longueur cassera en allemand.
- La pseudo-locale RTL expose chaque
left/rightcodé en dur dans votre mise en page avant qu'un seul mot d'arabe n'existe.
Exécutez ces deux-là à chaque build. Elles ne coûtent rien et détectent la plupart des régressions de mise en page la semaine où elles arrivent, plutôt que la semaine avant un lancement sur un nouveau marché.
Ensuite, les vraies langues sur du vrai matériel
Les pseudo-locales ne couvrent ni le rendu, ni les polices, ni la saisie. Pour cela il faut la vraie locale sur un vrai appareil — et c'est là que revient la boucle en vingt étapes.
La sortie consiste à lancer l'application directement dans la langue cible au lieu de reconfigurer l'appareil autour d'elle. Sur RobotActions, c'est une seule action — démarrer l'application testée dans la langue choisie, prendre vos captures, passer à la suivante — de sorte qu'une passe de douze langues sur un écran représente douze lancements plutôt que douze allers- retours dans une application de réglages que vous ne savez pas lire. La langue de l'appareil peut aussi être changée pour de bon quand vous avez besoin du contexte système complet : les dialogues système, les demandes d'autorisation et les feuilles de partage sont rendus par l'OS dans la langue de l'appareil, pas dans celle de votre application.
Une passe qui vaut la peine d'être automatisée, en gros :
const LOCALES = ["de-DE", "fr-FR", "ar-EG", "ja-JP", "tr-TR", "ru-RU", "fi-FI"];
for (const locale of LOCALES) {
await launchAppInLanguage(locale);
for (const screen of CRITICAL_SCREENS) {
await navigateTo(screen);
await screenshot(`${screen}-${locale}.png`);
}
}Comparez ensuite ces captures à celles de la version précédente plutôt que de lire les 84 à l'œil. Une comparaison visuelle signale celles qui ont changé ; un humain ne regarde que celles-là. Sans cette étape de comparaison, la tâche devient une corvée que personne ne répète après la première fois.
Choisissez la liste de locales délibérément. Sept locales bien choisies couvrent presque tous les modes de défaillance :
| Locale | Ce qu'elle couvre |
|---|---|
de-DE | Expansion du texte, mots composés |
fi-FI ou ru-RU | Expansion pire encore, plus le non-latin (russe) |
ar-EG | Reflet RTL, formes plurielles arabes, chiffres arabes orientaux |
ja-JP | Coupure de ligne CJK, police de repli, pas d'espaces entre les mots |
tr-TR | Bugs de casse sensibles à la locale |
fr-FR | Espacement de la ponctuation, formats — et votre plus grand marché à faible expansion |
en-XA | Chaînes codées en dur |
Ce qu'il faut vérifier programmatiquement, pas seulement à l'œil
Les captures d'écran couvrent la mise en page. Quelques points méritent des assertions automatiques parce qu'ils sont peu coûteux et sans ambiguïté :
- Aucun point de suspension visible dans un bouton ou une barre d'onglets. Une troncature dans un libellé est parfois acceptable ; dans un contrôle, elle ne l'est presque jamais.
- Aucun texte débordant de son conteneur. L'arbre des éléments vous donne les deux rectangles.
- Chaque chaîne visible diffère du build anglais (hors noms propres et termes connus pour être identiques). C'est la version automatique de « cherchez l'anglais en clair », et c'est la même astuce qui détecte les versions à moitié traduites.
- Les nombres et dates formatés se réanalysent correctement dans cette locale. Une assertion en aller-retour détecte le bug de saisie que des tests d'affichage seuls ne trouveront jamais.
La part qui relève du processus
La plupart des bugs de localisation sont introduits par une chaîne ajoutée le mardi qui précède une version, alors que la traduction prend une semaine. Ce n'est pas un échec des tests, et aucune automatisation d'appareil n'y remédie.
Deux habitudes, si :
- Aucune chaîne visible codée en dur, contrôlé en revue ou par le linter. Une chaîne codée en dur est intraduisible par définition, et la passe en pseudo-locale les rend immédiatement visibles si l'une passe entre les mailles.
- Concevoir pour la chaîne longue, pas pour l'anglaise. Si la maquette ne montre jamais que Save, le bouton sera dimensionné pour Save. Relire les maquettes avec la chaîne allemande en place ne coûte rien au moment du design et évite un correctif de mise en page au moment de la livraison.
Lancez votre application dans n'importe quelle langue sur un appareil réel →
Prêt à tester sur de vrais appareils ?
Connectez-vous avec Google ou GitHub et accédez à de vrais appareils iOS et Android depuis votre navigateur — gratuit à l'essai.