20 projets, 20 langues, date limite hier. 3e partie

Dernier article sur l' intégration de Serge + Smartcat . Dans cet article, je vais vous expliquer comment nous adaptons Serge à l'ensemble de l'entreprise, considérons 4 intégrations non standard et, en bonus, parlerons de 2 fonctionnalités qui peuvent vous simplifier la vie.

Articles précédents:

20 projets, 20 langues, date limite hier
20 projets, 20 langues, date limite hier. 2e partie

ÉvolutivitĂ©


Dans un article précédent, j'ai expliqué comment configurer Serge pour un référentiel unique. Dans notre entreprise, nous avons plusieurs dizaines de référentiels qui ont besoin de traductions, donc un serveur distinct pour la localisation a été alloué. La structure et l'environnement du fichier sont complÚtement identiques à ce qui est décrit dans l'article précédent. Chaque référentiel utilise sa propre instance de Serge. Afin de ne pas exécuter les commandes manuellement, chaque instance a une couronne, qui exécute successivement les commandes Serge: recevoir de nouvelles lignes du référentiel, recevoir de nouvelles traductions, analyser, envoyer de nouvelles lignes à Smartcat et envoyer de nouvelles traductions à Gitlab.

Options d'intégration


Deux ensembles de langues dans un référentiel


Commençons par le cas le plus simple. Imaginez que votre rĂ©fĂ©rentiel possĂšde plusieurs ensembles de fichiers de ressources. Par exemple, les chaĂźnes client et les API d'application sont stockĂ©es dans le mĂȘme rĂ©fĂ©rentiel, mais dans des rĂ©pertoires diffĂ©rents. Le client est traduit en 20 langues, l'API en 6.

Objectif : organiser une fourniture indépendante de traductions dans chacun des répertoires.
Solution :

  1. Mettre en place 2 projets dans Smartcat: en 6 langues et en 20.
  2. Configurez 2 projets sur le serveur de localisation.
  3. Dans le premier projet du fichier project1.cfg , ajoutez la ligne our $ unmerged_branch_mask = '^ (translateAPI-)'; # traite les branches non fusionnĂ©es correspondant Ă  ce masque , oĂč « translateAPI- » est le prĂ©fixe du nom de la branche. Le prĂ©fixe indiquera Ă  Serge que cette branche a besoin de traductions dans le rĂ©pertoire API.
  4. Dans le fichier project1.serge.tmpl , spécifiez le chemin d'accÚs aux fichiers de ressources dans le répertoire API dans le paramÚtre source_dir .
  5. De mĂȘme, pour le deuxiĂšme projet du fichier project2.cfg , ajoutez la ligne our $ unmerged_branch_mask = '^ (translateCLIENT-)'; # traite les branches non fusionnĂ©es correspondant Ă  ce masque , oĂč « translateCLIENT » est le prĂ©fixe des branches de ce projet. Le prĂ©fixe indiquera Ă  Serge que cette branche a besoin de traductions dans le rĂ©pertoire Client.
  6. Dans le fichier project2.serge.tmpl , spécifiez le chemin d'accÚs aux fichiers de ressources dans le répertoire CLIENT dans le paramÚtre source_dir .

Veuillez noter que les prĂ©fixes doivent ĂȘtre uniques parmi tous les projets configurĂ©s pour un rĂ©fĂ©rentiel.

Au total, nous avons 2 projets dans Smartcat et 2 projets correspondants sur le serveur de localisation. Les deux projets regardent le mĂȘme rĂ©fĂ©rentiel dans Gitlab, mais dans des rĂ©pertoires diffĂ©rents. Serge, en utilisant le prĂ©fixe de branche, comprend quelles lignes il doit envoyer pour traduction. Pour calculer le diff, la mĂȘme branche base-translate est utilisĂ©e.

Localisation Swagger


Dans notre entreprise, tous les produits, y compris la documentation, sont localisés. Nous introduisons maintenant la génération automatique de documentation à partir de swagger, et nous sommes confrontés à la nécessité de la localiser.
TĂąche : localiser le swagger avec un minimum d'effort.

Solution : dans le fichier myproject.tmpl.serge , ajoutez l'objet de donnĂ©es Ă  l'objet analyseur et rĂ©pertoriez-y les champs dont la valeur doit ĂȘtre extraite et envoyĂ©e pour traduction:

parser { plugin parse_json data { path_matches \/(summary|description)$ } } 

Une tùche similaire : il est nécessaire de traduire des textes à partir d'un fichier, mais pas tous, mais uniquement des textes légaux. Les autres textes sont fournis par une équipe marketing. Afin de ne pas compliquer la structure et de ne pas créer de fichier supplémentaire pour les textes juridiques, les clés de toutes les lignes légales ont reçu le préfixe «légal»:

 parser { plugin parse_json data { path_matches ^\/legal\..* } } 

Subtilités de traductions juridiques


Un autre cas intĂ©ressant. Nous avons un document juridique dont les conditions varient d'un pays Ă  l'autre. Mais, nĂ©anmoins, il s'agit d'une seule application et les fichiers de ressources se trouvent dans le mĂȘme rĂ©pertoire.

