Tips:一些记录,一些笔记

2024/05/27
MONDAY
杜牧说「东风不与周郎便,铜雀春深锁二乔」

01
Djoser
Djoser默认情况下是英文版的,比如下面这个报错,默认是以英文方式输出的:

02
Djoser的本地化支持
打开你的Django项目的「venv」你可以找到通过PIP安装的Djoser的目录:

可以看到,每一个语言对应的目录中都包含一个名为「django.po」的文件。
该文件中定义了本地化翻译的对应关系:
msgid:英文原文
msgstr:翻译后的本地化字符串
例如,德语的「django.po」文件的完整内容如下所示:
# Copyright (C) Sunscrapers# This file is distributed under the same license as the djoser package.## Translators:# Bertram Bühner <github@sheepyhollow.de>, 2020##, fuzzymsgid ""msgstr """Project-Id-Version: djoser\n""Report-Msgid-Bugs-To: \n""POT-Creation-Date: 2020-01-13 17:40+0100\n""Last-Translator: Bertram Bühner <github@sheepyhollow.de>\n""Language-Team: German\n""Language: de\n""MIME-Version: 1.0\n""Content-Type: text/plain; charset=UTF-8\n""Content-Transfer-Encoding: 8bit\n""Plural-Forms: nplurals=2; plural=(n > 1);\n"#: constants.py:4msgid "Unable to log in with provided credentials."msgstr "Eine Anmeldung ist mit den angegebenen Daten nicht möglich."#: constants.py:5msgid "User account is disabled."msgstr "Dieses Benutzerkonto ist deaktiviert."#: constants.py:6msgid "Invalid token for given user."msgstr "Das Token für diesen Benutzer ist ungültig."#: constants.py:7msgid "Invalid user id or user doesn't exist."msgstr "Die User-ID ist ungültig oder dieser Benutzer existiert nicht."#: constants.py:8msgid "Stale token for given user."msgstr "Das Token für diesen Benutzer ist abgelaufen."#: constants.py:9msgid "The two password fields didn't match."msgstr "Die beiden Passwörter stimmen nicht überein."#: constants.py:10#, python-brace-formatmsgid "The two {0} fields didn't match."msgstr "Die beiden {0}-Felder stimmen nicht überein."#: constants.py:11msgid "Invalid password."msgstr "Das Passwort ist ungültig."#: constants.py:12msgid "User with given email does not exist."msgstr "Es existiert kein Benutzer mit dieser E-Mailadresse."#: constants.py:13msgid "Unable to create account."msgstr "Das Benutzerkonto kann nicht angelegt werden."#: constants.py:15msgid """User model does not contain specified email field. Please see http://djoser.""readthedocs.io/en/latest/settings.html#USER_EMAIL_FIELD_NAME for more ""details."msgstr """Das user-model enthält kein E-Mail-Feld. Weitere Details unter ""http://djoser.readthedocs.io/en/latest/settings.html#USER_EMAIL_FIELD_NAME ""."#: templates/email/activation.html:4#, python-formatmsgid "Account activation on %(site_name)s"msgstr "Aktivierung des Benutzerkontos auf %(site_name)s"#: templates/email/activation.html:8 templates/email/activation.html:19#, python-formatmsgid """You're receiving this email because you need to finish activation process on ""%(site_name)s."msgstr """Sie erhalten diese E-Mail, da Sie den Aktivierungsprozess auf %(site_name)s.""abschließen müssen."#: templates/email/activation.html:10 templates/email/activation.html:22msgid "Please go to the following page to activate account:"msgstr "Bitte begeben Sie sich auf folgende Seite, um die Aktivierung abzuschließen:"#: templates/email/activation.html:13 templates/email/activation.html:25#: templates/email/confirmation.html:10 templates/email/confirmation.html:18#: templates/email/password_reset.html:14#: templates/email/password_reset.html:26msgid "Thanks for using our site!"msgstr "Vielen Dank für die Nutzung unserer Seite!"#: templates/email/activation.html:15 templates/email/activation.html:27#: templates/email/confirmation.html:12 templates/email/confirmation.html:20#: templates/email/password_reset.html:16#: templates/email/password_reset.html:28#, python-formatmsgid "The %(site_name)s team"msgstr "Das Team von %(site_name)s"#: templates/email/confirmation.html:4#, python-formatmsgid """%(site_name)s - Your account has been successfully created and activated!"msgstr """%(site_name)s - Ihr Benutzerkonto wurde erfolgreich erstellt und aktiviert!"#: templates/email/confirmation.html:8 templates/email/confirmation.html:16msgid "Your account has been created and is ready to use!"msgstr "Ihr Benutzerkonto wurde erstellt und ist freigeschaltet!"#: templates/email/password_reset.html:4#, python-formatmsgid "Password reset on %(site_name)s"msgstr "Zurücksetzen des Passworts auf %(site_name)s"#: templates/email/password_reset.html:8 templates/email/password_reset.html:20#, python-formatmsgid """You're receiving this email because you requested a password reset for your ""user account at %(site_name)s."msgstr """Sie erhalten diese E-Mail, da Sie das Zurücksetzen Ihres Passworts auf ""%(site_name)s angefordert haben."#: templates/email/password_reset.html:10#: templates/email/password_reset.html:22msgid "Please go to the following page and choose a new password:"msgstr "Bitte geben Sie auf der folgenden Seite ein neues Passwort ein:"#: templates/email/password_reset.html:12#: templates/email/password_reset.html:24msgid "Your username, in case you've forgotten:"msgstr "Ihr Benutzername - falls Sie ihn vergessen haben - lautet:"
默认情况下,Djoser支持的语言如下所示:

