Zoeken…


Syntaxis

  • gettext (bericht)
  • ngettext (enkelvoud, meervoud, nummer)
  • ugettext (bericht)
  • ungettext (enkelvoud, meervoud, nummer)
  • pgettext (context, bericht)
  • npgettext (context, enkelvoud, meervoud, nummer)
  • gettext_lazy (bericht)
  • ngettext_lazy (enkelvoud, meervoud, aantal = geen)
  • ugettext_lazy (bericht)
  • ungettext_lazy (enkelvoud, meervoud, aantal = geen)
  • pgettext_lazy (context, bericht)
  • npgettext_lazy (context, enkelvoud, meervoud, aantal = geen)
  • gettext_noop (bericht)
  • ugettext_noop (bericht)

Inleiding tot internationalisering

Opzetten

settings.py

from django.utils.translation import ugettext_lazy as _

USE_I18N = True  # Enable Internationalization
LANGUAGE_CODE = 'en'  # Language in which original texts are written
LANGUAGES = [  # Available languages
    ('en', _("English")),
    ('de', _("German")),
    ('fr', _("French")),
]

# Make sure the LocaleMiddleware is included, AFTER SessionMiddleware
# and BEFORE middlewares using internationalization (such as CommonMiddleware)
MIDDLEWARE_CLASSES = [
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.locale.LocaleMiddleware',
   'django.middleware.common.CommonMiddleware',
]

Tekenreeksen markeren als vertaalbaar

De eerste stap bij het vertalen is het markeren van strings als vertaalbaar . Hiermee worden ze door een van de gettext functies geleid (zie het gedeelte Syntaxis ). Hier is bijvoorbeeld een voorbeeld van een modeldefinitie:

from django.utils.translation import ugettext_lazy as _
# It is common to import gettext as the shortcut `_` as it is often used
# several times in the same file.

class Child(models.Model):

    class Meta:
        verbose_name = _("child")
        verbose_name_plural = _("children")

    first_name = models.CharField(max_length=30, verbose_name=_("first name"))
    last_name = models.CharField(max_length=30, verbose_name=_("last name"))
    age = models.PositiveSmallIntegerField(verbose_name=_("age"))

Alle tekenreeksen ingekapseld in _() zijn nu gemarkeerd als vertaalbaar. Wanneer ze worden afgedrukt, worden ze altijd weergegeven als de ingekapselde tekenreeks, ongeacht de gekozen taal (omdat er nog geen vertaling beschikbaar is).

Tekenreeksen vertalen

Dit voorbeeld is voldoende om te beginnen met vertalen. Meestal wilt u alleen strings markeren als vertaalbaar om te anticiperen op toekomstige internationalisering van uw project. Dit wordt dus behandeld in een ander voorbeeld .

Luie versus niet-luie vertaling

Wanneer niet-luie vertalingen worden gebruikt, worden tekenreeksen onmiddellijk vertaald.

>>> from django.utils.translation import activate, ugettext as _
>>> month = _("June")
>>> month
'June'
>>> activate('fr')
>>> _("June")
'juin'
>>> activate('de')
>>> _("June")
'Juni'
>>> month
'June'

Bij luiheid vindt vertaling alleen plaats wanneer het daadwerkelijk wordt gebruikt.

>>> from django.utils.translation import activate, ugettext_lazy as _
>>> month = _("June")
>>> month
<django.utils.functional.lazy.<locals>.__proxy__ object at 0x7f61cb805780>
>>> str(month)
'June'
>>> activate('fr')
>>> month
<django.utils.functional.lazy.<locals>.__proxy__ object at 0x7f61cb805780>
>>> "month: {}".format(month)
'month: juin'
>>> "month: %s" % month
'month: Juni'

