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

我希望用户可以设置语言和时区。
各位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,在用户管理界面上更改语言和时区,即可实时切换显示。

使用样品
这个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を利用
以上