إنشاء تطبيق جيد ليس بالأمر السهل. أيا كان التطبيق الفريد والمفيد الذي تكتبه ، إذا كان المستخدم لا يحب ذلك ، إذن ، كما يقولون ، لديك مشكلة كبيرة. معظم الناس لا يحبون ويخافون كل شيء لا يفهمونه. غالبًا ما تكون واجهة المستخدم والحروف هي الطرف المرئي من جبل الجليد الخاص بالتطبيق الخاص بك ، والذي يقيمه المستخدم وفقًا لذلك. لذلك ، فإن توطين كل شيء يراه المستخدم مهم للغاية.
تذكر أنه قبل عشر سنوات ، عندما كان الإنترنت قد بدأ للتو في دخول حياة الجماهير ، وكان العديد من عمالقة تكنولوجيا المعلومات اليوم في مرحلة بدء تشغيل الأقزام مع اثنين من الموظفين ، كان ترتيب الأشياء لإرسال رسالة إلى المستخدم باللغة الإنجليزية. وكان المستخدمون متعاطفين مع هذا. اليوم ، عندما يكون كل شيء موجودًا على الإنترنت ولا تحتاج إلى أن تكون سبعة أعمدة في جبينك ، أو أن يكون لديك تعليم عالي أو تعرف اللغة الإنجليزية لاستخدامها ، فإنه يعتبر من الأشكال السيئة عدم دعم الترجمة في تطبيقك. بالمناسبة ، في شركتنا ، يتم بالفعل ترجمة جميع نصوص واجهة المستخدم بـ 20 لغة وتتزايد قائمة اللغات المدعومة باستمرار.
في Go ، كما هو الحال في لغة صغيرة إلى حد ما ، يتم تطبيق جميع اتجاهات تطوير الويب الحديثة على مستوى الحزم الأساسية ولا تتطلب "رقصًا إضافيًا مع الدف". (بدأت أتعلم "Go" قبل بضع سنوات ، ولكني لا أزال أتذكر شعور "القوى العظمى المكتشفة" التي مررت بها في الأيام الأولى بعد تعلم هذه اللغة. بدا لي الآن أنه يمكنني تحقيق أي مهمة عن طريق كتابة سطرين فقط.)
بالطبع ، لم يتخطوا الترجمة في Go أيضًا. التعريب فيه متاح عملياً "خارج الصندوق" باستخدام الحزم الأساسية: golang.org/x/text/language و golang.org/x/text/message و golang.org/x/text/feature/plural . دعونا نلقي نظرة على مدى سهولة الوصول في Go خلال نصف ساعة فقط ، باستخدام هذه الحزم ، يمكنك تنفيذ مهمة غير تافهة مثل توطين الرسائل.
في المستقبل ، أقول إن الغرض من هذه المقالة هو في المقام الأول إظهار قوة وجمال Go وتسليط الضوء على الميزات الأساسية لحزم الرسائل للعمل مع الترجمة. إذا كنت تبحث عن حل لتطبيق الإنتاج ، فقد تحتاج إلى مكتبة جاهزة أفضل. مزايا go-i18n هي العديد من النجوم على جيثب (من بينها يوجد لي) ومرونة كبيرة. ومع ذلك ، هناك حجج ضد استخدامه: قد لا تحتاج إلى كل هذه المرونة والوظائف ؛ لماذا استخدام مكتبة خارجية عندما يتم تنفيذ كل شيء بالفعل باللغة نفسها ؛ إذا كان لديك بالفعل نظام الترجمة الخاص بك بتنسيقاته الخاصة ، فمن المحتمل ألا تعمل هذه المكتبة "كما هي" وستضطر إلى تعديلها على أي حال ؛ وفي النهاية ، فإن استخدام مكتبة تابعة لجهة خارجية ليس مثيرًا للاهتمام ومفيدًا مثل كيفية القيام بشيء بنفسك.
نقوم بصياغة المتطلبات الأساسية للمهمة التي يتم تنفيذها. هناك: أ) التسميات بتنسيق yaml: "label_name: translation text" ؛ يتم تحديد لغة الترجمة في اسم الملف ، على سبيل المثال ru.yml ؛ ب) قوالب البريد الإلكتروني في هتمل. من الضروري ، بناءً على معلمات الإدخال: الإعدادات المحلية ومجموعة البيانات ، إنشاء نص مترجم للرسالة.
ودعنا نبدأ ... ولكن أولاً ، بضع كلمات أخرى حول حزمة الرسائل (golang.org/x/text/message). إنه مصمم لتنسيق إخراج سلاسل مترجمة. تطبق الرسالة واجهة الحزمة fmt القياسية ويمكن أن تحل محلها. مثال للاستخدام:
message.SetString(language.Russian, "toxic", "") message.SetString(language.Japanese, "toxic", "毒性") message.NewPrinter(language.Russian).Println(“toxic”) message.NewPrinter(language.Japanese).Println(“toxic”)
لكي "ترى" العبوة ، يجب الإعلان عنها أولاً. في المثال ، يتم استخدام وظيفة SetString لهذا الغرض. بعد ذلك ، يتم إنشاء طابعة للغة المحددة ويتم عرض سلسلة مترجمة مباشرة.
لحل مشكلتنا ، يمكننا إنشاء ملف google به جميع العلامات ، لكن هذا ليس مناسبًا للغاية ، لأنه عند إضافة علامات جديدة ، سيتعين عليك إعادة إنشاء هذا الملف في كل مرة وإنشاء التطبيق مرة أخرى. هناك طريقة أخرى لإخبار رسالة عن علاماتنا وهي استخدام القواميس. القاموس هو عبارة عن بنية تنفذ واجهة البحث عن التصنيف Lookup (سلسلة المفاتيح) (سلسلة البيانات ، ok bool) .
خيار القواميس يناسبنا. أولاً ، نعرّف بنية القاموس ونطبق واجهة البحث الخاصة به:
type dictionary struct { Data map[string]string } func (d *dictionary) Lookup(key string) (data string, ok bool) { if value, ok := d.Data[key]; ok { return "\x02" + value, true } return "", false }
نقوم بتحليل جميع العلامات من ملفات yaml إلى مجموعة من القواميس ، وهي خريطة تنسيق القاموس [lang] * ، حيث lang هي علامة لغة بتنسيق BCP47 .
func parseYAMLDict() (map[string]catalog.Dictionary, error) { dir := "./translations" files, err := ioutil.ReadDir(dir) if err != nil { return nil, err } translations := map[string]catalog.Dictionary{} for _, f := range files { yamlFile, err := ioutil.ReadFile(dir + "/" + f.Name()) if err != nil { return nil, err } data := map[string]string{} err = yaml.Unmarshal(yamlFile, &data) if err != nil { return nil, err } lang := strings.Split(f.Name(), ".")[0] translations[lang] = &dictionary{Data: data} } return translations, nil }
نقوم بتثبيت مجموعة القواميس في دالة init بحيث يمكن استخدام القواميس بواسطة حزمة الرسائل عند بدء تشغيل التطبيق.
func init() { dict, err := parseYAMLDict() if err != nil { panic(err) } cat, err := catalog.NewFromMap(dict) if err != nil { panic(err) } message.DefaultCatalog = cat }
لذلك ، في الوقت الحالي ، حققنا توفر التوطين للعلامات من ملفاتنا في أي مكان في البرنامج:
message.NewPrinter(language.Russian).Println(“label_name”)
لقد حان الوقت للانتقال إلى الجزء الثاني من المهمة واستبدال التسميات المترجمة لدينا في قوالب البريد الإلكتروني. على سبيل المثال ، ضع في اعتبارك رسالة بسيطة - رسالة ترحيب عند تسجيل مستخدم:
مرحبا ، بيل سميث!
للتحليل ، نستخدم حزمة قياسية أخرى - html / template . عند تحليل القوالب في القالب ، يمكنك تعيين وظائفك من خلال .Funcs () :
template.New(tplName).Funcs(fmap).ParseFiles(tplName)
قم بإضافة وظيفة إلى القالب الذي سيقوم بترجمة الملصقات والمتغيرات البديلة فيها ، وسميها تترجم . رمز تحليل القالب:
قالب الرسالة الناتج. / قوالب / hello.html:
<!DOCTYPE html> <head> <title>{{translate "hello_subject"}}</title> </head> <body> {{translate "hello_msg" .Name .LastName}} </body> </html>
نظرًا لأننا في
الترجمة نستخدم وظيفة
Sprintf للترجمة ، سيتم خياطة المتغيرات في نص التسمية باستخدام بناء جملة هذه الوظيفة. على سبيل المثال ،
٪ s عبارة عن سلسلة ،
٪ d عبارة عن عدد صحيح.
ملفات الموسومة
en.yml
hello_subject: Greeting mail hello_msg: Hello, %s %s!
ru.yml
hello_subject: hello_msg: , %s %s!
في هذا ، من حيث المبدأ ، هذا كل شيء ، توطين الرسائل جاهز! بعد أن كتبنا بضع عشرات فقط من سطور التعليمات البرمجية ، حصلنا على وظائف قوية تجعل من الممكن ترجمة الأحرف بأي تعقيد بعشرات اللغات.
إذا كنت قد أحببت هذا المثال ، فيمكنك المضي قدمًا في تطبيق التعددية بشكل مستقل ، وذلك باستخدام أسماء المتغيرات للمتغيرات في التصنيفات بدلاً من ٪ s واستخدام الوظائف في التسميات. لم أقم بذلك عمداً من أجل ترك مجال لخيالك.
تتم كتابة التعليمات البرمجية في الأمثلة بشكل خاص لإظهار قدرات حزمة الرسائل ولا تدعي أنها مثالية ؛ قائمة كاملة من التعليمات البرمجية متوفرة على جيثب .