Membuat aplikasi yang baik tidak mudah. Apapun aplikasi unik dan berguna yang Anda tulis, jika pengguna tidak menyukainya, maka, seperti kata mereka, Anda memiliki masalah besar. Kebanyakan orang tidak suka dan menakuti segala sesuatu yang mereka tidak mengerti. Seringkali, antarmuka pengguna dan huruf adalah ujung yang terlihat dari gunung es aplikasi Anda, sesuai dengan yang dievaluasi pengguna. Karena itu, lokalisasi semua yang dilihat pengguna sangat penting.
Ingat bagaimana sepuluh tahun yang lalu, ketika Internet baru saja mulai memasuki kehidupan massa, dan banyak dari raksasa TI saat ini berada dalam tahap kerdil pemula dengan beberapa lusin karyawan, itu dalam urutan hal untuk mengirim surat kepada pengguna dalam bahasa Inggris. Dan pengguna bersimpati dengan ini. Hari ini, ketika semuanya hadir di Internet dan Anda tidak perlu tujuh bentang di dahi Anda, memiliki pendidikan tinggi atau tahu bahasa Inggris untuk menggunakannya, itu dianggap bentuk yang buruk tidak mendukung lokalisasi dalam aplikasi Anda. Omong-omong, di perusahaan kami, lokalisasi semua teks UI sudah dilakukan dalam 20 bahasa dan daftar bahasa yang didukung terus bertambah.
In Go, seperti dalam bahasa yang agak muda, semua tren pengembangan web modern diimplementasikan pada tingkat paket dasar dan tidak memerlukan tambahan "menari dengan rebana". (Saya mulai belajar Go beberapa tahun yang lalu, tetapi saya masih ingat perasaan "menemukan kekuatan super" yang saya alami pada hari-hari pertama setelah mempelajari bahasa ini. Tampaknya sekarang saya dapat mewujudkan tugas apa pun dengan menulis hanya beberapa baris.)
Tentu saja, mereka juga tidak melewati lokalisasi di Go. Pelokalan di dalamnya tersedia secara praktis “out of the box” menggunakan paket dasar: golang.org/x/text/language , golang.org/x/text/message dan golang.org/x/text/feature/plural . Mari kita lihat betapa mudahnya dalam Go hanya dalam setengah jam, menggunakan paket-paket ini, Anda dapat mengimplementasikan tugas yang tidak sepele seperti pelokalan pesan.
Ke depan, saya akan mengatakan bahwa tujuan artikel ini terutama untuk menunjukkan kekuatan dan keindahan Go dan untuk menyoroti fitur dasar dari paket pesan untuk bekerja dengan pelokalan. Jika Anda mencari solusi untuk aplikasi produksi, Anda mungkin menginginkan perpustakaan di luar rak yang lebih baik . Kelebihan dari go-i18n adalah banyak bintang di github (di antaranya ada milik saya) dan fleksibilitas yang tinggi. Namun, ada beberapa argumen yang menentang penggunaannya: Anda mungkin tidak memerlukan semua fleksibilitas dan fungsionalitas itu; mengapa menggunakan perpustakaan eksternal ketika semuanya sudah diimplementasikan dalam bahasa itu sendiri; jika Anda sudah memiliki sistem terjemahan Anda sendiri dengan formatnya sendiri, perpustakaan ini "apa adanya" kemungkinan besar tidak akan berfungsi dan Anda harus memodifikasinya; dan, pada akhirnya, menggunakan perpustakaan pihak ketiga tidak semenarik dan informatif seperti bagaimana melakukan sesuatu sendiri.
Kami merumuskan persyaratan dasar untuk tugas yang sedang dilaksanakan. Ada: a) label dalam format yaml: "label_name: terjemahan teks" ; bahasa terjemahan ditentukan dalam nama file, misalnya ru.yml; b) templat email dalam html. Diperlukan, berdasarkan pada parameter input: lokal dan array data, untuk menghasilkan teks pesan yang dilokalkan.
Dan mari kita mulai ... Tapi pertama-tama, beberapa kata lagi tentang paket pesan (golang.org/x/text/message). Ini dirancang untuk memformat output string lokal. Pesan mengimplementasikan antarmuka paket fmt standar dan dapat menggantikannya. Contoh penggunaan:
message.SetString(language.Russian, "toxic", "") message.SetString(language.Japanese, "toxic", "毒性") message.NewPrinter(language.Russian).Println(“toxic”) message.NewPrinter(language.Japanese).Println(“toxic”)
Agar paket dapat "melihat" label, pertama-tama harus dinyatakan. Dalam contoh ini, fungsi SetString digunakan untuk ini. Selanjutnya, printer dibuat untuk bahasa yang dipilih dan string terlokalisasi ditampilkan secara langsung.
Untuk mengatasi masalah kami, kami dapat membuat file-go dengan semua tag, tetapi ini tidak terlalu nyaman, karena ketika Anda menambahkan tag baru, Anda harus membuat ulang file ini setiap kali dan membangun aplikasi lagi. Cara lain untuk memberi tahu pesan tentang tag kami adalah dengan menggunakan kamus. Kamus adalah struktur yang mengimplementasikan antarmuka pencarian label, pencarian (string kunci) (string data, ok bool) .
Opsi kamus cocok untuk kita. Pertama, kami mendefinisikan struktur kamus dan mengimplementasikan antarmuka Pencarian untuk itu:
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 }
Sparsim semua label dari file yaml ke dalam kumpulan kamus, yang merupakan peta [lang] * peta format kamus , di mana lang adalah tag bahasa dalam format 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 }
Kami menginstal koleksi kamus di fungsi init sehingga kamus dapat digunakan oleh paket pesan saat aplikasi dimulai.
func init() { dict, err := parseYAMLDict() if err != nil { panic(err) } cat, err := catalog.NewFromMap(dict) if err != nil { panic(err) } message.DefaultCatalog = cat }
Jadi, saat ini, kami telah mencapai ketersediaan pelokalan label dari file kami di mana saja dalam program ini:
message.NewPrinter(language.Russian).Println(“label_name”)
Saatnya untuk beralih ke bagian kedua dari tugas dan mengganti label lokal kami di templat email. Misalnya, pertimbangkan pesan sederhana - surat sambutan saat mendaftarkan pengguna:
Halo, Bill Smith!
Untuk parsing, kami menggunakan paket standar lain - html / template . Saat mem- parsing templat dalam templat, Anda dapat mengatur fungsi Anda melalui .Funcs () :
template.New(tplName).Funcs(fmap).ParseFiles(tplName)
Tambahkan fungsi ke template yang akan menerjemahkan label dan mengganti variabel di dalamnya, dan menyebutnya menerjemahkan . Kode parsing templat:
Templat surat yang dihasilkan ./templates/hello.html:
<!DOCTYPE html> <head> <title>{{translate "hello_subject"}}</title> </head> <body> {{translate "hello_msg" .Name .LastName}} </body> </html>
Karena dalam
menerjemahkan kami menggunakan fungsi
Sprintf untuk pelokalan, variabel dalam teks label akan dijahit menggunakan sintaks dari fungsi ini. Sebagai contoh,
% s adalah sebuah string,
% d adalah bilangan bulat.
File yang ditandai
en.yml
hello_subject: Greeting mail hello_msg: Hello, %s %s!
ru.yml
hello_subject: hello_msg: , %s %s!
Mengenai hal ini, pada prinsipnya, itu saja, lokalisasi surat sudah siap! Setelah menulis hanya beberapa lusin baris kode, kami mendapatkan fungsionalitas yang kuat yang memungkinkan untuk melokalkan huruf dengan kerumitan dalam berbagai bahasa.
Jika Anda menyukai contoh ini, Anda bisa melangkah lebih jauh dan secara mandiri menerapkan pluralisasi, menggunakan nama variabel untuk variabel dalam label, bukan % s dan menggunakan fungsi dalam label. Saya sengaja tidak melakukan ini untuk meninggalkan ruang untuk imajinasi Anda.
Kode dalam contoh ditulis khusus untuk menunjukkan kemampuan paket pesan dan tidak mengklaim sebagai yang ideal, daftar lengkap kode tersedia di github .