Python adalah inti dari aplikasi terkenal di dunia seperti Youtube, Instagram dan Pinterest. Untuk maju di pasar dunia, aplikasi perlu pelokalan, yaitu adaptasi dengan karakteristik negara tertentu, dan internasionalisasi - terjemahan konten. Pada artikel ini, kami akan membagikan pengalaman kami tentang cara mempercepat otomasi terjemahan dan memecahkan beberapa masalah khas di bidang ini.

Pendahuluan
Ini adalah panduan singkat untuk menginternasionalkan (i18n) aplikasi python. Panduan ini akan menarik bagi semua programmer dengan pengalaman pengembangan python. Membaca sebuah artikel akan memakan waktu 10-15 menit.
Kami akan menggunakan alat gettext yang teruji termasuk dalam bahasa python.
Untuk memulainya, kita akan memahami apa itu internasionalisasi:
Internasionalisasi (I18N) adalah proses mengadaptasi aplikasi ke bahasa-bahasa di berbagai negara dan wilayah selain yang dikembangkan.
Tetapi ada juga konsep yang lebih luas:
Lokalisasi (L10N) adalah proses mengadaptasi aplikasi yang diinternasionalkan ke wilayah atau bahasa tertentu dengan menambahkan komponen khusus ke lokal yang diberikan dan menerjemahkan teks.
Pelokalan berarti terjemahan:
- format tanggal dan waktu;
- format angka;
- zona waktu
- sebuah kalender
- representasi mata uang;
- pajak / PPN;
- suhu dan tindakan lain;
- kode pos, telepon;
- pemformatan alamat;
- kode penyelesaian.

