Localisation d'applications et prise en charge RTL. Signaler Yandex.Taxi

Lors de la localisation du service, il est important de considérer attentivement la coordination des transferts entre eux. Le chef de l'équipe de développement Android du client Yandex.Taxi, Alexander Bonel, a parlé des pratiques et des outils qui simplifient la localisation. Dans la deuxième partie du rapport, Sasha a partagé l'expérience de la prise en charge de RTL dans l'application: ce qui est bon et ce qui ne fonctionne pas pour Android, quels problèmes surviennent en raison de la prise en charge de RTL et comment les minimiser à l'avenir.


- Dans mon rapport, je veux vous dire quelles idées et pratiques de base nous utilisons dans les équipes de développement des applications mobiles Taxis pour résoudre les problèmes liés à la localisation et à la mise à jour des traductions dans nos applications. Ensuite, je vais vous expliquer comment nous avons implémenté la prise en charge du travail en mode dessin de droite à gauche dans l'application.



Je vais commencer par la localisation. Tout d'abord, je voudrais clarifier la terminologie. Selon mes observations, un grand nombre de personnes pensent que la localisation se limite uniquement aux traductions, même si en fait cela résout également les problèmes liés à la mise en forme des nombres, des dates, de l'heure, du travail avec du texte et des symboles, aux aspects juridiques, à la fourniture de contenu au consommateur de cette manière qu'il avait une valeur sémantique pour lui et n'était pas perçu de manière ambiguë. Et bien plus. (Communication avec le public pour savoir qui a le nombre de langues prises en charge dans les applications - N.D.E.)

Je veux vous raconter une histoire qui s'est passée avec nous en 2014. Nous avons ensuite procédé à une refonte majeure de l'application Taxi. Dans l'une des prochaines versions, nous avons donné aux utilisateurs la possibilité d'indiquer le numéro d'entrée, ainsi que de consulter ces informations sur l'écran d'informations sur le voyage et, surtout, sur l'écran de notation de la commande, que nous avons montré à tous les utilisateurs, car nous voulions certainement obtenir une note pour le voyage .



A cette époque, nous étions plutôt frivoles sur le processus de localisation et les traductions. Pour la plupart, l'ensemble du processus était manuel. La mise à jour des textes dans les fichiers XML nécessaires, l'ajout de nouvelles traductions a été effectué manuellement. Et le facteur humain a joué un rôle. Le développeur a déterminé que le transfert suivant n'était pas dans la langue par défaut. Cela a conduit au fait que pour les utilisateurs ayant des paramètres régionaux du système différents de la langue russe, s'ils demandaient l'entrée, l'application se bloquait à la fin du voyage. Et les gens ne pouvaient pas passer une autre commande.

À cette époque, nous avions deux langues prises en charge dans l'application: le russe et l'anglais. Et nous ne travaillions qu'en Russie dans trois villes: Moscou, Iekaterinbourg, Saint-Pétersbourg.



Nous opérons actuellement dans 16 pays et sommes traduits en 18 langues. Je pense que vous comprenez tout le problème, si nous étions dans cet état à ce moment-là. Nous avons alors déjà réalisé que quelque chose devait être changé.



Dans Yandex, la plupart des développeurs d'applications mobiles utilisent le service développé en interne pour résoudre les problèmes liés à la localisation. Il a une interface utilisateur très pratique, il est possible de définir votre projet, de définir un ensemble de clés, un ensemble de langues dans lesquelles vous devez traduire le projet. Et après que les traductions apparaissent, elles peuvent être téléchargées dans n'importe quel format pratique. Il a également une très bonne intégration avec nos services internes. Il y a du versioning. Mais pour moi personnellement, en tant que développeur, la chose la plus importante est qu'il dispose d'une API, car cela suggère déjà que tout le travail manuel associé aux traductions peut être automatisé. Ce que nous avons fait. Nous avons développé un plugin pour Gradle. En fait, la mise à jour de la traduction dans l'application se résume désormais au fait que le développeur effectue une seule tâche: updateTranslations.



En première approximation, il se rend dans un service de localisation. Vérifie les traductions à jour, les télécharge dans le projet, les place dans les fichiers nécessaires. Mais en plus de cela, il vérifie également l'état des traductions dans le service de localisation par rapport à ce qui est maintenant dans le projet.



La prochaine fois que l'état git est exécuté, le développeur voit dans son répertoire de travail quels fichiers ont changé.



Il peut également rechercher dans le rapport HTML généré quelle clé pour quelle valeur dans quelle langue a changé.



Et il peut également voir quels problèmes sont actuellement présents dans les traductions de son projet.



Le plugin est configurable. Nous pouvons déterminer le nombre de langues prises en charge par notre application. Il est très important que les localisateurs commencent une nouvelle langue et qu'elle s'infiltre par inadvertance dans le projet, n'ayant pas passé par la relecture et la relecture.



Il existe également une fonction de remappage spécifique. J'en parlerai un peu plus tard plus en détail lorsque je parlerai de RTL.

Quels problèmes ce plugin analyse-t-il maintenant? Le problème que nous avons rencontré en 2014 est banal, le manque de traduction. Maintenant, pour ajouter une nouvelle ligne, une nouvelle traduction au projet, il ne suffit pas au développeur de la définir simplement dans le fichier XML.



Premièrement, s'il ne le fait pas dans les paramètres régionaux par défaut, alors sa clé nouvellement enroulée disparaîtra simplement lors de la prochaine synchronisation, et il le saura au stade de la compilation.



S'il détermine la clé dans le fichier par défaut, mais oublie de le faire dans le service de localisation, la prochaine fois que la mise à jour des traductions sera exécutée, il recevra une erreur du plug-in, qui lui dira: «Cette clé est dans votre projet, mais ce n'est pas dans le service de localisation, elle est là besoin de commencer. "



Le deuxième problème typique est le manque de traduction. Nous obtenons une liste de liens vers les clés pour lesquelles il n'y a pas de traduction, et, en règle générale, nous les référons à notre responsable afin qu'il établisse plus tard la communication avec les traducteurs. Le troisième point se produit souvent quand ils ont décidé de reconsidérer l'utilisation des arguments de format d'une certaine manière, et, par exemple, au lieu d'un format entier, ils ont commencé à utiliser le format de chaîne.

Mais en même temps, dans certaines traductions, ils ont oublié de changer le numéro sur la ligne.



Et le quatrième problème est également causé par le facteur humain, principalement dans la traduction. Si des caractères Unicode sont utilisés dans la traduction, il est très facile de se confondre dans le positionnement des caractères et au lieu d'un espace inextricable pour obtenir une césure sur une autre ligne - c'est ce dont nous essayons de nous débarrasser.

Il s'agit de localisation.

Maintenant, je veux parler de l'expérience de la mise en œuvre du support pour le rendu de droite à gauche dans l'application en utilisant l'exemple d'Israël. Nous avons lancé en 2018 sous la marque Yango en Israël. En fait, en Israël, les gens lisent différemment de vous et de moi. Ils lisent de droite à gauche.



Par où voulez-vous commencer? Avec Android, en principe, le support de rendu de droite à gauche est assez bien implémenté.

Cela commence par le fait que dans le manifeste d'application, dans l'élément Application, vous devez déclarer l'attribut supportRtl = "true". Mais je veux vous faire plaisir: si vous intégrez le SDK Facebook pour l'autorisation sociale dans vos applications, les développeurs Facebook attentionnés l'ont déjà fait pour vous. Et si vous ne validez pas le manifeste lors de la fusion, cet attribut avec la valeur true s'adaptera à votre application, et il pourra déjà le faire dans Rtl. C'est quelque chose à penser.

Je pense que la plupart de ceux qui sont assis dans le public ont probablement un support minimal pour Android 4.4. Quelqu'un a plus de chance - c'est 5.0 et plus. Quelqu'un pourrait être moins chanceux, et ils soutiennent 4.0, ou, Dieu nous en préserve, 2.3. Dans ce cas, vous aurez de gros problèmes, car la prise en charge complète de Rtl dans Android est apparue depuis la version 4.2. Par conséquent, avec minSdk 17th, vous simplifiez votre vie d'un ordre de grandeur.

Le transfert d'un projet pour travailler avec Rtl commence par l'outil de refactoring dans Android Studio - Ajoutez le support RTL lorsque cela est possible. Il faut rendre hommage, ça marche plutôt bien. Il parcourt les fichiers XML de votre balisage, examine la présence d'attributs avec des valeurs gauche et droite pour la gravité, pour les rembourrages, les marges et les remplace par start et end. Si vous voulez voir comment votre application fonctionne par défaut en mode de droite à gauche, vous n'avez pas besoin d'avoir du contenu avec les soi-disant caractères forts RTL - en hébreu ou en arabe. Il vous suffit d'activer Forcer la direction de mise en page RTL dans les paramètres du développeur.

Quelles sont les options de personnalisation de l'interface utilisateur et de rendu du texte qu'Android fournit pour RTL?



Le premier point est l'attribut layoutDirection, qui utilise l'option décrite Force RTL Layout Direction. Elle n'a que quatre significations possibles. Autrement dit, il est hérité par défaut du parent. Nous pouvons dire que la mise en page est dessinée en fonction des paramètres régionaux sélectionnés. Vous pouvez clairement dire qu'il est dessiné de droite à gauche ou de gauche à droite.

Le deuxième élément que beaucoup de gens évitent le plus souvent par habitude lorsqu'ils s'engagent dans l'alignement de texte est l'alignement de texte. Beaucoup continuent à utiliser la gravité. N'utilisez pas la gravité pour aligner le texte, mais utilisez textAlignment.

Le troisième attribut est la direction de rendu du texte, textDirection. Il a une configuration assez flexible. Il vous permet de déterminer comment le texte est rendu en fonction du premier caractère fort dans le texte, que ce soit à partir du jeu de caractères latin fort LTR ou à partir de l'hébreu fort RTL. Mais si vous prenez entièrement en charge RTL dans l'application, vous n'avez pas besoin de la contourner, car l'ignorance d'un artefact aussi drôle se produit.



Soit c'est un œuf de Pâques, soit est-ce un tel effet secondaire dans la mise en œuvre de editText: votre indice sur editText commence à se disperser. Par conséquent, dans tous les cas, vous devez lui attribuer une valeur.


Lien depuis la diapositive

Si vous devez observer un certain rendu de certaines ressources graphiques ou du balisage en mode RTL, Android offre la possibilité de définir le qualificatif ldrtl dans votre papa, dans lequel vous pouvez placer n'importe quelle ressource, et elle sera dessinée dans le mode de rendu RTL comme vous l'avez spécifié.

Parfois, il est nécessaire que le runtime dessine le texte provenant du backend tel quel, comment il est venu, en ignorant le mode dans lequel votre application fonctionne actuellement. En fait, dans le rendu de texte, cela est dû au fait que le texte est encadré par les soi-disant caractères de contrôle Bidi Unicode. La logique de travail avec ces caractères contient en elle-même la classe BidiFormatter, fournissant une seule méthode unicodeWrap. Il prend CharSequence en entrée et retourne une chaîne encadrée par ces caractères. Il y en a un nombre exhaustif et, en principe, il devrait résoudre la plupart de vos problèmes.

Mais s'il y a quelque chose de si spécifique, w3.org a un bon article sur la façon d'utiliser ces symboles.

Quels problèmes avons-nous rencontrés lorsque nous avons commencé le support RTL dans notre application? Tout d'abord, il s'agit d'un conflit de normes de localisation.

BCP47 est une norme de localisation plus récente, qui a notamment modifié les codes de certains paramètres régionaux. Et le fait est qu'il y a un problème avec la classe Java locale. Il fonctionne par défaut en mode de compatibilité descendante et convertit les codes locaux de BCP en ISO. Autrement dit, nous l'avons vu lorsque le code iw au lieu du code he a commencé à aller dans notre backend dans l'en-tête Accept-Language.


Lien depuis la diapositive

Si vous vous souvenez de la diapositive avec la configuration de notre plugin, un remappage était nécessaire juste pour cela - afin de traduire le contenu de he à iw.

Si vous devez utiliser le format BCP, cela est entièrement implémenté dans le projet Apache Cordova. Ils ont une classe de globalisation et une implémentation de localeToBcp47Language.



Un autre point qui «délivre» avec le support RTL dans l'application est les animations. Ici, l'avantage est, en fait, que seules les animations le long de l'axe X sont affectées, et peut-être que la seule solution ou approche qui vous aidera à éviter plus de problèmes est la possibilité de reconsidérer les animations absolues dans le sens des animations relatives.

Un problème qui n'est peut-être résolu que par la réflexion, car il est implémenté de manière rigide dans le composant lui-même est l'alignement des indices de TextInputLayout. Le fait est que si un indice est spécifié en caractères forts RTL en hébreu, il sera clairement aligné à droite, même si le contenu que vous entrez dans le texte de modification peut provenir de caractères latins. Et vice versa. Si votre indice est en latin, il sera clairement aligné à gauche. Cela ne peut être résolu que par réflexion.



En fin de compte, après avoir implémenté RTL dans votre application, il est logique de reconsidérer les niveaux de gravité des problèmes RTL analysés par Lint. Il n'y en a que quatre. Si vous ne prenez pas en charge RTL dans votre application, mais utilisez explicitement des attributs spécifiques RTL quelque part, alors c'est RtlEnabled (Lint vous en parlera).


Lien depuis la diapositive

Si vous prenez en charge RTL dans l'application, mais que la version minSdkVersion de votre application est inférieure à 17, vous devez également continuer à utiliser les attributs de type gauche et droit, vous ne pouvez pas utiliser uniquement les attributs de début et de fin dans votre balisage. C'est ce que RtlCompat analyse. RtlSymmetry jure quand il voit des rembourrages asymétriques. En général, mon avis est que aapt, lors du traitement des ressources, devrait planter s'il rencontre des rembourrages symétriques. Si vous avez besoin d'une sorte d'accès asymétrique, utilisez les marges comme paramètre de mise en page à part entière.

Enfin, le quatrième problème est la RTL codée en dur. C'est juste que dans les attributs, seules les valeurs de gauche et de droite sont indiquées. Essentiellement, cela annule l'outil de refactoring Ajouter le support RTL lorsque cela est possible. Tout vient de Lint en entrant dans RTL. Une implémentation d'analyse est également disponible dans AOSP dans la classe RtlDetector. Autrement dit, si l'imagination vous le permet, vous pouvez trouver quelque chose de vous-même en regardant comment l'analyse se déroule actuellement.

Mon rapport touche à sa fin. Je veux donner quelques thèses sur la construction de la localisation correcte dans notre application, à laquelle nous sommes parvenus au fil du temps.



Tout d'abord, au début du projet, pensez à l'internationalisation. Je ne l'ai pas vraiment mentionné. Ce n'est pas du tout la même chose que la localisation. En effet, l'internationalisation permet une localisation dans l'application, dans le produit. Cela fonctionne dès le départ en Java en raison du fait qu'il prend entièrement en charge Unicode, et en Android - en raison de son riche système de ressources. Peut-être que la seule chose qui peut arriver ici est notre fixation en tant que développeur sur le thème "J'écris l'application uniquement pour le russe, ce qui signifie que je ne la vérifierai qu'avec la langue russe." Et lorsque vous commencez à utiliser les langues arménienne, géorgienne, hébraïque ou arabe dans l'application, l'image semble complètement différente et décompose votre paradigme habituel.

Deuxième moment. Pensez à intégrer la localisation dans votre CI. Il est très décevant d'apprendre les problèmes liés aux traductions pendant la phase de test de la version candidate, pour laquelle vous pourriez vous préparer pendant plusieurs semaines. Autrement dit, nous exécutons maintenant cette tâche pour chaque demande de pool, afin que nous puissions être sûrs à l'avance que tout va bien avec les traductions et que nous pouvons geler le nouveau code dans la branche principale du projet.

Le troisième point. Respectez le travail des traducteurs et votre budget. Tout d'abord, supprimez les ressources inutilisées, car les gens peuvent continuer à consacrer du temps et de l'argent à la traduction de chaînes que vous n'utilisez finalement pas dans votre projet. Deuxièmement, suivez les traductions qui se trouvent dans votre référentiel dans le service de localisation, mais qui ne sont pas dans votre code.

Idéalement, si l'API de votre service de localisation fournit des informations sur le moment où une clé particulière a été ouverte et que vous pouvez utiliser des heuristiques comme «Si la clé a été ouverte il y a plus d'un mois», vérifiez sa présence dans la dernière révision du brunch principal. S'il n'est pas là, très probablement, c'est un candidat clair pour le supprimer et pour que les localisateurs n'y passent pas de temps.

Un candidat plus ou moins universel pour une solution miracle est de stocker des chaînes sur le backend, et non sur le client. À tout le moins, cela vous donnera la possibilité de toujours les garder pertinents du côté de l'application.

Nous avons un public d'utilisateurs très diversifié, chacun perçoit le monde et le contenu de l'application à sa manière. Notre tâche en tant que développeurs est d'aider à garder cette perception. Mon rapport à ce sujet est terminé. Merci beaucoup!

Source: https://habr.com/ru/post/fr456250/


All Articles