Django翻译的正确设置方式是什么?

33
我在Django 1.6上遇到了翻译不起作用的问题。我已经将以下内容添加到我的settings.py文件中:
LANGUAGE_CODE = 'en-us'
ugettext = lambda s: s
LANGUAGES = (
    ('en', ugettext('English')),
    ('de', ugettext('German')),
)

还添加了中间件:
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

每当我在使用需要本地化的字符串时,也适用于我的*.py文件:

from django.utils.translation import ugettext_lazy as _

我的模板以以下内容开头:
{% extends "base.html" %}
{% load i18n %}

在模板中,我使用了trans占位符。例如。
<h1>{% trans "Register a tank" %}</h1>

我已经在locale/de/LC_MESSAGES/django.po中提供了翻译。
msgid "Register a tank"
msgstr "Einen neuen Tank anmelden"

我的浏览器设置为首先请求德语内容: 浏览器设置 我错过了什么吗?
附言:我目前对这个项目还不太熟悉,它托管在GitHub上: https://github.com/frlan/blankspot

实际上发生了什么?是显示英文吗?还是没有显示任何翻译? - Burhan Khalid
把下面的编程内容从英语翻译成中文。仅返回翻译过的文本。 - frlan
你是否设置了 USE_I18N = True - Seitaridis
同时激活:USE_I18N = TrueUSE_L10N = True - frlan
你使用u18n的URL模式吗? urlpatterns = i18n_patterns( - petkostas
目前还没有——据我理解,它应该可以正常工作。 - frlan
6个回答

53

settings.py 中添加 LOCALE_PATHS 并设置如下:

import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)

请注意,LOCALE_PATHS 必须是一个元组(查看路径末尾的逗号)。
现在基于 LOCALE_PATHSlocale 文件夹应该在您项目的根目录中。
并确保您从项目的根目录运行命令 django-admin.py makemessages -l dedjango-admin.py compilemessages
djPrj
  |
  +---> djPrj
  |
  +---> djApp
  |
  +---> locale
  |
  +---> templates

同时,按照这里的说明,将MIDDLEWARE_CLASSES重新排列,使其在SessionMiddleware之后、CommonMiddleware之前,加入LocaleMiddleware

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

重新启动你的服务 (python manage.py runserver),然后再次检查。


为确保您的本地化应用于Django管理页面并使用Django的默认django.mo文件,请执行以下测试:

首先,在项目的主要urls.py中,将patterns替换为i18n_patterns

from django.conf.urls.i18n import i18n_patterns

urlpatterns = i18n_patterns('',
    url(r'^admin/', include(admin.site.urls)),
    # ...
)

现在前往带有de前缀的管理页面,例如:http://127.0.0.1:8000/de/admin/ 并且管理页面应该显示为德语。

好的,你能够看到Django管理页面的德语版本吗?

同时也检查一下你的视图是否带有de前缀。


根据您的项目代码,有些句子没有在trans块中。请将它们放入其中:
{% trans "your sentence" %}

同时,在您的视图和模型代码中,必须使用ugettext_lazy而不是ugettext(请阅读这里这里)。

将此替换为:

from django.utils.translation import ugettext as _ 

使用:

from django.utils.translation import ugettext_lazy as _

现在一切都将正常工作。


@frlan,你能在Django的管理页面中看到德语吗?(我已经更新了我的答案) - Omid Raha
你可以将最小使用案例的代码项目上传到某个地方吗? - Omid Raha
成功了!我刚刚按照上述方法在settings.py中添加了LANGUAGESLOCALE_PATHS,并运行了django-admin.py compilemessages命令。然后访问http://127.0.0.1:8000/contact/,页面标题显示为“注册气瓶”,联系页面的页眉显示为“Kontaktiere uns”(我的浏览器设置首选请求德语内容)。 - Omid Raha
对于字段,您必须使用ugettext_lazy而不是ugettext。将from django.utils.translation import ugettext as _替换为from django.utils.translation import ugettext_lazy as _ - Omid Raha
1
我的错。忘记更新那个特定的文件了。现在看起来好像可以工作了!耶。非常感谢。 - frlan
显示剩余6条评论

4

在我的情况下,我使用en-gb作为参数运行

django-admin.py makemessages -l en-gb

然而,正确的应该是en_GB。

django-admin.py makemessages -l en_GB


2
请在 django.po 文件中设置 已翻译的字符串,然后使用 python manage.py compilemessages 命令进行编译。
for e.g 

#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr "put appropriate translated string here"

