在Django用户中添加Language和Timezone设置,实现动态切换语言和时区以及切换时钟显示

我想做的事情

undefined

我希望用户可以设置语言和时区。

各位Django迷,大家好,Django在此(问候)。

我们非常了解Django对于I18N和L10N的支持,并且知道如何轻松地利用它们的功能。

如果需要多语言翻译,只需将 USE_I18N 设置为 True,并指定 LANGUAGE_CODE;如果需要格式本地化,只需将 USE_L10N 设置为 True;如果想要调整时区,只需将 USE_TZ 设置为 True,并指定 TIMEZONE。

同时,您只需使用Google翻译或DeepL翻译来创建翻译文件,就能构建全球应用程序。如果您正在使用Django创建应用程序,那么您可以立即制作出考虑国际化的应用程序。

然而,存在一个问题。

如果您开发了一款面向国际市场的应用程序,假设日本人、美国人、法国人和亚洲国家的人也在使用该应用程序,那么应该在哪里进行语言设置切换呢?

是的,这是settings.py文件。但是一旦修改了LANGUAGE_CODE设置,Django将会在指定的语言下进行输出。例如,如果将LANGUAGE_CODE设置为”ja”,Django将会以日语显示给各个国家的用户。这样一来,国际化的目的就变得不太清楚了。

个人来说,我觉得这很奇怪,但在Django的标准设置中,甚至无法在用户端更改语言,更别说时区了。这次我们要讲的是让用户能够自行修改这些设置的故事。

机构

关于语言

以下是基于Django手册的基本代码摘录。您可以将想要使用的语言传递给translation.activate,并将其值设置到cookie中。这样一来,Django就可以在这个会话中仅切换到所选的语言。

from django.conf import settings
from django.http import HttpResponse
from django.utils import translation
user_language = 'fr'
translation.activate(user_language)
response = HttpResponse(...)
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, user_language)

这次针对用户模型

关于时区的问题

基本代码源自Django手册中提取的内容。
将要使用的时区传递给timezone.activate。

import pytz

from django.utils import timezone

class TimezoneMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        tzname = request.session.get('django_timezone')
        if tzname:
            timezone.activate(pytz.timezone(tzname))
        else:
            timezone.deactivate()
        return self.get_response(request)

最后一步是在这些代码的基础上,定制用户模型并提供处理语言设置和时区设置的字段,使用户可以自行更改。

因此,我們為了這個目的準備了django-user-g11n。

Django 用户国际化

Django-user-g11n通过创建Django的自定义用户模型,并继承”TimeZoneAndUserLanguageSupportMixin”来为用户模型添加language和timezone两个字段,然后通过使用中间件来动态地更改设置的语言和时区。

顺便提一下,g11n是全球化的缩写,指的是I18n+L10N。

使用方法

如果您想立即尝试样品,请参考“使用样品”之前的部分。

首先,需要安装Django和django-user-g11n。

$ pip install django django-user-g11n

接下来我们将使用django-admin.py启动项目。

$ django-admin.py startproject example

接下来,我们要创建自定义用户模型。在这里,我们临时将其命名为”accounts”应用程序。

$ manage.py startapp accounts

完成应用后,需要修改 accounts/models.py 文件并添加自定义用户模型。
在此过程中,需要继承 UserLanguageSupportMixin 和 UserTimeZoneSupportMixin。

from django.contrib.auth import models as auth_models
from user_g11n.models import UserLanguageSupportMixin, UserTimeZoneSupportMixin


class User(UserTimeZoneSupportMixin,
           UserLanguageSupportMixin,
           auth_models.AbstractUser):
    pass

接下来是对settings.py文件的修改。

更改settings.py文件

我們會在INSTALLED_APPS中新增一個應用程式來使用我們定制的用戶模型,並添加用戶國際化。

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    .
    .
    .
    'accounts',  # Your Custom user model application
    'user_g11n', # Add
)

接下来,我们将更改MIDDLEWARE,并添加UserLanguageMiddleware和UserTimeZoneMiddleware。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    .
    .
    .
    'user_g11n.middleware.UserLanguageMiddleware', # Add
    'user_g11n.middleware.UserTimeZoneMiddleware', # Add
]

然后,指定AUTH_USER_MODEL,使得可以使用自定义用户模型。

AUTH_USER_MODEL = 'accounts.User'

接下来,将分别设置I18N、L10N、TZ和TIME_ZONE。

USE_I18N = True

USE_L10N = True

USE_TZ = True

TIME_ZONE = "Asia/Tokyo" # Change to your local timezone

完成更改后,执行迁移以创建数据库。

$ ./manage.py makemigrations && ./manage.py migrate

这就完成了。接下来创建superuser,在用户管理界面上更改语言和时区,即可实时切换显示。

undefined

使用样品

这个Django应用程序正在GitHub上进行开发。

请帮我克隆这个项目。

$ docker-compose up

试用样例应用程序后,可通过访问http://localhost:8000来进行。

总结

    • Djangoの国際化機構最高

 

    • 最初からこれ用意してくれよって思う。なぜないのか…

 

    • DjangoおぢさんはDjangoが大好き。

 

    今年(2020)はCovid-19の影響でDjango Congressなくなっちゃったけど、俺らの心のなかでは開催されているのだ!毎日のように・・・!

2022年5月进行更新。

由于 Django4 将 pytz替换为timezone,导致无法运行,因此我进行了更新。

对此进行了响应的如下所示。

    • Django3ならPytzを利用(timezoneは入れられれば使えるけど、面倒なので対応無し)

 

    • Django4で

USE_DEPRECATED_PYTZがFalseならばtimezoneを利用

USE_DEPRECATED_PYTZがTrueならばpytzを利用

以上

广告
将在 10 秒后关闭
bannerAds