Skip to main content

Django i18n: Οδηγός διεθνοποίησης και μετάφρασης

Από το settings.py έως την παραγωγή: ρυθμίστε το σύστημα μετάφρασης του Django, δημιουργήστε αρχεία PO, διαχειριστείτε τους πληθυντικούς και αυτοματοποιήστε τις μεταφράσεις με AI.

1

Εγκαταστήστε και εξαγάγετε συμβολοσειρές

Το πλαίσιο i18n του Django είναι ενσωματωμένο — χρειάζεται απλώς να το ενεργοποιήσετε. Εγκαταστήστε το django-locale-chain για έξυπνες εναλλακτικές επιλογές γλώσσας και, στη συνέχεια, χρησιμοποιήστε το makemessages για να εξαγάγετε τις μεταφράσιμες συμβολοσειρές από τον κώδικα Python και τα πρότυπά σας σε αρχεία PO.

Το Django χρησιμοποιεί το GNU gettext στο παρασκήνιο. Η εντολή makemessages σαρώνει τον κώδικά σας για κλήσεις gettext και ετικέτες προτύπων και, στη συνέχεια, δημιουργεί αρχεία .po. Μετά τη μετάφραση, το compilemessages τα μετατρέπει σε δυαδικά αρχεία .mo για γρήγορη αναζήτηση κατά την εκτέλεση.
Terminal
pip install django-locale-chain
Terminal
# Extract all translatable strings from Python and template files
python manage.py makemessages -l de -l ja -l es -l fr

# After translating .po files, compile to .mo (binary)
python manage.py compilemessages

# Project structure after running makemessages:
# locale/
# ├── de/
# │   └── LC_MESSAGES/
# │       ├── django.po    <-- translate this
# │       └── django.mo    <-- compiled (auto-generated)
# ├── ja/
# │   └── LC_MESSAGES/
# │       ├── django.po
# │       └── django.mo
# └── es/
#     └── LC_MESSAGES/
#         ├── django.po
#         └── django.mo
2

Ρύθμιση παραμέτρων και middleware

Ενεργοποιήστε τη διεθνοποίηση στο settings.py ορίζοντας USE_I18N = True, καθορίζοντας τη λίστα των υποστηριζόμενων LANGUAGES και προσθέτοντας το LocaleMiddleware στη στοίβα MIDDLEWARE. Το LocaleMiddleware ανιχνεύει τη γλώσσα του χρήστη από το πρόθεμα του URL, τη συνεδρία, τα cookie ή την κεφαλίδα Accept-Language.

settings.py
# settings.py

from django.utils.translation import gettext_lazy as _

# Default language
LANGUAGE_CODE = 'en'

# Enable i18n
USE_I18N = True
USE_L10N = True

# Languages your site supports
LANGUAGES = [
    ('en', _('English')),
    ('de', _('German')),
    ('ja', _('Japanese')),
    ('es', _('Spanish')),
    ('fr', _('French')),
    ('pt-br', _('Brazilian Portuguese')),
]