建议:您可以使用 django-rosetta 软件包从 UI 界面添加 已翻译的字符串 。在 django-admin 中添加 T-字符串很容易。 https://github.com/mbi/django-rosetta


我已经完成了这个(并在那一刻更新了问题——错过了那个。抱歉)。 - frlan
你是否添加了Django视图来设置语言,并添加了HTML下拉代码以将语言传递给该视图? - Nilesh
只是按照我上面提到的做了。我的想法是Django自己确定语言。(在边界内) - frlan
但是django-rosetta看起来非常好。 - frlan

2

检查 cookies 和 session -- 根据 Django 如何发现语言偏好,流程如下:

  1. 在 URL 中使用 i18n_patterns 时的语言前缀
  2. 当前用户会话中的 _language 键
  3. django_language cookie(或由 settings.LANGUAGE_COOKIE_NAME 指定)
  4. Accept-Language HTTP header(这是您的浏览器设置发送的内容)
  5. settings.LANGUAGE_CODE

由于您的浏览器设置偏好 'de',我怀疑 LocaleMiddleware 在前面的步骤 1-3 中做出了不同的决定。


1

例如下面这样,你可以把 英文 翻译成 法文。*我使用的是 Django 4.2.3。

首先,按照下面的方法,在 django-project 目录下创建一个 locale 文件夹。*你可以查看 我的答案 来了解如何设置模板:

django-project
 |-core
 |  |-settings.py
 |  └-urls.py
 |-my_app1
 |  |-views.py
 |  |-urls.py
 |  |-models.py
 |  |_admin.py
 |  └-apps.py
 |-my_app2
 |-templates
 |  └-index.html  
 └-locale # Here

然后,将core/settings.py设置如下。* LocaleMiddleware必须位于SessionMiddlewareCommonMiddleware之间。'en-us'默认设置为LANGUAGE_CODEcore/settings.py中:
# "core/settings.py"

MIDDLEWARE = [
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware', # Here
    'django.middleware.common.CommonMiddleware',
    ...
]

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True

from django.utils.translation import gettext_lazy as _

LANGUAGES = ( # Here
    ('en', _('English')),
    ('fr', _('French'))
)

并且,HelloWorld被翻译为gettext()并在控制台上输出,index.htmlmy_app1/views.pytest()中呈现如下。*您可以查看我的答案,解释何处使用gettext()gettext_lazy()

# "my_app1/views.py"

from django.shortcuts import render
from django.utils.translation import gettext as _

def test(request):
    print(_("Hello"), _("World")) # Here
    return render(request, 'index.html')

而且,在下面所示的my_app1/urls.py中,test()路径被设置为urlpatterns。*您可以查看我的问题我的答案,了解如何在Django中翻译URL:
# "my_app1/urls.py"

from django.urls import path
from . import views

app_name = "my_app1"

urlpatterns = [
    path('', views.test, name="test") # Here
]

而且,adminmy_app1路径在core/urls.py中使用i18n_patterns()设置为urlpatterns,如下所示。*您可以查看我的问题我的答案来解释i18n_patterns()中的prefix_default_language=False
# "core/urls.py"

from django.contrib import admin
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns

urlpatterns = i18n_patterns(
    path('admin/', admin.site.urls), # Here
    path('my_app1/', include('my_app1.urls')) # Here
)

而且,在templates/index.py中设置了3个标签,如下所示。*在Django模板中进行翻译时,需要使用{% load i18n %},并且可以使用{% translate %}{% trans %}进行翻译:

# "templates/index.py"

{% load i18n %}

{% translate "Hello" %} {% trans "World" %}

而且,在my_app1/models.py中,name字段和person模型的翻译如下所示:
# "my_app1/models.py"

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

class Person(models.Model):
    first_name = models.CharField(
        max_length=20, verbose_name=_("first name") # Here
    )
    last_name = models.CharField(
        max_length=20, verbose_name=_("last name") # Here
    )

    class Meta:
        verbose_name = _('person') # Here
        verbose_name_plural = _('persons') # Here

这是我的my_app1/admin.py文件的内容:
# "my_app1/admin.py"

from django.contrib import admin
from .models import Person

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    pass

而且,my_app1my_app1/apps.py 中被翻译如下所示:

# "my_app1/apps.py"

from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _

class MyApp1Config(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'my_app1'
    verbose_name = _('my_app1') # Here

现在,运行下面的命令。*你可以点击我的回答来解释下面的命令:
django-admin makemessages -l fr

然后,将 django.polocale/fr/LC_MESSAGES/ 中创建如下所示:
django-project
 |-core
 |  |-settings.py
 |  └-urls.py
 |-my_app1
 |  |-views.py
 |  |-urls.py
 |  |-models.py
 |  |_admin.py
 |  └-apps.py
 |-my_app2
 |-templates
 |  └-index.html  
 └-locale
    └-fr
       └-LC_MESSAGES
          └-django.po # Here

然后,在locale/fr/LC_MESSAGES/django.po中的每个msgstr ""分别添加BonjourMondeAnglaisFrançais,如下所示:
# "locale/fr/LC_MESSAGES/django.po"

...

#: .\core\settings.py:140
msgid "English"
msgstr "Anglais" # Here

#: .\core\settings.py:141
msgid "French"
msgstr "Français" # Here

#: .\my_app1\apps.py:7
msgid "my_app1"
msgstr "mon_app1" # Here

#: .\my_app1\models.py:6
msgid "first name"
msgstr "prénom"

#: .\my_app1\models.py:7
msgid "last name"
msgstr "nom de famille"

#: .\my_app1\models.py:13
msgid "person"
msgstr "personne"

#: .\my_app1\models.py:14
msgid "persons"
msgstr "personnes"

#: .\my_app1\views.py:5 .\templates\index.html:3
msgid "Hello"
msgstr "Bonjour" # Here

#: .\my_app1\views.py:5 .\templates\index.html:3
msgid "World"
msgstr "Monde" # Here

...

然后,运行以下命令将django.po编译为django.mo。*您可以查看我的答案来了解下面的命令的解释:
django-admin compilemessages

然后,django.polocale/fr/LC_MESSAGES/ 中被编译成 django.mo,如下所示:
django-project
 |-core
 |  |-settings.py
 |  └-urls.py
 |-my_app1
 |  |-views.py
 |  |-urls.py
 |  |-models.py
 |  |_admin.py
 |  └-apps.py
 |-my_app2
 |-templates
 |  └-index.html
 └-locale
    └-fr
       └-LC_MESSAGES
          |-django.po
          └-django.mo # Here

现在,http://localhost:8000/zh/my_app1/ 可以如下所示显示 你好,世界

enter image description here

以下是在控制台上输出的代码:Hello World
Hello World

而且,http://localhost:8000/fr/my_app1/ 可以如下所示显示 Bonjour Monde

enter image description here

并且,在控制台上输出Bonjour Monde

Bonjour Monde

而且,http://localhost:8000/en/admin/my_app1/person/add/ 可以显示如下所示的 Django Admin 的英文版本,包括应用程序、模型和字段标签:

enter image description here

而且,http://localhost:8000/fr/admin/my_app1/person/add/ 可以显示Django Admin的法语版本,包括下面所示的应用程序、模型和字段标签:

enter image description here

此外,您在浏览器中将语言设置为英语,如下所示。*这是Google Chrome

enter image description here

现在,如果您访问http://localhost:8000/my_app1/,则会被重定向到下面所示的http://localhost:8000/en/my_app1/

enter image description here

而且,您将浏览器中的语言设置为第一种语言,如下所示:法语

enter image description here

现在,如果您访问 http://localhost:8000/my_app1/,那么您将被重定向到下面的地址:http://localhost:8000/fr/my_app1/

enter image description here

此外,您可以从core/urls.py中的adminmy_app1路径中删除i18n_patterns(),如下所示:
# "core/urls.py"

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('my_app1/', include('my_app1.urls'))
]

# urlpatterns = i18n_patterns(
#     path('admin/', admin.site.urls), # Here
#     path('my_app1/', include('my_app1.urls')) # Here
# )

然后,您在浏览器中将English设置为第一语言,如下所示:

enter image description here

现在,http://localhost:8000/my_app1/ 可以如下所示显示 Hello World

enter image description here

并且,你在浏览器中将 法语 设置为第一语言,如下所示。

enter image description here

现在,http://localhost:8000/my_app1/ 可以如下所示显示 Bonjour Monde

enter image description here

最后,你可以根据我的回答中的链接1链接2来轻松创建一个用于Django和Django Admin的i18n切换器

0
你需要在设置中启用LocaleMiddleware,以便告诉Django基于浏览器设置进行语言检测。更改语言偏好会有效地设置Accept-Language标头。您可能需要在隐身窗口中检查,因为其他语言检测方式具有更高的优先级,例如用户会话和django_language cookie。

已经激活了。我刚刚更新了帖子。但还是谢谢你的提示。 - frlan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接