طريقة سهلة لإضافة لغات متعددة إلى موقعك

مقدمة


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

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

كتابة طريقة بديلة لتغيير الإعدادات المحلية لم تستغرقني سوى بضع ساعات ، والمحافظة على الوحدة الدلالية يقلل تمامًا التغييرات عند إضافة صفحات جديدة.

يمكن تنزيل الملفات المصدر لموقع العينة مع الترجمة التلقائية على github

البدائل الموجودة


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

  • إنشاء كتل html مكررة بنص بلغات مختلفة ، واحدة منها فقط تبقى نشطة للمستخدم ، والباقي مخفية (عرض: لا شيء).

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

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

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

الحل البديل


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

عند تغيير اللغة باستخدام منهج بديل ، هناك ثلاثة أطراف رئيسية:

  • أتش تي أم أل الصفحة مع القاعدة المعمول بها لاختيار محددات مع النص
  • خدمة js العامة ، وتتمثل مهمتها الرئيسية في استبدال عناصر النص textContet DOM وفقًا لقاعدة تصميم المحددات
  • ملف لغة JSON يحتوي على بنية تحتوي على كتل HTML بجميع اللغات المستخدمة عند تغيير الإعدادات المحلية

إن الامتثال لقواعد التصميم الخاصة بمتحددي العناصر القابلة للتغيير يلغي الحاجة إلى تغيير كود js الخاص بخدمة تغيير الإعدادات المحلية ، والتي تعد إضافة كبيرة من حيث قابلية تطوير المشروع.

قاعدة لبناء محددات


تشير معظم طرق تغيير لغة الصفحة (بين البديلين 1.3 و 2 جزئيًا) إلى أنك بحاجة إلى "تمييز" كتلة html المتغيرة بطريقة ما ، لأنها صحيحة عن طريق تغيير حقل الفصل الدراسي. تستخدم نفس الآلية خيارًا بديلًا.

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

  • القائمة

  • بطاقة العمل (المنزل)

  • مثال عملية الخدمة (مثال)

  • الشركاء (العملاء)

  • نطاق الخدمة (userfulBlock)

  • أمثلة على الخدمة (أمثلة)

  • جهات الاتصال والتعليقات (جهات الاتصال)


مثال الموقع
مثال الموقع

بعد ذلك ، نقوم بتقسيم كل كتلة إلى كتل وظيفية أصغر ، كما هو الحال مع مكتبة React.

مثال الموقع
مثال الموقع

نخصص أسماءنا للمناطق المحددة ونحصل على بنية النموذج:

  • القائمة

  • الرئيسية الرئيسية ، وصف ، أزرار

  • إحصائيات المثال ، العنوان ، الوصف ، الأزرار

  • أزرار العملاء

  • userfulBlock العنوان ، userfulCards ، elseBlock

  • أمثلة العنوان ، بطاقات

  • عناوين الاتصالات ، الوصف ، جهات الاتصال ، النموذج


نواصل هذا الإجراء حتى نصل إلى الكتل التي تحتوي على النص المصدر.

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

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

مثال الموقع
مثال الموقع

مثال على ملف json المحلي الناتج يمكن رؤيته على github

خدمة تغيير اللغة


خدمة تغيير اللغة هي وحدة تحتوي على وظيفة تحميل ملف الإعدادات المحلية

loadLocale(defLang) 

مع معلمة defLang الاختيارية - اللغة المحددة بعد تحميل الإعدادات المحلية (اللغة الافتراضية) ، وكذلك الوظيفة الرئيسية لتغيير الإعدادات المحلية الحالية

 changeLocale(lang) 

مبينا اللغة المطلوبة.

وظيفة تحميل الإعدادات المحلية


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

 function loadLocale(defLang) { var xhr = new XMLHttpRequest(); xhr.open("GET", 'http://localhost:3000/locale.json', true); xhr.onreadystatechange = saveLocale.bind(this); xhr.onerror = function () { console.log("no found page"); }; xhr.send(); function saveLocale() { if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) { locale = JSON.parse(xhr.responseText); console.log("locale loaded"); if(defLang) changeLocale(defLang); } } } 

وظيفة تغيير اللغة


أنواع البيانات


