Μετάβαση¶
Αν το έργο σας χρησιμοποιεί ήδη gettext, τα ερωτήματα που κρίνουν αν αυτή η βιβλιοθήκη είναι υιοθετήσιμη είναι στενά: ακυρώνει τους καταλόγους που ήδη έχετε, μπορεί να συνυπάρξει με τον κώδικα που δεν είστε έτοιμοι να αλλάξετε, και πόσο μέρος της μετακίνησης πρέπει να γίνει μονομιάς. Οι απαντήσεις, με τη συντομότερη πρώτη:
| Ερώτηση | Απάντηση |
|---|---|
Δουλεύουν ακόμη τα υπάρχοντα αρχεία .po και .mo; |
Ναι. Ίδια αρχεία, ίδια εργαλεία. |
| Μπορούν παλιές και νέες κλήσεις να ζουν σε ένα αρχείο; | Ναι, και μία αντιστοίχιση εξαγωγέα καλύπτει και τις δύο. |
| Αλλάζει το msgid; | Όχι από το .format(). Ναι από το %-format. |
| Πρέπει να μετακινηθεί όλο το έργο μονομιάς; | Όχι. Ένα σημείο κλήσης είναι έγκυρη αλλαγή. |
| Τι γίνεται με το Jinja, τα πρότυπα του Django, τη JavaScript; | Μένουν ανέγγιχτα, με τους ίδιους καταλόγους. |
Το υπόλοιπο αυτής της σελίδας είναι η λεπτομέρεια πίσω από καθένα από αυτά.
Από το .format(): το msgid δεν αλλάζει¶
Αυτή είναι η περίπτωση όπου η μετάβαση δεν κοστίζει σχεδόν τίποτα. Ένα μήνυμα
str.format και ένα μήνυμα t-string παράγουν το ίδιο κλειδί καταλόγου,
επειδή και στις δύο περιπτώσεις το κλειδί είναι το κείμενο με το {name} να
παραμένει μέσα του:
# Before
_("Hello {name}").format(name=name)
# After — the msgid is still "Hello {name}"
tr(t"Hello {name}")
Έτσι η υπάρχουσα μετάφραση μένει προσαρτημένη. Ξεκινώντας από έναν κατάλογο που περιέχει
αλλάξτε την κλήση, ξανακάντε εξαγωγή και ενημερώστε:
$ 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
Η καταχώριση που επιστρέφει διαφέρει σε δύο γραμμές μεταδεδομένων και σε τίποτα άλλο — ένα σχόλιο-δείκτη που την ταυτοποιεί ως μήνυμα t-string, και έναν αριθμό γραμμής πηγής:
Καμία σημαία fuzzy, καμία επαναμετάφραση, σε καμία γλώσσα. Το μήνυμα
αποδίδεται αμέσως:
$ 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 θα αναφέρει τους καταλόγους ως ξεπερασμένους
Εκείνο το σχόλιο-δείκτης και οι μετακινημένοι αριθμοί γραμμών αρκούν για
να πει το pybabel update --check ότι ένας κατάλογος χρειάζεται
αναδημιουργία, επειδή συγκρίνει ολόκληρη την καταχώριση και όχι μόνο τη
μετάφραση. Τρέξτε το πραγματικό pybabel update στο ίδιο commit με την
αλλαγή του κώδικα, και κάντε commit τους καταλόγους μαζί του — η ίδια
συνήθεια που ζητά ήδη η πύλη CI.
Από το %-format: το msgid αλλάζει, οπότε οι μεταφράσεις γίνονται fuzzy¶
Η σύνταξη printf ζει μέσα στο μήνυμα, οπότε η αντικατάστασή της ξαναγράφει
το κλειδί του καταλόγου. Δεν υπάρχει τρόπος να το αποφύγετε, και αυτό είναι το
ειλικρινές κόστος του να αφήσετε πίσω σας το %(name)s:
Το pybabel update αναγνωρίζει το νέο μήνυμα ως στενό συγγενή εκείνου που
αφαιρέθηκε και μεταφέρει την παλιά μετάφραση, σημειωμένη ως fuzzy:
#. gettext-tstrings
#: app.py:4
#, fuzzy, python-brace-format, python-format
msgid "Hello {name}"
msgstr "こんにちは %(name)s"
Τρία πράγματα που πρέπει να ξέρετε για αυτή την κατάσταση:
- Τίποτα δεν σπάει κατά την εκτέλεση. Οι καταχωρίσεις fuzzy εξαιρούνται
από το μεταγλωττισμένο
.mo, οπότε η εφαρμογή αποδίδει το πηγαίο μήνυμα μέχρι κάποιος άνθρωπος να επιβεβαιώσει το ζεύγος — η ίδια υποβάθμιση από την οποία περνά κάθε μήνυμα που έχει αναδιατυπωθεί. - Το CI μένει πράσινο όσο είναι fuzzy. Ο ελεγκτής συμβόλων κράτησης θέσης
προσπερνά τις καταχωρίσεις fuzzy, ακριβώς όπως κάνει και το
msgfmt --check-format, επειδή μια καταχώριση που δεν μπορεί να φτάσει στην εκτέλεση δεν πρέπει να ρίχνει ένα build. Τη στιγμή που ένας μεταφραστής καθαρίζει τη σημαία, η καταχώριση ελέγχεται όπως κάθε άλλη — οπότε ένα%(name)sπου έχει μείνει σε μια επιβεβαιωμένη μετάφραση πιάνεται τότε, που είναι ακριβώς το σημείο στο οποίο θα άρχιζε αλλιώς να αποδίδεται. - Η παλιά σημαία
python-formatταξιδεύει μαζί και πρέπει να διαγραφεί μαζί με τη σημαίαfuzzy, αλλιώς τοmsgfmt --check-formatθα συνεχίσει να εφαρμόζει κανόνες printf σε ένα μήνυμα brace-format.
Για τα επώνυμα σύμβολα κράτησης θέσης του printf η επεξεργασία είναι μηχανική
— το %(name)s γίνεται {name} και τίποτα άλλο δεν μετακινείται — οπότε ένας
μεγάλος κατάλογος είναι ένα πέρασμα με σενάριο, ακολουθούμενο από την
αναθεώρηση ενός μεταφραστή, και όχι μια επαναμετάφραση. Το θεσιακό %s δεν
είναι μηχανικό: δεν έχει όνομα για να μεταφερθεί, και η επιλογή ενός ονόματος
είναι το νόημα της αλλαγής.
Η μετάβαση μπορεί επομένως να προχωρήσει με όποιον ρυθμό επιτρέπει η αναθεώρηση: μια αμετάτρεπτη καταχώριση fuzzy είναι ένα ορατό κομμάτι δουλειάς μέσα στον κατάλογο, όχι ένα σπασμένο build.
Παλιές και νέες κλήσεις συνυπάρχουν¶
Ο εξαγωγέας που διαβάζει t-strings διαβάζει και τις συνηθισμένες κλήσεις gettext, οπότε μία αντιστοίχιση καλύπτει ένα αρχείο στη μέση της μετάβασης:
from gettext_tstrings import tr
from myapp.i18n import _
name = "Ada"
print(_("Save changes"))
print(tr(t"Hello {name}"))
Και τα δύο μηνύματα προσγειώνονται στο ίδιο πρότυπο, και μόνο εκείνο του t-string κουβαλά το σχόλιο-δείκτη που ενεργοποιεί τον επιπλέον έλεγχο αυτής της βιβλιοθήκης:
#: app.py:5
msgid "Save changes"
msgstr ""
#. gettext-tstrings
#: app.py:6
#, python-brace-format
msgid "Hello {name}"
msgstr ""
Αναγνωρίζει την _(), τα τέσσερα τυπικά ονόματα του gettext, τα ψευδώνυμα
tr() / ntr() και τις αναβαλλόμενες lazy_gettext() / lazy_pgettext().
Μια δική σας βοηθητική συνάρτηση πρέπει να
κατονομαστεί στην αντιστοίχιση.
Κατά την εκτέλεση τα δύο στυλ είναι εξίσου ανεξάρτητα: η
gettext.translation() επιστρέφει ένα αντικείμενο μεταφράσεων, και τόσο η _
όσο και τα σημεία εισόδου αυτής της βιβλιοθήκης διαβάζουν από αυτό.
Τι δεν μετακινείται¶
- Οι γλώσσες προτύπων. Το
{% trans %}του Jinja2, οι ετικέτες προτύπων του Django και οι εξαγωγείς τους για το Babel συνεχίζουν να δουλεύουν αμετάβλητοι και να τροφοδοτούν τους ίδιους καταλόγους PO. Τα t-strings είναι σύνταξη της Python· ισχύουν για πηγαίο κώδικα Python. - Τα αρχεία καταλόγων σας. Καμία αλλαγή μορφότυπου, κανένα νέο αρχείο, κανένα βήμα μετατροπής.
- Η πλατφόρμα μετάφρασής σας. Η ανταλλαγή
.poείναι πανομοιότυπη, και η σημαίαpython-brace-formatπου κουβαλά ένα μήνυμα t-string είναι η ίδια σημαία που κουβαλά ένα μήνυμα.format()— οπότε ο έλεγχος ποιότητας συμβόλων κράτησης θέσης συνεχίζει να δουλεύει. - Ο κώδικας εκτός Python. Ένας κατάλογος JavaScript ή C στο ίδιο έργο δεν επηρεάζεται.
Μια λίστα ελέγχου μετάβασης¶
- Προσθέστε το extra
babelεκεί όπου τρέχει τοpybabel, και αλλάξτε την αντιστοίχισηpythonστοbabel.cfgστη μέθοδοgettext_tstrings— μία αντιστοίχιση καλύπτει τότε και τα δύο στυλ, και το-kσυνεχίζει να δουλεύει για τις συνηθισμένες κλήσεις. - Μετατρέψτε πρώτα τα σημεία κλήσης με
.format(). Ξανακάντε εξαγωγή, τρέξτεpybabel updateκαι κάντε commit τους καταλόγους μαζί με τον κώδικα· μην περιμένετε καμία καταχώριση fuzzy. - Μετατρέψτε τα σημεία κλήσης με
%-format σε παρτίδες που μπορείτε να περάσετε από αναθεώρηση, ξαναγράφοντας τα σύμβολα κράτησης θέσης που μεταφέρθηκαν και καθαρίζοντας τις σημαίεςfuzzyκαιpython-format. - Διορθώστε ό,τι απορρίπτει ο περιορισμός: μια παρεμβολή πρέπει να είναι ένα
απλό όνομα, οπότε το
t"Hello {user.name}"γίνεται πρώτα τοπική μεταβλητή. Αυτό είναι επεξεργασία στο σημείο κλήσης, όχι στον κατάλογο. - Ενεργοποιήστε το
strict = trueστην αντιστοίχιση του εξαγωγέα μόλις ολοκληρωθεί το πέρασμα, ώστε ένα μήνυμα που δεν μπορεί να εξαχθεί να ρίχνει το build αντί να εξαφανίζεται από το πρότυπο. - Προσθέστε τον έλεγχο χρόνου εκτέλεσης από το
Στην παραγωγή: αποδώστε ένα μήνυμα ανά γλώσσα
που αποστέλλεται, μέσα από έναν αυστηρό
Translator.
Τα βήματα 2 και 3 είναι συνηθισμένα commit. Τίποτα σε αυτή τη λίστα δεν χρειάζεται μια ημέρα-ορόσημο.