每天40分玩转Django:Django国际化

news2024/12/28 16:45:00

Django国际化

一、今日学习内容概述

学习模块重要程度主要内容
国际化基础⭐⭐⭐⭐⭐基本概念、配置设置
字符串翻译⭐⭐⭐⭐⭐翻译标记、消息文件
模板国际化⭐⭐⭐⭐模板标签、过滤器
动态内容翻译⭐⭐⭐⭐模型字段、表单翻译

二、国际化基础配置

# settings.py

# 启用国际化
USE_I18N = True

# 启用本地化
USE_L10N = True

# 启用时区
USE_TZ = True

# 支持的语言
LANGUAGES = [
    ('en', 'English'),
    ('zh-hans', '简体中文'),
    ('ja', '日本語'),
]

# 默认语言
LANGUAGE_CODE = 'en'

# 翻译文件路径
LOCALE_PATHS = [
    BASE_DIR / 'locale',
]

# 中间件配置
MIDDLEWARE = [
    # ...
    'django.middleware.locale.LocaleMiddleware',
    # ...
]

三、代码中的字符串翻译

# models.py
from django.db import models
from django.utils.translation import gettext_lazy as _

class Article(models.Model):
    STATUS_CHOICES = [
        ('draft', _('草稿')),
        ('published', _('已发布')),
    ]
    
    title = models.CharField(_('标题'), max_length=200)
    content = models.TextField(_('内容'))
    status = models.CharField(
        _('状态'),
        max_length=10,
        choices=STATUS_CHOICES,
        default='draft'
    )
    created_at = models.DateTimeField(_('创建时间'), auto_now_add=True)
    
    class Meta:
        verbose_name = _('文章')
        verbose_name_plural = _('文章')

# views.py
from django.utils.translation import gettext as _
from django.contrib import messages

def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save()
            messages.success(request, _('文章创建成功!'))
            return redirect('article_detail', pk=article.pk)
    else:
        form = ArticleForm()
    
    return render(request, 'articles/create.html', {
        'title': _('创建新文章'),
        'form': form
    })

四、模板国际化

<!-- templates/base.html -->
{% load i18n %}
<!DOCTYPE html>
<html>
<head>
    <title>{% trans "我的网站" %}</title>
</head>
<body>
    <header>
        <h1>{% trans "欢迎访问" %}</h1>
        <div class="language-selector">
            <form action="{% url 'set_language' %}" method="post">
                {% csrf_token %}
                <input name="next" type="hidden" value="{{ request.path }}">
                <select name="language" onchange="this.form.submit()">
                    {% get_current_language as CURRENT_LANGUAGE %}
                    {% get_available_languages as LANGUAGES %}
                    {% for code, name in LANGUAGES %}
                        <option value="{{ code }}"
                                {% if code == CURRENT_LANGUAGE %}selected{% endif %}>
                            {{ name }}
                        </option>
                    {% endfor %}
                </select>
            </form>
        </div>
    </header>
    
    <nav>
        <ul>
            <li><a href="{% url 'home' %}">{% trans "首页" %}</a></li>
            <li><a href="{% url 'about' %}">{% trans "关于" %}</a></li>
            <li><a href="{% url 'contact' %}">{% trans "联系我们" %}</a></li>
        </ul>
    </nav>
    
    <main>
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        {% blocktrans %}
            版权所有 © {{ year }} 我的网站
        {% endblocktrans %}
    </footer>
</body>
</html>

五、国际化流程图

在这里插入图片描述

六、消息文件管理

6.1 创建和编译消息文件

# 创建/更新消息文件
python manage.py makemessages -l zh_hans
python manage.py makemessages -l ja

# 编译消息文件
python manage.py compilemessages

6.2 消息文件示例

# locale/zh_hans/LC_MESSAGES/django.po
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-01-19 10:00+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: models.py:8
msgid "标题"
msgstr "Title"

#: models.py:9
msgid "内容"
msgstr "Content"

#: templates/base.html:4
msgid "我的网站"
msgstr "My Website"

七、动态内容翻译

7.1 模型翻译

# models.py
from django.db import models
from django.utils.translation import gettext_lazy as _

class TranslatableModel(models.Model):
    """可翻译内容的基类"""
    class Meta:
        abstract = True

class ArticleTranslation(models.Model):
    article = models.ForeignKey('Article', on_delete=models.CASCADE)
    language = models.CharField(max_length=10, choices=settings.LANGUAGES)
    title = models.CharField(max_length=200)
    content = models.TextField()
    
    class Meta:
        unique_together = ('article', 'language')

class Article(TranslatableModel):
    # 基本字段保持原样
    created_at = models.DateTimeField(auto_now_add=True)
    
    def get_translation(self, language=None):
        """获取指定语言的翻译"""
        if language is None:
            language = get_language()
        
        try:
            return self.articletranslation_set.get(language=language)
        except ArticleTranslation.DoesNotExist:
            # 如果没有找到翻译,返回默认语言
            return self.articletranslation_set.get(
                language=settings.LANGUAGE_CODE
            )