إنها دالة متكررة تتمثل مهمتها الرئيسية في اجتياز الكائن الذي يحتوي على لغة الصفحة (باستخدام خوارزمية DFS). يتيح لك استخدام التكرار في إنشاء وظيفة تشفير الخوارزمية بأقصى قدر من الدقة والإيجاز قدر الإمكان ، ومع ذلك ، فإن الكثير من عمق التكرار يمكن أن يؤدي إلى تجاوز سعة مكدس. يمكن العثور على ميزات لحل هذه المشكلة في المنتدى الذي يحمل نفس الاسم ، أو عن طريق قراءة المقالات ذات الصلة على habr.com.

تعتمد الوظيفة العودية على معالجة 4 أنواع من البيانات:

  • حقل يحتوي على سلسلة من النص المصدر المستخدمة لإضافة إلى الصفحة.
    على سبيل المثال:

     "main": "    " 

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

     "menu":["Home","Example","Clients","Info","Contacts"] 

  • بنية بيانات متداخلة تحتوي على مجموعة الحقول الخاصة بها اللازمة للبناء
    بنية الصفحة. على سبيل المثال:

      "home": { "main": "selling quest from your video", "description": "for social networks & sites", "buttons": ["try","order"] } 

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

      "usefulCards": [ { "headline": "Marketers and agencies", "statistics": ["convers 26%", "retent 25%"], "button": "ORDER" }, { "headline": "Production studios and TV platforms", "statistics": ["convers 24%", "retent 33%"], "button": "ORDER" }, { "headline": "Conference creators", "statistics": ["convers 65%", "retent 15%"], "button": "ORDER" }, { "headline": "Bloggers and streamers", "statistics": ["convers 24%", "retent 33%"], "button": "ORDER" } ], 

    على الموقع ، قد يبدو كالتالي:

    مثال الموقع
    مثال الموقع


وظائف المعالجة


يتم إجراء معالجة نوع البيانات المصدر بواسطة وظيفة منفصلة

 function getText(key, object, name,startIndex) 

اسم حقل الإدخال الخاص بحقل البنية مع النص المصدر ، كائن الإعدادات المحلية الحالي الذي يحتوي على النص المراد إضافته ، واسم المحدد الحالي المطلوب للبحث عن عنصر DOM.

 function getText(key, object, name, startIndex) { var elementKey=0; if(startIndex) elementKey = startIndex; for ( ; elementKey < document.getElementsByClassName(name + "-" + key).length; elementKey++) if (!isNaN(elementKey)) document.getElementsByClassName(name + "-" + key)[elementKey].textContent = object[key]; } 

تتم معالجة مجموعة من السلاسل النص المصدر أيضًا بواسطة وظيفة منفصلة

 function getArrayText(key, object, name,startIndex) 

لا يختلف توقيع ونص هذه الوظيفة عن الماضي ، إلا أنه تم تعيين عناصر من الصفيف لعناصر DOM.

 function getArrayText(key, object, name, startIndex) { var elementKey=0; if(startIndex) elementKey = startIndex; for ( ; elementKey < document.getElementsByClassName(name + "-" + key).length; elementKey++) if (!isNaN(elementKey)) document.getElementsByClassName(name + "-" + key)[elementKey].textContent = object[key][elementKey % object[key].length]; } 

تتمثل الوظيفة الرئيسية المتكررة لاستبدال النص في تصنيف حقل اللغة الحالي في أحد الأنواع الأربعة أعلاه ورد الفعل المقابل للنوع الناتج:

 function changeText(name, object, startIndex) { for (key in object) if (Array.isArray(object[key]) && typeof object[key] != 'string' && typeof object[key][0] == 'string') getArrayText(key, object, name); else if (typeof object[key] == "object" ){ if(isNaN(key)) changeText(name + "-" + key, object[key]); else changeText(name, object[key],key); } else getText(key, object, name, startIndex); } 

تقبل هذه الوظيفة لغة اللغة الحالية ومحدد الجذر (في هذه الحالة ، "اللغة"). علاوة على ذلك ، عند الكشف عن بنية متداخلة أو مجموعة من الهياكل ، ستقوم الوظيفة بالتكرار بشكل متكرر ، وتغيير معلمات الإدخال وفقًا لذلك.

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

الخاتمة


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

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

يمكن تنزيل الملفات المصدر لموقع العينة مع الترجمة التلقائية على github .

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


All Articles