# Where Django looks for .po files
LOCALE_PATHS = [
    BASE_DIR / 'locale',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',       # <-- enables i18n
    'locale_chain.middleware.LocaleChainMiddleware',    # <-- smart fallbacks
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Το LocaleMiddleware πρέπει να τοποθετείται μετά το SessionMiddleware, επειδή διαβάζει τη συνεδρία, και πριν από το CommonMiddleware. Αν τοποθετηθεί με λανθασμένη σειρά, η ανίχνευση γλώσσας αποτυγχάνει χωρίς προειδοποίηση και όλοι οι χρήστες βλέπουν το προεπιλεγμένο LANGUAGE_CODE.

Διεθνοποίηση URL

Χρησιμοποιήστε το i18n_patterns() για να προσθέτετε αυτόματα στα URL σας το πρόθεμα του ενεργού κωδικού γλώσσας. Έτσι, κάθε γλώσσα αποκτά τον δικό της χώρο ονομάτων URL (/en/about/, /de/about/), κάτι που βελτιώνει το SEO και επιτρέπει στους χρήστες να κοινοποιούν συνδέσμους για συγκεκριμένη γλώσσα.

urls.py
# urls.py
from django.conf.urls.i18n import i18n_patterns
from django.urls import path, include

urlpatterns = [
    # Non-localized URLs (API, admin, etc.)
    path('api/', include('api.urls')),
]

urlpatterns += i18n_patterns(
    # These get prefixed with the language code: /en/about/, /de/about/
    path('', include('myapp.urls')),
    path('admin/', admin.site.urls),
    prefix_default_language=False,  # Skip prefix for default language
)
3

Επισήμανση συμβολοσειρών για μετάφραση

Το Django παρέχει δύο κύριες συναρτήσεις μετάφρασης: τη gettext() (με ψευδώνυμο _()) για συμβολοσειρές που αξιολογούνται κατά την επεξεργασία ενός αιτήματος και τη gettext_lazy() για συμβολοσειρές που αξιολογούνται κατά την εισαγωγή. Στα πρότυπα, χρησιμοποιήστε τις ετικέτες {% trans %} και {% blocktrans %}.

Στα views (κώδικας Python)

views.py
from django.utils.translation import gettext as _
from django.utils.translation import ngettext
from django.http import HttpResponse

def greeting_view(request):
    # Simple translation
    welcome = _("Welcome to our site")

    # Translation with variables (Python string formatting)
    user_greeting = _("Hello, %(name)s!") % {"name": request.user.username}

    # Plurals
    count = request.user.order_set.count()
    order_text = ngettext(
        "You have %(count)d order.",
        "You have %(count)d orders.",
        count,
    ) % {"count": count}

    return HttpResponse(f"{welcome}<br>{user_greeting}<br>{order_text}")

Στα πρότυπα

templates/myapp/index.html
{# Load the i18n template tags #}
{% load i18n %}

{# Simple translation #}
<h1>{% trans "Welcome to our site" %}</h1>

{# Translation with variables #}
{% blocktrans with name=user.username %}
  Hello, {{ name }}!
{% endblocktrans %}

{# Plurals in templates #}
{% blocktrans count count=order_count %}
  You have {{ count }} order.
{% plural %}
  You have {{ count }} orders.
{% endblocktrans %}

{# Mark strings as translatable but don't output them (for attributes, etc.) #}
{% trans "Submit" as submit_label %}
<button type="submit">{{ submit_label }}</button>

Στα μοντέλα και τις φόρμες

models.py
from django.db import models
from django.utils.translation import gettext_lazy as _

class Product(models.Model):
    name = models.CharField(_("product name"), max_length=200)
    description = models.TextField(_("description"), blank=True)

    class Meta:
        verbose_name = _("product")
        verbose_name_plural = _("products")

    def __str__(self):
        return self.name

# IMPORTANT: Use gettext_lazy (_) for anything evaluated at import time:
# - Model field labels, verbose_name, help_text
# - Form field labels
# - Class-level attributes
# Use gettext for anything evaluated at request time:
# - View functions, template tags
Η χρήση της gettext() αντί της gettext_lazy() σε πεδία μοντέλων, ετικέτες φορμών ή χαρακτηριστικά επιπέδου κλάσης έχει ως αποτέλεσμα οι συμβολοσειρές να μεταφράζονται μία φορά κατά την εισαγωγή, όταν ξεκινά ο διακομιστής, αντί σε κάθε αίτημα. Η μετάφραση παγιώνεται στη γλώσσα που ήταν ενεργή κατά την εισαγωγή — συνήθως στο προεπιλεγμένο LANGUAGE_CODE.

Μορφή αρχείων PO

Μετά την εκτέλεση του makemessages, το Django δημιουργεί αρχεία .po (Portable Object) για κάθε γλώσσα. Αυτά περιέχουν ζεύγη msgid/msgstr. Μεταφράστε τις τιμές msgstr και, στη συνέχεια, εκτελέστε το compilemessages για να δημιουργήσετε τα δυαδικά αρχεία .mo που διαβάζει το Django κατά την εκτέλεση.

locale/de/LC_MESSAGES/django.po
# locale/de/LC_MESSAGES/django.po

msgid "Welcome to our site"
msgstr "Willkommen auf unserer Seite"

msgid "Hello, %(name)s!"
msgstr "Hallo, %(name)s!"

#, python-format
msgid "You have %(count)d order."
msgid_plural "You have %(count)d orders."
msgstr[0] "Sie haben %(count)d Bestellung."
msgstr[1] "Sie haben %(count)d Bestellungen."

msgid "product name"
msgstr "Produktname"

msgid "description"
msgstr "Beschreibung"

msgid "product"
msgstr "Produkt"

msgid "products"
msgstr "Produkte"

msgid "Submit"
msgstr "Absenden"
4

Διαχείριση πληθυντικών και μεταβλητών

Το Django χρησιμοποιεί τη ngettext() για τον σχηματισμό πληθυντικού, ακολουθώντας τους κανόνες πληθυντικού του GNU gettext. Κάθε γλώσσα ορίζει πόσους τύπους πληθυντικού διαθέτει και τον τύπο επιλογής της σωστής μορφής. Τα αρχεία PO το δηλώνουν μέσω μιας κεφαλίδας Plural-Forms.

Plural forms by language
# English: 2 forms (singular, plural)
msgid "%(count)d item"
msgid_plural "%(count)d items"
msgstr[0] "%(count)d item"
msgstr[1] "%(count)d items"

# German: 2 forms (singular, plural)
msgstr[0] "%(count)d Artikel"
msgstr[1] "%(count)d Artikel"

# Russian: 3 forms (one, few, many)
msgstr[0] "%(count)d товар"        # 1 item
msgstr[1] "%(count)d товара"       # 2-4 items
msgstr[2] "%(count)d товаров"      # 5+ items

# Arabic: 6 forms (zero, one, two, few, many, other)
msgstr[0] "لا عناصر"               # 0
msgstr[1] "عنصر واحد"              # 1
msgstr[2] "عنصران"                 # 2
msgstr[3] "%(count)d عناصر"        # 3-10
msgstr[4] "%(count)d عنصرًا"       # 11-99
msgstr[5] "%(count)d عنصر"         # 100+

# Japanese: 1 form (no plural distinction)
msgstr[0] "%(count)d個のアイテム"

# In Python code, always use ngettext:
from django.utils.translation import ngettext

msg = ngettext(
    "%(count)d item",
    "%(count)d items",
    count,
) % {"count": count}
Μη χρησιμοποιείτε ποτέ f-strings της Python ή .format() μέσα σε κλήσεις gettext. Το εργαλείο εξαγωγής μεταφράσεων δεν μπορεί να τα αναλύσει. Χρησιμοποιήστε τη μορφοποίηση παλαιού τύπου %(): _('Hello, %(name)s!') % {'name': name}. Έτσι διασφαλίζεται επίσης ότι οι μεταφραστές βλέπουν τα σύμβολα κράτησης θέσης στα προγράμματα επεξεργασίας PO.

Αυτοματοποιήστε τον έλεγχο ποιότητας των μεταφράσεων

Εντοπίστε κλειδιά που λείπουν και λανθασμένα placeholders πριν φτάσουν στην παραγωγή με το i18n-validate. Δοκιμάστε τη διεπαφή χρήστη με ψευδομεταφράσεις μέσω του i18n-pseudo, πριν φτάσουν οι πραγματικές μεταφράσεις.

Συνηθισμένες παγίδες

Σύγχυση μεταξύ gettext() και gettext_lazy()

Χρησιμοποιήστε τη gettext_lazy() (με εισαγωγή ως _) για πεδία μοντέλων, ετικέτες φορμών και κάθε χαρακτηριστικό επιπέδου κλάσης που αξιολογείται κατά την εισαγωγή. Χρησιμοποιήστε τη gettext() για συναρτήσεις view και κώδικα που εκτελείται κατά την επεξεργασία αιτημάτων. Η σύγχυσή τους παγιώνει τις μεταφράσεις στη γλώσσα εκκίνησης του διακομιστή.

Παράλειψη εκτέλεσης του compilemessages

Το Django διαβάζει αρχεία .mo (μεταγλωττισμένα) και όχι αρχεία .po. Αν επεξεργαστείτε ένα αρχείο .po και δεν εκτελέσετε 'python manage.py compilemessages', οι αλλαγές σας δεν θα εμφανιστούν. Προσθέστε το compilemessages στο script διάθεσής σας.

Το LOCALE_PATHS δεν έχει ρυθμιστεί

Αν το LOCALE_PATHS είναι κενό ή παραπέμπει σε λανθασμένο κατάλογο, το makemessages δημιουργεί τα αρχεία .po σε λάθος σημείο και το Django δεν μπορεί να τα βρει κατά την εκτέλεση. Ορίζετε πάντα LOCALE_PATHS = [BASE_DIR / 'locale'] και επαληθεύετε ότι ο κατάλογος υπάρχει.

Απουσία του i18n_patterns από τα URL

Χωρίς το i18n_patterns(), τα URL δεν έχουν πρόθεμα γλώσσας και το Django βασίζεται αποκλειστικά σε cookie και κεφαλίδες για την ανίχνευση γλώσσας. Αυτό βλάπτει το SEO, επειδή δεν υπάρχουν URL ανά γλώσσα, και εμποδίζει την αλλαγή γλώσσας μέσω URL. Περικλείστε τα μοτίβα URL που απευθύνονται στους χρήστες με το i18n_patterns().

Έξυπνη εναλλακτική επιλογή γλώσσας με το django-locale-chain

Το σύστημα μετάφρασης του Django χρησιμοποιεί απευθείας το LANGUAGE_CODE όταν λείπει μια περιφερειακή παραλλαγή. Ένας χρήστης με γλώσσα pt-BR βλέπει Αγγλικά ακόμη και όταν διαθέτετε μεταφράσεις pt-PT. Το django-locale-chain το διορθώνει εγκαθιστώντας αλυσίδες εναλλακτικής επιλογής στο gettext: για το pt-BR δοκιμάζεται το pt-PT και μετά το pt, προτού χρησιμοποιηθεί η προεπιλεγμένη γλώσσα σας.

settings.py
# settings.py -- Smart fallback with django-locale-chain
# pip install django-locale-chain

MIDDLEWARE = [
    # ...
    'django.middleware.locale.LocaleMiddleware',
    'locale_chain.middleware.LocaleChainMiddleware',  # after LocaleMiddleware
    # ...
]

# That's it! 75 built-in fallback chains are now active:
# pt-BR user → tries pt-PT → tries pt → falls back to LANGUAGE_CODE
# es-MX user → tries es-419 → tries es → falls back to LANGUAGE_CODE
# fr-CA user → tries fr → falls back to LANGUAGE_CODE

# Optional: customize specific chains
LOCALE_FALLBACK_CHAINS = {
    "pt-BR": ["pt-PT", "pt"],
    "es-MX": ["es-419", "es"],
    "fr-CA": ["fr"],
}

# Or configure programmatically in AppConfig.ready():
from locale_chain import configure

class MyAppConfig(AppConfig):
    name = "myapp"

    def ready(self):
        configure(overrides={"zh-Hant-HK": ["zh-Hant-TW", "zh-Hant"]})

Προτεινόμενη δομή έργου

Project Structure
myproject/
├── myproject/
│   ├── settings.py          # i18n config, MIDDLEWARE, LANGUAGES
│   ├── urls.py              # i18n_patterns for URL prefixing
│   └── wsgi.py
├── myapp/
│   ├── models.py            # gettext_lazy for field labels
│   ├── views.py             # gettext for request-time strings
│   └── templates/
│       └── myapp/
│           └── index.html   # {% load i18n %}, {% trans %}, {% blocktrans %}
├── locale/                  # Created by makemessages
│   ├── de/
│   │   └── LC_MESSAGES/
│   │       ├── django.po    # German translations
│   │       └── django.mo    # Compiled binary
│   ├── ja/
│   │   └── LC_MESSAGES/
│   │       ├── django.po
│   │       └── django.mo
│   └── es/
│       └── LC_MESSAGES/
│           ├── django.po
│           └── django.mo
├── manage.py
└── requirements.txt

Δοκιμάστε τώρα το i18n Agent

Αφήστε εδώ το αρχείο μετάφρασής σας

JSON, YAML, PO, XML, CSV, Markdown, Properties

ή κάντε κλικ για να επιλέξετε αρχείο

Γλώσσες-στόχοι

Δεν απαιτείται εγγραφήΆμεση εκτίμηση

Εναλλακτική επιλογή γλώσσας με το django-locale-chain

Όταν λείπει ένα κλειδί μετάφρασης από μια περιφερειακή γλώσσα όπως το pt-BR, το Django μεταβαίνει απευθείας στη γλώσσα του προτύπου αντί να ελέγξει πρώτα τη γονική γλώσσα pt.

Terminal
pip install django-locale-chain
Configuration
# settings.py
LOCALE_CHAINS = {
    'pt-BR': ['pt', 'es', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
}

MIDDLEWARE = [
    ...
    'django_locale_chain.middleware.LocaleChainMiddleware',
    ...
]

Δείτε τον οδηγό μας για την εναλλακτική επιλογή γλώσσας, όπου θα βρείτε την πλήρη λίστα των υποστηριζόμενων πλαισίων και των 75 ενσωματωμένων αλυσίδων. Learn more →

Συχνές ερωτήσεις