Django
Internationalisering
Sök…
Syntax
- gettext (meddelande)
- ngettext (singular, plural, number)
- ugettext (meddelande)
- ungettext (singular, plural, number)
- pgettext (sammanhang, meddelande)
- npgettext (sammanhang, singular, plural, nummer)
- gettext_lazy (meddelande)
- ngettext_lazy (singular, plural, number = None)
- ugettext_lazy (meddelande)
- ungettext_lazy (singular, plural, number = None)
- pgettext_lazy (sammanhang, meddelande)
- npgettext_lazy (sammanhang, singular, plural, nummer = inget)
- gettext_noop (meddelande)
- ugettext_noop (meddelande)
Introduktion till internationalisering
Ställer in
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',
]
Markera strängar som översättningsbara
Det första steget i översättningen är att markera strängar som översättningsbara . Detta överför dem genom en av gettext
(se syntaxavsnittet ). Till exempel är här en exempelmodeldefinition:
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"))
Alla strängar inkapslade i _()
är nu markerade som översättningsbara. När de skrivs ut kommer de alltid att visas som den inkapslade strängen, oavsett vilket språk du har valt (eftersom ingen översättning finns tillgänglig ännu).
Översätta strängar
Detta exempel räcker för att komma igång med översättning. För det mesta vill du bara markera strängar som översättningsbara för att förutse framtida internationalisering av ditt projekt. Således täcks detta i ett annat exempel .
Lazy vs Non-Lazy översättning
När du använder icke-lat översättning översätts strängar omedelbart.
>>> from django.utils.translation import activate, ugettext as _
>>> month = _("June")
>>> month
'June'
>>> activate('fr')
>>> _("June")
'juin'
>>> activate('de')
>>> _("June")
'Juni'
>>> month
'June'
När du använder latitet sker översättning endast när den faktiskt används.
>>> 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'
Du måste använda lat översättning i fall där:
- Översättning kanske inte aktiveras (språk har inte valts) när
_("some string")
utvärderas - Vissa strängar kan utvärderas endast vid uppstart (t.ex. i klassattribut såsom definitioner av modell- och formulärfält)
Översättning i mallar
För att aktivera översättning i mallar måste du ladda i18n
biblioteket.
{% load i18n %}
Grundläggande översättning görs med trans
.
{% trans "Some translatable text" %}
{# equivalent to python `ugettext("Some translatable text")` #}
trans
stöder sammanhang:
{% trans "May" context "month" %}
{# equivalent to python `pgettext("May", "month")` #}
Att inkludera platshållare i din översättningssträng, som i:
_("My name is {first_name} {last_name}").format(first_name="John", last_name="Doe")
Du måste använda blocktrans
:
{% blocktrans with first_name="John" last_name="Doe" %}
My name is {{ first_name }} {{ last_name }}
{% endblocktrans %}
I stället för "John"
och "Doe"
du naturligtvis ha variabler och filter:
{% blocktrans with first_name=user.first_name last_name=user.last_name|title %}
My name is {{ first_name }} {{ last_name }}
{% endblocktrans %}
Om first_name
och last_name
redan är i ditt sammanhang kan du till och med utelämna with
klausulen:
{% blocktrans %}My name is {{ first_name }} {{ last_name }}{% endblocktrans %}
Men bara "toppnivå" -kontextvariabler kan användas. Detta fungerar INTE:
{% blocktrans %}
My name is {{ user.first_name }} {{ user.last_name }}
{% endblocktrans %}
Detta beror främst på att variabelns namn används som platshållare i översättningsfiler.
blocktrans
accepterar också pluralisering.
{% blocktrans count nb=users|length }}
There is {{ nb }} user.
{% plural %}
There are {{ nb }} users.
{% endblocktrans %}
Slutligen, oavsett i18n
biblioteket, kan du överföra översättningsbara strängar till malltaggar med syntaxen _("")
.
{{ site_name|default:_("It works!") }}
{% firstof var1 var2 _("translatable fallback") %}
Detta är ett magiskt inbyggt django-mallssystem för att härma en syntax för funktionssamtal men detta är inte ett funktionssamtal. _("It works!")
Överfördes till default
som en sträng '_("It works!")'
Som sedan analyseras en översättningsbar sträng, precis som name
skulle tolkas som en variabel och "name"
skulle vara analyserad som en sträng.
Översätta strängar
För att översätta strängar måste du skapa översättningsfiler. För att göra detta, django fartyg med kommandot management makemessages
.
$ django-admin makemessages -l fr
processing locale fr
Ovanstående kommando upptäcker alla strängar markerade som översättningsbara i dina installerade appar och skapar en språkfil för varje app för fransk översättning. Om du till exempel bara har en app myapp
innehåller översättningsbara strängar skapar det en fil myapp/locale/fr/LC_MESSAGES/django.po
. Den här filen kan se ut som följande:
# 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 ""
Du måste först fylla i platshållarna (betonas med stora bokstäver). Översätt sedan strängarna. msgid
är strängen markerad som översättningsbar i din kod. msgstr
här måste du skriva översättningen av strängen rätt ovan.
När en sträng innehåller platshållare måste du också inkludera dem i din översättning. Till exempel översätter du det senaste meddelandet på följande sätt:
#: 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>"
När din översättningsfil är klar måste du sammanställa .po
filerna till .mo
filer. Detta görs genom att ringa compilemessages
management:
$ django-admin compilemessages
Det är det, nu finns översättningar tillgängliga.
För att uppdatera dina översättningsfiler när du gör ändringar i din kod kan du django-admin makemessages -l fr
. Detta kommer att uppdatera .po
filer, behålla dina befintliga översättningar och lägga till de nya. Raderade strängar kommer fortfarande att finnas tillgängliga i kommentarer. För att uppdatera .po
filer för alla språk, kör django-admin makemessages -a
. När dina .po
filer har uppdaterats, glöm inte att köra django-admin compilemessages
igen för att generera .mo
filer.
Noop användning fall
(u)gettext_noop
låter dig markera en sträng som översättningsbar utan att översätta den faktiskt.
Ett typiskt fall är när du vill logga in ett meddelande för utvecklare (på engelska) men också vill visa det till klienten (på det begärda språket). Du kan skicka en variabel till gettext
, men dess innehåll kommer inte att upptäckas som en översättningsbar sträng eftersom den per definition är variabel. .
# 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))
.po
visas inte i .po
filen och du måste komma ihåg att det finns för att lägga till det manuellt. För att fixa detta kan du använda gettext_noop
.
error_message = ugettext_noop("Oops, something went wrong!")
logger.error(error_message)
messages.error(request, _(error_message))
Nu strängen "Oops, something went wrong!"
kommer att upptäckas och finnas tillgängligt i .po
filen när den genereras. Och felet kommer fortfarande att loggas på engelska för utvecklare.
Vanliga fallgropar
fuzzy översättningar
Ibland kanske makemessages
tror att strängen den hittade för översättning är något liknande den redan existerade översättningen. Det kommer att .po
i .po
filen med en speciell fuzzy
kommentar som denna:
#: templates/randa/map.html:91
#, fuzzy
msgid "Country"
msgstr "Länderinfo"
Även om översättningen är korrekt eller om du har uppdaterat den för att korrigera den kommer den inte att användas för att översätta ditt projekt om du inte tar bort fuzzy
kommentarrad.
Multiline strängar
makemessages
analyserar filer i olika format, från vanlig text till pythonkod och det är inte utformat för att följa alla möjliga regler för att ha flera linjer i dessa format. För det mesta kommer det att fungera bra med enstaka strängar men om du har konstruktion som denna:
translation = _("firstline"
"secondline"
"thirdline")
Det kommer bara att ta upp första firstline
för översättning. Lösning för detta är att undvika att använda multiline strängar när det är möjligt.