Objectif : dans le cadre d'un projet de traduction de plusieurs documents, chaque document doit ĂȘtre traduit dans une langue spĂ©cifique.

Ce qui a été fait :

  1. Un répertoire approprié a été créé pour chaque pays, à l'intérieur duquel se trouve un fichier source en anglais correspondant à ce pays.
  2. Le chemin de la variable source_dir est spécifié dans le répertoire partagé avec les fichiers de ressources.
  3. Nous activons la recherche de fichiers de ressources dans tous les sous - répertoires : source_process_subdirs YES
  4. Nous ajoutons un nouveau plugin Ă  la liste des plugins appelĂ©s, qui vous permet d'envoyer chaque fichier de ressource spĂ©cifique dans la langue souhaitĂ©e. À titre indicatif, utilisez le nom du rĂ©pertoire oĂč il se trouve:

 callback_plugins { :feature_branch { plugin feature_branch data { master_job job.base-translate } } :limit_languages { plugin limit_languages data { # all rules are processed top to bottom; each rule can add or remove languages # so the most priority rules are placed at the bottom if { # by default, don't localize file_matches . then { exclude_all_languages YES } } if { file_matches de-au\/ then { include_languages de-AT } } if { file_matches li-LI\/ then { include_languages li } } if { file_matches pt\/ then { include_languages pt-BR } } if { file_matches zh-Hans\/ then { include_languages zh-Hans } } # and so on.. } } 

Localisation lors du stockage de lignes dans la base de données


Notre systĂšme a une partie du code qui stocke les traductions dans la base de donnĂ©es, et pour un certain nombre de raisons, il ne peut pas se dĂ©placer vers des fichiers de ressources dans le rĂ©fĂ©rentiel. Cependant, nous devons ĂȘtre en mesure de livrer des traductions rapidement et automatiquement.

Tùche : organiser un processus de localisation continue si les lignes ne sont pas stockées dans le référentiel, mais dans la base de données.

Solution :

  1. Créez un référentiel, collectez et regroupez toutes les lignes de la base de données selon le principe qui nous convient (par le nombre de langues de traduction ou par produits).
  2. Créez un projet dans Smartcat.
  3. Commencez le cycle standard de localisation continue.
  4. Fusionnez les branches de traduction dans la branche base-translate.
  5. Par couronne, vérifiez la valeur de hachage du dernier commit dans base-translate. Si le hachage a changé, c'est-à-dire que de nouvelles traductions ont été générées, analysez la différence entre l'ancien et le hachage actuel et envoyez des lignes nouvelles / modifiées à la base de données.

Fonctionnalités bonus


Alertes


Les alertes de base Smartcat ne nous convenaient pas, car chaque équipe souhaite recevoir des notifications uniquement sur ses succursales et uniquement sur la disponibilité complÚte des traductions dans tous les fichiers de ressources du produit.

Il a Ă©tĂ© dĂ©cidĂ© de s'appuyer sur la disponibilitĂ© de toutes les traductions dans le rĂ©fĂ©rentiel et, si elles sont complĂštement prĂȘtes, d'envoyer des notifications au messager d'entreprise, dans notre cas, Google Chat.

TĂąche : organiser les alertes dans le rĂ©fĂ©rentiel, oĂč 8 Ă©quipes peuvent s'engager, dupliquer toutes les alertes dans le canal du service de documentation technique.

Solution :

  1. Convenez avec chaque équipe que le nom des branches doit contenir le nom de l'équipe. Utilisez toujours le préfixe translate- pour indiquer les branches qui ont besoin de traduction.
  2. Créez un pipeline qui s'exécute uniquement pour les branches préfixées par translate-.
  3. Dans le pipeline, déterminez à quelle commande appartient la branche, vérifiez la présence de lignes avec une valeur vide et, s'il n'y en a pas, envoyez des notifications de disponibilité au canal approprié. Comme le code est assez volumineux, je l'ai mis dans un script.

Ci


 check-translations: stage: check-translations image: node:8.14.0 tags: - devops script: - chmod +x ./notification.sh - ./notification.sh only: - base-translate - /^translate.*$/ when: always 

Script d'alerte


 #!/bin/bash hangouts(){ curl -X POST --max-time 180 -H "Content-Type: application/json; charset=UTF-8" --data "{ \"cards\": [{\"header\": {\"title\": \"LOCALIZATION IS READY\",\"subtitle\": \"REPOSITORY NAME\",\"imageUrl\": \"https://avatanplus.com/files/resources/mid/5775880ee27f8155a31b7a50.png\"},\"sections\": [{\"widgets\": [{\"keyValue\": {\"topLabel\": \"Translation is finished in the branch\",\"content\": \"$1\"}}]},{\"widgets\": [{\"buttons\": [{\"textButton\": {\"text\": \"SEE COMMIT\",\"onClick\": {\"openLink\": {\"url\": \"https://gitlab.loc/common/publisher-client/commit/$2\"}}}}]}]}]}]}" "$3" || true } cd app/translations if echo "$CI_COMMIT_REF_NAME" | grep "commandname1"; then grep -rl '\:\s\"\"' *.json >> result.file if [ -s network.file ]; then echo "Translations are not ready"; cat result.file else hangouts $CI_COMMIT_REF_NAME $CI_COMMIT_SHA $HANGOUTS_NOTIFICATIONS_COMMAND_NAME_1 hangouts $CI_COMMIT_REF_NAME $CI_COMMIT_SHA $HANGOUTS_NOTIFICATIONS_DOC fi fi if echo "$CI_COMMIT_REF_NAME" | grep "commandname2"; then grep -rl '\:\s\"\"' *.json >> result.file if [ -s result.file ]; then echo "Translations are not ready"; cat result.file else hangouts $CI_COMMIT_REF_NAME $CI_COMMIT_SHA $HANGOUTS_NOTIFICATIONS_COMMAND_NAME_2 hangouts $CI_COMMIT_REF_NAME $CI_COMMIT_SHA $HANGOUTS_NOTIFICATIONS_DOC fi fi ... if echo "$CI_COMMIT_REF_NAME" | grep "commandname8"; then grep -rl '\:\s\"\"' *.json >> result.file if [ -s result.file ]; then echo "Translations are not ready"; cat result.file else hangouts $CI_COMMIT_REF_NAME $CI_COMMIT_SHA $HANGOUTS_NOTIFICATIONS_COMMAND_NAME_8 hangouts $CI_COMMIT_REF_NAME $CI_COMMIT_SHA $HANGOUTS_NOTIFICATIONS_DOC fi fi 

Affectations de traducteur via l'API Smartcat




Voici Ă  quoi ressemble notre gestionnaire de localisation quand vient le temps d'affecter toutes les branches Ă  la traduction.

En moyenne, nous avons plus de 10 succursales dans notre travail chaque jour. Dans Smartcat, chaque paire de langues est un document distinct et des traducteurs doivent ĂȘtre affectĂ©s Ă  chacun de ces documents. Manuellement. Imaginez: 40 Ă  60 rendez-vous chaque jour. Pour simplifier ce processus, nous avons pris rendez-vous via l'API et l'avons Ă©galement mis dans le pipeline. Ce travail est lancĂ© par le bouton. Une question raisonnable: pourquoi ne pas rendre les affectations automatiques lors de l'envoi de transferts, et ne pas placer d'appel de mĂ©thode dans le plugin Smartcat, et non dans le pipeline?

Plusieurs raisons expliquent cette décision:

  1. Le facteur humain. Malgré le fait que nous construisons des processus et essayons de les respecter, des lignes non lues ou des lignes sans contexte entrent réguliÚrement dans Smartcat. L'affectation automatique dans ce cas entraßnerait des dépenses supplémentaires pour nous, car certaines lignes seraient envoyées pour traduction deux fois: avant et aprÚs l'édition.
  2. RĂ©partition des rĂŽles. Les projets sont configurĂ©s et gĂ©rĂ©s au niveau du serveur de localisation par l'ingĂ©nieur de localisation ou le rĂ©dacteur technique du projet. Les rendez-vous et la communication avec les traducteurs sont assurĂ©s par le responsable de la localisation. Ainsi, les affectations doivent ĂȘtre gĂ©rables, transparentes et accessibles via l'interface graphique.

Solution: lorsque le responsable de la localisation considĂšre que les lignes de cette branche sont prĂȘtes Ă  ĂȘtre traduites, il appuie sur un bouton dans Gitlab. Toute l'Ă©quipe de traducteurs est affectĂ©e Ă  cette branche. La tĂąche est assumĂ©e par le traducteur qui a rĂ©pondu le premier.

Ci


 assignee: stage: assignee image: node:8.14.0 tags: - devops script: - chmod +x ./assignee.sh - ./assignee.sh only: - base-translate - /^translate.*$/ - assignee when: manual 

Script d'affectation


 #!/bin/bash if echo "$CI_COMMIT_REF_NAME" | grep "translate-"; then node -pe "JSON.parse(process.argv[1]).documents.forEach(function(elem){ if(elem.name.indexOf(\"$CI_COMMIT_REF_NAME\") !== -1) { console.log(elem.id) } });" "$(curl -XGET -H "Authorization: Basic $SMARTCAT_API_KEY" -H "Content-type: application/json" "https://smartcat.ai/api/integration/v1/project/$SMARTCAT_PROJECT_ID")" >> documents fi sed '$d' documents > documents.list while read LINE; do bash -c "curl -XPOST -H 'Authorization: Basic $SMARTCAT_API_KEY' -H "Content-type:application/json" -d '{"documentIds":[\""$LINE"\"],"stageNumber": 1}' 'https://smartcat.ai/api/integration/v1/document/assignFromMyTeam'";done < documents.list 

Ceci conclut ma série d'articles sur l'intégration et la configuration de localisations continues. Je me ferai un plaisir de répondre à toutes vos questions.

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


All Articles