Pelokalan melampaui penerjemahan konten ke bahasa lain. Ada parameter budaya dan fungsional yang juga perlu diperhatikan. Sebagai contoh, format tanggal di Amerika Utara adalah "MM / DD / YYYY", tetapi di sebagian besar negara Asia ditulis sebagai "DD / MM / YYYY".
Contoh kesalahan terjemahan aplikasi yang terkenalContoh lain berkaitan dengan tampilan nama dalam aplikasi. Di Amerika Serikat, memanggil seseorang dengan nama dapat diterima dan bahkan lebih disukai, nama pelanggan ditampilkan di header segera setelah pelanggan masuk. Namun, di Jepang yang sebaliknya adalah benar: memanggil seseorang dengan nama tidak sopan atau bahkan ofensif. Pelokalan harus mempertimbangkan hal ini dan menghindari penggunaan nama untuk audiens Jepang.
Dalam artikel ini kami hanya akan mempertimbangkan internasionalisasi, tetapi mekanisme lokalisasi dibangun dengan cara yang sama. Perpustakaan yang disebutkan dalam artikel ini mendukung pelokalan aplikasi.
Jenis utama
Internasionalisasi dibagi menjadi:
- Terjemahan data secara langsung dalam skrip python.
- Terjemahan data di mesin templat.
- Terjemahan data disimpan dalam database.
1. Terjemahan data skrip python
Agar internasionalisasi kita berfungsi, kita perlu memahami perpustakaan babel dan toolkit distutils untuk mengelola perakitan proyek untuk dijual dan seterusnya.
Persiapan Terjemahan
Untuk memulainya, kita perlu membuat daftar terjemahan. Untuk mulai dengan, kami menginstal perpustakaan
Babel - ini adalah python-library yang diakui secara umum untuk melokalisasi dan mengkonversi tanggal, mata uang, dengan tambahan yang mudah untuk membangun proyek (dibahas di bawah).
Python menyediakan toolkit untuk multi bahasa - gettext. GNU gettext sebenarnya adalah solusi pelokalan universal yang menyediakan dukungan untuk bahasa pemrograman lain dalam pesan multibahasa. Gettext digunakan tidak hanya dalam banyak bahasa pemrograman, tetapi juga dalam terjemahan sistem operasi, ini adalah perangkat lunak yang teruji dengan baik dan didistribusikan secara bebas yang tersedia di
github .
Agar terjemahan berfungsi, Anda perlu mengimpor modul gettext dan meneruskan skrip dengan terjemahan ke input. Pertama, kami menandai semua string yang diterjemahkan dengan fungsi khusus _ ('some_text'). Panggilan ke fungsi ini dalam proyek akan terlihat seperti ini:
import gettext import os localedir = os.path.join(os.path.abspath('/path/to/locales'), 'locales') translate = gettext.translation('domain_name', localedir, ['ru']) _ = translate.gettext print(_('some_text')) print(_('some_text_2'))
Dalam sepotong kecil kode, buat objek internasionalisasi yang menggunakan direktori 'locales' sebagai sumber frasa yang diterjemahkan. Direktori 'locales' belum dibuat, tetapi di dalamnya aplikasi akan mencari terjemahan saat runtime.
Untuk singkatnya, fungsi translate.gettext akan dilambangkan sebagai _. Garis bawah adalah nama umum untuk fungsi ini, yang dikenali oleh komunitas Python.
Fungsi _ () menandai baris yang akan diterjemahkan. Modul gettext disertai dengan alat xgettext, yang mem-parsing penanda string _ () dengan kode dan membentuk Template Objek Portabel (pot-file). Untuk membuat file pot, mari kembali ke perpustakaan Babel yang terinstal, yang memiliki banyak fitur untuk mendukung internasionalisasi. Babel memperluas setup.py build script, yang dapat ditulis menggunakan pustaka python distutils standar atau paket setuptools pihak ketiga pilihan Anda. Perakitan modul Python berada di luar cakupan artikel kami, untuk lebih jelasnya, lihat
dokumentasi . Yang diperlukan hanyalah membuat file setup.py dengan konten berikut:
from babel.messages import frontend as babel from distutils.core import setup setup(name='foo', version='1.0', cmdclass = {'extract_messages': babel.extract_messages, 'init_catalog': babel.init_catalog, 'update_catalog': babel.update_catalog, 'compile_catalog': babel.compile_catalog,} )
Jadi, kami membuat instruksi untuk membangun proyek dan menambahkan empat tim internasionalisasi dari perpustakaan babel. Pertimbangkan perintah-perintah ini secara lebih rinci dalam urutan penggunaan.
extract_messagesPerintah ini adalah pembungkus di atas alat xgettext GNU, yang mem-parsing tag _ () diterjemahkan ke dalam file pot. Untuk menjalankan, Anda memerlukan beberapa pengaturan untuk perakitan. Untuk melakukan ini, di direktori root, buat file setup.cfg dengan konten:
[extract_messages] input_dirs = foobar output_file = foobar/locales/messages.pot
- input_dirs - nama direktori tempat semua label dalam kode _ () akan dipilih untuk terjemahan.
- output_file - path untuk file .pot yang dihasilkan
Untuk menjalankan perintah, jalankan di konsol:
$ python setup.py extract_messages
running extract_messages extracting messages from foobar/__init__.py extracting messages from foobar/core.py ... writing PO template file to foobar/locales/messages.pot
Dalam file pot, baris yang ditandai dikumpulkan dalam daftar dari mana penerjemah kemudian dapat membuat terjemahan untuk masing-masing bahasa yang diinginkan.
Selanjutnya, Anda perlu membuat terjemahan untuk beberapa bahasa. Untuk melakukan ini, gunakan perintah babel berikut.
init_catalogPerintah ini adalah pembungkus di atas alat GNU msginit, yang membuat direktori terjemahan baru berdasarkan file pot.
$ python setup.py init_catalog -l en -i foobar/locales/messages.pot \ -o foobar/locales/en/LC_MESSAGES/base.po
running init_catalog creating catalog 'foobar/locales/en/LC_MESSAGES/messages.po' based on 'foobar/locales/messages.pot'
Penting! File pelokalan disimpan dengan cara tertentu, sesuai dengan konvensi:
locales // LC_MESSAGES / .po
- direktori dengan terjemahan ke dalam bahasa tertentu, dalam kasus kami adalah bahasa Inggris (en). Mungkin juga ada direktori dengan terjemahan tidak hanya ke dalam bahasa tertentu, tetapi juga mempertimbangkan fitur tambahan akun. Misalnya, terjemahan bahasa Inggris untuk Amerika Serikat adalah en_US;
- domain dengan terjemahan. Jika aplikasi kita bertambah, terjemahan akan dibagi menjadi beberapa domain agar tidak terlalu membebani satu file.
update_catalogPerintah ini adalah pembungkus di atas alat GNU msgmerge, yang memperbarui direktori terjemahan yang ada untuk file * .po.
Saat menambahkan terjemahan baru, kami cukup menjalankan perintah:
$ python setup.py update_catalog -l en -i foobar/locales/messages.pot \ -o foobar/locales/en/LC_MESSAGES/base.po
running update_catalog updating catalog 'foobar/locales/en/LC_MESSAGES/base.po' based on 'foobar/locales/messages.pot'
Kami juga dapat menentukan lokalisasi dalam bahasa Rusia dengan menetapkan ru alih-alih en.
compile_catalogPerintah terakhir adalah pembungkus di atas alat GNU msgfmt. Dibutuhkan pesan yang dapat diterjemahkan dari file * .po dan mengkompilasinya menjadi file * .mo biner untuk mengoptimalkan kinerja.
$ python setup.py compile_catalog --directory foobar/locales --domain base
running compile_catalog compiling catalog to foobar/locales/en/LC_MESSAGES/base.mo
--directory - path ke direktori dengan pelokalan,
--domain - bendera untuk menentukan domain terjemahan, kami tentukan sesuai dengan domain aplikasi yang ada.
Skrip python hanya berfungsi dengan terjemahan * .mo yang dioptimalkan. Oleh karena itu, dengan perubahan apa pun, sehingga muncul dalam aplikasi, perlu untuk mengkompilasi ulang file dengan pelokalan. Untuk bekerja dengan file terjemahan, Anda dapat menggunakan aplikasi poedit - ini tersedia untuk semua sistem operasi dan perangkat lunak yang didistribusikan secara bebas.
poedit - aplikasi terjemahanSetiap terjemahan ditampilkan sebagai baris terpisah, dan ini nyaman. Setelah menyelesaikan pekerjaan dengan terjemahan, saat menyimpan perubahan, file biner * .mo dengan semua perubahan dikompilasi secara otomatis.
Akibatnya, struktur katalog terjemahan akan terlihat seperti ini:
locales ├── en │ └── LC_MESSAGES │ ├── base.mo │ └── base.po ├── ru │ └── LC_MESSAGES │ ├── base.mo │ └── base.po └── messages.pot
Konvensi Nama Penanda Terjemahanpo-file berisi terjemahan teks dan secara logis digabungkan menjadi file dengan nama umum. Grup-grup ini disebut domain. Dalam contoh di atas, hanya ada satu domain bernama basis. Dalam aplikasi besar, akan ada lebih banyak domain, dan daftar terjemahan perlu ditulis dengan mempertimbangkan struktur aplikasi.
Hal ini diperlukan untuk menjaga keseragaman nama token terjemahan untuk menghilangkan kebingungan lebih lanjut dalam terjemahan. Misalnya, kami memiliki formulir dengan menyimpan data pengguna di halaman profil pengguna:
profile.user_form.component.title: Data pengguna
profile.user_form.component.save: Simpan
profile.user_form.field.username: Nama pengguna
profile.user_form.field.password: Kata sandi
Penerapan AplikasiUntuk menyebarkan dan menggunakan aplikasi di buruh pelabuhan, Anda perlu mengkompilasi file terjemahan ke file * .mo biner menggunakan perintah berikut:
$ python setup.py compile_catalog --domain <>
Kami menyarankan untuk mengecualikan file * .mo dan * .pot di .gitignore:
# Terjemahan
* .mo
* .pot2. Terjemahan data di mesin templat
Dengan pelokalan dalam templating, semuanya menjadi sedikit lebih mudah. Pertimbangkan mesin template python paling populer - jinja. Untuk mesin template ini, dukungan untuk gettext-lokalisasi melalui add-on sudah diterapkan. Untuk mengaktifkan add-on, Anda harus menentukan jalur ke modul add-in di konstruktor Lingkungan. Untuk platform multibahasa, Anda perlu mengunduh terjemahan satu kali dan menambahkan objek terjemahan ke objek Lingkungan selama inisialisasi aplikasi:
translations = get_gettext_translations() env = Environment(extensions=['jinja2.ext.i18n']) env.install_gettext_translations(translations)
Kemudian dalam templat kita cukup menggunakan konstruk:
{{ gettext('some_text') }} {{ gettext('Hello %(name)s!')|format(name='World') }}
3. Terjemahan data yang disimpan dalam database
Mari kita pertimbangkan opsi untuk bekerja dengan terjemahan dalam database relasional yang paling umum. Perlu dicatat bahwa implementasi terjemahan dan lokalisasi untuk database noSQL dan newSQL serupa.
Catatan: kami tidak akan mempertimbangkan kasus ketika terjemahan untuk setiap bahasa disimpan dalam kolom terpisah. Implementasi seperti itu memerlukan pembatasan skala dan risiko lainnya dengan dukungan aplikasi lebih lanjut.
1) Baris terpisah untuk setiap bahasa
Dengan pendekatan ini, untuk setiap bahasa, terjemahan ke bahasa tertentu dalam baris didasarkan pada nilai kolom, misalnya language_code. Jika nilai en ada di kolom ini, maka semua nilai yang diterjemahkan harus merujuk ke negara dan wilayah tertentu.

