Χρήση msgctxt: Προσθήκη Πλαισίου στις Μεταφράσεις Gettext

Μεταφράζετε την αγγλική λέξη «Book» στα Γερμανικά και ο μεταφραστής σας επιστρέφει με σιγουριά «Buch». Τρεις εβδομάδες αργότερα, καταφθάνει μια αναφορά σφάλματος: το κουμπί «Book a table» στη φόρμα κράτησης σας γράφει τώρα «Buch a table» – το ουσιαστικό, όχι το ρήμα. Η λέξη ήταν σωστή. Το πλαίσιο έλειπε. Αυτή είναι μια από τις πιο συνηθισμένες σιωπηλές αποτυχίες στην τοπική προσαρμογή λογισμικού, και η λύση υπάρχει στο Gettext εδώ και δεκαετίες: msgctxt.
Αν έχετε παραδώσει ποτέ μια μετάφραση όπου μια ενιαία αγγλική συμβολοσειρά ήταν σωστή σε ένα σημείο και ακατανόητη σε άλλο, τότε έχετε αντιμετωπίσει το πρόβλημα της ασάφειας. Η ίδια λέξη πηγής αντιστοιχεί σε διαφορετικές μεταφράσεις ανάλογα με το πού εμφανίζεται. Χωρίς το msgctxt, ο μεταφραστής (άνθρωπος ή AI) δεν έχει τρόπο να διακρίνει αυτές τις περιπτώσεις, επειδή το μόνο που βλέπει είναι η απλή συμβολοσειρά msgid "Book". Αυτός ο οδηγός εξηγεί πώς λειτουργεί το msgctxt στο Gettext, πώς να επισημάνετε τον πηγαίο κώδικά σας με _x() και _ex(), πώς εμφανίζεται στα αρχεία .po σας, και γιατί μια διοχέτευση μετάφρασης με επίγνωση του πλαισίου είναι ο μόνος αξιόπιστος τρόπος για να αποδοθούν σωστά αυτές οι συμβολοσειρές σε μεγάλη κλίμακα.
Το Πρόβλημα της Ασάφειας: Μια Λέξη, Πολλές Σημασίες
Η φυσική γλώσσα είναι γεμάτη λέξεις που συμπτύσσονται σε ένα ενιαίο αγγλικό token αλλά διαχωρίζονται σε πολλές λέξεις σε άλλες γλώσσες. Ο μεταφραστής βλέπει μόνο την αρχική συμβολοσειρά, οπότε όταν δύο άσχετα στοιχεία UI μοιράζονται την ίδια αγγλική λέξη, μοιράζονται το ίδιο msgid – και το Gettext τα συγχωνεύει σε μία καταχώριση.
Λέξεις που διαχωρίζονται σε διαφορετικές γλώσσες
Εξετάστε τρία κλασικά παραδείγματα:
- «Book» – το ουσιαστικό (ένα αντικείμενο σε ένα ράφι) έναντι του ρήματος («Book a flight»). Γερμανικά: Buch έναντι buchen.
- «Post» – δημοσίευση περιεχομένου έναντι αποστολής αλληλογραφίας. Γαλλικά: publier έναντι courrier.
- «Order» – μια ακολουθία/ταξινόμηση έναντι μιας αγοράς. Ισπανικά: orden έναντι pedido.
Στα Αγγλικά, ο κώδικάς σας χρησιμοποιεί την ίδια ακριβή συμβολοσειρά και στις δύο θέσεις:
// Somewhere in a library catalog screen
echo __( 'Book', 'mytextdomain' );
// Somewhere in a reservation form button
echo __( 'Book', 'mytextdomain' );
Πώς πανομοιότυπες συμβολοσειρές συμπτύσσονται σε μία καταχώριση
Όταν εκτελείτε wp i18n make-pot ή xgettext, και οι δύο κλήσεις συμπτύσσονται σε μία καταχώριση .po:
#: catalog.php:42 reservation-form.php:88
msgid "Book"
msgstr ""
Υπάρχει ακριβώς ένα msgstr για συμπλήρωση. Ό,τι κι αν επιλέξει ο μεταφραστής, μία από τις δύο οθόνες θα είναι λάθος. Ο μεταφραστής δεν μπορεί να το διορθώσει αυτό ακόμα κι αν κατανοεί το πρόβλημα, επειδή η ίδια η μορφή δεν του επιτρέπει να παρέχει δύο μεταφράσεις για ένα msgid. Η ασάφεια είναι ενσωματωμένη στα δεδομένα.
Τι είναι το msgctxt και πώς διευκρινίζει;
Το msgctxt είναι μια συμβολοσειρά πλαισίου που συνδέεται με μια καταχώριση μετάφρασης. Η σύντομη απάντηση: προσθέτει ένα δεύτερο κλειδί δίπλα στο msgid, έτσι το Gettext αντιμετωπίζει το (context, msgid) ως ένα μοναδικό ζεύγος. Δύο καταχωρίσεις με το ίδιο msgid αλλά διαφορετικό msgctxt γίνονται δύο ξεχωριστές, ανεξάρτητα μεταφράσιμες συμβολοσειρές.
Στο μοντέλο αναζήτησης του Gettext, μια μετάφραση κανονικά κλειδώνεται μόνο από την αρχική συμβολοσειρά. Με το msgctxt, το κλειδί γίνεται ο συνδυασμός πλαισίου συν την αρχική συμβολοσειρά. Αυτός είναι ολόκληρος ο μηχανισμός, και γι' αυτό λειτουργεί τόσο καθαρά: δεν αλλάζετε το εμφανιζόμενο κείμενο, αλλά μόνο το εσωτερικό κλειδί αναζήτησης.
Η γραμμή msgctxt σε ένα αρχείο .po
Σε ένα αρχείο .po, το πλαίσιο εμφανίζεται στη δική του γραμμή ακριβώς πάνω από το msgid:
#: catalog.php:42
msgctxt "noun"
msgid "Book"
msgstr "Buch"
#: reservation-form.php:88
msgctxt "verb"
msgid "Book"
msgstr "Reservieren"
Τώρα υπάρχουν δύο καταχωρίσεις. Έχουν πανομοιότυπες τιμές msgid αλλά διακριτές τιμές msgctxt, οπότε η καθεμία αποκτά το δικό της msgstr. Ο κατάλογος αποδίδει Buch. το κουμπί κράτησης αποδίδει Reservieren. Το runtime επιλέγει το σωστό επειδή ο κώδικάς σας του είπε ποιο πλαίσιο να χρησιμοποιήσει.
Συγκρίνετε το με την προβληματική έκδοση με μία μόνο καταχώριση παραπάνω. Η διαφορά δεν είναι η ποιότητα της μετάφρασης – είναι αν το μοντέλο δεδομένων επιτρέπει καν να υπάρχει η σωστή απάντηση.
Σήμανση του Κώδικά σας: _x() και _ex()
Για να εκπέμψετε το msgctxt στο πρότυπό σας .po, καλείτε μια λειτουργία μετάφρασης με επίγνωση του πλαισίου αντί για την απλή. Στο WordPress αυτές είναι οι _x() και η αδελφή της που κάνει echo _ex(). στο ακατέργαστο Gettext αντιστοιχούν στο pgettext().
Επιλογή μεταξύ _x() και _ex()
Η απλή συνάρτηση __() λαμβάνει τη συμβολοσειρά και το πεδίο κειμένου. Η παραλλαγή με πλαίσιο εισάγει το πλαίσιο ως το δεύτερο όρισμα:
// Without context - ambiguous
__( 'Book', 'mytextdomain' );
// With context - the second argument is the msgctxt
_x( 'Book', 'noun', 'mytextdomain' ); // returns the translated string
_ex( 'Book', 'verb', 'mytextdomain' ); // echoes it directly
// Real-world disambiguation
_x( 'Post', 'verb: publish content', 'mytextdomain' );
_x( 'Post', 'noun: mail item', 'mytextdomain' );
_x( 'Order', 'sequence or sorting', 'mytextdomain' );
_x( 'Order', 'customer purchase', 'mytextdomain' );
Το δεύτερο όρισμα είναι η ετικέτα πλαισίου. Δεν εμφανίζεται ποτέ στους χρήστες σας – υπάρχει καθαρά για να διευκρινίσει, τόσο για την αναζήτηση του Gettext όσο και για όποιον (ή ό,τι) κάνει τη μετάφραση. Γράψτε τα πλαίσια ως σύντομες, περιγραφικές υποδείξεις: 'noun', 'verb', 'button label', 'admin menu'. Ένα ασαφές πλαίσιο όπως '1' είναι τεχνικά έγκυρο αλλά άχρηστο για έναν μεταφραστή.
Όταν αναγεννάτε το πρότυπο, ο εξολκέας αναγνωρίζει αυτές τις κλήσεις και εκπέμπει τη γραμμή msgctxt. Εργαλεία όπως το Poedit και άλλοι επεξεργαστές PO ομαδοποιούν στη συνέχεια τις καταχωρίσεις ορατά ανά πλαίσιο, έτσι ώστε ένας ανθρώπινος μεταφραστής να βλέπει αμέσως ότι το «Book (noun)» και το «Book (verb)» είναι δύο διαφορετικές εργασίες. Αν εξακολουθείτε να ρυθμίζετε την αλυσίδα εργαλείων εξαγωγής σας ή παλεύετε με τον τρόπο που οι μεταβλητές αλληλεπιδρούν με αυτές τις συμβολοσειρές, ο οδηγός μας για τη μετάφραση αρχείων PO χωρίς να χαλάσετε τις μεταβλητές κώδικα καλύπτει τη γύρω ροή εργασίας σε βάθος.
Γιατί Αδαείς Μεταφραστές – και Πολλά Εργαλεία AI – το Κάνουν Λάθος
Εδώ είναι το δυσάρεστο μέρος. Η προσθήκη του msgctxt στην πηγή σας είναι απαραίτητη αλλά όχι επαρκής. Το πλαίσιο βοηθάει μόνο αν αυτό που κάνει τη μετάφραση το διαβάζει πραγματικά.
Ο τρόπος αποτυχίας λόγω απορριφθέντος πλαισίου
Ένα αδαές script μαζικής μετάφρασης κάνει το εξής: επαναλαμβάνει τις καταχωρίσεις, αρπάζει κάθε msgid, το στέλνει σε ένα API μετάφρασης και γράφει το αποτέλεσμα στο msgstr. Δεν κοιτάζει ποτέ τη γραμμή msgctxt. Έτσι, παρόλο που γράψατε προσεκτικά _x( 'Book', 'noun' ) και _x( 'Book', 'verb' ), το script στέλνει δύο πανομοιότυπα αιτήματα – «translate Book» – και επικολλά την ίδια απάντηση και στα δύο. Όλη η προσπάθεια σήμανσης απορρίπτεται στο τελευταίο βήμα.
Πολλά εργαλεία μετάφρασης AI γενικού σκοπού έχουν το ίδιο τυφλό σημείο. Είναι κατασκευασμένα για να μεταφράζουν κείμενο, και το msgctxt είναι μεταδεδομένα, όχι κείμενο. Αν το εργαλείο ισοπεδώσει το .po σας σε μια λίστα συμβολοσειρών πριν το στείλει στο μοντέλο, το πλαίσιο δεν φτάνει ποτέ στην προτροπή του μοντέλου. Το μοντέλο, στερούμενο οποιουδήποτε σήματος, καταλήγει στην πιο στατιστικά κοινή έννοια της λέξης – συνήθως το ουσιαστικό για το «Book», την έννοια «δημοσίευση» για το «Post» – και μεταφράζει σιωπηλά λάθος τη μειοψηφική περίπτωση. Δεν θα δείτε ένα σφάλμα. Θα δείτε μια αναφορά σφάλματος από έναν Γερμανό χρήστη εβδομάδες αργότερα.
Το Πλαίσιο και οι Πληθυντικοί έχουν την ίδια Βασική Αιτία
Εδώ είναι επίσης που διασταυρώνονται ο χειρισμός πληθυντικών και το πλαίσιο, επειδή και τα δύο εξαρτώνται από την κατανόηση της δομής του Gettext από το εργαλείο αντί να αντιμετωπίζει το αρχείο ως απλό κείμενο. Αν οι συμβολοσειρές σας περιλαμβάνουν επίσης μορφές που βασίζονται σε καταμέτρηση, η ίδια δομική επίγνωση έχει σημασία – την αναλύουμε στον οδηγό κατανόηση των πληθυντικών του Gettext.
Πώς μια διοχέτευση με επίγνωση του πλαισίου χρησιμοποιεί το msgctxt
Μια διοχέτευση μετάφρασης που σέβεται το msgctxt κάνει το αντίθετο από το αδαές script. Αναλύει το αρχείο .po ως δομημένα δεδομένα, διατηρεί το πλαίσιο κάθε καταχώρισης συνδεδεμένο με την αρχική του συμβολοσειρά, και περνάει αυτό το πλαίσιο στην AI ως μέρος της προτροπής – έτσι το μοντέλο γνωρίζει ότι μεταφράζει το «Book» συγκεκριμένα ως ρήμα, όχι αφηρημένα.
Το πλαίσιο ως σήμα πρώτης κατηγορίας
Αυτός είναι ακριβώς ο τρόπος με τον οποίο το SimplePoTranslate προσεγγίζει το πρόβλημα. Η AI με επίγνωση του πλαισίου του διαβάζει τη γραμμή msgctxt ως ένα σήμα πρώτης κατηγορίας: όταν δύο καταχωρίσεις μοιράζονται ένα msgid αλλά διαφέρουν στο πλαίσιο, μεταφράζονται ως οι ξεχωριστές συμβολοσειρές που πραγματικά είναι, και η υπόδειξη πλαισίου ενημερώνει την επιλογή λέξεων του μοντέλου. Το αποτέλεσμα είναι ότι το «Book (noun)» επιστρέφει ως Buch ενώ το «Book (verb)» επιστρέφει ως buchen ή reservieren – αυτόματα, χωρίς να χρειάζεται να διορθώνετε με το χέρι κάθε ασαφή όρο.
Εξίσου σημαντικό, η διοχέτευση διατηρεί τη γραμμή msgctxt στην έξοδο. Ένα λιγότερο ισχυρό εργαλείο μπορεί να αφαιρέσει το πλαίσιο κατά τη διάρκεια της αμφίδρομης μετάφρασης, συγχωνεύοντας αθόρυβα τις δύο καταχωρίσεις σας σε μία και επανεισάγοντας την ασάφεια στην επόμενη συγχώνευση. Η Πλήρης υποστήριξη Gettext σημαίνει ότι το πλαίσιο επιβιώνει της μετάφρασης, της μεταγλώττισης του .mo, και τυχόν μεταγενέστερων επανεισαγωγών – έτσι η αποσαφήνισή σας είναι ανθεκτική, όχι μια εφάπαξ χειροκίνητη επιδιόρθωση. Σε συνδυασμό με το Syntax Locking για τους placeholders μέσα σε αυτές τις συμβολοσειρές, λαμβάνετε μεταφράσεις που είναι τόσο πλαισιακά σωστές όσο και δομικά άθικτες.
Εξακολουθείτε να έχετε την ιδιοκτησία της απόφασης σήμανσης – μόνο εσείς γνωρίζετε ότι ένα συγκεκριμένο «Book» είναι ρήμα. Αλλά μόλις έχετε σχολιάσει την πηγή σας με _x() και _ex(), μια διοχέτευση με επίγνωση του πλαισίου μετατρέπει αυτή τη σχολιασμό σε σωστές μεταφράσεις σε κάθε γλώσσα-στόχο χωρίς να χρειάζεται επίβλεψη ανά συμβολοσειρά.
Συμπέρασμα
Το πρόβλημα της ασάφειας – μία αγγλική λέξη, πολλές σημασίες – δεν είναι μια ιδιομορφία που μπορείτε να αγνοήσετε. είναι ένα δομικό χαρακτηριστικό του τρόπου με τον οποίο το Gettext αποθηκεύει τις συμβολοσειρές. Η λύση είναι το msgctxt: σχολιάστε ασαφείς συμβολοσειρές στην πηγή σας με _x() και _ex(), δώστε σε κάθε εμφάνιση μια σαφή ετικέτα πλαισίου και αφήστε το Gettext να κλειδώσει τη μετάφραση στο ζεύγος (context, msgid). Αυτό το μέρος είναι δική σας ευθύνη, και διαρκεί λίγα λεπτά.
Το πιο δύσκολο μέρος είναι να βεβαιωθείτε ότι το βήμα μετάφρασης σας πραγματικά τιμά αυτό το πλαίσιο αντί να το απορρίπτει. Αδαείς scripts και εργαλεία AI μόνο κειμένου απορρίπτουν το msgctxt και επανεισάγουν ακριβώς το σφάλμα που προσπαθούσατε να αποτρέψετε. Μια διοχέτευση με επίγνωση του πλαισίου διαβάζει το πλαίσιο, μεταφράζει σωστά κάθε αποσαφηνισμένη καταχώριση και το διατηρεί μέσω της μεταγλώττισης και των επανεισαγωγών.
Είστε έτοιμοι να σταματήσετε να παραδίδετε μεταφράσεις που αγνοούν το πλαίσιο; Δοκιμάστε το SimplePoTranslate δωρεάν — δεν απαιτείται πιστωτική κάρτα. Η δωρεάν βαθμίδα χειρίζεται πραγματικά αρχεία
.poκαι.potμε πλήρη υποστήριξη πλαισίου msgctxt, έτσι οι αποσαφηνισμένες συμβολοσειρές σας μεταφράζονται σωστά από την πρώτη φορά.