
ماذا يحدث عندما يبدأ بيع منتجك في بلد آخر بلغته وخصائصه الثقافية؟ على الأرجح ، ينتظر التوطين له. في معظم الحالات ، ما عليك سوى ترجمة ملفات الموارد بحيث تكون القوائم وعناصر الواجهة باللغة المألوفة للمستخدم. ولكن ما يجب فعله إذا كان أساس ما تبيعه هو البيانات ، وهي الكثير ، فهي تأتي باستمرار ، بكميات كبيرة وتتطلب ترجمة منتظمة. وليس لغة واحدة فقط ، بل عدة لغات في وقت واحد.
تحت الخفض ، ستجد قصة عن كيفية حل هذه المشكلة في 2GIS. سأخبرك بمثال الحالة الأخيرة في دبي ، لكن الممارسات تنطبق على أي لغة.
عن العربية
بدأت هذه القصة كاملة مع إطلاق 2GIS في دبي ، حيث يتم استخدام لغتين: العربية والإنجليزية.
الدقة العالية للبيانات هي أهم قيمة للشركة. ويتحقق ذلك من خلال العمل اليدوي لرسامي الخرائط والمتخصصين على الأرض. في دبي ، حيث يعرف كل من المتخصصين المحليين والمستخدمين النهائيين اللغة الإنجليزية ، في البداية تم إدخال البيانات فيها فقط. في عملية النمو ، قرروا عدم التوقف عند ذلك وإضافة اللغة العربية.
فيجي
لعمل رسامي الخرائط ، لدينا برنامجنا الخاص. هذا الشيء يسمى فيجي ويعمل كنظام رئيسي لجمع بيانات الخرائط.
لقد كتبنا بالفعل كيف تساعد فيجي رسامي الخرائط في تحرير المنازل ورسم الطرق. البيانات التي تم تحميلها من فيجي بعد المعالجة والتحضير تذهب إلى المنتج النهائي لإرضاء المستخدمين. في المقالة ، أتحدث عن بالضبط ما قمنا به في فيجي لتحرير / تخزين / عرض البيانات متعددة اللغات.
الشروط
في الفريق نستخدم مفردات محددة. فيما يلي أربعة أمثلة ↓
يدعم النظام العمل بنوعين من اللغات:
لغة
البيانات الوصفية - اللغة التي تُعرض بها جميع عناصر تحكم المستخدم: واجهة المستخدم والبيانات الوصفية.
لغة
البيانات - لغة يتم فيها عرض قيم سمات الكائنات الجغرافية وبعض الدلائل والمصنفات.
اللغات مرتبطة بالأقاليم. يمكن أن تحتوي المنطقة على نوعين من اللغات:
اللغة الرئيسية للإقليم هي اللغة المعتمدة رسميًا في تلك المنطقة.
اللغة الإضافية للمنطقة هي اللغة التي نريد إصدار المنتج بها. يأتي بالإضافة إلى الرئيسي.
اللغات واللهجات
قد تختلف اللهجات المعتمدة في مناطق مختلفة من البلاد بشكل كبير. لذلك ، في بعض الأنظمة ، يتم تخزين جوهر اللغة (= النسخة الأساسية) واللهجات بشكل منفصل ، ثم عند تفريغها. بالنسبة لنا ، بدا هذا النهج معقدًا للغاية ، لذلك قررنا اعتبار كل لهجة كلغة مستقلة.
فارق بسيط في اللغات واللهجات العربية. لكل لغة ، تحتاج إلى إدخال علامة اتجاه حامل النقل بقيمتين: من اليسار إلى اليمين ومن اليمين إلى اليسار. بشكل افتراضي ، يجب أن يتحرك حامل الخراطيش من اليسار إلى اليمين. إذا تم تعيين القيمة من اليمين إلى اليسار ، فأنت بحاجة إلى تغيير اتجاه حامل الخراطيش لجميع الحقول المتعددة اللغات القابلة للتعديل. تمت كتابة كيفية القيام بذلك في المنتجات النهائية
هنا . كان علينا أن نفعل نفس الشيء.
الانجذاب إلى الأقاليم
ينقسم عالمنا كله إلى مناطق معينة - قد تكون هذه دولًا ومناطق ومناطق. لكل منطقة نحدد عدة لغات ، تعتبر واحدة منها واحدة رئيسية ، والبقية - إضافية. تتم الترجمة من اللغة الأساسية إلى اللغات الإضافية.
على سبيل المثال ، في حالة دبي ، تركنا اللغة الإنجليزية كلغة رئيسية ، لأنها تحتوي على الكثير من البيانات. تم جعل اللغة العربية اختيارية.
أدخل وتغيير اللغة
لكي يعمل رسامو الخرائط بشكل مريح ، أعدنا تصميم واجهتنا في تلك الأماكن التي يُقصد بها الإدخال متعدد اللغات.

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