Untuk skema yang dijelaskan, data dalam tabel akan terlihat seperti ini:
Keuntungan:- Implementasi yang sederhana dan efisien.
- Pertanyaan sederhana saat menggunakan kode bahasa tertentu.
Kerugian:Terjemahan ke berbagai bahasa dapat disimpan dalam tabel yang berbeda. Dengan demikian, Anda tidak tahu berapa banyak bahasa yang diterjemahkan sepenuhnya oleh aplikasi Anda.
Solusi ini cocok untuk aplikasi yang awalnya tidak memerlukan internasionalisasi penuh semua data. Tetapi dimungkinkan untuk menambahkan terjemahan untuk wilayah baru saat bisnis berkembang.
Permintaan data adalah sebagai berikut:
SELECT p.product_name, p.price, p.description FROM product p WHERE p.language_code = @language_code;
2) Pisahkan tabel dengan terjemahan
Dalam pendekatan ini, untuk setiap tabel yang membutuhkan pelokalan, kami membuat tabel dengan terjemahan.
Pro:- Tidak perlu bergabung dengan tabel untuk data yang tidak diterjemahkan.
- Kueri menjadi mudah karena ada tabel terpisah untuk terjemahan.
- Tidak ada perbedaan dalam data.
- Selain terjemahan, dimungkinkan untuk secara efektif melokalkan sisa data dalam tabel bahasa.
Kerugian:- Dalam aplikasi besar, tabel terjemahannya membengkak dan melambat. Saat mengoptimalkan aplikasi, akan perlu untuk mengimplementasikan migrasi data pada tabel terpisah.
Permintaan data adalah sebagai berikut:
SELECT tp.text, p.price, tc.text, c.contact_name FROM order_line o, product p, customer c, translation tp, translation tc, language l WHERE o.product_id = p.id AND o.customer_id = c.id AND p.name_translation_id = tp.id AND c.name_translation_id = tc.id AND tp.language_id = l.id AND tc.language_id = l.id AND l.name = @language_code AND o.id = ***;
3) Membuat entitas untuk bidang yang diterjemahkan dan yang tidak diterjemahkan
Dalam solusi ini, tabel entitas yang berisi satu atau beberapa bidang yang diterjemahkan memperluas data dengan yang tidak diterjemahkan.
Pro:- Tidak perlu menggabungkan tabel terjemahan dengan tabel yang berisi data yang tidak memerlukan terjemahan. Oleh karena itu, pengambilan sampel data tersebut akan memiliki kinerja yang lebih baik,
- Sangat mudah untuk menulis pertanyaan ORM,
- Permintaan SQL sederhana untuk mendapatkan teks yang diterjemahkan,
- Mudah untuk mendukung terjemahan data tertentu ke dalam semua bahasa yang tersedia.
Kerugian:- Kompleksitas relatif dari implementasi.
Berikut adalah contoh kueri yang akan mengambil teks yang diterjemahkan:
SELECT pt.product_name, pt.description, p.price FROM order_line o, product p, product_translation pt, language l WHERE o.product_id = p.id AND AND p.id = pt.product_non_trans_id AND pt.language_id = l.id AND l.name = @language_code;
Kesimpulan
Saat melokalkan dan menginternasionalkan aplikasi untuk pasar internasional, berbagai metode dapat digunakan, yang masing-masing memiliki fitur dan batasan tertentu.
Dalam artikel ini, kami memeriksa jenis internasionalisasi berikut:
- dalam kode: kami menggunakan terjemahan saat membuat layanan atau aplikasi dengan gui;
- dalam templat: kami gunakan saat mengembangkan aplikasi web tanpa antarmuka dinamis;
- dalam database: gunakan saat menyimpan data pengguna atau yang dihasilkan secara dinamis.
Kami berharap artikel kami akan membantu Anda memilih metode yang paling cocok untuk proyek Anda.