7.2 表单翻译

# forms.py
from django import forms
from django.utils.translation import gettext_lazy as _

class ContactForm(forms.Form):
    name = forms.CharField(
        label=_('姓名'),
        max_length=100,
        error_messages={
            'required': _('请输入您的姓名'),
            'max_length': _('姓名长度不能超过100个字符'),
        }
    )
    email = forms.EmailField(
        label=_('电子邮箱'),
        error_messages={
            'required': _('请输入您的电子邮箱'),
            'invalid': _('请输入有效的电子邮箱地址'),
        }
    )
    message = forms.CharField(
        label=_('留言内容'),
        widget=forms.Textarea,
        error_messages={
            'required': _('请输入留言内容'),
        }
    )

八、URL国际化

# urls.py
from django.conf.urls.i18n import i18n_patterns
from django.urls import path, include

urlpatterns = [
    path('i18n/', include('django.conf.urls.i18n')),
]

urlpatterns += i18n_patterns(
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')),
)

九、JavaScript国际化

// static/js/i18n.js
const gettext = function(msgid) {
    return window.TRANSLATIONS[msgid] || msgid;
};

const interpolate = function(fmt, obj) {
    return fmt.replace(/%\(\w+\)s/g, function(match) {
        return String(obj[match.slice(2,-2)]);
    });
};

// 使用示例
const message = gettext('欢迎访问,%(name)s!');
const welcomeMessage = interpolate(message, {name: 'John'});

十、日期和数字格式化

# views.py
from django.utils.formats import date_format, number_format
from django.utils import translation

def format_example(request):
    current_language = translation.get_language()
    
    # 格式化日期
    today = date.today()
    formatted_date = date_format(today, format='DATETIME_FORMAT')
    
    # 格式化数字
    number = 1234567.89
    formatted_number = number_format(
        number,
        decimal_pos=2,
        use_l10n=True
    )
    
    return render(request, 'format_example.html', {
        'formatted_date': formatted_date,
        'formatted_number': formatted_number,
    })

通过本章学习,你应该能够:

  1. 配置Django国际化
  2. 实现字符串翻译
  3. 处理动态内容翻译
  4. 使用本地化格式

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch 国产化替代方案之一 Easysearch 的介绍与部署指南

一、前言 在国内数字化转型浪潮和 信创 大背景下&#xff0c;“替代进口”成为许多企业级应用所需要面对的重要课题&#xff0c;搜索领域也不例外。 Elasticsearch&#xff08;简称 ES&#xff09;作为一款业界领先的全文搜索和分析引擎&#xff0c;虽然功能强大&#xff0c;但…

Ubuntu 24.04.1 LTS 配置静态固定IP地址

查看网络配置信息 ip addr使用该命令查看网卡名字&#xff0c;一般是ens33或者ens32 修改配置文件 打开 /etc/netplan/下面的yaml配置文件 根据自己的需要配置 network:ethernets:ens33: # 配置的网卡的名称addresses: [192.168.23.140/24] # 配置的静态ip地址和掩码d…

Deep Deterministic Policy Gradient (DDPG)算法

代码 import torch import torch.nn as nn import torch.optim as optim import numpy as np import gym import random from collections import deque# 定义 Actor 网络 class Actor(nn.Module):def __init__(self, state_dim, action_dim, max_action):super(Actor, self).…

C++ OCR 文字识别

一.引言 文字识别&#xff0c;也称为光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;&#xff0c;是一种将不同形式的文档&#xff08;如扫描的纸质文档、PDF文件或数字相机拍摄的图片&#xff09;中的文字转换成可编辑和可搜索的数据的技术。随着技…

【解决报错】AttributeError: ‘NoneType‘ object has no attribute ‘group‘

学习爬虫时&#xff0c;遇到如下报错&#xff1a; 报错原因&#xff1a; 正则表达式的 search 或 finditer 方法没有找到任何匹配项&#xff0c;可能是换行符处理不当等。 解决方法如下&#xff1a; 在正则表达式末尾加上re.S即可&#xff0c;re.S是一个编译标志&#xff0c…

JVM实战—3.JVM垃圾回收的算法和全流程

大纲 1.JVM内存中的对象何时会被垃圾回收 2.JVM中的垃圾回收算法及各算法的优劣 3.新生代和老年代的垃圾回收算法 4.避免本应进入S区的对象直接升入老年代 5.Stop the World问题分析 6.JVM垃圾回收的原理核心流程 7.问题汇总 1.JVM内存中的对象何时会被垃圾回收 (1)什么…

基于SpringBoot在线音乐系统平台功能实现十八

一、前言介绍&#xff1a; 1.1 项目摘要 随着互联网技术的迅猛发展和普及&#xff0c;人们对音乐的获取和欣赏方式发生了巨大改变。传统的音乐播放方式&#xff0c;如CD、磁带或本地下载的音乐文件&#xff0c;已经不能满足用户日益增长的需求。用户更希望通过网络直接获取各…

RouYi-Vue框架,环境搭建以及使用