في الواقع ، قد تكون هناك حاجة لتحرير البيانات بلغة إضافية فقط إذا كان رسام الخرائط نفسه يعرف عدة لغات ولا يريد اللجوء إلى مترجم. لكل شخص آخر ، هناك CrowdIn.
Crowdin ، أو نقل الدفق
لذلك ، لقد مكننا رسامي الخرائط لدينا لملء البيانات بلغات مختلفة. ولكن من الأفضل بكثير تسليم مهمة الترجمة إلى المحترفين.
أول ما يتبادر إلى الذهن عند ترجمة التطبيق هو إعطاء ملفات الموارد للمترجمين وبعد نقلها مرة أخرى.
في هذا الصدد ، ساعدتنا منصة CrowdIn كثيرًا. يسمح لك بإعادة توجيه ملفاتك إلى مترجمين محترفين. الشيء الوحيد المتبقي هو دمج البيانات المترجمة في نظامنا.
الوضع معقد بسبب حقيقة أن البيانات تأتي إلينا في تدفق مستمر ، لذلك نود الحصول على ترجمات بشكل مستمر.
قمنا بتحسين النظام على النحو التالي: إذا تم إجراء تغييرات في اللغة الرئيسية للمنطقة ، نقوم بتحميل التغييرات للترجمة إلى جميع اللغات الإضافية لهذه المنطقة. نقوم باستثناءات للحالات التي قام فيها رسام الخرائط بنفسه بالترجمة. هنا نعتقد أنه يفهم ما يفعله ، وليس هناك حاجة لتوصيل مترجم.
لكل دليل أو كائن خريطة ، لدينا إصدار من طرف إلى طرف ، والذي يزداد مع كل تحديث للبيانات. حتى نتمكن من الحصول على جميع التغييرات بسرعة من إصدار معين.
نظام الإصدار بسيط وفعال للغاية ، ولكن له عيب كبير: في الواقع ، لدينا قائمة انتظار واحدة ولا يمكننا إدارتها بأي شكل من الأشكال. أقصى ما لدينا هو تخطي الإصدار. هناك حاجة للتحول إلى قائمة انتظار عادية ، على سبيل المثال ، إلى RabitMQ أو Kafka ، ولكن لم تصل اليدين بعد.
لتحديث المحتوى بسرعة ، كتبنا خدمة صغيرة تعمل في ثلاثة تيارات.
يقوم الدفق الأول (Saver) بنسخ جميع البيانات التي تتطلب الترجمة ، ويقوم بإنشاء ملفات xml منها.
يرسلها الثاني (تصدير) إلى CrowdIn ويضعها في المشروع المطلوب ، مما يشير إلى اللغة الرئيسية التي نترجم منها ، وقائمة باللغات التي نترجم إليها.
يستقصي (الاستيراد) الثالث دوريًا واجهة برمجة تطبيقات CrowdIn للملفات التي تمت ترجمتها وتثبيتها بنسبة 100٪ ، ويستورد الملفات النهائية إلى قاعدة بياناتنا.

بدون أشعل النار لم تستطع القيام به. تعثرنا على نظام إصدار البيانات الخاص بنا.
عندما قمنا بتنزيل ترجمة الكلمة ، تم تحديث إصدار البيانات وسقطت الكلمة مرة أخرى في الترجمة.
لتجنب حلقة لا نهائية من الترجمة ، بدأنا في تسجيل البيانات. يتم تمييز كل كلمة مترجمة ، مما يلغي إرسالها المتكرر إلى CrowdIn.
البرنامج التعليمي
الآن سأخبرك كيف يحدث العمل مع CrowdIn. هناك العديد من الطرق للعمل مع النظام الأساسي ، على سبيل المثال ، يمكنك تحميل الملفات إلى مستودع Git و CrowdIn نفسها تمتصها. لكننا اعتقدنا أن العمل من خلال واجهة برمجة التطبيقات يبدو أكثر ملاءمة.
لدى CrowdIn برنامج
تعليمي مفصل للغاية ، ولكن أدناه سأكتب كيف قمنا بذلك.
نحتاج إلى الحصول على مفتاح API ، والذي سنقوم بإرفاقه بكل طلب من طلباتنا ، حتى يتحقق النظام منا. نذهب إلى علامة التبويب API في إعدادات المشروع ونلقي نظرة على ما هو مكتوب في عمود مفتاح API.

