我花了几个小时搜索这个网站和其他网站,并阅读了Django文档,但我还没有找到解决我的Django翻译问题的方法。我应该补充一点,我是一个Django新手,如果我做些傻事,请提前道歉。
我正在使用Django 1.10和Python 3.5.2。
我的情况
我的应用程序的每个注册用户都将分配一个语言代码。此代码将存储在django.contrib.auth.models
User
模型的扩展中(所以UserExtend
模型,1-1映射到User
)。当用户登录时,我想阅读此语言代码,从而将用户访问的所有页面翻译成该语言。为此,我正在激活翻译并将语言代码存储在会话变量中。但是,我发现在用户登录并重定向到另一个页面后,字符串不会被翻译。如果我登录用户但省略了重定向代码(即只是再次显示登录页面),字符串 已翻译(我通过创建language_code
'de-DE'
的用户来检查并使用_de前缀创建和编译虚拟翻译),但只要我使用我的菜单去其他地方,我们就会再次回到英语。
我的假设:
LocaleMiddleware
尝试通过以下算法确定用户的语言偏好:首先,它在请求的URL中查找语言前缀。只有在根
i18n_patterns
中使用URLconf
函数时才会执行此操作。有关语言前缀以及如何国际化URL模式的详细信息,请参阅国际化:URL模式。如果失败,它会在当前用户的会话中查找
LANGUAGE_SESSION_KEY
密钥。如果失败,它会查找
cookie
。 (所以,我不得不将cookie标记为代码,因为编辑不会让我发布,除非我这样做....)使用的Cookie名称由
LANGUAGE_COOKIE_NAME
设置设置。 (默认名称为django_language
。)如果失败,它会查看Accept-Language HTTP标头。此标头由您的浏览器发送,并按优先级顺序告诉服务器您喜欢哪种语言。 Django尝试在标题中使用每种语言,直到找到具有可用翻译的语言。
如果失败,则使用全局
LANGUAGE_CODE
设置。
由此,我相信我应该能够使用会话实现我的项目的全局翻译,而不是i18n_patterns
。
同样来自Django doc(https://docs.djangoproject.com/en/1.10/topics/i18n/translation/#explicitly-setting-the-active-language),显然下面的代码应足以保留我的翻译语言。
from django.utils import translation
user_language = 'fr'
translation.activate(user_language)
request.session[translation.LANGUAGE_SESSION_KEY] = user_language
似乎没有这样做。请注意,如果我将这样的代码添加到我的所有视图的顶部,那么实际上我确实会保留翻译,除非我的模板嵌入了一个表单。表格似乎并不了解请求,所以他们似乎总是保留英文翻译。
我的代码:
settings.py:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'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',
]
# Authentication
## Not sure if these two are necessary, but one of the many tutorials I've been looking at suggested I do them.
LOGIN_REDIRECT_URL = '/' # It means home view
LOGIN_URL = 'login'
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE = 'en-AU'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = (
('en', _('English')),
('de', _('German')),
)
base.html中菜单的定义
<div class="nav navbar-nav pull-md-right">
{% if user.is_authenticated %}
{# Translators: Welcome message, of the form "Welcome, [user's first name] [user's surname]!" #}
<span class="nav-item nav-link text-muted">{% blocktrans with first_name=user.first_name last_name=user.last_name %}Welcome, {{ first_name }} {{ last_name }}!{% endblocktrans %}</span>
<a class="nav-item nav-link" href="{% url 'logout' %}">{% trans "Sign out" %}</a>
{% else %}
<a class="nav-item nav-link" href="#">{% trans "Register" %}</a>
<a class="nav-item nav-link" href="{% url 'login' %}">{% trans "Sign in" %}</a>
{% endif %}
</div>
的login.html:
{% extends 'appname/base.html' %}
{% load staticfiles %}
{% load i18n %}
{% block title_block %}{% trans "Sign in" %}{% endblock %}
{% block header_block %}
<link href="{% static 'css/login.css' %}" rel="stylesheet">
{% endblock %}
{% block body_block %}
<div class="container">
{% if form.errors %}
<div class="form-signin alert-danger">
<!-- Display this message even for an inactive account. -->
{% trans "Your login details were invalid. Please try again." %}
</div>
{% endif %}
{% if next %}
<div class="form-signin alert-danger">
{% if user.is_authenticated %}
{% trans "Your account doesn't have access to this page. To proceed, please login with an account that has access." %}
{% else %}
{% trans "Please log in to see this page." %}
{% endif %}
</div>
{% endif %}
<form class="form-signin" method="post" action="{% url 'login' %}">
{% csrf_token %}
<h2 class="form-signin-heading">{% trans "Please sign in" %}</h2>
{{ form.username.label_tag}}
{{ form.username }}
{{ form.password.label_tag}}
{{ form.password }}
<div class="checkbox">
<!-- Not yet implemented. Probably stick this into the form as well. -->
<label>
<input type="checkbox" value="remember-me"> {% trans "Remember me" %}
</label>
</div>
<div class="">
Forgot login
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">{% trans "Sign in" %}</button>
<input type="hidden" name="next" value="{{ next }}" />
</form>
</div>
{% endblock %}
views.py:
from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.utils import translation
from django.utils.translation import LANGUAGE_SESSION_KEY
from django import forms
from appname.forms import LoginForm
def index(request):
# Hack. I'm sure this is not the right thing to do.
user_language = request.session.get(LANGUAGE_SESSION_KEY)
translation.activate(user_language)
# Do stuff
return render(request, 'appname/index.html', context=context_dict)
def login_user(request):
user_language = request.session.get(LANGUAGE_SESSION_KEY)
translation.activate(user_language)
if request.method == "POST":
form = LoginForm(request, data=request.POST)
username = request.POST['username']
password = request.POST['password']
if form.is_valid():
fw_username = form.cleaned_data['username']
fw_password = form.cleaned_data['password']
user = authenticate(username=fw_username, password=fw_password)
if user is not None and user.is_active:
login(request, user)
user_language = user.extended.language_code.language_code
translation.activate(user_language)
request.session[LANGUAGE_SESSION_KEY] = user_language
return HttpResponseRedirect('/')
else:
form = LoginForm() # Display unbound form
return render(request, 'appname/login.html', { 'form': form })
def us(request):
# Hack. I'm sure this is not the right thing to do.
user_language_code = request.session.get(LANGUAGE_SESSION_KEY)
translation.activate(user_language_code)
return render(request, 'appname/us.html')
项目/ urls.py:
from django.conf.urls import url, include
from django.conf.urls.static import static
from django.conf import settings
from django.contrib import admin
from django.contrib.auth import views as auth_views
from appname import views
from appname.forms import LoginForm
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^appname/', include('appname.urls')), # Any URLs starting with appname are to be handled by the mindatot app
# url(r'^login/$', auth_views.login, {'template_name': 'appname/login.html', 'authentication_form': LoginForm}, name='login'),
url(r'^login/$', views.login_user, name='login'),
url(r'^logout/$', auth_views.logout, {'next_page': 'login'}, name='logout'),
url(r'^admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
forms.py:
from django.contrib.auth.forms import AuthenticationForm
from django import forms
from django.utils import translation
from django.utils.translation import ugettext as _
# If you don't do this you cannot use Bootstrap CSS
class LoginForm(AuthenticationForm):
# I'm confused. How do I translate this one?
#user_language = session.get(LANGUAGE_SESSION_KEY)
#translation.activate(user_language)
username = forms.CharField(label=_("Username"), max_length=30, widget=forms.TextInput(attrs={'class': 'form-control', 'name': 'username'}))
password = forms.CharField(label=_("Password"), max_length=30, widget=forms.PasswordInput(attrs={'class': 'form-control', 'name': 'password'}))
提前谢谢!
更新12/10/2016:
我遇到了以下Stack Overflow问题Django form and i18n,这已经解决了我的表单翻译问题(uggettext_lazy
获取请求和会话信息,似乎)。
所以我现在唯一的问题是,我是否真的需要进行translation.activate并从会话中获取每个视图的语言代码?谢谢!