使用若以框架需要配置node.js&#xff0c;如果不了解可以去看node.js安装&#xff0c;uni-app的配置使用_uniapp使用nodejs类库-CSDN博客 安装若依 首先是去若以官网下载自己所需要的框架类型 RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff…

XL系列433芯片、2.4G收发芯片 通讯对码说明

XL系列433芯片对码说明&#xff1a; 发射芯片 XL4456 通过数据脚接收高低电平然后经过调制将波形发出&#xff0c;而接收芯片 XL520 通过接收波形后进行解调&#xff0c;数据脚输出高低电平。至于具体的通信协议&#xff0c;需要用户自定义&#xff0c;一般而言&#xff0c;使…

蓝牙BLE开发——解决iOS设备获取MAC方式

解决iOS设备获取MAC方式 uniapp 解决 iOS 获取 MAC地址&#xff0c;在Android、iOS不同端中互通&#xff0c;根据MAC 地址处理相关的业务场景&#xff1b; 文章目录 解决iOS设备获取MAC方式监听寻找到新设备的事件BLE工具效果图APP监听设备返回数据解决方式ArrayBuffer转16进制…

期权懂|如何计算期权卖方平仓后的盈利?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 如何计算期权卖方平仓后的盈利&#xff1f; 期权卖方平仓后的盈利计算涉及多个因素&#xff0c;包括期权的交易价格、平仓价格以及权利金的变动等。 交易价格&#xff1a;期权卖…

QT:一个TCP客户端自动连接的测试模型

版本 1:没有取消按钮 测试效果&#xff1a; 缺陷&#xff1a; 无法手动停止 测试代码 CMakeLists.txt cmake_minimum_required(VERSION 3.19) project(AutoConnect LANGUAGES CXX)find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets Network)qt_standard_project_setup(…

uniapp中wx.getFuzzyLocation报错如何解决

一、用wx.getLocation接口审核不通过 用uniapp开发小程序时难免需要获取当前地理位置。 代码如下&#xff1a; uni.getLocation({type: wgs84,success: function (res) {console.log(当前位置的经度&#xff1a; res.longitude);console.log(当前位置的纬度&#xff1a; r…

解决Ubuntu下无法装载 Windows D盘的问题

电脑安装了 Windows 和 Ubuntu 24.04 后&#xff0c;在Ubuntu系统上装载 D盘&#xff0c;发现无法装载错误如下&#xff1a; Error mounting /dev/nvme0n1p4 at /media/jackeysong/Data: wrong fs type, bad option, bad superblock on /dev/nvme0n1p4, missing codepage or h…

硬件设计-高速电路的过孔

目录 摘要 &#xff1a; 过孔的机械特性&#xff1a; 过孔直径&#xff1a; 过孔焊盘尺寸 摘要 &#xff1a; 过孔这个词指得是印刷电路板&#xff08; PCB &#xff09;上的孔。过孔可以用做焊接插装器件的焊&#xff08; Through hole) &#xff0c;也可用做连接层间走…

mysql索引的理解

1、索引是什么&#xff1f; 索引&#xff1a;简单理解就是我们字典的目录&#xff0c;一个索引可以找得到多个记录。 作用加快我们数据库的查询速度。索引本身较大&#xff0c;往往存储在磁盘的文件里。可能存储在单独的索引文件中&#xff0c;也可能和数据一起存储在数据文件…

【WRF模拟】如何得到更佳的WRF模拟效果?

【WRF模拟】如何得到更佳的WRF模拟效果&#xff1f; 模型配置&#xff08;The Model Configuration&#xff09;1.1 模拟区域domain设置1.2 分辨率Resolution (horizontal and vertical)案例&#xff1a;The Derecho of 29-30 June 2012 1.3 初始化和spin-up预热过程案例1-有无…

IOS safari 播放 mp4 遇到的坎儿

起因 事情的起因是调试 IOS 手机下播放服务器接口返回的 mp4 文件流失败。对于没调试过移动端和 Safari 的我来说着实费了些功夫&#xff0c;网上和AI也没有讲明白。好在最终大概理清楚了&#xff0c;在这里整理出来供有缘人参考。 问题 因为直接用 IOS 手机的浏览器打开页面…

单片机+人体红外感应的防盗系统设计(仿真+源码+PCB文件+报告)

资料下载地址&#xff1a;单片机人体红外感应的防盗系统设计(仿真源码PCB文件报告) 1、功能介绍 (1)该设计包括硬件和软件设计两个部分。 (2)本红外线防盗报警系统由热释电红外传感器、报警器、单片机控制电路、LED控制电路及相关的控制管理软件组成。用户终端完成信息采集、处…

网络攻防实践

1. 学习总结 黛蛇蠕虫案例&#xff1a; 原理&#xff1a;利用系统漏洞&#xff0c;并集成攻击代码。其中&#xff0c;通过蜜罐技术并进行数据分析所获取的攻击场景如下&#xff1a; 外部感染源攻陷蜜罐主机 执行Shellcode后获取主机权限后连接控制命令服务器&#xff0c;获取F…