首页 > 其他分享 >Django国际化和本地化

Django国际化和本地化

时间:2024-04-19 11:12:55浏览次数:20  
标签:翻译 国际化 本地化 django ar 字符串 Django my es

国际化和本地化

定义

国际化和本地化的目标是让同一站点为不同的用户提供定制化的语言和格式服务。

Django支持文本、格式化日期、时间、数字以及时区的翻译。

实际上,Django 做了两件事:

  • 允许开发者和模板设计者指定在他们的app中哪些部分需要进行翻译或者格式化成当地的语言、习惯、用法和习俗;
  • 根据用户的偏好习惯,使用钩子,进行Web本地化。

基本原理是:

  • 浏览器通过LANGUAGE_CODE在HTTP请求头中告诉网站后台服务器,用户所需要的页面语言;
  • 网站服务器在渲染页面时,根据LANGUAGE_CODE查询每个需要翻译成对应语言的文本字符串,并将其替换到网页内,最后将网页返回给用户浏览器。

下面是一些术语:

  • 国际化internationalization

为本地化准备软件。通常由开发者完成。

  • 本地化localization

编写翻译和本地格式化。通常由翻译者完成。

翻译和格式化分别由 USE_I18N 和 USE_L10N 控制。但是这两个功能都涉及国际化和本地化。这两个配置的名字是 Django 的历史原因所导致。

  • locale name

本地化名字

要么是ll表中列出的语言,要么是ll_CC表中列出的国家。比如 itde_ATespt_BRsr_Latn。这些名称具有特定的规范,不了解的可以百度。

  • language code

语言的代码。比如:itde-atespt-br 。语言代码一般用小写表示,但是 HTTP Accept-Language header 不区分大小写。用破折号来间隔。

  • message file

·消息文件。纯文本文件。代表一种语言,包含所有可用的 translation strings ,以及它们如何在给定的语言里表示。消息文件的文件扩展名是 .po 。

  • translation string

可以翻译的文字。

  • format file

格式文件是一个 Python 模块,用于定义本地数据格式。

要使用国际化和本地化功能,需要开启'django.middleware.locale.LocaleMiddleware'中间件,它需要位于session中间件之后,Common中间件之前。

国际化

为了使 Django 项目可以翻译,你需要在 Python 代码和HTML模板中添加少量钩子。这些钩子被称为 translation strings 。它们告诉Django,如果在终端用户语言里,这个文本有对应的翻译,那么应该使用翻译后的文本。(标记字符串是你的职责,系统只会翻译它知道的字符串。)

然后, Django 提供工具将翻译字符串提取到 message file 中。这个文件让翻译者方便地提供翻译字符串。一旦翻译者完成了 message file ,就必须编译它。这个过程依赖 GNU gettext 工具集。

完成后,Django 会根据用户的语言偏好,对网页进行即时翻译。

Django 的国际化钩子默认是开启的,这意味着在框架的某些位置存在一些 i18n 相关的开销。如果你不提供国际化能力,你应该在配置文件里设置 USE_I18N = False 。然后 Django 将进行优化,以免加载国际化机制,较少开销,提高性能。

所以,国际化的第一步是在视图和HTML模板中标识要翻译的文本。

通过gettext()函数指定需要翻译的字符串,按照惯例,将其作为下划线( _ )导入,以保存输入。如下所示:

from django.http import HttpResponse
from django.utils.translation import gettext as _

def my_view(request):
    output = _("Welcome to my site.")
    return HttpResponse(output)

这等同于:

from django.http import HttpResponse
from django.utils.translation import gettext

def my_view(request):
    output = gettext("Welcome to my site.")
    return HttpResponse(output)

可使用计算值,所以也等同于:

def my_view(request):
    words = ['Welcome', 'to', 'my', 'site.']
    output = _(' '.join(words))
    return HttpResponse(output)

也等同于:

def my_view(request):
    sentence = 'Welcome to my site.'
    output = _(sentence)
    return HttpResponse(output)

传递给 _() or gettext() 的字符串可以使用占位符,这是 Python 标准命名字符串插值语法指定的。:

def my_view(request, m, d):
    output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}
    return HttpResponse(output)

如果你想给翻译人员一些提示,可以添加一个以Translators为前缀的注释,例如:

def my_view(request):
    # Translators: This message appears on the home page only
    output = ugettext("Welcome to my site.")

这个注释将出现在 .po 文件中与所翻译词条相关的词条上方,并且也会被大部分翻译工具显示。比如:

#. Translators: This message appears on the home page only
# path/to/python/file.py:123
msgid "Welcome to my site."
msgstr ""

不翻译gettext_noop()

使用 django.utils.translation.gettext_noop() 将字符串标记为不用翻译。这个字符会稍后使用变量来翻译。

使用该方法的场景是:如果你有一个常量字符串,该字符串以源语言存储,它们通过系统或用户进行交换(比如数据库里的字符串),但应该在最后的时间点进行翻译,比如当字符串展示给用户时。

复数形式ngettext()

使用 django.utils.translation.ngettext() 函数来处理英语中单复数的区别。

ngettext() 带有三个参数:单数翻译字符串,复数翻译字符串和对象的数量。

from django.http import HttpResponse
from django.utils.translation import ngettext

def hello_world(request, count):
    page = ngettext(
        'there is %(count)d object',
        'there are %(count)d objects',
    count) % {
        'count': count,
    }
    return HttpResponse(page)

这个方法给你提供了一种简便的方式,但不是那么可靠,可能会出现各种坑,随便用用就行。

上下文标记

一些词有很多不同含义,比如 "May" ,它指五月或者表示一个动词。

为了使翻译者在不同上下文中正确翻译这些词组,可以使用 django.utils.translation.pgettext() 函数,或者如果字符串需要复数形式的话,可以使用 django.utils.translation.npgettext() 函数,来帮助翻译者,提供语境。

两者都使用上下文字符串作为第一个变量。

例如:

from django.utils.translation import pgettext

month = pgettext("month name", "May")

或者:

from django.db import models
from django.utils.translation import pgettext_lazy

class MyThing(models.Model):
    name = models.CharField(help_text=pgettext_lazy(
        'help text for MyThing model', 'This is the help text'))

将以下面的形式出现在 .po 文件中:

msgctxt "month name"
msgid "May"
msgstr ""

惰性翻译

有时候,我们需要对一些字符串进行惰性翻译,而不是立刻翻译。这需要使用gettext_lazy() 方法。

比如下面的常见场景:

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

class MyThing(models.Model):
    name = models.CharField(help_text=_('This is the help text'))


class AnotherThing(models.Model):
    kind = models.ForeignKey(
        ThingKind,
        on_delete=models.CASCADE,
        related_name='kinds',
        verbose_name=_('kind'),
    )

    def is_mouse(self):
        return self.kind.type == MOUSE_TYPE
    is_mouse.short_description = _('Is it a mouse?')

class MoreThing(models.Model):
    name = models.CharField(_('name'), help_text=_('This is the help text'))

    class Meta:
        verbose_name = _('my thing')
        verbose_name_plural = _('my things')

HTML模板的国际化

在模版文件中,要标识一个待翻译的文本,需要使用{% translate %}模板标签,但首先你要在模版的顶部加载{% load i18n %}。比如:

{% load i18n %}
<title>{% translate "This is the title." %}</title>
<title>{% translate myvar %}</title>

注意:从Django3.1开始原有的trans标签更名为translate,但为了向后兼容,trans依然可用!

要注意的是translate标签内部不可以有内嵌的模板变量

如果你想提前翻译字符串但是不显示出来,可以使用下面的方法:

{% translate "This is the title" as the_title %}

<title>{{ the_title }}</title>
<meta name="description" content="{{ the_title }}">

上面的做法实际上相当于定义了几个模板变量,下面则是更加复杂的用法:

{% translate "starting point" as start %}
{% translate "end point" as end %}
{% translate "La Grande Boucle" as race %}

<h1>
  <a href="/" title="{% blocktranslate %}Back to '{{ race }}' homepage{% endblocktranslate %}">{{ race }}</a>
</h1>
<p>
{% for stage in tour_stages %}
    {% cycle start end %}: {{ stage }}{% if forloop.counter|divisibleby:2 %}<br>{% else %}, {% endif %}
{% endfor %}
</p>

translate标签还支持上下文标记,通过context关键字:

{% translate "May" context "month name" %}

{% translate %}模板标签不同,blocktranslate标签允许你通过使用占位符来标记由文字和可变内容组成的复杂句子进行翻译,如下例所示:

{% blocktranslate %}This string will have {{ value }} inside.{% endblocktranslate %}

原blocktrans标签更名为blocktranslate,向后兼容。

还可以像下面一样使用:

{% blocktranslate with amount=article.price %}
That will cost $ {{ amount }}.
{% endblocktranslate %}

{% blocktranslate with myvar=value|filter %}
This will have {{ myvar }} inside.
{% endblocktranslate %}

甚至在一个blocktrans标签内内使用多个表达式:

{% blocktranslate with book_t=book|title author_t=author|title %}
This is {{ book_t }} by {{ author_t }}
{% endblocktranslate %}

还有复数形式:

{% blocktranslate count counter=list|length %}
There is only one {{ name }} object.
{% plural %}
There are {{ counter }} {{ name }} objects.
{% endblocktranslate %}

甚至更复杂的:

% blocktranslate with amount=article.price count years=i.length %}
That will cost $ {{ amount }} per year.
{% plural %}
That will cost $ {{ amount }} per {{ years }} years.
{% endblocktranslate %}

模板内对翻译的注释

就像 Python 代码一样,可以使用 comment 标签对翻译者进行提示:

{% comment %}Translators: View verb{% endcomment %}
{% translate "View" %}

{% comment %}Translators: Short intro blurb{% endcomment %}
<p>{% blocktranslate %}A multiline translatable
literal.{% endblocktranslate %}</p>

或者使用 {# ... #} 单行注释:

{# Translators: Label of a button that triggers search #}
<button type="submit">{% translate "Go" %}</button>

{# Translators: This is a text of the base template #}
{% blocktranslate %}Ambiguous translatable block of text{% endblocktranslate %}

本地化

一旦标记好需要翻译的文本(也就是国际化)后,就需要进行本地化,也就是创建翻译用的消息文件。

消息文件(Message File)是Django用于保存翻译关系的文件,你的网站应该为每种支持的语言建立一个消息文件。

建立消息文件是通过django-admin makemessages命令完成的。

在项目的根目录下,也就是包含manage.py的目录下,运行下面的命令:

django-admin makemessages -l de

其中的de表示你要本地化的国家,例如pt_BR表示巴西葡萄牙语,奥地利德语为de_AT,印尼语为id。

或者使用下面的方式:

python manage.py makemessages -l zh-cn  //中文简体
python manage.py makemessages -l en    //英文

执行命令后,Django会在根目录及其子目录下搜集所有需要翻译的字符串,默认情况下它会搜索.html、.txt和.py文件,然后在根目录的locale/LANG/LC_MESSAGES目录下创建一个django.po文件。对于上面的例子,目录就是locale/de/LC_MESSAGES/,文件就是locale/de/LC_MESSAGES/django.po

注意:在Windows下,需要提前安装GNU gettext工具!

否则会弹出下面的错误:

CommandError: Can't find msguniq. Make sure you have GNU gettext tools 0.15 or newer installed.

.po文件的格式非常简单!

每个.po文件首先包含一小部分元数据,例如翻译维护者的联系信息,但文件的大部分是翻译对照:被翻译字符串和特定语言的实际翻译文本之间的简单映射。

例如,有一个像下面这样的待翻译字符串:

_("Welcome to my site.")

.po文件中将包含一条下面样子的条目:

#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr ""

这三行内容各自代表下面的意思:

  • 第一行通过注释表达该条要翻译的字符串在视图或模版中的位置;
  • msgid:要翻译的字符串。不要修改它。
  • msgstr:翻译后的文本。一开始它是空的,需要翻译人员逐条填写。

这是一个文本文件,需要专业的翻译人员将所有的msgstr空白‘填写’齐全。如果你的项目比较大,这可能是个磨人的事。

编译消息文件

当完成消息文件的创建和翻译工作后,或者对文件修改后,需要将其编译成对应的*.mo文件,Django在运行时将使用*.mo文件对网站进行国际化翻译。

进入项目根目录,运行下面的命令,进行语言文件编译:

django-admin compilemessages

Django将自动搜索所有的.po文件,将它们都翻译成.mo文件。

至此,国际化和本地化就完成了。你的网站页面将根据访问者使用语言的不同,展示为不同的语言版本,比如中文、英文、法文、德文之类。

附件

下面列出了所有可用于各种系统设置的语言代码对照表:

  • af 南非荷兰语
  • sq 阿尔巴尼亚语
  • ar-sa 阿拉伯语(沙特阿拉伯)
  • ar-iq 阿拉伯语(伊拉克)
  • ar-eg 阿拉伯语(埃及)
  • ar-ly 阿拉伯语(利比亚)
  • ar-dz 阿拉伯语(阿尔及利亚)
  • ar-ma 阿拉伯语(摩洛哥)
  • ar-tn 阿拉伯语(突尼斯)
  • ar-om 阿拉伯语(阿曼)
  • ar-ye 阿拉伯语(也门)
  • ar-sy 阿拉伯语(叙利亚)
  • ar-jo 阿拉伯语(约旦)
  • ar-lb 阿拉伯语(黎巴嫩)
  • ar-kw 阿拉伯语(科威特)
  • ar-ae 阿拉伯语(阿拉伯联合酋长国)
  • ar-bh 阿拉伯语(巴林)
  • ar-qa 阿拉伯语(卡塔尔)
  • eu 巴斯克语
  • bg 保加利亚语
  • be 贝劳语
  • ca 加泰罗尼亚语
  • zh-tw 中文(中国台湾)
  • zh-cn 中文(中华人民共和国)
  • zh-hk 中文(中国香港特别行政区)
  • zh-sg 中文(新加坡)
  • hr 克罗地亚语
  • cs 捷克语
  • da 丹麦语
  • nl 荷兰语(标准)
  • nl-be 荷兰语(比利时)
  • en 英语
  • en-us 英语(美国)
  • en-gb 英语(英国)
  • en-au 英语(澳大利亚)
  • en-ca 英语(加拿大)
  • en-nz 英语(新西兰)
  • en-ie 英语(爱尔兰)
  • en-za 英语(南非)
  • en-jm 英语(牙买加)
  • en 英语(加勒比)
  • en-bz 英语(伯利兹)
  • en-tt 英语(特立尼达)
  • et 爱沙尼亚语
  • fo 法罗语
  • fa 波斯语
  • fi 芬兰语
  • fr 法语(标准)
  • fr-be 法语(比利时)
  • fr-ca 法语(加拿大)
  • fr-ch 法语(瑞士)
  • fr-lu 法语(卢森堡)
  • gd 盖尔语(苏格兰)
  • gd-ie 盖尔语(爱尔兰)
  • de 德语(标准)
  • de-ch 德语(瑞士)
  • de-at 德语(奥地利)
  • de-lu 德语(卢森堡)
  • de-li 德语(列支敦士登)
  • el 希腊语
  • he 希伯来语
  • hi 北印度语
  • hu 匈牙利语
  • is 冰岛语
  • in 印度尼西亚语
  • it 意大利语(标准)
  • it-ch 意大利语(瑞士)
  • ja 日语
  • ko 朝鲜语
  • ko 朝鲜语(韩国)
  • lv 拉脱维亚语
  • lt 立陶宛语
  • mk FYRO 马其顿语
  • ms 马来西亚语
  • mt 马耳他语
  • no 挪威语(博克马尔)
  • no 挪威语(尼诺斯克)
  • pl 波兰语
  • pt-br 葡萄牙语(巴西)
  • pt 葡萄牙语(葡萄牙)
  • rm 拉丁语系
  • ro 罗马尼亚语
  • ro-mo 罗马尼亚语(摩尔达维亚)
  • ru 俄语
  • ru-mo 俄语(摩尔达维亚)
  • sz 萨摩斯语(拉普兰)
  • sr 塞尔维亚语(西里尔)
  • sr 塞尔维亚语(拉丁)
  • sk 斯洛伐克语
  • sl 斯洛文尼亚语
  • sb 索布语
  • es 西班牙语(西班牙传统)
  • es-mx 西班牙语(墨西哥)
  • es 西班牙语(西班牙现代)
  • es-gt 西班牙语(危地马拉)
  • es-cr 西班牙语(哥斯达黎加)
  • es-pa 西班牙语(巴拿马)
  • es-do 西班牙语(多米尼加共和国)
  • es-ve 西班牙语(委内瑞拉)
  • es-co 西班牙语(哥伦比亚)
  • es-pe 西班牙语(秘鲁)
  • es-ar 西班牙语(阿根廷)
  • es-ec 西班牙语(厄瓜多尔)
  • es-cl 西班牙语(智利)
  • es-uy 西班牙语(乌拉圭)
  • es-py 西班牙语(巴拉圭)
  • es-bo 西班牙语(玻利维亚)
  • es-sv 西班牙语(萨尔瓦多)
  • es-hn 西班牙语(洪都拉斯)
  • es-ni 西班牙语(尼加拉瓜)
  • es-pr 西班牙语(波多黎各)
  • sx 苏图语
  • sv 瑞典语
  • sv-fi 瑞典语(芬兰)
  • th 泰语
  • ts 汤加语
  • tn 瓦纳语
  • tr 土耳其语
  • uk 乌克兰语
  • ur 乌尔都语
  • ve 文达语
  • vi 越南语
  • xh 科萨语
  • ji 依地语
  • zu 祖鲁语
 

标签:翻译,国际化,本地化,django,ar,字符串,Django,my,es
From: https://www.cnblogs.com/cutesnow/p/18145372

相关文章

  • CentOS+Django+uWSGI+Celery+Supervisor配置
    目录背景目录安装配置Supervisor1.生成配置文件2.修改配置文件3.创建进程文件创建uwsgi.conf进程文件创建celery进程文件启动supervisor启动supervisor查看所有进程的状态常用命令配置文件详解背景使用Django开发的项目需要部署到CentOS中,项目中使用了Celery和uWSGI......
  • django 不推荐使用 makemigrations migrate
    个人使用感触,希望大家交流讨论发现用django去管理数据库这些操作,以下两点可能感觉用着还可以,1.对于定义好表结构,字段的这些,并且开发中不修改,很少修改的用着还行,2.习惯用这种方式的,php的laravel也是,不过,试过之后,就很少用了;我说说我的理由:1.最简单的,这边该维护model维护mo......
  • 3小时搞定DRF框架 | Django REST framework前后端分离框架实践
    DRF(全称DjangoRESTframework)是一个用于构建WebAPI的强力工具集,是一个基于Django的PythonWeb框架,它为开发人员提供了一套快速开发RESTfulAPI的工具,它能够自动化API可视化、文档化,实现接口的自动化测试以及自动化的API路由、序列化、视图、验证、分页、版本管理、认证等......
  • 【Django】
    https://www.djangoproject.com/MTVAnaconda:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D创建和管理虚拟环境,这些环境可以包含不同版本的Python和安装的包,这在数据科学工具的使用中非常有用;Pip没有内置支持环境隔离,需要依赖其他工具,如virtualenv或venv来......
  • Django Page not found at 问题排查
    1、确认请求路径是否正确,与setting.py中进行对比2、如果setting中路径是导入app中的路径,setting.py的路径需要是否正确,还要要看对应app下urls.py中的路径是否正确 3、如果是请求上传的图片,需要确认setting.py中配置文件路基没,如果配置了需要确认base_dir指向的路基是否正确......
  • Elasticsearch之-Django框架集成
    目录Elasticsearch之-Django框架集成一、elasticsearch-dsl库的使用二、与django框架集成Elasticsearch之-Django框架集成需要安装的库:安装:pip3installelasticsearch-dsl一、elasticsearch-dsl库的使用#示例fromdatetimeimportdatetimefromelasticsearch_dslimpo......
  • 【Python】Django中的static资源访问404的问题
    [本文出自天外归云的博客园]如果你发现你本地部署没问题,部署到生产环境服务器后提示404找不到静态资源文件。不是你的代码有问题,而是你没有使用--insecure参数启动服务。pythonmanage.pyrunserver0.0.0.0:8000--insecure但是这个insecure参数在Django4中已经去掉了,所以......
  • Python+Django+Html网页版人脸识别考勤打卡系统
    程序示例精选Python+Django+Html人脸识别考勤打卡系统如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助!前言这篇博客针对《Python+Django+Html网页版人脸识别考勤打卡系统》编写代码,代码整洁,规则,易读。学习与应用推荐首选。运行结果文章......
  • python计算机毕设【附源码】养老院管理系统(django+mysql+论文)
    本系统(程序+源码)带文档lw万字以上  文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:随着社会的快速发展,人口老龄化问题日益凸显。养老院作为为老年人提供居住、医疗、康复、娱乐等综合服务的场所,其管理水平和服务质量对老年人的生活质量有着......
  • Django ModelSerializer 中如何实现自定义验证
    随着Web开发的日益复杂化,对数据验证的需求也日益增加。DjangoRESTframework提供了一套强大的、灵活的验证系统,帮助开发者轻松处理各种复杂情况。本文将重点探讨DjangoModelSerializer中如何实现自定义验证。1.简介DjangoModelSerializer不仅简化了序列化过程,还内建了......