可以看到,其中并不包含中文(zh-hans)
这里的语言编码的简写是与Django本身的语言代码(LANGUAGE_CODE)保持一致的。
Django中的LANGUAGE_CODE:
https://docs.djangoproject.com/en/5.0/ref/settings/#language-code
支持的语言代码完整列表:
http://www.i18nguy.com/unicode/language-identifiers.html
03
实现「中文」本地化支持
在了解了Djoser官方的源码是如何实现语言的本地化支持后,我们就可以按照一样的方式,扩展「中文」的本地化支持了。
前面访问的路径是第三方包的安装目录,我们不对别人的源码修改,避免出现不必要的麻烦与不可预期的错误。
首先,在自己的项目中创建路径「locale」

注意,上面这里有个错误,创建本地化相关路径的时候,不能带上「__init__.py」文件,否则你将会遇到如下文所示的错误:
Django: module 'locale' has no attribute 'normalize'
正确的路径:

语言代码中如果有「-」在设置文件路径名称的时候,应该替换为「下划线」
编辑其中的本地化文件「django.po」:
# Copyright (C) Sunscrapers# This file is distributed under the same license as the djoser package.#msgid ""msgstr """Project-Id-Version: djoser\n""Report-Msgid-Bugs-To: \n""POT-Creation-Date: 2024-05-27 15:06-1800\n""Last-Translator: Adamhuan <dkseven_eli@163.com>\n""Language-Team: Chinese\n""Language: zh-hans\n""MIME-Version: 1.0\n""Content-Type: text/plain; charset=UTF-8\n""Content-Transfer-Encoding: 8bit\n""Plural-Forms: nplurals=2; plural=(n > 1);\n"#: djoser/constants.py:4msgid "No active account found with the given credentials"msgstr "不正确的身份验证"#: djoser/constants.py:5msgid "Unable to log in with provided credentials."msgstr "无法使用提供的凭据登录."#: djoser/constants.py:6msgid "User account is disabled."msgstr "禁用用户帐户."#: djoser/constants.py:7msgid "Invalid token for given user."msgstr "给定用户的令牌无效."#: djoser/constants.py:8msgid "Invalid user id or user doesn't exist."msgstr "无效的用户id或用户不存在."#: djoser/constants.py:9msgid "Stale token for given user."msgstr "给定用户的陈旧令牌."#: djoser/constants.py:10msgid "The two password fields didn't match."msgstr "两个密码字段不匹配."#: djoser/constants.py:11#, python-brace-formatmsgid "The two {0} fields didn't match."msgstr "两个{0}字段不匹配."#: djoser/constants.py:12msgid "Invalid password."msgstr "无效的密码."#: djoser/constants.py:13msgid "User with given email does not exist."msgstr "给定电子邮件的用户不存在."#: djoser/constants.py:14msgid "Unable to create account."msgstr "无法创建帐户."#: djoser/templates/email/activation.html:4#, python-formatmsgid "Account activation on %(site_name)s"msgstr "激活账户 %(site_name)s"#: djoser/templates/email/activation.html:8#: djoser/templates/email/activation.html:19#, python-formatmsgid """You're receiving this email because you need to finish activation process on ""%(site_name)s."msgstr """你收到这封邮件是因为你需要完成激活过程 ""%(site_name)s."#: djoser/templates/email/activation.html:10#: djoser/templates/email/activation.html:21msgid "Please go to the following page to activate account:"msgstr "请到以下页面激活帐户:"#: djoser/templates/email/activation.html:13#: djoser/templates/email/activation.html:24#: djoser/templates/email/confirmation.html:10#: djoser/templates/email/confirmation.html:18#: djoser/templates/email/password_changed_confirmation.html:10#: djoser/templates/email/password_changed_confirmation.html:18#: djoser/templates/email/password_reset.html:14#: djoser/templates/email/password_reset.html:26#: djoser/templates/email/username_changed_confirmation.html:10#: djoser/templates/email/username_changed_confirmation.html:18#: djoser/templates/email/username_reset.html:14#: djoser/templates/email/username_reset.html:26msgid "Thanks for using our site!"msgstr "感谢使用我们的网站!"#: djoser/templates/email/activation.html:15#: djoser/templates/email/activation.html:26#: djoser/templates/email/confirmation.html:12#: djoser/templates/email/confirmation.html:20#: djoser/templates/email/password_changed_confirmation.html:12#: djoser/templates/email/password_changed_confirmation.html:20#: djoser/templates/email/password_reset.html:16#: djoser/templates/email/password_reset.html:28#: djoser/templates/email/username_changed_confirmation.html:12#: djoser/templates/email/username_changed_confirmation.html:20#: djoser/templates/email/username_reset.html:16#: djoser/templates/email/username_reset.html:28#, python-formatmsgid "The %(site_name)s team"msgstr "团队 %(site_name)s"#: djoser/templates/email/confirmation.html:4#, python-formatmsgid """%(site_name)s - Your account has been successfully created and activated!"msgstr "%(site_name)s - 您已成功激活账号!"#: djoser/templates/email/confirmation.html:8#: djoser/templates/email/confirmation.html:16msgid "Your account has been created and is ready to use!"msgstr "您的帐户已经创建,可以使用了!"#: djoser/templates/email/password_changed_confirmation.html:4#, python-formatmsgid "%(site_name)s - Your password has been successfully changed!"msgstr "%(site_name)s - 您已成功修改密码!"#: djoser/templates/email/password_changed_confirmation.html:8#: djoser/templates/email/password_changed_confirmation.html:16msgid "Your password has been changed!"msgstr "Su contraseña ha sido cambiada!"#: djoser/templates/email/password_reset.html:4#, python-formatmsgid "Password reset on %(site_name)s"msgstr "Reseteo de contraseña en %(site_name)s"#: djoser/templates/email/password_reset.html:8#: djoser/templates/email/password_reset.html:20#, python-formatmsgid """You're receiving this email because you requested a password reset for your ""user account at %(site_name)s."msgstr """您收到这封邮件是因为您请求重置您的""用户帐户在 %(site_name)s"#: djoser/templates/email/password_reset.html:10#: djoser/templates/email/password_reset.html:22msgid "Please go to the following page and choose a new password:"msgstr "请进入以下页面并选择新密码"#: djoser/templates/email/password_reset.html:12#: djoser/templates/email/password_reset.html:24#: djoser/templates/email/username_reset.html:12#: djoser/templates/email/username_reset.html:24msgid "Your username, in case you've forgotten:"msgstr "你的用户名,以防你忘了:"#: djoser/templates/email/username_changed_confirmation.html:4#, python-formatmsgid "%(site_name)s - Your username has been successfully changed!"msgstr "%(site_name)s - 您已成功修改了用户名!"#: djoser/templates/email/username_changed_confirmation.html:8#: djoser/templates/email/username_changed_confirmation.html:16msgid "Your username has been changed!"msgstr "Su usuario ha sido cambiado!"#: djoser/templates/email/username_reset.html:4#, python-formatmsgid "Username reset on %(site_name)s"msgstr "用户名重置 %(site_name)s"#: djoser/templates/email/username_reset.html:8#: djoser/templates/email/username_reset.html:20#, python-formatmsgid """You're receiving this email because you requested a username reset for your ""user account at %(site_name)s."msgstr """你收到这封邮件是因为你请求重置你的用户名在 %(site_name)s"#: djoser/templates/email/username_reset.html:10#: djoser/templates/email/username_reset.html:22msgid "Please go to the following page and choose a new username:"msgstr "请进入以下页面并选择一个新用户名:"
然后,在Django的全局配置文件「settings.py」中进行配置:
LOCALE_PATHS = [Path(BASE_DIR).joinpath('locale')]
然后,通过Django的django-admin生成本地化代码运行时的「.mo」文件:
(venv) (base) adamhuan@Leviathan django_daily_media % ls -ltr locale/zh-hans/LC_MESSAGEStotal 24-rw-r--r-- 1 adamhuan staff 391 May 27 14:53 __init__.py-rw-r--r-- 1 adamhuan staff 6629 May 27 15:09 django.po(venv) (base) adamhuan@Leviathan django_daily_media %(venv) (base) adamhuan@Leviathan django_daily_media % django-admin compilemessages --locale=zh-hansprocessing file django.po in Users/adamhuan/PycharmProjects/django_daily_media/locale/zh-hans/LC_MESSAGES(venv) (base) adamhuan@Leviathan django_daily_media %(venv) (base) adamhuan@Leviathan django_daily_media % ls -ltr locale/zh-hans/LC_MESSAGEStotal 32-rw-r--r-- 1 adamhuan staff 391 May 27 14:53 __init__.py-rw-r--r-- 1 adamhuan staff 6629 May 27 15:09 django.po-rw-r--r-- 1 adamhuan staff 3374 May 27 15:45 django.mo(venv) (base) adamhuan@Leviathan django_daily_media %
需要注意的是「每次 po 文件的修改」都需要重新进行重新编译,生成对应的「mo」文件。
然后,重新运行Django项目:

04
看看效果

可以看到,Djoser的提示信息已经变成中文了。
它在本地化文件中定义的位置:

END
温馨提示
如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。




