Django中没有持久的翻译

时间:2016-10-11 12:46:54

标签: django session translation

我花了几个小时搜索这个网站和其他网站,并阅读了Django文档,但我还没有找到解决我的Django翻译问题的方法。我应该补充一点,我是一个Django新手,如果我做些傻事,请提前道歉。

我正在使用Django 1.10和Python 3.5.2。

我的情况

我的应用程序的每个注册用户都将分配一个语言代码。此代码将存储在django.contrib.auth.models User模型的扩展中(所以UserExtend模型,1-1映射到User)。当用户登录时,我想阅读此语言代码,从而将用户访问的所有页面翻译成该语言。为此,我正在激活翻译并将语言代码存储在会话变量中。但是,我发现在用户登录并重定向到另一个页面后,字符串不会被翻译。如果我登录用户但省略了重定向代码(即只是再次显示登录页面),字符串 已翻译(我通过创建language_code 'de-DE'的用户来检查并使用_de前缀创建和编译虚拟翻译),但只要我使用我的菜单去其他地方,我们就会再次回到英语。

我的假设:

根据Django文档(https://docs.djangoproject.com/en/1.10/topics/i18n/translation/#how-django-discovers-language-preference)

  

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并从会话中获取每个视图的语言代码?谢谢!

0 个答案:

没有答案