Ana içeriğe geç

Geçiş

Projeniz zaten gettext kullanıyorsa, bu kütüphanenin benimsenebilir olup olmadığına karar veren sorular dardır: elinizdeki katalogları geçersiz kılıyor mu, değiştirmeye hazır olmadığınız kodla bir arada yaşayabilir mi ve taşınmanın ne kadarı aynı anda olmak zorunda. Yanıtlar, en kısasından başlayarak:

Soru Yanıt
Var olan .po ve .mo dosyaları hâlâ çalışıyor mu? Evet. Aynı dosyalar, aynı araçlar.
Eski ve yeni çağrılar tek bir dosyada yaşayabilir mi? Evet; tek bir çıkarıcı eşlemesi ikisini de kapsar.
msgid değişiyor mu? .format()ten geçişte hayır. %-formattan geçişte evet.
Tüm proje aynı anda taşınmak zorunda mı? Hayır. Tek bir çağrı noktası geçerli bir değişikliktir.
Peki Jinja, Django şablonları, JavaScript? Dokunulmadan kalır, aynı kataloglar.

Sayfanın geri kalanı, bunların her birinin ardındaki ayrıntıdır.

.format()ten: msgid değişmez

Geçişin neredeyse hiçbir bedeli olmadığı durum budur. Bir str.format mesajı ile bir t-string mesajı aynı katalog anahtarını türetir; çünkü anahtar, her iki durumda da içinde {name} bırakılmış metindir:

# Before
_("Hello {name}").format(name=name)

# After — the msgid is still "Hello {name}"
tr(t"Hello {name}")

Böylece var olan çeviri bağlı kalır. Şunu tutan bir katalogdan başlayarak

#: app.py:6
#, python-brace-format
msgid "Hello {name}"
msgstr "こんにちは {name}"

çağrıyı değiştirin, yeniden çıkarın ve güncelleyin:

$ pybabel extract -F babel.cfg -o locales/messages.pot .
extracting messages from app.py (encoding="utf-8")
writing PO template file to locales/messages.pot
$ pybabel update -i locales/messages.pot -d locales
updating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot

Geri gelen girdi, iki satırlık üstveride ayrışır ve başka hiçbir yerde değil — onu bir t-string mesajı olarak tanımlayan bir işaret yorumu ve bir kaynak satır numarası:

#. gettext-tstrings
#: app.py:4
#, python-brace-format
msgid "Hello {name}"
msgstr "こんにちは {name}"

Hiçbir dilde ne fuzzy bayrağı ne de yeniden çeviri. Mesaj anında render edilir:

$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
$ python app.py
こんにちは Ada

update --check katalogları güncel değil diye raporlayacak

O işaret yorumu ve kayan satır numaraları, pybabel update --checkin bir kataloğun yeniden üretilmesi gerektiğini söylemesine yeter; çünkü yalnızca çeviriyi değil, girdinin tamamını karşılaştırır. Gerçek pybabel update komutunu kod değişikliğiyle aynı commit'te çalıştırın ve katalogları onunla birlikte commit'leyin — bu, CI kapısının zaten istediği alışkanlığın aynısıdır.

%-formattan: msgid değişir, çeviriler fuzzy olur

Printf sözdizimi mesajın içinde yaşar; dolayısıyla onu değiştirmek katalog anahtarını yeniden yazar. Bunun etrafından dolaşmanın yolu yoktur ve %(name)si geride bırakmanın dürüst bedeli budur:

# Before
_("Hello %(name)s") % {"name": name}

# After — a different msgid
tr(t"Hello {name}")

pybabel update, yeni mesajı kaldırılan mesajın yakın akrabası olarak tanır ve eski çeviriyi fuzzy işaretiyle karşıya taşır:

#. gettext-tstrings
#: app.py:4
#, fuzzy, python-brace-format, python-format
msgid "Hello {name}"
msgstr "こんにちは %(name)s"

Bu durum hakkında bilinmesi gereken üç şey:

  • Çalışma zamanında hiçbir şey bozulmaz. Fuzzy girdiler derlenmiş .mo dosyasının dışında bırakılır; böylece bir insan çifti onaylayana dek uygulama kaynak mesajı render eder — yeniden yazılmış her mesajın geçtiği aynı alçalma.
  • Onlar fuzzy'yken CI yeşil kalır. Yer tutucu denetleyicisi, tıpkı msgfmt --check-format gibi fuzzy girdileri atlar; çünkü çalışma zamanına ulaşamayan bir girdi bir derlemeyi düşürmemelidir. Bir çevirmen bayrağı temizlediği anda girdi diğerleri gibi denetlenir — yani onaylanmış bir çeviride kalmış bir %(name)s tam o noktada yakalanır; zaten render edilmeye başlayacağı nokta da orasıdır.
  • Eski python-format bayrağı da yolculuk eder ve fuzzy bayrağıyla birlikte silinmelidir; yoksa msgfmt --check-format brace-format bir mesaja printf kurallarını uygulamayı sürdürür.