يجب إضافة هذا المفتاح في نهاية كل طلب من منصتك. على سبيل المثال ، مثل هذا:
احصل على:
https://api.crowdin.com/api/project/{myLitleProject}/download/all.zip?key={project-key}
2. قم بإنشاء مجلد حيث سنقوم بتحميل الملفات داخل المشروع.
var uri = $"project/{_projectName}/add-directory?key={apiKey}"; var content = new MultipartFormDataContent { { new StringContent(crowdInDirectoryPath), "name" } }; return PostAsync(uri, content);
هناك لحظة خرقاء صغيرة. نحن نكتب خدمة ، سيكون من الجيد إذا تحقق في البداية لمعرفة ما إذا كان المجلد الذي نحتاجه موجودًا قبل محاولة إنشائه. ليس لدى CrowdIn طريقة عادية للتحقق من وجود مجلد ، لذلك نرسل طلب إنشاء. إذا لم يكن موجودًا ، فسيقوم CrowdIn بإنشائه وإرجاع الرمز 200. إذا كان هناك مجلد ، فلن يقوم بإنشاء أي شيء وسيعيد الرمز 500.
3. تصدير الملفات. تحتوي وظيفة ملف الإضافة على الكثير من الخيارات والمعلمات ، وكيفية القراءة وأين. فيما يلي مثال لكيفية تحميل البيانات بملفات xml.
مثالنضع جميع البيانات التي سنقوم بترجمتها إلى ملفات xml بالبنية التالية.
<LocalizableDocument> <LocalizableValues> <LocalizableValue> … <Attributes> <LocalizableAttributeValue> <AttributeName/> <Value/> </LocalizableAttributeValue> </Attributes> </LocalizableValue> </LocalizableValues> </LocalizableDocument>
لكي يقوم CrowdIn بتحليل البيانات من الملف الذي يجب ترجمته ، يجب تحديده. للقيام بذلك ، تحتاج إلى كتابة صفيف من معلمات translatable_elements مع المسارات إلى العناصر الضرورية للمستند في المحتوى. في حالتنا ، بدا الأمر كما يلي:
var uri = $"project/{_projectName}/add-file?key={apiKey}"; var content = new MultipartFormDataContent { { new StringContent("/LocalizableDocument/LocalizableValues/LocalizableValue/Attributes/LocalizableAttributeValue/Value"), "translatable_elements[0]" } }; foreach (var filePath in filePaths) { var fileName = Path.GetFileName(filePath); var fileStream = File.OpenRead(filePath); var fileContent = new StreamContent(fileStream); content.Add(fileContent, $"files[{_crowdInDirectoryPath}/{fileName}]", fileName); } return PostAsync(uri, content);
يرجى ملاحظة ما يلي: تنص الوثائق على أنه يمكن لـ CrowdIn مضغ 20 ملفًا كحد أقصى في المرة الواحدة ، في حين يجب ألا يتجاوز حجم الملف الواحد 100 ميغابايت.
4. نكتشف الملفات التي قمنا بترجمتها بالكامل. نقوم بذلك باستخدام أمر للغة معينة.
var uri = $"project/{_projectName}/language-status?key={apiKey}"; var content = new MultipartFormDataContent {{ new StringContent(langCode), "language" } }; return PostAsync(uri, content);
سوف تعيدنا المنصة شيئًا مثل هذا:
<item> <node_type>directory</node_type> <id>29812</id> <name>Version 1.0</name> <files> <item> <node_type>file</node_type> <id>29827</id> <name>strings.xml</name> <node_type>file</node_type> <phrases>7</phrases> <translated>0</translated> <approved>0</approved> <words>32</words> <words_translated>0</words_translated> <words_approved>0</words_approved> </item> </files> </item>
نحن هنا مهتمون بالقيم <المترجمة /> و <المعتمدة />. يعرض الأول النسبة المئوية للخطوط المترجمة في هذا الملف ، والثاني يظهر النسبة المئوية للقيم المعتمدة إذا ، بالإضافة إلى المترجم ، شارك المراجع أيضًا في سير العمل. اعتمادًا على سير العمل لدينا ، على سبيل المثال ، عند 100 ، نعتبر الوثيقة مترجمة وموافق عليها. الآن يمكن استيراد هذا الملف إلينا.
5. قم باستيراد الملف مرة أخرى إلى نظامنا.
يتم ذلك مع طلب GET بسيط.
https://api.crowdin.com/api/project/{_projectName}/export-file?file={_crowdInDirectoryPath}/{fileName}&language={langCode}&key={project-key}
يتم إلغاء تسلسل الملف الناتج ويتم استيراد البيانات إلى نظامنا.
بدلا من الاستنتاج
بشكل عام ، هذا كل شيء. بالطبع ، ما زلنا بحاجة إلى تحسين عرض التوقيعات على خريطة فيجي بحيث يتم عرضها باللغة الصحيحة ، اعتمادًا على المنطقة التي يحكمها رسام الخرائط الآن. كان من الضروري الاتفاق مع الأنظمة الأخرى على كيفية تزويدنا ببيانات متعددة اللغات ، لكن هذه قصة أخرى.
ونتيجة لذلك ، تلقينا الخدمة بروح "تشغيل ونسي". يقوم رسامي الخرائط بإدخال البيانات ، وترجمة المترجمين ، والشيخ راضي ، وتقوم الخدمة بتحميل البيانات عند الضرورة ، ونحن نحل مشاكل أكثر إلحاحًا دون التفكير في كيفية عمل نظامنا بعدة لغات.