20 مشروعًا ، 20 لغة ، الموعد النهائي أمس. الجزء 3

المادة النهائية على التكامل سيرج + Smartcat . في هذه المقالة ، سوف أخبرك كيف يمكننا توسيع نطاق Serge إلى الشركة بأكملها ، والنظر في 4 عمليات تكامل غير قياسية ، وكمكافأة ، نتحدث عن اثنين من الميزات التي يمكن أن تبسط حياتك.

المقالات السابقة:

20 مشروعًا ، 20 لغة ، الموعد النهائي أمس
20 مشروعًا ، 20 لغة ، الموعد النهائي أمس. الجزء 2

التدرجية


في مقال سابق ، تحدثت عن كيفية تكوين سيرج لمستودع واحد. في شركتنا ، لدينا عدة عشرات من المستودعات التي تحتاج إلى ترجمة ، لذلك تم تخصيص خادم منفصل للترجمة. تتشابه بنية الملف وبيئةه تمامًا مع ما تم وصفه في المقالة السابقة. يستخدم كل مستودع مثيل خاص به من Serge. من أجل عدم تنفيذ الأوامر يدويًا ، يكون لكل مثيل تاج ، يعمل على التوالي على أوامر Serge: تلقي أسطر جديدة من المستودع وتلقي ترجمات جديدة والتحليل وإرسال خطوط جديدة إلى Smartcat وإرسال ترجمات جديدة إلى Gitlab.

خيارات التكامل


مجموعتان من اللغات في مستودع واحد


لنبدأ بأبسط الحالات. تخيل أن مستودعك لديه عدة مجموعات من ملفات الموارد. على سبيل المثال ، يتم تخزين سلاسل العميل وواجهة برمجة التطبيقات للتطبيق في نفس المستودع ، ولكن في دلائل مختلفة. يتم ترجمة العميل إلى 20 لغة ، API في 6.

الهدف : تنظيم عرض مستقل للترجمات في كل من الأدلة.
الحل :

  1. قم بإعداد مشروعين في Smartcat: بست لغات و 20.
  2. قم بإعداد مشروعين على خادم الترجمة.
  3. في المشروع الأول في ملف project1.cfg ، أضف السطر our $ unmerged_branch_mask = '^ (translateAPI-)'؛ # معالجة الفروع غير المدمجة المطابقة لهذا القناع ، حيث " translateAPI- " هي بادئة اسم الفرع. ستشير البادئة لـ Serge إلى أن هذا الفرع يحتاج إلى ترجمات في دليل API.
  4. في ملف project1.serge.tmpl ، حدد المسار إلى ملفات الموارد في دليل API في المعلمة source_dir .
  5. وبالمثل ، بالنسبة للمشروع الثاني في ملف project2.cfg ، أضف السطر الخاص بنا $ unmerged_branch_mask = '^ (translateCLIENT-)'؛ # معالجة الفروع غير المدمجة المطابقة لهذا القناع ، حيث " translateCLIENT " هي البادئة لفروع هذا المشروع. ستشير البادئة إلى سيرج أن هذا الفرع يحتاج إلى ترجمات في دليل العميل.
  6. في ملف project2.serge.tmpl ، حدد المسار إلى ملفات الموارد في دليل العميل في المعلمة source_dir .

يرجى ملاحظة أن البادئات يجب أن تكون فريدة بين جميع المشاريع التي تم تكوينها لمستودع واحد.

إجمالاً ، لدينا مشروعان في Smartcat ومشروعان متماثلان على خادم الترجمة. ينظر كلا المشروعين إلى نفس المستودع في Gitlab ، ولكن في دلائل مختلفة. يفهم سيرج ، باستخدام بادئة الفرع ، الخطوط التي يحتاجها لإرسالها للترجمة. لحساب الفرق ، يتم استخدام نفس فرع ترجمة القاعدة.

توطين اختيال


في شركتنا ، يتم ترجمة جميع المنتجات ، بما في ذلك الوثائق. نحن الآن نقدم التوليد التلقائي للوثائق من swagger ، ونحن نواجه الحاجة إلى توطينها.
المهمة : توطين اختيال بأقل جهد ممكن.

الحل : في ملف myproject.tmpl.serge ، أضف كائن البيانات إلى كائن المحلل اللغوي وأدرج فيه الحقول التي يجب استخراج قيمتها وإرسالها للترجمة:

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

مهمة مماثلة : من الضروري ترجمة النصوص من ملف ، ولكن ليس كل شيء ، ولكن النصوص القانونية فقط. يتم توفير النصوص الأخرى من قبل فريق التسويق. من أجل عدم تعقيد الهيكل وعدم إنشاء ملف إضافي للنصوص القانونية ، تلقت مفاتيح جميع الخطوط القانونية البادئة "legal":

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

تفاصيل الترجمات القانونية


حالة أخرى مثيرة للاهتمام. لدينا وثيقة قانونية تختلف شروطها من بلد إلى آخر. ولكن ، مع ذلك ، هذا هو تطبيق وملفات الموارد في نفس الدليل.

الهدف : في إطار مشروع واحد لترجمة عدة مستندات ، يجب ترجمة كل وثيقة إلى لغة واحدة محددة.

ما تم القيام به :

  1. تم إنشاء دليل مناسب لكل بلد ، والذي يوجد داخله ملف مصدر باللغة الإنجليزية يتعلق بذلك البلد.
  2. يتم تحديد مسار المتغير source_dir إلى الدليل المشترك مع ملفات الموارد.
  3. نقوم بتمكين البحث عن ملفات الموارد في جميع الدلائل الفرعية : source_process_subdirs YES
  4. نضيف مكونًا إضافيًا جديدًا إلى قائمة المكونات الإضافية المسماة ، والتي تتيح لك إرسال كل ملف مورد محدد إلى اللغة المطلوبة. كدليل ، استخدم اسم الدليل حيث يقع:

 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.. } } 

التعريب عند تخزين الصفوف في قاعدة البيانات


يحتوي نظامنا على جزء من الكود الذي يخزن الترجمات في قاعدة البيانات ، ولعدد من الأسباب لا يمكن نقله إلى ملفات الموارد في المستودع. ومع ذلك ، نحتاج إلى أن نكون قادرين على تقديم الترجمات بسرعة وبشكل تلقائي.

المهمة : تنظيم عملية التعريب المستمر إذا لم يتم تخزين الصفوف في المستودع ، ولكن في قاعدة البيانات.

الحل :

  1. قم بإنشاء مستودع وجمع وتجميع فيه جميع الأسطر من قاعدة البيانات وفقًا للمبدأ الذي يناسبنا (حسب عدد لغات الترجمة أو حسب المنتجات).
  2. إنشاء مشروع في Smartcat.
  3. بدء الدورة القياسية للتوطين المستمر.
  4. دمج فروع الترجمة في فرع الترجمة الأساسية.
  5. بواسطة التاج ، تحقق من قيمة تجزئة الالتزام الأخير بترجمة الأساس. إذا تم تغيير التجزئة ، أي تم إنشاء ترجمات جديدة ، وتحليل الفرق بين التجزئة القديمة والحالية ، وإرسال صفوف جديدة / تم تغييرها إلى قاعدة البيانات.

ميزات المكافأة


تحذير


لم تكن تنبيهات Smartcat الأساسية مناسبة لنا ، لأن كل فريق يرغب في تلقي إعلامات فقط عن فروعه وعن الاستعداد التام للترجمات في جميع ملفات الموارد الخاصة بالمنتج.

تقرر الاعتماد على توفر جميع الترجمات في المستودع ، وإذا كانت جاهزة تمامًا ، أرسل الإشعارات إلى مراسلة الشركة ، في حالتنا ، دردشة Google.

المهمة : تنظيم التنبيهات في المستودع ، حيث يمكن لثمانية فرق الالتزام ، وتكرار جميع التنبيهات في قناة قسم الوثائق التقنية.

الحل :

  1. اتفق مع كل فريق على أن اسم الفروع يجب أن يحتوي على اسم الفريق. لا تزال تستخدم ترجمة البادئة - للإشارة إلى الفروع التي تحتاج إلى ترجمة.
  2. إنشاء خط أنابيب يعمل فقط للفروع مسبوقة بـ translate-.
  3. في خط الأنابيب ، حدد الأمر الذي ينتمي إليه الفرع ، وتحقق من وجود خطوط ذات قيمة فارغة ، وإذا لم يكن هناك أي شيء ، أرسل إخطارات الاستعداد للقناة المناسبة. نظرًا لأن الكود ضخم جدًا ، فقد قمت بوضعه في برنامج نصي.

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 

تنبيه البرنامج النصي


 #!/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 

تعيينات المترجم عبر واجهة برمجة تطبيقات Smartcat




هذا ما يبدو عليه مدير الترجمة لدينا عندما يحين الوقت لتعيين جميع الفروع للترجمة.

في المتوسط ​​، لدينا أكثر من 10 فروع في عملنا كل يوم. في Smartcat ، كل زوج لغة هو مستند منفصل ، ويجب تعيين المترجمين لكل مستند من هذا القبيل. يدويا. تخيل: 40-60 التعيينات كل يوم. لتبسيط هذه العملية ، قمنا بتحديد موعد من خلال واجهة برمجة التطبيقات ، ووضعناها أيضًا في طور الإعداد. يتم إطلاق هذه الوظيفة عن طريق الزر. سؤال معقول: لماذا لا تجعل المهام تلقائية عند إرسال التحويلات ، ولا تجري مكالمة طريقة في المكون الإضافي Smartcat ، وليس في خط الأنابيب؟

هناك عدة أسباب لهذا القرار:

  1. العامل البشري. على الرغم من حقيقة أننا نبني العمليات ونحاول الالتزام بها ، إلا أن الخطوط أو الخطوط غير المقروءة بدون سياق تنضم إلى Smartcat بانتظام. يعني التعيين التلقائي في هذه الحالة نفقات إضافية لنا ، حيث سيتم إرسال بعض الأسطر للترجمة مرتين: قبل التحرير وبعده.
  2. توزيع الأدوار. يتم تكوين المشاريع وإدارتها على مستوى خادم الترجمة من قبل مهندس التعريب أو الكاتب التقني للمشروع. تتم معالجة المواعيد والتواصل مع المترجمين بواسطة مدير الترجمة. وبالتالي ، يجب أن تكون المهام قابلة للإدارة وشفافة ويمكن الوصول إليها من خلال واجهة المستخدم الرسومية.

الحل: عندما يرى مدير التوطين أن الخطوط الموجودة في هذا الفرع جاهزة للترجمة ، تضغط على زر في Gitlab. يتم تعيين فريق المترجمين بأكمله لهذا الفرع. يتم تنفيذ المهمة من قبل المترجم الذي استجاب أولاً.

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 

النصي الاحالة


 #!/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 

بهذا تنتهي سلسلة مقالاتي حول دمج وتكوين الترجمات المستمرة. سأكون سعيدًا للإجابة على أي من أسئلتك.

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


All Articles