Adlandırılmış printf yer tutucularında düzenleme mekaniktir — %(name)s, {name} olur ve başka hiçbir şey kımıldamaz — dolayısıyla büyük bir katalog, bir yeniden çeviri değil, betikle yapılan bir geçiş ve ardından bir çevirmen incelemesidir. Konumsal %s mekanik değildir: taşınacak bir adı yoktur ve bir ad seçmek, değişikliğin ta kendisidir.

Geçiş bu yüzden incelemenin izin verdiği hızda ilerleyebilir: dönüştürülmemiş bir fuzzy girdi, bozuk bir derleme değil, katalogda görünen bir iş parçasıdır.

Eski ve yeni çağrılar bir arada yaşar

t-string okuyan çıkarıcı, sıradan gettext çağrılarını da okur; dolayısıyla tek bir eşleme, geçişin ortasındaki bir dosyayı kapsar:

[gettext_tstrings: **.py]
encoding = utf-8
from gettext_tstrings import tr
from myapp.i18n import _

name = "Ada"
print(_("Save changes"))
print(tr(t"Hello {name}"))

Her iki mesaj da aynı şablona iner ve yalnızca t-string olanı, bu kütüphanenin ek denetimini açan işaret yorumunu taşır:

#: app.py:5
msgid "Save changes"
msgstr ""

#. gettext-tstrings
#: app.py:6
#, python-brace-format
msgid "Hello {name}"
msgstr ""

_() işlevini, dört standart gettext adını, tr() / ntr() takma adlarını ve ertelenmiş lazy_gettext() / lazy_pgettext() işlevlerini tanır. Kendi yardımcınızın eşlemede adlandırılması gerekir.

Çalışma zamanında iki tarz eşit ölçüde bağımsızdır: gettext.translation() tek bir çeviri nesnesi döndürür ve hem _ hem de bu kütüphanenin giriş noktaları ondan okur.

Taşınmayanlar

  • Şablon dilleri. Jinja2'nin {% trans %} yapısı, Django'nun şablon etiketleri ve onların Babel çıkarıcıları değişmeden çalışmayı sürdürür ve aynı PO kataloglarını beslemeye devam eder. t-string'ler Python sözdizimidir; Python kaynağına uygulanırlar.
  • Katalog dosyalarınız. Biçim değişikliği yok, yeni dosya yok, dönüştürme adımı yok.
  • Çeviri platformunuz. .po alışverişi birebir aynıdır ve bir t-string mesajının taşıdığı python-brace-format bayrağı, bir .format() mesajının taşıdığı bayrağın aynısıdır — dolayısıyla yer tutucu QA'sı çalışmayı sürdürür.
  • Python olmayan kod. Aynı projedeki bir JavaScript ya da C kataloğu etkilenmez.

Bir geçiş kontrol listesi

  1. pybabelın çalıştığı yere babel ekstrasını ekleyin ve babel.cfg içindeki python eşlemesini gettext_tstrings yöntemine çevirin — o zaman tek bir eşleme her iki tarzı da kapsar ve -k, sıradan çağrılar için çalışmayı sürdürür.
  2. Önce .format() çağrı noktalarını dönüştürün. Yeniden çıkarın, pybabel update çalıştırın ve katalogları kodla birlikte commit'leyin; fuzzy girdi beklemeyin.
  3. %-format çağrı noktalarını, inceletebileceğiniz gruplar hâlinde dönüştürün; karşıya taşınan yer tutucuları yeniden yazın ve fuzzy ile python-format bayraklarını temizleyin.
  4. Kısıtlamanın reddettiklerini düzeltin: bir interpolasyon yalın bir ad olmak zorundadır; yani t"Hello {user.name}" önce bir yerel değişkene dönüşür. Bu, bir katalog düzenlemesi değil, bir çağrı noktası düzenlemesidir.
  5. Süpürme bittiğinde çıkarıcı eşlemesinde strict = true ayarını açın; böylece çıkarılamayan bir mesaj şablondan yok olmak yerine derlemeyi düşürür.
  6. Üretimde sayfasındaki çalışma zamanı denetimini ekleyin: sevk edilen her dil için bir mesajı katı bir Translator üzerinden render edin.

  7. ve 3. adımlar sıradan commit'lerdir. Bu listedeki hiçbir şey bir bayrak günü gerektirmez.