Je moet luie vertaling gebruiken in gevallen waarin:

  • Vertaling is mogelijk niet geactiveerd (taal niet geselecteerd) wanneer _("some string") wordt geëvalueerd
  • Sommige tekenreeksen kunnen alleen worden geëvalueerd bij het opstarten (bijv. In klasse-attributen zoals definities van model- en formuliervelden)

Vertaling in sjablonen

Om vertaling in sjablonen in te schakelen, moet u de i18n bibliotheek laden.

{% load i18n %}

Basisvertaling wordt gemaakt met de trans sjabloontag.

{% trans "Some translatable text" %}
{# equivalent to python `ugettext("Some translatable text")` #}

De trans sjabloontag ondersteunt context:

{% trans "May" context "month" %}
{# equivalent to python `pgettext("May", "month")` #}

Plaatsaanduidingen opnemen in uw vertaalreeks, zoals in:

_("My name is {first_name} {last_name}").format(first_name="John", last_name="Doe")

U moet de blocktrans sjabloontag gebruiken:

{% blocktrans with first_name="John" last_name="Doe" %}
  My name is {{ first_name }} {{ last_name }}
{% endblocktrans %}

Natuurlijk kun je in plaats van "John" en "Doe" variabelen en filters gebruiken:

{% blocktrans with first_name=user.first_name last_name=user.last_name|title %}
  My name is {{ first_name }} {{ last_name }}
{% endblocktrans %}

Als first_name en last_name zijn al in uw context, kunt u zelfs weglaten with clausule:

{% blocktrans %}My name is {{ first_name }} {{ last_name }}{% endblocktrans %}

Alleen contextvariabelen op het hoogste niveau kunnen worden gebruikt. Dit gaat niet werken:

{% blocktrans %}
    My name is {{ user.first_name }} {{ user.last_name }}
{% endblocktrans %}

Dit komt vooral omdat de variabelenaam als tijdelijke aanduiding wordt gebruikt in vertaalbestanden.

De blocktrans sjabloontag accepteert ook pluralisatie.

{% blocktrans count nb=users|length }}
    There is {{ nb }} user.
{% plural %}
    There are {{ nb }} users.
{% endblocktrans %}

Ten slotte kunt u, ongeacht de i18n bibliotheek, vertaalbare tekenreeksen doorgeven aan sjabloontags met de syntaxis _("") .

{{ site_name|default:_("It works!") }}
{% firstof var1 var2 _("translatable fallback") %}

Dit is een magisch ingebouwd django-sjabloonsysteem om een syntaxis van een functieoproep na te bootsen, maar dit is geen functieoproep. _("It works!") Doorgegeven aan de default als een tekenreeks '_("It works!")' Die vervolgens een vertaalbare tekenreeks wordt ontleed, net zoals de name zou worden ontleed als een variabele en "name" zou zijn ontleed als een string.

Tekenreeksen vertalen

Om strings te vertalen, moet u vertaalbestanden maken. Om dit te doen, wordt django geleverd met het managementcommando makemessages .

$ django-admin makemessages -l fr
processing locale fr

De bovenstaande opdracht ontdekt alle tekenreeksen die zijn gemarkeerd als vertaalbaar in uw geïnstalleerde apps en maakt voor elke app een taalbestand voor Franse vertaling. Als u bijvoorbeeld slechts één app myapp die vertaalbare tekenreeksen bevat, maakt dit een bestand myapp/locale/fr/LC_MESSAGES/django.po . Dit bestand kan er als volgt uitzien:

# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-07-24 14:01+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: myapp/models.py:22
msgid "user"
msgstr ""

#: myapp/models.py:39
msgid "A user already exists with this email address."
msgstr ""

#: myapp/templates/myapp/register.html:155
#, python-format
msgid ""
"By signing up, you accept our <a href=\"%(terms_url)s\" "
"target=_blank>Terms of services</a>."
msgstr ""

U moet eerst de tijdelijke aanduidingen invullen (benadrukt met hoofdletters). Vertaal vervolgens de tekenreeksen. msgid is de string gemarkeerd als vertaalbaar in uw code. msgstr is waar je de vertaling van de string hierboven moet schrijven.

Wanneer een string tijdelijke aanduidingen bevat, moet u deze ook in uw vertaling opnemen. U vertaalt bijvoorbeeld het laatste bericht als volgt:

#: myapp/templates/myapp/register.html:155
#, python-format
msgid ""
"By signing up, you accept our <a href=\"%(terms_url)s\" "
"target=_blank>Terms of services</a>."
msgstr ""
"En vous inscrivant, vous acceptez nos <a href=\"%(terms_url)s\" "
"target=_blank>Conditions d'utilisation</a>"

Zodra uw vertaling bestand is voltooid, moet u het compileren .po bestanden in .mo bestanden. Dit wordt gedaan door de opdracht compilemessages management aan te roepen:

$ django-admin compilemessages

Dat is alles, nu zijn vertalingen beschikbaar.

Om uw vertaalbestanden bij te werken wanneer u uw code wijzigt, kunt u django-admin makemessages -l fr . Hiermee worden .po bestanden bijgewerkt, uw bestaande vertalingen behouden en de nieuwe toegevoegd. Verwijderde tekenreeksen blijven beschikbaar in reacties. Om te updaten .po bestanden voor alle talen, run django-admin makemessages -a . Zodra uw .po bestanden zijn bijgewerkt, vergeet dan niet om django-admin compilemessages opnieuw uit te voeren om .mo bestanden te genereren.

Noop use case

(u)gettext_noop kunt u een string markeren als vertaalbaar zonder deze daadwerkelijk te vertalen.

Een typisch gebruik is wanneer u een bericht voor ontwikkelaars wilt loggen (in het Engels) maar dit ook aan de client wilt weergeven (in de gevraagde taal). U kunt een variabele doorgeven aan gettext , maar de inhoud ervan wordt niet ontdekt als een vertaalbare tekenreeks omdat deze per definitie variabel is. .

# THIS WILL NOT WORK AS EXPECTED
import logging 
from django.contrib import messages

logger = logging.getLogger(__name__)

error_message = "Oops, something went wrong!"
logger.error(error_message)
messages.error(request, _(error_message))

Het foutbericht verschijnt niet in het .po bestand en u moet onthouden dat het bestaat om het handmatig toe te voegen. Om dit op te lossen, kunt u gettext_noop .

error_message = ugettext_noop("Oops, something went wrong!")
logger.error(error_message)
messages.error(request, _(error_message))

Nu de string "Oops, something went wrong!" wordt ontdekt en beschikbaar in het .po bestand wanneer het wordt gegenereerd. En de fout wordt nog steeds in het Engels vastgelegd voor ontwikkelaars.

Veel voorkomende valkuilen

vage vertalingen

Soms denken makemessages dat de string die het voor vertaling heeft gevonden, enigszins lijkt op de reeds bestaande vertaling. Het zal bij het markeren in het .po bestand met een speciale fuzzy opmerking als deze:

#: templates/randa/map.html:91
#, fuzzy
msgid "Country"
msgstr "Länderinfo"

Zelfs als de vertaling correct is of als u deze hebt bijgewerkt om deze te corrigeren, wordt deze niet gebruikt om uw project te vertalen, tenzij u de fuzzy commentaarregel verwijdert.

Multiline snaren

makemessages ontleedt bestanden in verschillende formaten, van platte tekst tot python-code en het is niet ontworpen om alle mogelijke regels te volgen voor het hebben van meerdere regels in deze formaten. Meestal werkt het prima met tekenreeksen met één regel, maar als je zo'n constructie hebt:

translation = _("firstline"
"secondline"
"thirdline")

Het haalt alleen de eerste firstline voor vertaling. Oplossing hiervoor is om indien mogelijk het gebruik van multilijnstrings te vermijden.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow