{"title":"翻译","version":"5.1","locale":"zh-hans","docname":"topics/i18n/translation","url":"/zh-hans/5.1/topics/i18n/translation/","canonical":"https://djangodocs.dev/zh-hans/5.1/topics/i18n/translation/","summary":"为了使 Django 项目可以翻译，你需要在 Python 代码和模板中添加少量钩子。这些钩子被成为 translation strings 。","html":"<h1>翻译<a class=\"heading-anchor\" href=\"#translation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<section id=\"overview\">\n<h2>概况<a class=\"heading-anchor\" href=\"#overview\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>为了使 Django 项目可以翻译，你需要在 Python 代码和模板中添加少量钩子。这些钩子被成为 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/i18n/#term-translation-string\"><span class=\"xref std std-term\">translation strings</span></a> 。它们告知Django：如果在终端用户语言里，这个文本有对应的翻译，那么应该使用翻译。标记字符串是你的职责，系统只会翻译它知道的字符串。</p>\n<p>然后 Django 提供工具将翻译字符串提取到 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/i18n/#term-message-file\"><span class=\"xref std std-term\">message file</span></a> 中。这个文件让翻译者方便地提供翻译字符串。一旦翻译者填写了 message file ，就必须编译它。这个过程依赖 GNU gettext 工具集。</p>\n<p>一旦完成这些步骤，Django 将根据用户的语言偏好，动态地将 web 应用程序翻译成每种可用的语言。</p>\n<p>Django 的国际化钩子默认是开启的，这意味着在框架的某些位置存在一些 i18n 相关的开销。如果你不使用国际化，你应该在配置文件里设置 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-USE_I18N\"><code class=\"xref std std-setting docutils literal notranslate\">USE_I18N = False</code></a> 。然后 Django 将进行优化，以免加载国际化机制。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>确保你的项目已经激活了翻译（最快的办法是检查 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 是否包含 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.middleware.locale.LocaleMiddleware\" title=\"django.middleware.locale.LocaleMiddleware\"><code class=\"xref py py-mod docutils literal notranslate\">django.middleware.locale.LocaleMiddleware</code></a> ）。如果还没有激活，请查看“ Django 如何发现语言偏好（ <a class=\"reference internal\" href=\"#how-django-discovers-language-preference\"><span class=\"std std-ref\">Django 如何发现语言偏好</span></a> ）”。</p>\n</aside>\n</section>\n<section id=\"internationalization-in-python-code\">\n<h2>在 Python 代码中进行国际化<a class=\"heading-anchor\" href=\"#internationalization-in-python-code\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"standard-translation\">\n<h3>标准翻译<a class=\"heading-anchor\" href=\"#standard-translation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>使用函数 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext\" title=\"django.utils.translation.gettext\"><code class=\"xref py py-func docutils literal notranslate\">gettext()</code></a> 来指定翻译字符串。按照惯例，将其作为下划线( _ )导入，以保存输入。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>Python 标准库 <code class=\"docutils literal notranslate\">gettext</code> 模块在全局命名空间里安装了 <code class=\"docutils literal notranslate\">_()</code> 。在 Django 里，我们没有遵循这个做法，出于下面两个原因：</p>\n<ol class=\"arabic simple\">\n<li><p>有时，对于特定文件，你应该使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext_lazy\" title=\"django.utils.translation.gettext_lazy\"><code class=\"xref py py-func docutils literal notranslate\">gettext_lazy()</code></a> 作为默认翻译方法。如果全局命名空间里没有 <code class=\"docutils literal notranslate\">_()</code> ，开发者必须考虑哪个是最合适的翻译函数。</p></li>\n<li><p>下划线(&quot;_&quot;) 用于表示在 Python 的交互式终端和 doctest 测试中 &quot;上一个结果&quot; 。安装全局 <code class=\"docutils literal notranslate\">_()</code> 函数会引发冲突。导入 <code class=\"docutils literal notranslate\">gettext()</code> 替换 <code class=\"docutils literal notranslate\">_()</code> 可以避免这个问题。</p></li>\n</ol>\n</aside>\n<aside class=\"admonition-what-functions-may-be-aliased-as admonition\" role=\"note\">\n<p class=\"admonition-title\">哪些函数能以 <code class=\"docutils literal notranslate\">_</code> 为别名？</p>\n<p>由于 <code class=\"docutils literal notranslate\">xgettext</code> （<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> 使用）的工作方式，只有带有单一字符串参数的函数才能当做 <code class=\"docutils literal notranslate\">_</code> 引入：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext\" title=\"django.utils.translation.gettext\"><code class=\"xref py py-func docutils literal notranslate\">gettext()</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext_lazy\" title=\"django.utils.translation.gettext_lazy\"><code class=\"xref py py-func docutils literal notranslate\">gettext_lazy()</code></a></p></li>\n</ul>\n</aside>\n<p>在这个例子里，文本  <code class=\"docutils literal notranslate\">&quot;Welcome to my site.&quot;</code>  被标记为翻译字符串：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext <span class=\"k\">as</span> _\n\n\n<span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    output <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;Welcome to my site.&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span>output<span class=\"p\">)</span>\n</code></pre></div>\n<p>代码里可以不使用别名。这个例子与上一个例子等同：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext\n\n\n<span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    output <span class=\"o\">=</span> gettext<span class=\"p\">(</span><span class=\"s2\">&quot;Welcome to my site.&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span>output<span class=\"p\">)</span>\n</code></pre></div>\n<p>翻译适用于计算值。这个例子与前面两个例子等同：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    words <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;Welcome&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;to&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;my&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;site.&quot;</span><span class=\"p\">]</span>\n    output <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s2\">&quot; &quot;</span><span class=\"o\">.</span>join<span class=\"p\">(</span>words<span class=\"p\">))</span>\n    <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span>output<span class=\"p\">)</span>\n</code></pre></div>\n<p>翻译适用于变量。同样，这个例子和上面的等同：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    sentence <span class=\"o\">=</span> <span class=\"s2\">&quot;Welcome to my site.&quot;</span>\n    output <span class=\"o\">=</span> _<span class=\"p\">(</span>sentence<span class=\"p\">)</span>\n    <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span>output<span class=\"p\">)</span>\n</code></pre></div>\n<p>(像上述两个例子那样，使用变量或计算值的警告是： Django 的翻译字符检测实用程序 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a> 不能找到这些字符串。更多细节在稍后的  <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a>  介绍。)</p>\n<p>传递到 <code class=\"docutils literal notranslate\">_()</code> or <code class=\"docutils literal notranslate\">gettext()</code>  的字符串可以使用占位符，这是 Python 标准命名字符串插值语法指定的。例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<span class=\"p\">,</span> m<span class=\"p\">,</span> d<span class=\"p\">):</span>\n    output <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;Today is </span><span class=\"si\">%(month)s</span><span class=\"s2\"> </span><span class=\"si\">%(day)s</span><span class=\"s2\">.&quot;</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span><span class=\"s2\">&quot;month&quot;</span><span class=\"p\">:</span> m<span class=\"p\">,</span> <span class=\"s2\">&quot;day&quot;</span><span class=\"p\">:</span> d<span class=\"p\">}</span>\n    <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span>output<span class=\"p\">)</span>\n</code></pre></div>\n<p>这是技巧使得特定语言翻译可以重新排序占位符字段。比如，一条英文翻译可能是 <code class=\"docutils literal notranslate\">&quot;Today is November 26.&quot;</code> ，而对于西班牙翻译可能就是  <code class=\"docutils literal notranslate\">&quot;Hoy es 26 de noviembre.&quot;</code> ——其中月份和日期占位符互相交换。</p>\n<p>所以，当你有多个参数的时候，你应该使用命名字符串插值（比如 %(day)s ）而不是位置插值（比如 %s 或 %d ）。如果你使用位置插值，翻译时就不会对占位符字段重新排序。</p>\n<p>因为字符串提取由 <code class=\"docutils literal notranslate\">xgettext</code> 命令行完成，Django 仅支持由 <code class=\"docutils literal notranslate\">gettext</code> 支持的语法。特别是，<code class=\"docutils literal notranslate\">xgettext</code> 尚未支持 Python <a class=\"reference external\" href=\"https://docs.python.org/3/reference/lexical_analysis.html#f-strings\" title=\"(in Python v3.14)\"><span class=\"xref std std-ref\">f-strings</span></a> ，而 JavaScript 模板字符串需要 <code class=\"docutils literal notranslate\">gettext</code> 0.21+ 。</p>\n</section>\n<section id=\"comments-for-translators\">\n<span id=\"translator-comments\"></span><h3>为翻译者提供注释<a class=\"heading-anchor\" href=\"#comments-for-translators\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你想为翻译者提供一些翻译字段的提示，你可以添加以 <code class=\"docutils literal notranslate\">Translators</code> 为前缀的注释。例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span> <span class=\"nf\">my_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"c1\"># Translators: This message appears on the home page only</span>\n    output <span class=\"o\">=</span> gettext<span class=\"p\">(</span><span class=\"s2\">&quot;Welcome to my site.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>这个注释将出现在 <code class=\"docutils literal notranslate\">.po</code> 文件中与所翻译词条相关的词条下方，并且也应该由大部分翻译工具显示。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>为了完整起见，这是 <code class=\"docutils literal notranslate\">.po</code> 文件的相应片段：</p>\n<div class=\"code-block\" data-language=\"po\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Po</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Po code\"><code><span class=\"c1\">#. Translators: This message appears on the home page only</span>\n<span class=\"c1\"># path/to/python/file.py:123</span>\n<span class=\"nv\">msgid</span> <span class=\"s\">&quot;Welcome to my site.&quot;</span>\n<span class=\"nv\">msgstr</span> <span class=\"s\">&quot;&quot;</span>\n</code></pre></div>\n</aside>\n<p>这个办法在模板里也同样适用。查看 <a class=\"reference internal\" href=\"#translator-comments-in-templates\"><span class=\"std std-ref\">模板内对翻译的注释</span></a> 来获取更多详情。</p>\n</section>\n<section id=\"marking-strings-as-no-op\">\n<h3>标记不用翻译的字符<a class=\"heading-anchor\" href=\"#marking-strings-as-no-op\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext_noop\" title=\"django.utils.translation.gettext_noop\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.gettext_noop()</code></a> 来将字符串标记不用翻译的翻译字符串。这个字符会稍后使用变量来翻译。</p>\n<p>使用该方法的场景是：如果你有一个常量字符串，该字符串以源语言存储，它们通过系统或用户进行交换（比如数据库里的字符串），但应该最后可能的时间点进行翻译，比如当字符串展示给用户时。</p>\n</section>\n<section id=\"pluralization\">\n<h3>多元化<a class=\"heading-anchor\" href=\"#pluralization\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>使用  <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.ngettext\" title=\"django.utils.translation.ngettext\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.ngettext()</code></a>  函数指定多元化信息。</p>\n<p><code class=\"docutils literal notranslate\">ngettext()</code> 带有三个参数：单数翻译字符串，复数翻译字符串和一些对象。</p>\n<p>当你需要 Django 应用本地化为复数形式的数量和复杂度大于英语中使用的两种形式的语言时，该函数非常有用。（'object' 表示单数，'objects' 表示  <code class=\"docutils literal notranslate\">count</code>  不同于1时的所有情况，不论其值如何）</p>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> ngettext\n\n\n<span class=\"k\">def</span> <span class=\"nf\">hello_world</span><span class=\"p\">(</span>request<span class=\"p\">,</span> count<span class=\"p\">):</span>\n    page <span class=\"o\">=</span> ngettext<span class=\"p\">(</span>\n        <span class=\"s2\">&quot;there is </span><span class=\"si\">%(count)d</span><span class=\"s2\"> object&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;there are </span><span class=\"si\">%(count)d</span><span class=\"s2\"> objects&quot;</span><span class=\"p\">,</span>\n        count<span class=\"p\">,</span>\n    <span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;count&quot;</span><span class=\"p\">:</span> count<span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n    <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span>page<span class=\"p\">)</span>\n</code></pre></div>\n<p>在这个例子里，对象的数量作为 count 变量传递给翻译语言。</p>\n<p>要注意复数形式是复杂的，并且在每种语言中工作方式不同。比较 count 和 1 并不总是正确的规则。该代码看着很复杂，但会对某些语言产生不正确的结果：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> ngettext\n<span class=\"kn\">from</span> <span class=\"nn\">myapp.models</span> <span class=\"kn\">import</span> Report\n\ncount <span class=\"o\">=</span> Report<span class=\"o\">.</span>objects<span class=\"o\">.</span>count<span class=\"p\">()</span>\n<span class=\"k\">if</span> count <span class=\"o\">==</span> <span class=\"mi\">1</span><span class=\"p\">:</span>\n    name <span class=\"o\">=</span> Report<span class=\"o\">.</span>_meta<span class=\"o\">.</span>verbose_name\n<span class=\"k\">else</span><span class=\"p\">:</span>\n    name <span class=\"o\">=</span> Report<span class=\"o\">.</span>_meta<span class=\"o\">.</span>verbose_name_plural\n\ntext <span class=\"o\">=</span> ngettext<span class=\"p\">(</span>\n    <span class=\"s2\">&quot;There is </span><span class=\"si\">%(count)d</span><span class=\"s2\"> </span><span class=\"si\">%(name)s</span><span class=\"s2\"> available.&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;There are </span><span class=\"si\">%(count)d</span><span class=\"s2\"> </span><span class=\"si\">%(name)s</span><span class=\"s2\"> available.&quot;</span><span class=\"p\">,</span>\n    count<span class=\"p\">,</span>\n<span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span><span class=\"s2\">&quot;count&quot;</span><span class=\"p\">:</span> count<span class=\"p\">,</span> <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> name<span class=\"p\">}</span>\n</code></pre></div>\n<p>不要尝试实现自定义的单数或复数逻辑，它会出错的。像在这种例子中，请考虑以下内容：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>text <span class=\"o\">=</span> ngettext<span class=\"p\">(</span>\n    <span class=\"s2\">&quot;There is </span><span class=\"si\">%(count)d</span><span class=\"s2\"> </span><span class=\"si\">%(name)s</span><span class=\"s2\"> object available.&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;There are </span><span class=\"si\">%(count)d</span><span class=\"s2\"> </span><span class=\"si\">%(name)s</span><span class=\"s2\"> objects available.&quot;</span><span class=\"p\">,</span>\n    count<span class=\"p\">,</span>\n<span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;count&quot;</span><span class=\"p\">:</span> count<span class=\"p\">,</span>\n    <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> Report<span class=\"o\">.</span>_meta<span class=\"o\">.</span>verbose_name<span class=\"p\">,</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" id=\"pluralization-var-notes\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>当使用 <code class=\"docutils literal notranslate\">ngettext()</code> 时，要确保为每一个变量使用一个名称。上面的例子中，请注意我们在两个翻译字符串中如何使用 <code class=\"docutils literal notranslate\">name</code> Python 变量。该例子除了上面提到的错误外，还会遇到下面的问题：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>text <span class=\"o\">=</span> ngettext<span class=\"p\">(</span>\n    <span class=\"s2\">&quot;There is </span><span class=\"si\">%(count)d</span><span class=\"s2\"> </span><span class=\"si\">%(name)s</span><span class=\"s2\"> available.&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;There are </span><span class=\"si\">%(count)d</span><span class=\"s2\"> </span><span class=\"si\">%(plural_name)s</span><span class=\"s2\"> available.&quot;</span><span class=\"p\">,</span>\n    count<span class=\"p\">,</span>\n<span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;count&quot;</span><span class=\"p\">:</span> Report<span class=\"o\">.</span>objects<span class=\"o\">.</span>count<span class=\"p\">(),</span>\n    <span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> Report<span class=\"o\">.</span>_meta<span class=\"o\">.</span>verbose_name<span class=\"p\">,</span>\n    <span class=\"s2\">&quot;plural_name&quot;</span><span class=\"p\">:</span> Report<span class=\"o\">.</span>_meta<span class=\"o\">.</span>verbose_name_plural<span class=\"p\">,</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>当运行 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages</code></a> 时，你将会收到一个错误：</p>\n<div class=\"code-block\" data-language=\"pytb\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Pytb</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Pytb code\"><code><span class=\"x\">a format specification for argument &#39;name&#39;, as in &#39;msgstr[0]&#39;, doesn&#39;t exist in &#39;msgid&#39;</span>\n</code></pre></div>\n</aside>\n</section>\n<section id=\"contextual-markers\">\n<span id=\"id1\"></span><h3>上下文标记<a class=\"heading-anchor\" href=\"#contextual-markers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>一些词组有很多不同含义，比如 <code class=\"docutils literal notranslate\">&quot;May&quot;</code> ，它指五月或者表示一个动词。为了使翻译者在不同上下文中正确翻译这些词组，可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.pgettext\" title=\"django.utils.translation.pgettext\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.pgettext()</code></a> 函数，或者如果字符串需要复数形式的话，可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.npgettext\" title=\"django.utils.translation.npgettext\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.npgettext()</code></a> 函数。两者都使用上下文字符串作为第一个变量。</p>\n<p>在生成的 <code class=\"docutils literal notranslate\">.po</code> 文件中，字符串将会频繁出现，因为相同字符串 ( 上下文将在 <code class=\"docutils literal notranslate\">msgctxt</code> 行上显示) 有不同的上下文标记，所以允许翻译者为每个字符串给出不同翻译。</p>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> pgettext\n\nmonth <span class=\"o\">=</span> pgettext<span class=\"p\">(</span><span class=\"s2\">&quot;month name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;May&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>或者：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> pgettext_lazy\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyThing</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>\n        help_text<span class=\"o\">=</span>pgettext_lazy<span class=\"p\">(</span><span class=\"s2\">&quot;help text for MyThing model&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;This is the help text&quot;</span><span class=\"p\">)</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>将以下方形式出现在 <code class=\"docutils literal notranslate\">.po</code> 文件中：</p>\n<div class=\"code-block\" data-language=\"po\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Po</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Po code\"><code><span class=\"nv\">msgctxt</span> <span class=\"s\">&quot;month name&quot;</span>\n<span class=\"nv\">msgid</span> <span class=\"s\">&quot;May&quot;</span>\n<span class=\"nv\">msgstr</span> <span class=\"s\">&quot;&quot;</span>\n</code></pre></div>\n<p>上下文标记也由 <a class=\"reference internal\" href=\"#std-templatetag-translate\"><code class=\"xref std std-ttag docutils literal notranslate\">translate</code></a> 和 <a class=\"reference internal\" href=\"#std-templatetag-blocktranslate\"><code class=\"xref std std-ttag docutils literal notranslate\">blocktranslate</code></a> 模板标签支持。</p>\n</section>\n<section id=\"lazy-translation\">\n<span id=\"lazy-translations\"></span><h3>惰性翻译<a class=\"heading-anchor\" href=\"#lazy-translation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>当访问值而不是调用它们时，使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#module-django.utils.translation\" title=\"django.utils.translation: Internationalization support.\"><code class=\"xref py py-mod docutils literal notranslate\">django.utils.translation</code></a> 中翻译函数的惰性版本 (在名称中加入 <code class=\"docutils literal notranslate\">lazy</code> 前缀来识别) 来延迟翻译字符串。</p>\n<p>这些函数存储对字符串的惰性引用 —— 并非真实的翻译。当在字符串上下文里使用字符串时，才会翻译。比如模板渲染。</p>\n<p>当对这些函数的调用位于模块加载时执行的代码路径中时，这一点非常重要。</p>\n<p>在定义模型、表单和模型表单的时候，很容易遇见这种情况，因为 Django 已经实现了这些，所以它们的字段实际是类级别的属性。因此，请确保以下情况下使用惰性翻译：</p>\n<section id=\"model-fields-and-relationships-verbose-name-and-help-text-option-values\">\n<h4>模型字段和相关的 <code class=\"docutils literal notranslate\">verbose_name</code> 与 <code class=\"docutils literal notranslate\">help_text</code> 选项值<a class=\"heading-anchor\" href=\"#model-fields-and-relationships-verbose-name-and-help-text-option-values\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>比如下面这个模型，为了翻译其中 <em>name</em> 字段的帮助提示，可以这么做：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyThing</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>help_text<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;This is the help text&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>你可以通过使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/options/#django.db.models.Options.verbose_name\" title=\"django.db.models.Options.verbose_name\"><code class=\"xref py py-attr docutils literal notranslate\">verbose_name</code></a> 选项来将  <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\">ForeignKey</code></a>, <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyField</code></a> 或 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/fields/#django.db.models.OneToOneField\" title=\"django.db.models.OneToOneField\"><code class=\"xref py py-class docutils literal notranslate\">OneToOneField</code></a> 关系标记为可翻译：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span> <span class=\"nc\">MyThing</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    kind <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>\n        ThingKind<span class=\"p\">,</span>\n        on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<span class=\"p\">,</span>\n        related_name<span class=\"o\">=</span><span class=\"s2\">&quot;kinds&quot;</span><span class=\"p\">,</span>\n        verbose_name<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;kind&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>就像你在 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/options/#django.db.models.Options.verbose_name\" title=\"django.db.models.Options.verbose_name\"><code class=\"xref py py-attr docutils literal notranslate\">verbose_name</code></a> 中所做的那样，你应该为关系提供一个小写的详细名称文本，因为 Django 会在需要时自动为其命名。</p>\n</section>\n<section id=\"model-verbose-names-values\">\n<h4>模型详细名称的值<a class=\"heading-anchor\" href=\"#model-verbose-names-values\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>建议始终提供显式的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/options/#django.db.models.Options.verbose_name\" title=\"django.db.models.Options.verbose_name\"><code class=\"xref py py-attr docutils literal notranslate\">verbose_name</code></a> 和  <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/options/#django.db.models.Options.verbose_name_plural\" title=\"django.db.models.Options.verbose_name_plural\"><code class=\"xref py py-attr docutils literal notranslate\">verbose_name_plural</code></a> 选项，而不是依赖 Django 查看模型的类名来确定以英文为主而且有点简单的详细名称：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyThing</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">),</span> help_text<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;This is the help text&quot;</span><span class=\"p\">))</span>\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        verbose_name <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;my thing&quot;</span><span class=\"p\">)</span>\n        verbose_name_plural <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;my things&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"model-methods-description-argument-to-the-display-decorator\">\n<h4>模型方法 <code class=\"docutils literal notranslate\">description</code> 参数用于 <code class=\"docutils literal notranslate\">&#64;display</code> 装饰器。<a class=\"heading-anchor\" href=\"#model-methods-description-argument-to-the-display-decorator\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>对于模型方法，你可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.display\" title=\"django.contrib.admin.display\"><code class=\"xref py py-func docutils literal notranslate\">display()</code></a> 装饰器的 <code class=\"docutils literal notranslate\">description</code> 参数来提供翻译给 Django 和管理站点：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n<span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyThing</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    kind <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>\n        ThingKind<span class=\"p\">,</span>\n        on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<span class=\"p\">,</span>\n        related_name<span class=\"o\">=</span><span class=\"s2\">&quot;kinds&quot;</span><span class=\"p\">,</span>\n        verbose_name<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;kind&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">)</span>\n\n    <span class=\"nd\">@admin</span><span class=\"o\">.</span>display<span class=\"p\">(</span>description<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;Is it a mouse?&quot;</span><span class=\"p\">))</span>\n    <span class=\"k\">def</span> <span class=\"nf\">is_mouse</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span>kind<span class=\"o\">.</span>type <span class=\"o\">==</span> MOUSE_TYPE\n</code></pre></div>\n</section>\n</section>\n<section id=\"working-with-lazy-translation-objects\">\n<h3>使用惰性翻译对象<a class=\"heading-anchor\" href=\"#working-with-lazy-translation-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\">gettext_lazy()</code> 调用的结果可以在你在其他 Django 代码中使用字符串（一个 <a class=\"reference external\" href=\"https://docs.python.org/3/library/stdtypes.html#str\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\">str</code></a> 对象）的地方使用，但它可能无法与任意的 Python 代码一起工作。例如，以下代码将不起作用，因为 <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/requests/\">requests</a> 库不处理 <code class=\"docutils literal notranslate\">gettext_lazy</code> 对象：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>body <span class=\"o\">=</span> gettext_lazy<span class=\"p\">(</span><span class=\"s2\">&quot;I </span><span class=\"se\">\\u2764</span><span class=\"s2\"> Django&quot;</span><span class=\"p\">)</span>  <span class=\"c1\"># (Unicode :heart:)</span>\nrequests<span class=\"o\">.</span>post<span class=\"p\">(</span><span class=\"s2\">&quot;https://example.com/send&quot;</span><span class=\"p\">,</span> data<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;body&quot;</span><span class=\"p\">:</span> body<span class=\"p\">})</span>\n</code></pre></div>\n<p>要想避免这些问题，你可以在文本字符传递给非 Django 代码之前，将  <code class=\"docutils literal notranslate\">gettext_lazy()</code> 对象转换为文本字符。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>requests<span class=\"o\">.</span>post<span class=\"p\">(</span><span class=\"s2\">&quot;https://example.com/send&quot;</span><span class=\"p\">,</span> data<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;body&quot;</span><span class=\"p\">:</span> <span class=\"nb\">str</span><span class=\"p\">(</span>body<span class=\"p\">)})</span>\n</code></pre></div>\n<p>如果你觉得 <code class=\"docutils literal notranslate\">gettext_lazy</code> 这个名字有点长，你可以定义它的别名为下划线 <code class=\"docutils literal notranslate\">_</code> ，像这样：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyThing</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>help_text<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;This is the help text&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>在模型和工具函数里使用 <code class=\"docutils literal notranslate\">gettext_lazy()</code> 和 <code class=\"docutils literal notranslate\">ngettext_lazy()</code> 来标记字符串是个常用方法。但在代码的其他地方使用这些对象时，你要确保它们不会被不小心转化为字符串，因为它们要尽量晚一些被转换（以便正确的语言环境生效）。这需要使用下面所描述的帮助函数。</p>\n<section id=\"lazy-translations-and-plural\">\n<span id=\"lazy-plural-translations\"></span><h4>惰性翻译与复数<a class=\"heading-anchor\" href=\"#lazy-translations-and-plural\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>当为复数字符串 (<code class=\"docutils literal notranslate\">n[p]gettext_lazy</code>) 使用惰性翻译时，通常不知道字符串定义时  <code class=\"docutils literal notranslate\">number</code> 参数值。因此，你可以传递一个关键字名称来作为  <code class=\"docutils literal notranslate\">number</code> 参数而不是整数。然后，在插值期间，会在字典里查找 <code class=\"docutils literal notranslate\">number</code>。例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django</span> <span class=\"kn\">import</span> forms\n<span class=\"kn\">from</span> <span class=\"nn\">django.core.exceptions</span> <span class=\"kn\">import</span> ValidationError\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> ngettext_lazy\n\n\n<span class=\"k\">class</span> <span class=\"nc\">MyForm</span><span class=\"p\">(</span>forms<span class=\"o\">.</span>Form<span class=\"p\">):</span>\n    error_message <span class=\"o\">=</span> ngettext_lazy<span class=\"p\">(</span>\n        <span class=\"s2\">&quot;You only provided </span><span class=\"si\">%(num)d</span><span class=\"s2\"> argument&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;You only provided </span><span class=\"si\">%(num)d</span><span class=\"s2\"> arguments&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;num&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">clean</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"k\">if</span> error<span class=\"p\">:</span>\n            <span class=\"k\">raise</span> ValidationError<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>error_message <span class=\"o\">%</span> <span class=\"p\">{</span><span class=\"s2\">&quot;num&quot;</span><span class=\"p\">:</span> number<span class=\"p\">})</span>\n</code></pre></div>\n<p>如果字符串恰好包含一个未命名的占位符，你可以直接插入 <code class=\"docutils literal notranslate\">number</code> 参数：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span> <span class=\"nc\">MyForm</span><span class=\"p\">(</span>forms<span class=\"o\">.</span>Form<span class=\"p\">):</span>\n    error_message <span class=\"o\">=</span> ngettext_lazy<span class=\"p\">(</span>\n        <span class=\"s2\">&quot;You provided </span><span class=\"si\">%d</span><span class=\"s2\"> argument&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;You provided </span><span class=\"si\">%d</span><span class=\"s2\"> arguments&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">clean</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># ...</span>\n        <span class=\"k\">if</span> error<span class=\"p\">:</span>\n            <span class=\"k\">raise</span> ValidationError<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>error_message <span class=\"o\">%</span> number<span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"formatting-strings-format-lazy\">\n<h4>格式化字符串：<code class=\"docutils literal notranslate\">format_lazy()</code><a class=\"heading-anchor\" href=\"#formatting-strings-format-lazy\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>当 <code class=\"docutils literal notranslate\">format_string</code> 或 <a class=\"reference external\" href=\"https://docs.python.org/3/library/stdtypes.html#str.format\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\">str.format()</code></a> 的任何参数包含惰性转换对象时，Python的 <a class=\"reference external\" href=\"https://docs.python.org/3/library/stdtypes.html#str.format\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\">str.format()</code></a> 方法将不起作用。相反，你可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.text.format_lazy\" title=\"django.utils.text.format_lazy\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.text.format_lazy()</code></a> ，它会创建一个仅当结果包含在字符串里时会才运行 <code class=\"docutils literal notranslate\">str.format()</code> 的惰性对象。比如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils.text</span> <span class=\"kn\">import</span> format_lazy\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy\n\n<span class=\"o\">...</span>\nname <span class=\"o\">=</span> gettext_lazy<span class=\"p\">(</span><span class=\"s2\">&quot;John Lennon&quot;</span><span class=\"p\">)</span>\ninstrument <span class=\"o\">=</span> gettext_lazy<span class=\"p\">(</span><span class=\"s2\">&quot;guitar&quot;</span><span class=\"p\">)</span>\nresult <span class=\"o\">=</span> format_lazy<span class=\"p\">(</span><span class=\"s2\">&quot;</span><span class=\"si\">{name}</span><span class=\"s2\">: </span><span class=\"si\">{instrument}</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span> name<span class=\"o\">=</span>name<span class=\"p\">,</span> instrument<span class=\"o\">=</span>instrument<span class=\"p\">)</span>\n</code></pre></div>\n<p>在这种情况下，在 <code class=\"docutils literal notranslate\">result</code> 中的惰性翻译仅在字符串(通常在模板渲染时间)里使用 <code class=\"docutils literal notranslate\">result</code> 时才会被转换成字符串。</p>\n</section>\n<section id=\"other-uses-of-lazy-in-delayed-translations\">\n<h4>延迟翻译中惰性(lazy)的其他用法<a class=\"heading-anchor\" href=\"#other-uses-of-lazy-in-delayed-translations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>对于“你想延迟翻译，但不得不传递要翻译的字符串作为参数到其他函数”的情况，你可以在惰性调用中包装这个函数。比如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils.functional</span> <span class=\"kn\">import</span> lazy\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\n\n<span class=\"k\">def</span> <span class=\"nf\">to_lower</span><span class=\"p\">(</span>string<span class=\"p\">):</span>\n    <span class=\"k\">return</span> string<span class=\"o\">.</span>lower<span class=\"p\">()</span>\n\n\nto_lower_lazy <span class=\"o\">=</span> lazy<span class=\"p\">(</span>to_lower<span class=\"p\">,</span> <span class=\"nb\">str</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>然后：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>lazy_string <span class=\"o\">=</span> to_lower_lazy<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;My STRING!&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"localized-names-of-languages\">\n<h3>语言的本地化名称<a class=\"heading-anchor\" href=\"#localized-names-of-languages\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.utils.translation.get_language_info\">\n<span class=\"sig-name descname\">get_language_info</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">lang_code</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.utils.translation.get_language_info\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\">get_language_info()</code> 函数提供关于语言的详细信息：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> activate<span class=\"p\">,</span> get_language_info\n<span class=\"gp\">&gt;&gt;&gt; </span>activate<span class=\"p\">(</span><span class=\"s2\">&quot;fr&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>li <span class=\"o\">=</span> get_language_info<span class=\"p\">(</span><span class=\"s2\">&quot;de&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"nb\">print</span><span class=\"p\">(</span>li<span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">],</span> li<span class=\"p\">[</span><span class=\"s2\">&quot;name_local&quot;</span><span class=\"p\">],</span> li<span class=\"p\">[</span><span class=\"s2\">&quot;name_translated&quot;</span><span class=\"p\">],</span> li<span class=\"p\">[</span><span class=\"s2\">&quot;bidi&quot;</span><span class=\"p\">])</span>\n<span class=\"go\">German Deutsch Allemand False</span>\n</code></pre></div>\n<p>字典的 <code class=\"docutils literal notranslate\">name</code>, <code class=\"docutils literal notranslate\">name_local</code>, 以及 <code class=\"docutils literal notranslate\">name_translated</code> 属性分别包含用英语、该语言本身以及当前启用的语言的名称。<code class=\"docutils literal notranslate\">bidi</code> 属性仅对于双向(bi-directional)语言为 True 。</p>\n<p>语言信息的来源是 <code class=\"docutils literal notranslate\">django.conf.locale</code> 模块。模板代码也可以使用类似方式访问信息。</p>\n</section>\n</section>\n<section id=\"internationalization-in-template-code\">\n<span id=\"specifying-translation-strings-in-template-code\"></span><h2>在模板代码中国际化<a class=\"heading-anchor\" href=\"#internationalization-in-template-code\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/templates/language/\"><span class=\"doc\">Django templates</span></a> 中的翻译使用两个模板标签，并且语法与 Python 代码中的语法略有不同。要使模板访问这些标签，需要在模板顶部加入 <code class=\"docutils literal notranslate\">{% load i18n %}</code> 。与所有模板标签一样，这个标签需要在所有需要翻译的模板中加载，甚至那些从其他模板继承(extend)而来的模板，也需要继承  <code class=\"docutils literal notranslate\">i18n</code> 标签。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>在渲染模板的时候，翻译后的字符串不会被转义。这使你在翻译中包含 HTML ，比如为了强调，但潜在的危险字符（比如 <code class=\"docutils literal notranslate\">&quot;</code>）也将保持不变。</p>\n</aside>\n<section id=\"translate-template-tag\">\n<span id=\"std-templatetag-translate\"></span><span id=\"std-templatetag-trans\"></span><h3><code class=\"docutils literal notranslate\">translate</code> 模板标签<a class=\"heading-anchor\" href=\"#translate-template-tag\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\">{% translate %}</code> 模板标签可以翻译一个常量字符串（包含在单引号或双引号中）或变量内容：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;This is the title.&quot;</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;/</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"nv\">myvar</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;/</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>如果存在 <code class=\"docutils literal notranslate\">noop</code> 选项，变量查找仍然会发生，但翻译会被跳过。这在将来需要翻译的内容中“存根化”时很有用：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;myvar&quot;</span> <span class=\"nv\">noop</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;/</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>在内部，内联翻译使用了 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext\" title=\"django.utils.translation.gettext\"><code class=\"xref py py-func docutils literal notranslate\">gettext()</code></a> 调用。</p>\n<p>如果模板变量（如上面的 <code class=\"docutils literal notranslate\">myvar</code> ）传递给了一个标签，该标签将在运行时首先将这些变量解析为字符串，然后在消息目录里查找变量。</p>\n<p>在 <code class=\"docutils literal notranslate\">{% translate %}</code> 中，不可能在字符串中混合模板变量。如果你的翻译需要变量字符串（占位符），请使用 <a class=\"reference internal\" href=\"#std-templatetag-blocktranslate\"><code class=\"xref std std-ttag docutils literal notranslate\">{% blocktranslate %}</code></a> 替代。</p>\n<p>如果你想获取一个已翻译的字符串而不显示它，你可以使用以下语法：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;This is the title&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">the_title</span> <span class=\"cp\">%}</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">the_title</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">meta</span> <span class=\"na\">name</span><span class=\"o\">=</span><span class=\"s\">&quot;description&quot;</span> <span class=\"na\">content</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">the_title</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>在实际应用中，你可以使用这个方法来获取一个可以在模板中多个地方使用的字符串，或者作为其他模板标签或过滤器的参数使用输出内容：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;starting point&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">start</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;end point&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">end</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;La Grande Boucle&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">race</span> <span class=\"cp\">%}</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span>\n  <span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;/&quot;</span> <span class=\"na\">title</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"cp\">%}</span><span class=\"s\">Back to &#39;</span><span class=\"cp\">{{</span> <span class=\"nv\">race</span> <span class=\"cp\">}}</span><span class=\"s\">&#39; homepage</span><span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">race</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">stage</span> <span class=\"k\">in</span> <span class=\"nv\">tour_stages</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">cycle</span> <span class=\"nv\">start</span> <span class=\"nv\">end</span> <span class=\"cp\">%}</span>: <span class=\"cp\">{{</span> <span class=\"nv\">stage</span> <span class=\"cp\">}}{%</span> <span class=\"k\">if</span> <span class=\"nb\">forloop</span><span class=\"nv\">.counter</span><span class=\"o\">|</span><span class=\"nf\">divisibleby</span><span class=\"o\">:</span><span class=\"m\">2</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;</span><span class=\"nt\">br</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span>, <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">{% translate %}</code> 也支持使用 <code class=\"docutils literal notranslate\">context</code> 关键词的 <a class=\"reference internal\" href=\"#contextual-markers\"><span class=\"std std-ref\">上下文标记</span></a>：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;May&quot;</span> <span class=\"nv\">context</span> <span class=\"s2\">&quot;month name&quot;</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n</section>\n<section id=\"blocktranslate-template-tag\">\n<span id=\"std-templatetag-blocktranslate\"></span><span id=\"std-templatetag-blocktrans\"></span><h3><code class=\"docutils literal notranslate\">blocktranslate</code> 模板标签<a class=\"heading-anchor\" href=\"#blocktranslate-template-tag\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>与 <a class=\"reference internal\" href=\"#std-templatetag-translate\"><code class=\"xref std std-ttag docutils literal notranslate\">translate</code></a> 标签相反，<code class=\"docutils literal notranslate\">blocktranslate</code> 标签允许你通过使用占位符来标记由文字和变量内容组成的复杂句子以进行翻译：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"cp\">%}</span>This string will have <span class=\"cp\">{{</span> <span class=\"nv\">value</span> <span class=\"cp\">}}</span> inside.<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>要翻译模板表达式，比如访问对象属性或使用模板过滤器，你需要将表达式绑定到一个本地变量中，以便在翻译块内使用。示例：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"k\">with</span> <span class=\"nv\">amount</span><span class=\"o\">=</span><span class=\"nv\">article.price</span> <span class=\"cp\">%}</span>\nThat will cost $ <span class=\"cp\">{{</span> <span class=\"nv\">amount</span> <span class=\"cp\">}}</span>.\n<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"k\">with</span> <span class=\"nv\">myvar</span><span class=\"o\">=</span><span class=\"nv\">value</span><span class=\"o\">|</span><span class=\"nf\">filter</span> <span class=\"cp\">%}</span>\nThis will have <span class=\"cp\">{{</span> <span class=\"nv\">myvar</span> <span class=\"cp\">}}</span> inside.\n<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>你可以在单个 <code class=\"docutils literal notranslate\">blocktranslate</code> 标签内使用多个表达式：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"k\">with</span> <span class=\"nv\">book_t</span><span class=\"o\">=</span><span class=\"nv\">book</span><span class=\"o\">|</span><span class=\"nf\">title</span> <span class=\"nv\">author_t</span><span class=\"o\">=</span><span class=\"nv\">author</span><span class=\"o\">|</span><span class=\"nf\">title</span> <span class=\"cp\">%}</span>\nThis is <span class=\"cp\">{{</span> <span class=\"nv\">book_t</span> <span class=\"cp\">}}</span> by <span class=\"cp\">{{</span> <span class=\"nv\">author_t</span> <span class=\"cp\">}}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>仍然支持以前的更简洁的格式：<code class=\"docutils literal notranslate\">{% blocktranslate with book|title as book_t and author|title as author_t %}</code>。</p>\n</aside>\n<p>其他块标签（例如 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\">{% for %}</code></a> 或 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/templates/builtins/#std-templatetag-if\"><code class=\"xref std std-ttag docutils literal notranslate\">{% if %}</code></a>）不能在 <code class=\"docutils literal notranslate\">blocktranslate</code> 标签内使用。</p>\n<p>如果解决一个区块参数失败，<code class=\"docutils literal notranslate\">blocktranslate</code> 将回到默认语言，暂时停用当前活动的语言与 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.deactivate_all\" title=\"django.utils.translation.deactivate_all\"><code class=\"xref py py-func docutils literal notranslate\">deactivate_all()</code></a> 函数。</p>\n<p>该标签也提供复数形式。要使用它：</p>\n<ul class=\"simple\">\n<li><p>指定并绑定名称为 <code class=\"docutils literal notranslate\">count</code> 的计数器值。该值将用于选择正确的复数形式。</p></li>\n<li><p>在 <code class=\"docutils literal notranslate\">{% blocktranslate %}</code> 和 <code class=\"docutils literal notranslate\">{% endblocktranslate %}</code> 标签中，用 <code class=\"docutils literal notranslate\">{% plural %}</code> 标签指定单数和复数形式，将它们分开。</p></li>\n</ul>\n<p>例子：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"nv\">count</span> <span class=\"nv\">counter</span><span class=\"o\">=</span><span class=\"nv\">list</span><span class=\"o\">|</span><span class=\"nf\">length</span> <span class=\"cp\">%}</span>\nThere is only one <span class=\"cp\">{{</span> <span class=\"nv\">name</span> <span class=\"cp\">}}</span> object.\n<span class=\"cp\">{%</span> <span class=\"k\">plural</span> <span class=\"cp\">%}</span>\nThere are <span class=\"cp\">{{</span> <span class=\"nv\">counter</span> <span class=\"cp\">}}</span> <span class=\"cp\">{{</span> <span class=\"nv\">name</span> <span class=\"cp\">}}</span> objects.\n<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>更复杂的例子：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"k\">with</span> <span class=\"nv\">amount</span><span class=\"o\">=</span><span class=\"nv\">article.price</span> <span class=\"nv\">count</span> <span class=\"nv\">years</span><span class=\"o\">=</span><span class=\"nv\">i.length</span> <span class=\"cp\">%}</span>\nThat will cost $ <span class=\"cp\">{{</span> <span class=\"nv\">amount</span> <span class=\"cp\">}}</span> per year.\n<span class=\"cp\">{%</span> <span class=\"k\">plural</span> <span class=\"cp\">%}</span>\nThat will cost $ <span class=\"cp\">{{</span> <span class=\"nv\">amount</span> <span class=\"cp\">}}</span> per <span class=\"cp\">{{</span> <span class=\"nv\">years</span> <span class=\"cp\">}}</span> years.\n<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>当你同时使用复数功能和将值绑定到本地变量上时，请记住，<code class=\"docutils literal notranslate\">blocktranslate</code> 结构在内部被转换为 <code class=\"docutils literal notranslate\">ngettext</code> 调用。这意味着同样的 <a class=\"reference internal\" href=\"#pluralization-var-notes\"><span class=\"std std-ref\">关于 ngettext 变量的注释</span></a> 适用。</p>\n<p>不能在 <code class=\"docutils literal notranslate\">blocktranslate</code> 内执行反向 URL 查找，应该在之前获取（并存储）它们：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;path.to.view&#39;</span> <span class=\"nv\">arg</span> <span class=\"nv\">arg2</span> <span class=\"k\">as</span> <span class=\"nv\">the_url</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"cp\">%}</span>\nThis is a URL: <span class=\"cp\">{{</span> <span class=\"nv\">the_url</span> <span class=\"cp\">}}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>如果你想获取一个已翻译的字符串而不显示它，你可以使用以下语法：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"nv\">asvar</span> <span class=\"nv\">the_title</span> <span class=\"cp\">%}</span>The title is <span class=\"cp\">{{</span> <span class=\"nv\">title</span> <span class=\"cp\">}}</span>.<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">the_title</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">title</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">meta</span> <span class=\"na\">name</span><span class=\"o\">=</span><span class=\"s\">&quot;description&quot;</span> <span class=\"na\">content</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">the_title</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>事实上你可以使用这个办法来获取一个在模板中多处使用的字符串，或将输出作为其他模板标签或过滤器的参数。</p>\n<p><code class=\"docutils literal notranslate\">{% blocktranslate %}</code> 也支持使用 <code class=\"docutils literal notranslate\">context</code> 关键字的 <a class=\"reference internal\" href=\"#contextual-markers\"><span class=\"std std-ref\">上下文标记</span></a> ：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"k\">with</span> <span class=\"nv\">name</span><span class=\"o\">=</span><span class=\"nv\">user.username</span> <span class=\"nv\">context</span> <span class=\"s2\">&quot;greeting&quot;</span> <span class=\"cp\">%}</span>Hi <span class=\"cp\">{{</span> <span class=\"nv\">name</span> <span class=\"cp\">}}{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">{% blocktranslate %}</code> 支持的另一个功能是 <code class=\"docutils literal notranslate\">trimmed</code> 选项。这个选项将删除 <code class=\"docutils literal notranslate\">{% blocktranslate %}</code> 标签的内容开头和结尾的换行符，替换每一行开头和结尾的空白，并使用空格字符将所有行合并为一行。这对于缩进 <code class=\"docutils literal notranslate\">{% blocktranslate %}</code> 标签的内容而不使缩进字符出现在 <code class=\"docutils literal notranslate\">.po</code> 文件中的对应条目中非常有用，从而简化了翻译过程。</p>\n<p>例如，下面的 <code class=\"docutils literal notranslate\">{% blocktranslate %}</code> 标签：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"nv\">trimmed</span> <span class=\"cp\">%}</span>\n  First sentence.\n  Second paragraph.\n<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>如果没有指定 <code class=\"docutils literal notranslate\">trimmed</code> 选项，将在 <code class=\"docutils literal notranslate\">.po</code> 文件中生成条目 <code class=\"docutils literal notranslate\">&quot;First sentence. Second paragraph.&quot;</code>，而不是 <code class=\"docutils literal notranslate\">&quot;\\n&#160; First sentence.\\n&#160; Second paragraph.\\n&quot;</code>。</p>\n</section>\n<section id=\"string-literals-passed-to-tags-and-filters\">\n<h3>传递字符串给标签和过滤器<a class=\"heading-anchor\" href=\"#string-literals-passed-to-tags-and-filters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可以通过使用熟悉的 <code class=\"docutils literal notranslate\">_()</code> 语法来翻译传递给标签和过滤器的字符串字面值作为参数：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">some_tag</span> <span class=\"kp\">_</span><span class=\"o\">(</span><span class=\"s2\">&quot;Page not found&quot;</span><span class=\"o\">)</span> <span class=\"nv\">value</span><span class=\"o\">|</span><span class=\"nf\">yesno</span><span class=\"o\">:</span><span class=\"kp\">_</span><span class=\"o\">(</span><span class=\"s2\">&quot;yes,no&quot;</span><span class=\"o\">)</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>在这种情况下，标签和过滤器将看到翻译后的字符串，因此它们不需要知道翻译。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>在这个例子里，翻译基础结构将被传递字符串 <code class=\"docutils literal notranslate\">&quot;yes,no&quot;</code> ，而不是单独的字符 <code class=\"docutils literal notranslate\">&quot;yes&quot;</code> 和 <code class=\"docutils literal notranslate\">&quot;no&quot;</code> 。翻译后的字符串需要包含逗号，以便过滤器解析代码时知道如何分割参数。比如，一名德国翻译者可以将 <code class=\"docutils literal notranslate\">&quot;yes,no&quot;</code> 翻译为 <code class=\"docutils literal notranslate\">&quot;ja,nein&quot;</code> （保持逗号不变）。</p>\n</aside>\n</section>\n<section id=\"comments-for-translators-in-templates\">\n<span id=\"translator-comments-in-templates\"></span><h3>模板内对翻译的注释<a class=\"heading-anchor\" href=\"#comments-for-translators-in-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>就像 Python 代码一样，对翻译者的提示可以使用注释来标注，使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/templates/builtins/#std-templatetag-comment\"><code class=\"xref std std-ttag docutils literal notranslate\">comment</code></a> 标签：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">comment</span> <span class=\"cp\">%}</span><span class=\"c\">Translators: View verb</span><span class=\"cp\">{%</span> <span class=\"k\">endcomment</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;View&quot;</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">comment</span> <span class=\"cp\">%}</span><span class=\"c\">Translators: Short intro blurb</span><span class=\"cp\">{%</span> <span class=\"k\">endcomment</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"cp\">%}</span>A multiline translatable\nliteral.<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>或者使用 <code class=\"docutils literal notranslate\">{#</code> ... <code class=\"docutils literal notranslate\">#}</code>  单行注释：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"c\">{# Translators: Label of a button that triggers search #}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">button</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;submit&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;Go&quot;</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;/</span><span class=\"nt\">button</span><span class=\"p\">&gt;</span>\n\n<span class=\"c\">{# Translators: This is a text of the base template #}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">blocktranslate</span> <span class=\"cp\">%}</span>Ambiguous translatable block of text<span class=\"cp\">{%</span> <span class=\"k\">endblocktranslate</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>为了完整起见，这些是生成 <code class=\"docutils literal notranslate\">.po</code> 文件的相应片段：</p>\n<div class=\"code-block\" data-language=\"po\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Po</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Po code\"><code><span class=\"c1\">#. Translators: View verb</span>\n<span class=\"c1\"># path/to/template/file.html:10</span>\n<span class=\"nv\">msgid</span> <span class=\"s\">&quot;View&quot;</span>\n<span class=\"nv\">msgstr</span> <span class=\"s\">&quot;&quot;</span>\n\n<span class=\"c1\">#. Translators: Short intro blurb</span>\n<span class=\"c1\"># path/to/template/file.html:13</span>\n<span class=\"nv\">msgid</span> <span class=\"s\">&quot;&quot;</span>\n<span class=\"s\">&quot;A multiline translatable&quot;</span>\n<span class=\"s\">&quot;literal.&quot;</span>\n<span class=\"nv\">msgstr</span> <span class=\"s\">&quot;&quot;</span>\n\n<span class=\"c1\"># ...</span>\n\n<span class=\"c1\">#. Translators: Label of a button that triggers search</span>\n<span class=\"c1\"># path/to/template/file.html:100</span>\n<span class=\"nv\">msgid</span> <span class=\"s\">&quot;Go&quot;</span>\n<span class=\"nv\">msgstr</span> <span class=\"s\">&quot;&quot;</span>\n\n<span class=\"c1\">#. Translators: This is a text of the base template</span>\n<span class=\"c1\"># path/to/template/file.html:103</span>\n<span class=\"nv\">msgid</span> <span class=\"s\">&quot;Ambiguous translatable block of text&quot;</span>\n<span class=\"nv\">msgstr</span> <span class=\"s\">&quot;&quot;</span>\n</code></pre></div>\n</aside>\n</section>\n<section id=\"switching-language-in-templates\">\n<span id=\"std-templatetag-language\"></span><h3>在模板中选择语言<a class=\"heading-anchor\" href=\"#switching-language-in-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果想在模板中选择语言，可以使用 <code class=\"docutils literal notranslate\">language</code> 模板标签：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">load</span> <span class=\"nv\">i18n</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">get_current_language</span> <span class=\"k\">as</span> <span class=\"nv\">LANGUAGE_CODE</span> <span class=\"cp\">%}</span>\n<span class=\"cm\">&lt;!-- Current language: </span><span class=\"cp\">{{</span> <span class=\"nv\">LANGUAGE_CODE</span> <span class=\"cp\">}}</span><span class=\"cm\"> --&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;Welcome to our page&quot;</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">language</span> <span class=\"s1\">&#39;en&#39;</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">get_current_language</span> <span class=\"k\">as</span> <span class=\"nv\">LANGUAGE_CODE</span> <span class=\"cp\">%}</span>\n    <span class=\"cm\">&lt;!-- Current language: </span><span class=\"cp\">{{</span> <span class=\"nv\">LANGUAGE_CODE</span> <span class=\"cp\">}}</span><span class=\"cm\"> --&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;Welcome to our page&quot;</span> <span class=\"cp\">%}</span><span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endlanguage</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>第一次出现的 &quot;Welcome to our page&quot; 使用当前语言，后面出现的使用英语。</p>\n</section>\n<section id=\"other-tags\">\n<span id=\"i18n-template-tags\"></span><h3>其他标签<a class=\"heading-anchor\" href=\"#other-tags\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>下面这些标签同样需要先引入 <code class=\"docutils literal notranslate\">{% load i18n %}</code>.</p>\n<section id=\"get-available-languages\">\n<span id=\"std-templatetag-get_available_languages\"></span><h4><code class=\"docutils literal notranslate\">get_available_languages</code><a class=\"heading-anchor\" href=\"#get-available-languages\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">{% get_available_languages as LANGUAGES %}</code> 返回一个元组列表，其中第一个元素是:term:language code，第二个元素是语言名称(翻译成当前活动的语言环境)。</p>\n</section>\n<section id=\"get-current-language\">\n<span id=\"std-templatetag-get_current_language\"></span><h4><code class=\"docutils literal notranslate\">get_current_language</code><a class=\"heading-anchor\" href=\"#get-current-language\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">{% get_current_language as LANGUAGE_CODE %}</code> 返回字符串类型的当前用户首选语言. 类似: <code class=\"docutils literal notranslate\">en-us</code>. 详情参阅 <a class=\"reference internal\" href=\"#how-django-discovers-language-preference\"><span class=\"std std-ref\">Django 如何发现语言偏好</span></a>.</p>\n</section>\n<section id=\"get-current-language-bidi\">\n<span id=\"std-templatetag-get_current_language_bidi\"></span><h4><code class=\"docutils literal notranslate\">get_current_language_bidi</code><a class=\"heading-anchor\" href=\"#get-current-language-bidi\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">{% get_current_language_bidi as LANGUAGE_BIDI %}</code> 返回当前语言文字的阅读方向。如果是 <code class=\"docutils literal notranslate\">True</code> ，则是从右向左阅读的语言，比如希伯来语，阿拉伯语。如果是 <code class=\"docutils literal notranslate\">False</code> ，则是从左向右阅读的语言，比如英语，法语，德语等。</p>\n</section>\n<section id=\"i18n-context-processor\">\n<span id=\"template-translation-vars\"></span><h4><code class=\"docutils literal notranslate\">i18n</code> 上下文处理器<a class=\"heading-anchor\" href=\"#i18n-context-processor\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>如果启用了 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/templates/api/#django.template.context_processors.i18n\" title=\"django.template.context_processors.i18n\"><code class=\"xref py py-class docutils literal notranslate\">django.template.context_processors.i18n</code></a> 上下文处理器，则每个 <code class=\"docutils literal notranslate\">RequestContext</code> 都可以访问上面所定义的 <code class=\"docutils literal notranslate\">LANGUAGES</code>, <code class=\"docutils literal notranslate\">LANGUAGE_CODE</code> 和 <code class=\"docutils literal notranslate\">LANGUAGE_BIDI</code> 。</p>\n</section>\n<section id=\"get-language-info\">\n<span id=\"std-templatetag-get_language_info\"></span><h4><code class=\"docutils literal notranslate\">get_language_info</code><a class=\"heading-anchor\" href=\"#get-language-info\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>你还可以使用提供的模板标签和过滤器获取有关任何可用语言的信息。要获取有关单个语言的信息，使用 <code class=\"docutils literal notranslate\">{% get_language_info %}</code> 标签：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">get_language_info</span> <span class=\"nv\">for</span> <span class=\"nv\">LANGUAGE_CODE</span> <span class=\"k\">as</span> <span class=\"nv\">lang</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">get_language_info</span> <span class=\"nv\">for</span> <span class=\"s2\">&quot;pl&quot;</span> <span class=\"k\">as</span> <span class=\"nv\">lang</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>然后你可以访问这些信息：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code>Language code: <span class=\"cp\">{{</span> <span class=\"nv\">lang.code</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;</span><span class=\"nt\">br</span><span class=\"p\">&gt;</span>\nName of language: <span class=\"cp\">{{</span> <span class=\"nv\">lang.name_local</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;</span><span class=\"nt\">br</span><span class=\"p\">&gt;</span>\nName in English: <span class=\"cp\">{{</span> <span class=\"nv\">lang.name</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;</span><span class=\"nt\">br</span><span class=\"p\">&gt;</span>\nBi-directional: <span class=\"cp\">{{</span> <span class=\"nv\">lang.bidi</span> <span class=\"cp\">}}</span>\nName in the active language: <span class=\"cp\">{{</span> <span class=\"nv\">lang.name_translated</span> <span class=\"cp\">}}</span>\n</code></pre></div>\n</section>\n<section id=\"get-language-info-list\">\n<span id=\"std-templatetag-get_language_info_list\"></span><h4><code class=\"docutils literal notranslate\">get_language_info_list</code><a class=\"heading-anchor\" href=\"#get-language-info-list\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>你也可以使用 <code class=\"docutils literal notranslate\">{% get_language_info_list %}</code> 模板标签来检索语言列表的信息（例如，<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGES\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGES</code></a> 中指定的有效语言）。查看 <a class=\"reference internal\" href=\"#set-language-redirect-view\"><span class=\"std std-ref\">关于 set_language 重定向视图的章节</span></a> 了解如何使用 <code class=\"docutils literal notranslate\">{% get_language_info_list %}</code> 来显示语言选择器。</p>\n<p>除元组的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGES\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGES</code></a> 样式列表之外，<code class=\"docutils literal notranslate\">{% get_language_info_list %}</code> 也支持语言代码列表。如果在视图中这么做：</p>\n<div class=\"code-block\" data-language=\"python\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code>context <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s2\">&quot;available_languages&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;en&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;es&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;fr&quot;</span><span class=\"p\">]}</span>\n<span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s2\">&quot;mytemplate.html&quot;</span><span class=\"p\">,</span> context<span class=\"p\">)</span>\n</code></pre></div>\n<p>你可以在模板中迭代这些语言：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">get_language_info_list</span> <span class=\"nv\">for</span> <span class=\"nv\">available_languages</span> <span class=\"k\">as</span> <span class=\"nv\">langs</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">lang</span> <span class=\"k\">in</span> <span class=\"nv\">langs</span> <span class=\"cp\">%}</span> ... <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n</section>\n<section id=\"template-filters\">\n<span id=\"std-templatefilter-language_name_translated\"></span><span id=\"std-templatefilter-language_bidi\"></span><span id=\"std-templatefilter-language_name_local\"></span><span id=\"std-templatefilter-language_name\"></span><h4>模板过滤器<a class=\"heading-anchor\" href=\"#template-filters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>为方便起见，还提供了一些过滤器：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">{{ LANGUAGE_CODE|language_name }}</code> (&quot;German&quot;)</p></li>\n<li><p><code class=\"docutils literal notranslate\">{{ LANGUAGE_CODE|language_name_local }}</code> (&quot;Deutsch&quot;)</p></li>\n<li><p><code class=\"docutils literal notranslate\">{{ LANGUAGE_CODE|language_bidi }}</code> (False)</p></li>\n<li><p><code class=\"docutils literal notranslate\">{{ LANGUAGE_CODE|language_name_translated }}</code> (&quot;německy&quot;, 当活动语言为捷克语时)</p></li>\n</ul>\n</section>\n</section>\n</section>\n<section id=\"internationalization-in-javascript-code\">\n<h2>国际化：在 JavaScript 代码里<a class=\"heading-anchor\" href=\"#internationalization-in-javascript-code\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>向 JavaScript 添加翻译会带来一些问题：</p>\n<ul class=\"simple\">\n<li><p>JavaScript 代码无权访问 <code class=\"docutils literal notranslate\">gettext</code> 实现。</p></li>\n<li><p>JavaScript 代码无权访问 <code class=\"docutils literal notranslate\">.po</code> 或 <code class=\"docutils literal notranslate\">.mo</code> 文件；它们需要通过服务器传递。</p></li>\n<li><p>JavaScript 的翻译目录应该尽可能小。</p></li>\n</ul>\n<p>Django 为这三个问题提供了解决方案：它将翻译传递给Javascript，因此你可以从 JavaScript 内部调用 <code class=\"docutils literal notranslate\">gettext</code> 等。</p>\n<p>解决这三个问题的主要解决办法是下面的 <code class=\"docutils literal notranslate\">JavaScriptCatalog</code> 视图，该视图生成一个JavaScript 库，该库具有模仿 <code class=\"docutils literal notranslate\">gettext</code> 接口的函数，外加一个翻译字符串数组。</p>\n<section id=\"module-django.views.i18n\">\n<span id=\"the-javascriptcatalog-view\"></span><h3><code class=\"docutils literal notranslate\">JavaScriptCatalog</code> 视图<a class=\"heading-anchor\" href=\"#module-django.views.i18n\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.views.i18n.JavaScriptCatalog\">\n<em class=\"property\"><span class=\"k\">class</span> </em><span class=\"sig-name descname\">JavaScriptCatalog</span><a class=\"heading-anchor\" href=\"#django.views.i18n.JavaScriptCatalog\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个视图，该视图生成一个 JavaScript 代码库，该库带有一个模仿 <code class=\"docutils literal notranslate\">gettext</code> 界面的函数，外加一个翻译字符串的数组。</p>\n<p><strong>属性</strong></p>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.views.i18n.JavaScriptCatalog.domain\">\n<span class=\"sig-name descname\">domain</span><a class=\"heading-anchor\" href=\"#django.views.i18n.JavaScriptCatalog.domain\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>翻译域包含要添加到视图输出中的字符串。默认为 <code class=\"docutils literal notranslate\">'djangojs'</code> 。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.views.i18n.JavaScriptCatalog.packages\">\n<span class=\"sig-name descname\">packages</span><a class=\"heading-anchor\" href=\"#django.views.i18n.JavaScriptCatalog.packages\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>已安装的应用程序的程序名列表。这些 app 应包含一个 <code class=\"docutils literal notranslate\">locale</code> 目录。所有这些目录加上  <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a>  里的目录会合并到一个目录里。默认是 <code class=\"docutils literal notranslate\">None</code> ，意味着在 JavaScript 输出中提供所有来自 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\">INSTALLED_APPS</code></a> 的可用翻译。</p>\n</dd></dl>\n\n<p><strong>默认值实例</strong> ：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.views.i18n</span> <span class=\"kn\">import</span> JavaScriptCatalog\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;jsi18n/&quot;</span><span class=\"p\">,</span> JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;javascript-catalog&quot;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p><strong>自定义包实例</strong> ：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>urlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span>\n        <span class=\"s2\">&quot;jsi18n/myapp/&quot;</span><span class=\"p\">,</span>\n        JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">(</span>packages<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;your.app.label&quot;</span><span class=\"p\">]),</span>\n        name<span class=\"o\">=</span><span class=\"s2\">&quot;javascript-catalog&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>如果你的根 URLconf 使用 <a class=\"reference internal\" href=\"#django.conf.urls.i18n.i18n_patterns\" title=\"django.conf.urls.i18n.i18n_patterns\"><code class=\"xref py py-func docutils literal notranslate\">i18n_patterns()</code></a> ，<code class=\"docutils literal notranslate\">JavaScriptCatalog</code> 也必须被 <code class=\"docutils literal notranslate\">i18n_patterns()</code> 包装，这样目录才会被正确的生成。</p>\n<p><code class=\"docutils literal notranslate\">i18n_patterns()</code> 实例：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.conf.urls.i18n</span> <span class=\"kn\">import</span> i18n_patterns\n\nurlpatterns <span class=\"o\">=</span> i18n_patterns<span class=\"p\">(</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;jsi18n/&quot;</span><span class=\"p\">,</span> JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;javascript-catalog&quot;</span><span class=\"p\">),</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n<p>后面出现的 <code class=\"docutils literal notranslate\">packages</code> 参数比前面出现的参数优先级更高。在相同文字出现冲突翻译的时候，这点很重要。</p>\n<p>如果你使用多个 <code class=\"docutils literal notranslate\">JavaScriptCatalog</code> 视图，并且它们中的某些视图定义了相同的字符串，那么最后加载的目录中的字符串拥有优先级。</p>\n</section>\n<section id=\"using-the-javascript-translation-catalog\">\n<h3>使用 JavaScript 翻译目录<a class=\"heading-anchor\" href=\"#using-the-javascript-translation-catalog\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>要使用目录，请像这样引入动态生成的js：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">script</span> <span class=\"na\">src</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;javascript-catalog&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">script</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>这使用反向 URL 查询来查找 JavaScript 目录视图。当加载目录后，JavaScript 代码能使用以下方法：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">gettext</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">ngettext</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">interpolate</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">get_format</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">gettext_noop</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">pgettext</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">npgettext</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">pluralidx</code></p></li>\n</ul>\n<section id=\"gettext\">\n<h4><code class=\"docutils literal notranslate\">gettext</code><a class=\"heading-anchor\" href=\"#gettext\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">gettext</code> 函数的行为类似于 Python 代码中的标准 <code class=\"docutils literal notranslate\">gettext</code> 接口：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>document<span class=\"o\">.</span>write<span class=\"p\">(</span>gettext<span class=\"p\">(</span><span class=\"s2\">&quot;this is to be translated&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n</section>\n<section id=\"ngettext\">\n<h4><code class=\"docutils literal notranslate\">ngettext</code><a class=\"heading-anchor\" href=\"#ngettext\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">ngettext</code> 函数提供了一个用于复数化单词和短语的接口：</p>\n<div class=\"code-block\" data-language=\"javascript\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">JavaScript</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"JavaScript code\"><code><span class=\"kd\">const</span> <span class=\"nx\">objectCount</span> <span class=\"o\">=</span> <span class=\"mf\">1</span> <span class=\"c1\">// or 0, or 2, or 3, ...</span>\n<span class=\"kd\">const</span> <span class=\"nx\">string</span> <span class=\"o\">=</span> <span class=\"nx\">ngettext</span><span class=\"p\">(</span>\n    <span class=\"s1\">&#39;literal for the singular case&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;literal for the plural case&#39;</span><span class=\"p\">,</span>\n    <span class=\"nx\">objectCount</span>\n<span class=\"p\">);</span>\n</code></pre></div>\n</section>\n<section id=\"interpolate\">\n<h4><code class=\"docutils literal notranslate\">interpolate</code><a class=\"heading-anchor\" href=\"#interpolate\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">interpolate</code> 函数支持动态填充格式字符串(format string)。插值语法借鉴自 Python，因此 <code class=\"docutils literal notranslate\">interpolate</code> 函数支持位置插值和命名插值。</p>\n<ul>\n<li><p>位置插值：<code class=\"docutils literal notranslate\">obj</code> 包含一个 JavaScript 数组对象，其元素值然后按照它们在 <code class=\"docutils literal notranslate\">fmt</code> 占位符中出现的顺序依次插值。例如：</p>\n<div class=\"code-block\" data-language=\"javascript\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">JavaScript</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"JavaScript code\"><code><span class=\"kd\">const</span> <span class=\"nx\">formats</span> <span class=\"o\">=</span> <span class=\"nx\">ngettext</span><span class=\"p\">(</span>\n  <span class=\"s1\">&#39;There is %s object. Remaining: %s&#39;</span><span class=\"p\">,</span>\n  <span class=\"s1\">&#39;There are %s objects. Remaining: %s&#39;</span><span class=\"p\">,</span>\n  <span class=\"mf\">11</span>\n<span class=\"p\">);</span>\n<span class=\"kd\">const</span> <span class=\"nx\">string</span> <span class=\"o\">=</span> <span class=\"nx\">interpolate</span><span class=\"p\">(</span><span class=\"nx\">formats</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"mf\">11</span><span class=\"p\">,</span> <span class=\"mf\">20</span><span class=\"p\">]);</span>\n<span class=\"c1\">// string is &#39;There are 11 objects. Remaining: 20&#39;</span>\n</code></pre></div>\n</li>\n<li><p>命名插值：通过将可选的布尔参数 <code class=\"docutils literal notranslate\">named</code> 设置为 <code class=\"docutils literal notranslate\">true</code> 来选择此模式。<code class=\"docutils literal notranslate\">obj</code> 包含一个 JavaScript 对象或关联数组。例如：</p>\n<div class=\"code-block\" data-language=\"javascript\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">JavaScript</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"JavaScript code\"><code><span class=\"kd\">const</span> <span class=\"nx\">data</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n  <span class=\"nx\">count</span><span class=\"o\">:</span> <span class=\"mf\">10</span><span class=\"p\">,</span>\n  <span class=\"nx\">total</span><span class=\"o\">:</span> <span class=\"mf\">50</span>\n<span class=\"p\">};</span>\n\n<span class=\"kd\">const</span> <span class=\"nx\">formats</span> <span class=\"o\">=</span> <span class=\"nx\">ngettext</span><span class=\"p\">(</span>\n    <span class=\"s1\">&#39;Total: %(total)s, there is %(count)s object&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;there are %(count)s of a total of %(total)s objects&#39;</span><span class=\"p\">,</span>\n    <span class=\"nx\">data</span><span class=\"p\">.</span><span class=\"nx\">count</span>\n<span class=\"p\">);</span>\n<span class=\"kd\">const</span> <span class=\"nx\">string</span> <span class=\"o\">=</span> <span class=\"nx\">interpolate</span><span class=\"p\">(</span><span class=\"nx\">formats</span><span class=\"p\">,</span> <span class=\"nx\">data</span><span class=\"p\">,</span> <span class=\"kc\">true</span><span class=\"p\">);</span>\n</code></pre></div>\n</li>\n</ul>\n<p>尽管如此，你不应该使用字符串插值：这仍然是 JavaScript，因此代码必须进行重复的正则表达式替换。这并不像 Python 中的字符串插值那么快，所以请确保你真的需要这么做（比如，与 <code class=\"docutils literal notranslate\">ngettext</code> 结合产生合适的复数形式）。</p>\n</section>\n<section id=\"get-format\">\n<h4><code class=\"docutils literal notranslate\">get_format</code><a class=\"heading-anchor\" href=\"#get-format\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">get_format</code> 函数可以访问配置的 i18n 格式设置，并可以检索给定设置名称的格式字符串：</p>\n<div class=\"code-block\" data-language=\"javascript\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">JavaScript</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"JavaScript code\"><code><span class=\"nb\">document</span><span class=\"p\">.</span><span class=\"nx\">write</span><span class=\"p\">(</span><span class=\"nx\">get_format</span><span class=\"p\">(</span><span class=\"s1\">&#39;DATE_FORMAT&#39;</span><span class=\"p\">));</span>\n<span class=\"c1\">// &#39;N j, Y&#39;</span>\n</code></pre></div>\n<p>它可以访问以下设置：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-DATE_FORMAT\"><code class=\"xref std std-setting docutils literal notranslate\">DATE_FORMAT</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-DATE_INPUT_FORMATS\"><code class=\"xref std std-setting docutils literal notranslate\">DATE_INPUT_FORMATS</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-DATETIME_FORMAT\"><code class=\"xref std std-setting docutils literal notranslate\">DATETIME_FORMAT</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-DATETIME_INPUT_FORMATS\"><code class=\"xref std std-setting docutils literal notranslate\">DATETIME_INPUT_FORMATS</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-DECIMAL_SEPARATOR\"><code class=\"xref std std-setting docutils literal notranslate\">DECIMAL_SEPARATOR</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-FIRST_DAY_OF_WEEK\"><code class=\"xref std std-setting docutils literal notranslate\">FIRST_DAY_OF_WEEK</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-MONTH_DAY_FORMAT\"><code class=\"xref std std-setting docutils literal notranslate\">MONTH_DAY_FORMAT</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-NUMBER_GROUPING\"><code class=\"xref std std-setting docutils literal notranslate\">NUMBER_GROUPING</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-SHORT_DATE_FORMAT\"><code class=\"xref std std-setting docutils literal notranslate\">SHORT_DATE_FORMAT</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-SHORT_DATETIME_FORMAT\"><code class=\"xref std std-setting docutils literal notranslate\">SHORT_DATETIME_FORMAT</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-THOUSAND_SEPARATOR\"><code class=\"xref std std-setting docutils literal notranslate\">THOUSAND_SEPARATOR</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-TIME_FORMAT\"><code class=\"xref std std-setting docutils literal notranslate\">TIME_FORMAT</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-TIME_INPUT_FORMATS\"><code class=\"xref std std-setting docutils literal notranslate\">TIME_INPUT_FORMATS</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-YEAR_MONTH_FORMAT\"><code class=\"xref std std-setting docutils literal notranslate\">YEAR_MONTH_FORMAT</code></a></p></li>\n</ul>\n<p>这对于保持与Python呈现的值的格式一致性非常有用。</p>\n</section>\n<section id=\"gettext-noop\">\n<h4><code class=\"docutils literal notranslate\">gettext_noop</code><a class=\"heading-anchor\" href=\"#gettext-noop\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>这模拟了 <code class=\"docutils literal notranslate\">gettext</code> 函数，但不执行任何操作，返回那传递给它的所有内容：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>document<span class=\"o\">.</span>write<span class=\"p\">(</span>gettext_noop<span class=\"p\">(</span><span class=\"s2\">&quot;this will not be translated&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>这对于在将来需要翻译的代码中删除部分代码时很有用。</p>\n</section>\n<section id=\"pgettext\">\n<h4><code class=\"docutils literal notranslate\">pgettext</code><a class=\"heading-anchor\" href=\"#pgettext\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">pgettext</code> 函数的行为类似于 Python 变体(<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.pgettext\" title=\"django.utils.translation.pgettext\"><code class=\"xref py py-func docutils literal notranslate\">pgettext()</code></a>)，它提供了一个上下文相关的单词：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>document<span class=\"o\">.</span>write<span class=\"p\">(</span>pgettext<span class=\"p\">(</span><span class=\"s2\">&quot;month name&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;May&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n</section>\n<section id=\"npgettext\">\n<h4><code class=\"docutils literal notranslate\">npgettext</code><a class=\"heading-anchor\" href=\"#npgettext\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">npgettext</code> 函数也像 Python 变体 (<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.npgettext\" title=\"django.utils.translation.npgettext\"><code class=\"xref py py-func docutils literal notranslate\">npgettext()</code></a>) 一样工作，提供 <strong>复数</strong> 的上下文翻译词汇：</p>\n<div class=\"code-block\" data-language=\"javascript\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">JavaScript</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"JavaScript code\"><code><span class=\"nb\">document</span><span class=\"p\">.</span><span class=\"nx\">write</span><span class=\"p\">(</span><span class=\"nx\">npgettext</span><span class=\"p\">(</span><span class=\"s1\">&#39;group&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;party&#39;</span><span class=\"p\">,</span> <span class=\"mf\">1</span><span class=\"p\">));</span>\n<span class=\"c1\">// party</span>\n<span class=\"nb\">document</span><span class=\"p\">.</span><span class=\"nx\">write</span><span class=\"p\">(</span><span class=\"nx\">npgettext</span><span class=\"p\">(</span><span class=\"s1\">&#39;group&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;party&#39;</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">));</span>\n<span class=\"c1\">// parties</span>\n</code></pre></div>\n</section>\n<section id=\"pluralidx\">\n<h4><code class=\"docutils literal notranslate\">pluralidx</code><a class=\"heading-anchor\" href=\"#pluralidx\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\">pluralidx</code> 函数的工作方式类似于 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/templates/builtins/#std-templatefilter-pluralize\"><code class=\"xref std std-tfilter docutils literal notranslate\">pluralize</code></a> 模板过滤器，它确定给定的 <code class=\"docutils literal notranslate\">count</code> 是否应该使用单词的复数形式：</p>\n<div class=\"code-block\" data-language=\"javascript\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">JavaScript</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"JavaScript code\"><code><span class=\"nb\">document</span><span class=\"p\">.</span><span class=\"nx\">write</span><span class=\"p\">(</span><span class=\"nx\">pluralidx</span><span class=\"p\">(</span><span class=\"mf\">0</span><span class=\"p\">));</span>\n<span class=\"c1\">// true</span>\n<span class=\"nb\">document</span><span class=\"p\">.</span><span class=\"nx\">write</span><span class=\"p\">(</span><span class=\"nx\">pluralidx</span><span class=\"p\">(</span><span class=\"mf\">1</span><span class=\"p\">));</span>\n<span class=\"c1\">// false</span>\n<span class=\"nb\">document</span><span class=\"p\">.</span><span class=\"nx\">write</span><span class=\"p\">(</span><span class=\"nx\">pluralidx</span><span class=\"p\">(</span><span class=\"mf\">2</span><span class=\"p\">));</span>\n<span class=\"c1\">// true</span>\n</code></pre></div>\n<p>在这种最简单的情况下，如果不需要自定义复数，那么会对整数 <code class=\"docutils literal notranslate\">1</code> 返回 <code class=\"docutils literal notranslate\">false</code> ，其他数返回 <code class=\"docutils literal notranslate\">true</code> 。</p>\n<p>然而，在所有语言中复数化并不是这么简单。如果语言不支持复数化，那么就需要提供一个空值。</p>\n<p>此外，如果复数的规则复杂，目录视图将渲染一个条件表达式。它将返回  <code class=\"docutils literal notranslate\">true</code> (如果是复数) 或 <code class=\"docutils literal notranslate\">false</code> (如果不是复数) 的值。</p>\n</section>\n</section>\n<section id=\"the-jsoncatalog-view\">\n<h3><code class=\"docutils literal notranslate\">JSONCatalog</code> 视图<a class=\"heading-anchor\" href=\"#the-jsoncatalog-view\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.views.i18n.JSONCatalog\">\n<em class=\"property\"><span class=\"k\">class</span> </em><span class=\"sig-name descname\">JSONCatalog</span><a class=\"heading-anchor\" href=\"#django.views.i18n.JSONCatalog\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>为了使用其他客户端的库来控制翻译，你可能需要利用 <code class=\"docutils literal notranslate\">JSONCatalog</code> 视图。它类似于 <a class=\"reference internal\" href=\"#django.views.i18n.JavaScriptCatalog\" title=\"django.views.i18n.JavaScriptCatalog\"><code class=\"xref py py-class docutils literal notranslate\">JavaScriptCatalog</code></a> ，但返回一个 JSON 响应。</p>\n<p>查看 <a class=\"reference internal\" href=\"#django.views.i18n.JavaScriptCatalog\" title=\"django.views.i18n.JavaScriptCatalog\"><code class=\"xref py py-class docutils literal notranslate\">JavaScriptCatalog</code></a> 文档来了解关于 <code class=\"docutils literal notranslate\">domain</code> 和 <code class=\"docutils literal notranslate\">packages</code> 属性的可能值和使用。</p>\n<p>响应格式如下：</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>{\n    &quot;catalog&quot;: {\n        # Translations catalog\n    },\n    &quot;formats&quot;: {\n        # Language formats for date, time, etc.\n    },\n    &quot;plural&quot;: &quot;...&quot;  # Expression for plural forms, or null.\n}\n</code></pre></div>\n</dd></dl>\n\n</section>\n<section id=\"note-on-performance\">\n<h3>性能说明<a class=\"heading-anchor\" href=\"#note-on-performance\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>各种 JavaScript/JSON i18n 视图在每次请求时从 <code class=\"docutils literal notranslate\">.mo</code> 文件生成日历。因为其输出是恒定的，至少对于给定版本的站点来说，它是缓存的一个很好的选择。</p>\n<p>服务端缓存将减少 CPU 负载。使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/cache/#django.views.decorators.cache.cache_page\" title=\"django.views.decorators.cache.cache_page\"><code class=\"xref py py-func docutils literal notranslate\">cache_page()</code></a> 装饰器很容易实现。要在翻译变化时让缓存失效，需要提供一个版本相关的键前缀，如下例所示，或将视图映射到版本相关的 URL ：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.views.decorators.cache</span> <span class=\"kn\">import</span> cache_page\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.i18n</span> <span class=\"kn\">import</span> JavaScriptCatalog\n\n<span class=\"c1\"># The value returned by get_version() must change when translations change.</span>\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span>\n        <span class=\"s2\">&quot;jsi18n/&quot;</span><span class=\"p\">,</span>\n        cache_page<span class=\"p\">(</span><span class=\"mi\">86400</span><span class=\"p\">,</span> key_prefix<span class=\"o\">=</span><span class=\"s2\">&quot;jsi18n-</span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span> <span class=\"o\">%</span> get_version<span class=\"p\">())(</span>\n            JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">()</span>\n        <span class=\"p\">),</span>\n        name<span class=\"o\">=</span><span class=\"s2\">&quot;javascript-catalog&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>客户端缓存将节省带宽并让网站加载速度变快。如果你正在使用 ETags（<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.middleware.http.ConditionalGetMiddleware\" title=\"django.middleware.http.ConditionalGetMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">ConditionalGetMiddleware</code></a>），那么你已经被覆盖了。否则，你可以应用条件装饰器（<a class=\"reference internal\" href=\"/zh-hans/5.1/topics/conditional-view-processing/#conditional-decorators\"><span class=\"std std-ref\">conditional decorators</span></a>）。在下面的例子中，当你重启应用程序服务时，缓存将失效。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils</span> <span class=\"kn\">import</span> timezone\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.decorators.http</span> <span class=\"kn\">import</span> last_modified\n<span class=\"kn\">from</span> <span class=\"nn\">django.views.i18n</span> <span class=\"kn\">import</span> JavaScriptCatalog\n\nlast_modified_date <span class=\"o\">=</span> timezone<span class=\"o\">.</span>now<span class=\"p\">()</span>\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span>\n        <span class=\"s2\">&quot;jsi18n/&quot;</span><span class=\"p\">,</span>\n        last_modified<span class=\"p\">(</span><span class=\"k\">lambda</span> req<span class=\"p\">,</span> <span class=\"o\">**</span>kw<span class=\"p\">:</span> last_modified_date<span class=\"p\">)(</span>\n            JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">()</span>\n        <span class=\"p\">),</span>\n        name<span class=\"o\">=</span><span class=\"s2\">&quot;javascript-catalog&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>你甚至可以将 JavaScript 目录预生成作为部署过程的一部分，并将其作为静态文件提供。这种激进的技术在 <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-statici18n/\">django-statici18n</a> 中实现。</p>\n</section>\n</section>\n<section id=\"module-django.conf.urls.i18n\">\n<span id=\"internationalization-in-url-patterns\"></span><span id=\"url-internationalization\"></span><h2>国际化：在 URL 模式中<a class=\"heading-anchor\" href=\"#module-django.conf.urls.i18n\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 提供两种方式来国际化 URL 模式：</p>\n<ul class=\"simple\">\n<li><p>将语言前缀添加到 URL 模式的根，来使得 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.middleware.locale.LocaleMiddleware\" title=\"django.middleware.locale.LocaleMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">LocaleMiddleware</code></a> 从请求的 URL 中检测要激活的语言。</p></li>\n<li><p>通过 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext_lazy\" title=\"django.utils.translation.gettext_lazy\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.gettext_lazy()</code></a> 函数使得 URL 模式本身可翻译。</p></li>\n</ul>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>使用这些特性需要为每个请求设置一个激活的语言；换句话说，你需要在 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 设置中包含 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.middleware.locale.LocaleMiddleware\" title=\"django.middleware.locale.LocaleMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">django.middleware.locale.LocaleMiddleware</code></a> 。</p>\n</aside>\n<section id=\"language-prefix-in-url-patterns\">\n<h3>URL 模式中的语言前缀<a class=\"heading-anchor\" href=\"#language-prefix-in-url-patterns\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.conf.urls.i18n.i18n_patterns\">\n<span class=\"sig-name descname\">i18n_patterns</span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\">*</span>urls</em>, <em class=\"sig-param\">prefix_default_language<span class=\"o\">=</span><span class=\"default_value\">True</span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.conf.urls.i18n.i18n_patterns\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>这个函数可以在根URLconf中使用，Django 会自动将当前激活的语言代码添加到 <a class=\"reference internal\" href=\"#django.conf.urls.i18n.i18n_patterns\" title=\"django.conf.urls.i18n.i18n_patterns\"><code class=\"xref py py-func docutils literal notranslate\">i18n_patterns()</code></a> 中定义的所有 URL 模式中。</p>\n<p>设置 <code class=\"docutils literal notranslate\">prefix_default_language</code> 为 <code class=\"docutils literal notranslate\">False</code> 会从默认语言( <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> )中删除前缀。这在向现有网站添加翻译时非常有用，这样当前的网址就不会改变。</p>\n<p>URL 模式举例：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.conf.urls.i18n</span> <span class=\"kn\">import</span> i18n_patterns\n<span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> include<span class=\"p\">,</span> path\n\n<span class=\"kn\">from</span> <span class=\"nn\">about</span> <span class=\"kn\">import</span> views <span class=\"k\">as</span> about_views\n<span class=\"kn\">from</span> <span class=\"nn\">news</span> <span class=\"kn\">import</span> views <span class=\"k\">as</span> news_views\n<span class=\"kn\">from</span> <span class=\"nn\">sitemap.views</span> <span class=\"kn\">import</span> sitemap\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;sitemap.xml&quot;</span><span class=\"p\">,</span> sitemap<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;sitemap-xml&quot;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n\nnews_patterns <span class=\"o\">=</span> <span class=\"p\">(</span>\n    <span class=\"p\">[</span>\n        path<span class=\"p\">(</span><span class=\"s2\">&quot;&quot;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>index<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;index&quot;</span><span class=\"p\">),</span>\n        path<span class=\"p\">(</span><span class=\"s2\">&quot;category/&lt;slug:slug&gt;/&quot;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>category<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;category&quot;</span><span class=\"p\">),</span>\n        path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;slug:slug&gt;/&quot;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>details<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;detail&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">],</span>\n    <span class=\"s2\">&quot;news&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n\nurlpatterns <span class=\"o\">+=</span> i18n_patterns<span class=\"p\">(</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;about/&quot;</span><span class=\"p\">,</span> about_views<span class=\"o\">.</span>main<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;about&quot;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;news/&quot;</span><span class=\"p\">,</span> include<span class=\"p\">(</span>news_patterns<span class=\"p\">,</span> namespace<span class=\"o\">=</span><span class=\"s2\">&quot;news&quot;</span><span class=\"p\">)),</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>定义了这些 URL 模式后，Django 将自动将语言前缀添加到由 <code class=\"docutils literal notranslate\">i18n_patterns</code> 函数添加的 URL 模式中。示例：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> reverse\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> activate\n\n<span class=\"gp\">&gt;&gt;&gt; </span>activate<span class=\"p\">(</span><span class=\"s2\">&quot;en&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;sitemap-xml&quot;</span><span class=\"p\">)</span>\n<span class=\"go\">&#39;/sitemap.xml&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;news:index&quot;</span><span class=\"p\">)</span>\n<span class=\"go\">&#39;/en/news/&#39;</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>activate<span class=\"p\">(</span><span class=\"s2\">&quot;nl&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;news:detail&quot;</span><span class=\"p\">,</span> kwargs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;slug&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;news-slug&quot;</span><span class=\"p\">})</span>\n<span class=\"go\">&#39;/nl/news/news-slug/&#39;</span>\n</code></pre></div>\n<p>使用 <code class=\"docutils literal notranslate\">prefix_default_language=False</code> 和 <code class=\"docutils literal notranslate\">LANGUAGE_CODE='en'</code>，URL 将是：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>activate<span class=\"p\">(</span><span class=\"s2\">&quot;en&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;news:index&quot;</span><span class=\"p\">)</span>\n<span class=\"go\">&#39;/news/&#39;</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>activate<span class=\"p\">(</span><span class=\"s2\">&quot;nl&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;news:index&quot;</span><span class=\"p\">)</span>\n<span class=\"go\">&#39;/nl/news/&#39;</span>\n</code></pre></div>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>只允许 <a class=\"reference internal\" href=\"#django.conf.urls.i18n.i18n_patterns\" title=\"django.conf.urls.i18n.i18n_patterns\"><code class=\"xref py py-func docutils literal notranslate\">i18n_patterns()</code></a> 在根URLconf中运行。在包含的URLconf中使用它时会弹出 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/exceptions/#django.core.exceptions.ImproperlyConfigured\" title=\"django.core.exceptions.ImproperlyConfigured\"><code class=\"xref py py-exc docutils literal notranslate\">ImproperlyConfigured</code></a> 异常。</p>\n</aside>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>确保没有可能与自动添加的语言前缀冲突的非前缀 URL 模式。</p>\n</aside>\n</section>\n<section id=\"translating-url-patterns\">\n<span id=\"translating-urlpatterns\"></span><h3>翻译URL模式<a class=\"heading-anchor\" href=\"#translating-url-patterns\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>URL模式也可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext_lazy\" title=\"django.utils.translation.gettext_lazy\"><code class=\"xref py py-func docutils literal notranslate\">gettext_lazy()</code></a> 函数标记。例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.conf.urls.i18n</span> <span class=\"kn\">import</span> i18n_patterns\n<span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> include<span class=\"p\">,</span> path\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\n<span class=\"kn\">from</span> <span class=\"nn\">about</span> <span class=\"kn\">import</span> views <span class=\"k\">as</span> about_views\n<span class=\"kn\">from</span> <span class=\"nn\">news</span> <span class=\"kn\">import</span> views <span class=\"k\">as</span> news_views\n<span class=\"kn\">from</span> <span class=\"nn\">sitemaps.views</span> <span class=\"kn\">import</span> sitemap\n\nurlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s2\">&quot;sitemap.xml&quot;</span><span class=\"p\">,</span> sitemap<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;sitemap-xml&quot;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n\nnews_patterns <span class=\"o\">=</span> <span class=\"p\">(</span>\n    <span class=\"p\">[</span>\n        path<span class=\"p\">(</span><span class=\"s2\">&quot;&quot;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>index<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;index&quot;</span><span class=\"p\">),</span>\n        path<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;category/&lt;slug:slug&gt;/&quot;</span><span class=\"p\">),</span> news_views<span class=\"o\">.</span>category<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;category&quot;</span><span class=\"p\">),</span>\n        path<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;slug:slug&gt;/&quot;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>details<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;detail&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">],</span>\n    <span class=\"s2\">&quot;news&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n\nurlpatterns <span class=\"o\">+=</span> i18n_patterns<span class=\"p\">(</span>\n    path<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;about/&quot;</span><span class=\"p\">),</span> about_views<span class=\"o\">.</span>main<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s2\">&quot;about&quot;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;news/&quot;</span><span class=\"p\">),</span> include<span class=\"p\">(</span>news_patterns<span class=\"p\">,</span> namespace<span class=\"o\">=</span><span class=\"s2\">&quot;news&quot;</span><span class=\"p\">)),</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>在创建了翻译之后，<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/urlresolvers/#django.urls.reverse\" title=\"django.urls.reverse\"><code class=\"xref py py-func docutils literal notranslate\">reverse()</code></a> 函数将以当前活动语言返回 URL。示例：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> reverse\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> activate\n\n<span class=\"gp\">&gt;&gt;&gt; </span>activate<span class=\"p\">(</span><span class=\"s2\">&quot;en&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;news:category&quot;</span><span class=\"p\">,</span> kwargs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;slug&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;recent&quot;</span><span class=\"p\">})</span>\n<span class=\"go\">&#39;/en/news/category/recent/&#39;</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>activate<span class=\"p\">(</span><span class=\"s2\">&quot;nl&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s2\">&quot;news:category&quot;</span><span class=\"p\">,</span> kwargs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;slug&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;recent&quot;</span><span class=\"p\">})</span>\n<span class=\"go\">&#39;/nl/nieuws/categorie/recent/&#39;</span>\n</code></pre></div>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>在大多数情况下，最好只在带有语言代码前缀的模式块中使用翻译后的网址(使用  <a class=\"reference internal\" href=\"#django.conf.urls.i18n.i18n_patterns\" title=\"django.conf.urls.i18n.i18n_patterns\"><code class=\"xref py py-func docutils literal notranslate\">i18n_patterns()</code></a> )，以避免无意中翻译的网址导致与未翻译的网址模式冲突的可能性。</p>\n</aside>\n</section>\n<section id=\"reversing-in-templates\">\n<span id=\"id2\"></span><h3>在模板中反向解析URL<a class=\"heading-anchor\" href=\"#reversing-in-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果本地化的URLs在模板中解析，那么它们会始终使用当前的语言。要链接其他语言中的URL，需使用 <a class=\"reference internal\" href=\"#std-templatetag-language\"><code class=\"xref std std-ttag docutils literal notranslate\">language</code></a> 模板标签。它可以在随附的模板部分中启用给定的语言：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">load</span> <span class=\"nv\">i18n</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">get_available_languages</span> <span class=\"k\">as</span> <span class=\"nv\">languages</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">translate</span> <span class=\"s2\">&quot;View this category in:&quot;</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">lang_code</span><span class=\"o\">,</span> <span class=\"nv\">lang_name</span> <span class=\"k\">in</span> <span class=\"nv\">languages</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">language</span> <span class=\"nv\">lang_code</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;category&#39;</span> <span class=\"nv\">slug</span><span class=\"o\">=</span><span class=\"nv\">category.slug</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">lang_name</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endlanguage</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p><a class=\"reference internal\" href=\"#std-templatetag-language\"><code class=\"xref std std-ttag docutils literal notranslate\">language</code></a> 标签将语言代码作为唯一的参数。</p>\n</section>\n</section>\n<section id=\"localization-how-to-create-language-files\">\n<span id=\"how-to-create-language-files\"></span><h2>本地化：如何创建语言文件<a class=\"heading-anchor\" href=\"#localization-how-to-create-language-files\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>一旦标记了应用程序的字符串文字以供以后翻译，就需要写入（或获取）翻译。这里介绍一下方法。</p>\n<section id=\"message-files\">\n<h3>消息文件<a class=\"heading-anchor\" href=\"#message-files\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>首先需要为新语言创建 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/i18n/#term-message-file\"><span class=\"xref std std-term\">message file</span></a> 文件。消息文件是一个纯文本文件，代表一种语言，它包含所有可用的翻译字段以及如何以给定语言表示。消息文件扩展名是 <code class=\"docutils literal notranslate\">.po</code> 文件。</p>\n<p>Django 附带的工具 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a> 会自动创建并保存这些文件。</p>\n<aside class=\"admonition-gettext-utilities admonition\" role=\"note\">\n<p class=\"admonition-title\">Gettext 实用程序</p>\n<p><code class=\"docutils literal notranslate\">makemessages</code> 命令（和稍后讨论的 <code class=\"docutils literal notranslate\">compilemessages</code> ）使用来自 GNU 文字工具集的命令行：<code class=\"docutils literal notranslate\">xgettext</code>, <code class=\"docutils literal notranslate\">msgfmt</code>, <code class=\"docutils literal notranslate\">msgmerge</code> 和 <code class=\"docutils literal notranslate\">msguniq</code> 。</p>\n<p><code class=\"docutils literal notranslate\">gettext</code> 实用工具集支持的最低版本是 0.15 。</p>\n</aside>\n<p>要创建或更新消息文件，请运行此命令：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin makemessages -l de\n</code></pre></div>\n<p>...其中 <code class=\"docutils literal notranslate\">de</code> 是你要创建的消息文件的 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/i18n/#term-locale-name\"><span class=\"xref std std-term\">locale name</span></a> 。例如，<code class=\"docutils literal notranslate\">pt_BR</code> 是葡萄牙语，<code class=\"docutils literal notranslate\">de_AT</code> 是奥地利德语，<code class=\"docutils literal notranslate\">id</code> 是印尼语。</p>\n<p>脚本应该从以下两个位置之一来运行：</p>\n<ul class=\"simple\">\n<li><p>你的 Django 项目的根目录（就是包含 <code class=\"docutils literal notranslate\">manage.py</code> 的那个目录）。</p></li>\n<li><p>Django app的根目录。</p></li>\n</ul>\n<p>脚本会遍历你的项目源代码树或者应用程序源代码库，并抽出所有要被翻译的字符串（查看 <a class=\"reference internal\" href=\"#how-django-discovers-translations\"><span class=\"std std-ref\">Django 如何发现翻译</span></a> 并确保 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> 被正确设置）。它在 <code class=\"docutils literal notranslate\">locale/LANG/LC_MESSAGES</code> 目录中创建（或更新）消息文件。以德语为例，这个文件会是 <code class=\"docutils literal notranslate\">locale/de/LC_MESSAGES/django.po</code> 。</p>\n<p>在项目的根目录执行 <code class=\"docutils literal notranslate\">makemessages</code> 命令时，提取的字符串将自动分发到合适的消息文件。这就是说，从包含 <code class=\"docutils literal notranslate\">locale</code> 目录的 app 文件中提取的字符串将进入该目录下的消息文件中。从不包含任何  <code class=\"docutils literal notranslate\">locale</code> 目录的 app 文件中提取的字符串将进入 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> 中列出的第一个目录下的消息文件，如果 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> 为空，则会报错。</p>\n<p>默认情况下，<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a> 会检查具有 <code class=\"docutils literal notranslate\">.html</code>、<code class=\"docutils literal notranslate\">.txt</code> 或 <code class=\"docutils literal notranslate\">.py</code> 文件扩展名的每个文件。如果您想覆盖此默认设置，请使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#cmdoption-makemessages-extension\"><code class=\"xref std std-option docutils literal notranslate\">--extension</code></a> 或 <code class=\"docutils literal notranslate\">-e</code> 选项来指定要检查的文件扩展名：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin makemessages -l de -e txt\n</code></pre></div>\n<p>用逗号分隔多个扩展名，并/或多次使用 <code class=\"docutils literal notranslate\">-e</code> 或 <code class=\"docutils literal notranslate\">--extension</code>：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin makemessages -l de -e html,txt -e xml\n</code></pre></div>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>从 JavaScript 源码中创建消息文件时（<a class=\"reference internal\" href=\"#creating-message-files-from-js-code\"><span class=\"std std-ref\">creating message files from JavaScript source code</span></a>），你需要使用特别的 <code class=\"docutils literal notranslate\">djangojs</code> 域，而不是 <code class=\"docutils literal notranslate\">-e js</code> 。</p>\n</aside>\n<aside class=\"admonition-using-jinja2-templates admonition\" role=\"note\">\n<p class=\"admonition-title\">使用 Jinja2 模板？</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> 不识别Jinja2模板的语法。要从包含Jinja2模板的项目中提取字符串，需要使用 <a class=\"reference external\" href=\"https://babel.pocoo.org/en/latest/\">Babel</a> 的 <a class=\"reference external\" href=\"https://babel.pocoo.org/en/latest/messages.html#message-extraction\">Message Extracting</a> 。</p>\n<p>以下是一个示例的 <code class=\"docutils literal notranslate\">babel.cfg</code> 配置文件：</p>\n<div class=\"code-block\" data-language=\"ini\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Ini</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Ini code\"><code><span class=\"c1\"># Extraction from Python source files</span>\n<span class=\"k\">[python: **.py]</span>\n\n<span class=\"c1\"># Extraction from Jinja2 templates</span>\n<span class=\"k\">[jinja2: **.jinja]</span>\n<span class=\"na\">extensions</span> <span class=\"o\">=</span> <span class=\"s\">jinja2.ext.with_</span>\n</code></pre></div>\n<p>确保列出所有正在使用的扩展名。否则Babel不会识别这些扩展名定义的标签，并会完全忽略包含它们的Jinja2模板。</p>\n<p>Babel提供了与 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> 类似的功能，通常可以替换它，并且不会依赖 <code class=\"docutils literal notranslate\">gettext</code> 。获取更多信息，请查阅关于使用消息目录（ <a class=\"reference external\" href=\"https://babel.pocoo.org/en/latest/messages.html\">working with message catalogs</a> ）的文档。</p>\n</aside>\n<aside class=\"admonition-no-gettext admonition\" role=\"note\">\n<p class=\"admonition-title\">没有 gettext？</p>\n<p>如果你还没有安装 <code class=\"docutils literal notranslate\">gettext</code> ，<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> 将创建一个空文件。如果是这种情况，要么安装 <code class=\"docutils literal notranslate\">gettext</code> ，要么复制英文消息文件(如果可用) (<code class=\"docutils literal notranslate\">locale/en/LC_MESSAGES/django.po</code>) 并将其作为起点，即一个空的翻译文件。</p>\n</aside>\n<aside class=\"admonition-working-on-windows admonition\" role=\"note\">\n<p class=\"admonition-title\">在 Windows 上工作？</p>\n<p>如果你正在使用Windows并且需要安装 GNU gettext 程序以便 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> 工作，请参阅 <a class=\"reference internal\" href=\"#gettext-on-windows\"><span class=\"std std-ref\">Windows 上的 gettext</span></a> 了解更多信息。</p>\n</aside>\n<p>每个 <code class=\"docutils literal notranslate\">.po</code> 文件包含少量的元数据（例如翻译维护者的联系方式等等）以及大量的翻译文件 —— 要翻译的字符串以及实际翻译的字段之间的映射。</p>\n<p>例如，如果 Djanog 程序包含一段 <code class=\"docutils literal notranslate\">&quot;Welcome to my site.&quot;</code> 的翻译字符串，像这样：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>_<span class=\"p\">(</span><span class=\"s2\">&quot;Welcome to my site.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>... 然后 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a> 将创建一个包含以下代码片段的 <code class=\"docutils literal notranslate\">.po</code> 文件 —— 一条消息：</p>\n<div class=\"code-block\" data-language=\"po\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Po</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Po code\"><code><span class=\"kd\">#: path/to/python/module.py:23</span>\n<span class=\"nv\">msgid</span> <span class=\"s\">&quot;Welcome to my site.&quot;</span>\n<span class=\"nv\">msgstr</span> <span class=\"s\">&quot;&quot;</span>\n</code></pre></div>\n<p>快速解释：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">msgid</code> 是显示在源代码中需要翻译的字符串。不要改动它。</p></li>\n<li><p><code class=\"docutils literal notranslate\">msgstr</code> 是你翻译后的字符串。一开始它是空的，因此你需要填充它。确保在翻译中保留引号。</p></li>\n<li><p>为了方便，每个消息包含以前缀为 <code class=\"docutils literal notranslate\">#</code> 且位于 <code class=\"docutils literal notranslate\">msgid</code> 行上方的注释行的形式的注释行，这个注释行报货文件名和需要翻译字符串的行号。</p></li>\n</ul>\n<p>长消息是特殊的情况。这里，在 <code class=\"docutils literal notranslate\">msgstr</code> (or <code class=\"docutils literal notranslate\">msgid</code>) 后的第一个字符串是空字符串。然后内容本身就会在接下来的几行中以每行一串的形式写出来。这些字符串被直接连接起来。不要忘了字符串中尾部的空格，否则，它们会被粘贴在一起而不留空白！</p>\n<aside class=\"admonition-mind-your-charset admonition\" role=\"note\">\n<p class=\"admonition-title\">注意你的字符集</p>\n<p>由于 <code class=\"docutils literal notranslate\">gettext</code> 工具内部的工作方式以及我们希望在 Django 核心和您的应用程序中允许非 ASCII 源字符串，您 <strong>必须</strong> 使用 UTF-8 作为您的 <code class=\"docutils literal notranslate\">.po</code> 文件的编码（在创建 <code class=\"docutils literal notranslate\">.po</code> 文件时的默认编码）。这意味着每个人都将使用相同的编码，这在 Django 处理 <code class=\"docutils literal notranslate\">.po</code> 文件时非常重要。</p>\n</aside>\n<aside class=\"admonition-fuzzy-entries admonition\" role=\"note\">\n<p class=\"admonition-title\">模糊条目</p>\n<p>当翻译是从例如已翻译的字符串中推断出来的时候，:djadmin:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>makemessages`有时会生成标记为“模糊”的翻译条目。在默认情况下，模糊条目**不会**被 :djadmin:<a href=\"#id3\"><span class=\"problematic\" id=\"id4\">`</span></a>compilemessages`处理。</p>\n</aside>\n<p>要重新检查所有源代码和模板以查找新的翻译字符串，并更新 <strong>所有</strong> 语言的消息文件，请运行以下命令：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin makemessages -a\n</code></pre></div>\n</section>\n<section id=\"compiling-message-files\">\n<h3>编译消息文件<a class=\"heading-anchor\" href=\"#compiling-message-files\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>创建消息文件后，以及每次修改它时，你需要把它编译成更有效的形式，以供 <code class=\"docutils literal notranslate\">gettext</code> 使用。使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages</code></a> 工具来执行此操作。</p>\n<p>这个工具会运行在所有可用的 <code class=\"docutils literal notranslate\">.po</code> 文件上，并创建 <code class=\"docutils literal notranslate\">.mo</code> 文件，这些文件是经过优化以供 <code class=\"docutils literal notranslate\">gettext</code> 使用的二进制文件。在与您运行 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a> 的相同目录中，可以像这样运行 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages</code></a>：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin compilemessages\n</code></pre></div>\n<p>这就行了。可以使用你的翻译文件了。</p>\n<aside class=\"admonition-working-on-windows admonition\" role=\"note\">\n<p class=\"admonition-title\">在 Windows 上工作？</p>\n<p>如果你正在使用Windows并且需要安装 GNU gettext 程序以便 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages</code></a> 工作，请参阅 <a class=\"reference internal\" href=\"#gettext-on-windows\"><span class=\"std std-ref\">Windows 上的 gettext</span></a> 了解更多信息。</p>\n</aside>\n<aside class=\"admonition-po-files-encoding-and-bom-usage admonition\" role=\"note\">\n<p class=\"admonition-title\"><code class=\"docutils literal notranslate\">.po</code> 文件：编码和 BOM 的使用。</p>\n<p>Django 只支持使用UTF-8编码的 <code class=\"docutils literal notranslate\">.po</code> 文件并且没有任何BOM(字节顺序标记),因此如果文本编辑器默认在文件开头添加这个标记,那么你需要重新配置它.</p>\n</aside>\n</section>\n<section id=\"troubleshooting-gettext-incorrectly-detects-python-format-in-strings-with-percent-signs\">\n<h3>疑难解答: <code class=\"docutils literal notranslate\">gettext()</code> 在带有百分号的字符串中错误地检测 <code class=\"docutils literal notranslate\">python-format</code><a class=\"heading-anchor\" href=\"#troubleshooting-gettext-incorrectly-detects-python-format-in-strings-with-percent-signs\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在某些情况下,带有百分号的字符串跟着一个空格和一个字符串转换换类型( <a class=\"reference external\" href=\"https://docs.python.org/3/library/stdtypes.html#old-string-formatting\" title=\"(in Python v3.14)\"><span class=\"xref std std-ref\">string conversion type</span></a> ) (例如 <code class=\"docutils literal notranslate\">_(&quot;10% interest&quot;)</code> ),:func:~django.utils.translation.gettext 会错误地使用 <code class=\"docutils literal notranslate\">python-format</code> 标记字符串.</p>\n<p>如果试着使用已被错误标记的字符串来编译消息文件,会得到一个消息,例如&quot; 'msgid' 和 'msgstr' 格式数量不匹配&quot;( number of format specifications in 'msgid' and 'msgstr' does not match ),或者&quot;'msgstr' 不是有效的 Python 格式字符串,与'msgid'不同 &quot;( 'msgstr' is not a valid Python format string, unlike 'msgid').</p>\n<p>要解决这个问题，可以通过添加第二个百分号来转义百分号：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext <span class=\"k\">as</span> _\n\noutput <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;10</span><span class=\"si\">%%</span><span class=\"s2\"> interest&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>或者可以使用非python格式（ <code class=\"docutils literal notranslate\">no-python-format</code> ），这样所有百分号会被视为文字：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"c1\"># xgettext:no-python-format</span>\noutput <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;10</span><span class=\"si\">% i</span><span class=\"s2\">nterest&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"creating-message-files-from-javascript-source-code\">\n<span id=\"creating-message-files-from-js-code\"></span><h3>从 JavaScript 源码中创建消息文件<a class=\"heading-anchor\" href=\"#creating-message-files-from-javascript-source-code\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>您可以像处理其他 Django 消息文件一样创建和更新消息文件，使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a> 工具。唯一的区别是，您需要明确指定在 gettext 术语中称为域的内容，这里是 <code class=\"docutils literal notranslate\">djangojs</code> 域，通过提供一个 <code class=\"docutils literal notranslate\">-d djangojs</code> 参数，就像这样：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin makemessages -d djangojs -l de\n</code></pre></div>\n<p>这会创建或更新德语的JavaScript 消息文件。更新消息文件后，像执行普通 Django 消息文件那样运行  <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages</code></a> 即可。</p>\n</section>\n<section id=\"gettext-on-windows\">\n<span id=\"id3\"></span><h3>Windows 上的 <code class=\"docutils literal notranslate\">gettext</code><a class=\"heading-anchor\" href=\"#gettext-on-windows\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>仅适用于需要提取消息ID或编译消息文件（<code class=\"docutils literal notranslate\">.po</code>）的场景。翻译工作本身涉及编辑这种已存在的文件，但如果你想创建你自己的消息文件，或者想要测试或编译一个已改动的消息文件，需下载一个预编译的二进制安装器（<a class=\"reference external\" href=\"https://mlocati.github.io/articles/gettext-iconv-windows.html\">a precompiled binary installer</a>）。</p>\n<p>您也可以使用从其他地方获取的 <code class=\"docutils literal notranslate\">gettext</code> 二进制文件，只要 <code class=\"docutils literal notranslate\">xgettext --version</code> 命令正常工作即可。如果在 Windows 命令提示符中输入命令 <code class=\"docutils literal notranslate\">xgettext --version</code> 时弹出窗口显示 &quot;<code class=\"docutils literal notranslate\">xgettext.exe</code> 生成了错误并将被 Windows 关闭&quot;，请不要尝试使用 Django 的翻译工具与带有 <code class=\"docutils literal notranslate\">gettext</code> 包的系统一起使用。</p>\n</section>\n<section id=\"customizing-the-makemessages-command\">\n<span id=\"customizing-makemessages\"></span><h3>自定义 <code class=\"docutils literal notranslate\">makemessages</code> 命令<a class=\"heading-anchor\" href=\"#customizing-the-makemessages-command\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果要给 <code class=\"docutils literal notranslate\">xgettext</code> 传递额外的参数，则需要创建自定义的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> 命令，并覆盖它的 <code class=\"docutils literal notranslate\">xgettext_options</code> 属性：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.core.management.commands</span> <span class=\"kn\">import</span> makemessages\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Command</span><span class=\"p\">(</span>makemessages<span class=\"o\">.</span>Command<span class=\"p\">):</span>\n    xgettext_options <span class=\"o\">=</span> makemessages<span class=\"o\">.</span>Command<span class=\"o\">.</span>xgettext_options <span class=\"o\">+</span> <span class=\"p\">[</span><span class=\"s2\">&quot;--keyword=mytrans&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>如果需要更多的灵活性，也可以给自定义的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">makemessages</code></a> 命令添加新的参数：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.core.management.commands</span> <span class=\"kn\">import</span> makemessages\n\n\n<span class=\"k\">class</span> <span class=\"nc\">Command</span><span class=\"p\">(</span>makemessages<span class=\"o\">.</span>Command<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">add_arguments</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> parser<span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>add_arguments<span class=\"p\">(</span>parser<span class=\"p\">)</span>\n        parser<span class=\"o\">.</span>add_argument<span class=\"p\">(</span>\n            <span class=\"s2\">&quot;--extra-keyword&quot;</span><span class=\"p\">,</span>\n            dest<span class=\"o\">=</span><span class=\"s2\">&quot;xgettext_keywords&quot;</span><span class=\"p\">,</span>\n            action<span class=\"o\">=</span><span class=\"s2\">&quot;append&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">handle</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>options<span class=\"p\">):</span>\n        xgettext_keywords <span class=\"o\">=</span> options<span class=\"o\">.</span>pop<span class=\"p\">(</span><span class=\"s2\">&quot;xgettext_keywords&quot;</span><span class=\"p\">)</span>\n        <span class=\"k\">if</span> xgettext_keywords<span class=\"p\">:</span>\n            <span class=\"bp\">self</span><span class=\"o\">.</span>xgettext_options <span class=\"o\">=</span> makemessages<span class=\"o\">.</span>Command<span class=\"o\">.</span>xgettext_options<span class=\"p\">[:]</span> <span class=\"o\">+</span> <span class=\"p\">[</span>\n                <span class=\"s2\">&quot;--keyword=</span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span> <span class=\"o\">%</span> kwd <span class=\"k\">for</span> kwd <span class=\"ow\">in</span> xgettext_keywords\n            <span class=\"p\">]</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>handle<span class=\"p\">(</span><span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>options<span class=\"p\">)</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"miscellaneous\">\n<h2>杂项<a class=\"heading-anchor\" href=\"#miscellaneous\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"the-set-language-redirect-view\">\n<span id=\"set-language-redirect-view\"></span><h3><code class=\"docutils literal notranslate\">set_language</code> 重定向试图<a class=\"heading-anchor\" href=\"#the-set-language-redirect-view\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.views.i18n.set_language\">\n<span class=\"sig-name descname\">set_language</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">request</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.views.i18n.set_language\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>方便起见，Django 附带了一个视图 <a class=\"reference internal\" href=\"#django.views.i18n.set_language\" title=\"django.views.i18n.set_language\"><code class=\"xref py py-func docutils literal notranslate\">django.views.i18n.set_language()</code></a> ，它可以设置用户语言首选项，并且重定向到一个给定的URL，或者默认情况下，会返回到上一页。</p>\n<p>要激活这个视图，需要在你的 URLconf 中添加下面这行代码：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>path<span class=\"p\">(</span><span class=\"s2\">&quot;i18n/&quot;</span><span class=\"p\">,</span> include<span class=\"p\">(</span><span class=\"s2\">&quot;django.conf.urls.i18n&quot;</span><span class=\"p\">)),</span>\n</code></pre></div>\n<p>（注意这个例子会使视图在 <code class=\"docutils literal notranslate\">/i18n/setlang/</code> 下可用。）</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>确保在 <a class=\"reference internal\" href=\"#django.conf.urls.i18n.i18n_patterns\" title=\"django.conf.urls.i18n.i18n_patterns\"><code class=\"xref py py-func docutils literal notranslate\">i18n_patterns()</code></a> 中不包含上述 URL —— 它需要独立于语言才能正常工作。</p>\n</aside>\n<p>视图期望通过 <code class=\"docutils literal notranslate\">POST</code> 方法调用，并在请求中设置 <code class=\"docutils literal notranslate\">language</code> 参数。如果 session 支持是可用的，视图会在用户的 session 中保存语言选择。它也会将语言选择保存在默认名为 <code class=\"docutils literal notranslate\">django_language</code> （名称可以通过 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_NAME\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_NAME</code></a> 设置改变）的 cookie 中。</p>\n<p>在设置语言选择后，Django 会检查 <code class=\"docutils literal notranslate\">POST</code> 或 <code class=\"docutils literal notranslate\">GET</code> 数据中的 <code class=\"docutils literal notranslate\">next</code> 参数。如果找到这个参数并且 Django 认为它是一个安全的链接（也就是说它不指向其他主机并使用安全模式），将会重定向到这个链接。否则，Django 可能会重定向到 <code class=\"docutils literal notranslate\">Referer</code> header 里的 URL，如果没设置这个 URL，则会跳转到 <code class=\"docutils literal notranslate\">/</code> ，这取决于请求的性质。</p>\n<ul class=\"simple\">\n<li><p>如果请求接受 HTML 内容（基于其 <code class=\"docutils literal notranslate\">Accept</code> HTTP头），将始终执行回退。</p></li>\n<li><p>如果请求不接受 HTML，只有在设置了 <code class=\"docutils literal notranslate\">next</code> 参数的情况下才会进行回退。否则将返回 204 状态码（无内容）。</p></li>\n</ul>\n<p>这里是一个模板代码的例子：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">load</span> <span class=\"nv\">i18n</span> <span class=\"cp\">%}</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">form</span> <span class=\"na\">action</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;set_language&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{%</span> <span class=\"k\">csrf_token</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">input</span> <span class=\"na\">name</span><span class=\"o\">=</span><span class=\"s\">&quot;next&quot;</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;hidden&quot;</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">redirect_to</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">select</span> <span class=\"na\">name</span><span class=\"o\">=</span><span class=\"s\">&quot;language&quot;</span><span class=\"p\">&gt;</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">get_current_language</span> <span class=\"k\">as</span> <span class=\"nv\">LANGUAGE_CODE</span> <span class=\"cp\">%}</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">get_available_languages</span> <span class=\"k\">as</span> <span class=\"nv\">LANGUAGES</span> <span class=\"cp\">%}</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">get_language_info_list</span> <span class=\"nv\">for</span> <span class=\"nv\">LANGUAGES</span> <span class=\"k\">as</span> <span class=\"nv\">languages</span> <span class=\"cp\">%}</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">language</span> <span class=\"k\">in</span> <span class=\"nv\">languages</span> <span class=\"cp\">%}</span>\n            <span class=\"p\">&lt;</span><span class=\"nt\">option</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">language.code</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">language.code</span> <span class=\"o\">==</span> <span class=\"nv\">LANGUAGE_CODE</span> <span class=\"cp\">%}</span> <span class=\"na\">selected</span><span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span><span class=\"p\">&gt;</span>\n                <span class=\"cp\">{{</span> <span class=\"nv\">language.name_local</span> <span class=\"cp\">}}</span> (<span class=\"cp\">{{</span> <span class=\"nv\">language.code</span> <span class=\"cp\">}}</span>)\n            <span class=\"p\">&lt;/</span><span class=\"nt\">option</span><span class=\"p\">&gt;</span>\n        <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;/</span><span class=\"nt\">select</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">input</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;submit&quot;</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;Go&quot;</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>在这个例子中，Django 会在 <code class=\"docutils literal notranslate\">redirect_to</code> 变量中查找用户将要重定向的网址。</p>\n</section>\n<section id=\"explicitly-setting-the-active-language\">\n<span id=\"id4\"></span><h3>显式设置语言<a class=\"heading-anchor\" href=\"#explicitly-setting-the-active-language\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可能想显式地为当前会话设置语言。例如，可能是从另一个系统检索用户的语言偏好。你已经了解了 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.activate\" title=\"django.utils.translation.activate\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.activate()</code></a> 。这只适用于当前进程。要将整个会话的语言保留在 cookie 中，请在响应上设置 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_NAME\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_NAME</code></a> ：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.conf</span> <span class=\"kn\">import</span> settings\n<span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils</span> <span class=\"kn\">import</span> translation\n\nuser_language <span class=\"o\">=</span> <span class=\"s2\">&quot;fr&quot;</span>\ntranslation<span class=\"o\">.</span>activate<span class=\"p\">(</span>user_language<span class=\"p\">)</span>\nresponse <span class=\"o\">=</span> HttpResponse<span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\nresponse<span class=\"o\">.</span>set_cookie<span class=\"p\">(</span>settings<span class=\"o\">.</span>LANGUAGE_COOKIE_NAME<span class=\"p\">,</span> user_language<span class=\"p\">)</span>\n</code></pre></div>\n<p>通常你想同时使用这两者：<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.activate\" title=\"django.utils.translation.activate\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.activate()</code></a> 改变这个线程的语言，并设置cookie使此首选项在以后的请求中保持不变。</p>\n</section>\n<section id=\"using-translations-outside-views-and-templates\">\n<h3>使用视图和模板外的翻译<a class=\"heading-anchor\" href=\"#using-translations-outside-views-and-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>虽然 Django 提供了一套丰富的i18n工具用于视图和模板，但它并不会限制 Django 特定代码的使用。Django 翻译机制可用于将任何文本翻译成 Django 支持的语言（当然，需要存在合适的翻译目录）。你可以加载翻译目录，激活它并翻译你选择的语言，但记住要切换回原始语言，因为激活语言目录是在每个线程基础上完成的，这样的改变将影响在同一线程中运行的代码。</p>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils</span> <span class=\"kn\">import</span> translation\n\n\n<span class=\"k\">def</span> <span class=\"nf\">welcome_translated</span><span class=\"p\">(</span>language<span class=\"p\">):</span>\n    cur_language <span class=\"o\">=</span> translation<span class=\"o\">.</span>get_language<span class=\"p\">()</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        translation<span class=\"o\">.</span>activate<span class=\"p\">(</span>language<span class=\"p\">)</span>\n        text <span class=\"o\">=</span> translation<span class=\"o\">.</span>gettext<span class=\"p\">(</span><span class=\"s2\">&quot;welcome&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">finally</span><span class=\"p\">:</span>\n        translation<span class=\"o\">.</span>activate<span class=\"p\">(</span>cur_language<span class=\"p\">)</span>\n    <span class=\"k\">return</span> text\n</code></pre></div>\n<p>不论 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a>  和中间件设置的是什么，用 <code class=\"docutils literal notranslate\">'de'</code> 值调用的这个函数都会得到 <code class=\"docutils literal notranslate\">&quot;Willkommen&quot;</code> 。</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.get_language\" title=\"django.utils.translation.get_language\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.get_language()</code></a> 会返回当前进程所使用的语言，<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.activate\" title=\"django.utils.translation.activate\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.activate()</code></a> 会为当前进程激活翻译目录，<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.check_for_language\" title=\"django.utils.translation.check_for_language\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.check_for_language()</code></a> 会检查 Django 是否支持给定的语言。</p>\n<p>为了协助编写更简洁的代码，这里还有一个上下文管理器 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.override\" title=\"django.utils.translation.override\"><code class=\"xref py py-func docutils literal notranslate\">django.utils.translation.override()</code></a> ，它会在输入时存储当前语言，并在退出时恢复它。有了它，上面的例子可变为：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils</span> <span class=\"kn\">import</span> translation\n\n\n<span class=\"k\">def</span> <span class=\"nf\">welcome_translated</span><span class=\"p\">(</span>language<span class=\"p\">):</span>\n    <span class=\"k\">with</span> translation<span class=\"o\">.</span>override<span class=\"p\">(</span>language<span class=\"p\">):</span>\n        <span class=\"k\">return</span> translation<span class=\"o\">.</span>gettext<span class=\"p\">(</span><span class=\"s2\">&quot;welcome&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"language-cookie\">\n<h3>Language cookie<a class=\"heading-anchor\" href=\"#language-cookie\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>可以使用一些设置来调整语言cookie选项：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_NAME\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_NAME</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_AGE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_AGE</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_DOMAIN\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_DOMAIN</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_HTTPONLY\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_HTTPONLY</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_PATH\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_PATH</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_SAMESITE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_SAMESITE</code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_SECURE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_SECURE</code></a></p></li>\n</ul>\n</section>\n</section>\n<section id=\"implementation-notes\">\n<h2>实施说明<a class=\"heading-anchor\" href=\"#implementation-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"specialties-of-django-translation\">\n<span id=\"specialties-of-django-i18n\"></span><h3>Django 翻译的特性<a class=\"heading-anchor\" href=\"#specialties-of-django-translation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 翻译机制使用 Python 自带的标准 <code class=\"docutils literal notranslate\">gettext</code> 模块。如果你知道  <code class=\"docutils literal notranslate\">gettext</code> ，你可能注意到了 Django 翻译的这些特性：</p>\n<ul class=\"simple\">\n<li><p>字符串域为 <code class=\"docutils literal notranslate\">django</code> 或 <code class=\"docutils literal notranslate\">djangojs</code> 。这个字符串域用来区分在相同消息文件库(message-file library,通常为 <code class=\"docutils literal notranslate\">/usr/share/locale/</code> )中存有数据的不同项目。<code class=\"docutils literal notranslate\">django</code> 域被用于 Python和模板翻译字符串，以及加载到全局翻译目录。<code class=\"docutils literal notranslate\">djangojs</code> 域只用于 JavaScript 的翻译目录来确保它们尽可能小。</p></li>\n<li><p>Django 不会单独使用 <code class=\"docutils literal notranslate\">xgettext</code> 。它在 <code class=\"docutils literal notranslate\">xgettext</code> 和 <code class=\"docutils literal notranslate\">msgfmt</code> 周围使用 Python 装饰器。这主要是为了方便。</p></li>\n</ul>\n</section>\n<section id=\"how-django-discovers-language-preference\">\n<span id=\"id5\"></span><h3>Django 如何发现语言偏好<a class=\"heading-anchor\" href=\"#how-django-discovers-language-preference\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>一旦你准备好了翻译——或者，如果你想使用Django自带的翻译——那么你需要激活你的项目的翻译。</p>\n<p>在后台，Django 有一个非常灵活的模型来决定使用哪一种语言——在全局使用，还是特定用户使用，还是二者都有。</p>\n<p>在全局范围内设置语言偏好，需要设置 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> 。Django 使用这个语言作为默认翻译 —— 如果通过 locale 中间件所使用的方法之一没有找到匹配的翻译，那么这是最后的尝试（见下文）。</p>\n<p>如果你指向用你的母语运行 Django ，那么你需要做的就是设置 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> 并确保存在相应的消息文件及其编译版本 (<code class=\"docutils literal notranslate\">.mo</code>) 。</p>\n<p>如果你想让每个独立用户指定他们想要的语言，则还需要使用 <code class=\"docutils literal notranslate\">LocaleMiddleware</code> 。<code class=\"docutils literal notranslate\">LocaleMiddleware</code> 可以基于请求中的数据启用语言选择。它为每个用户定制内容。</p>\n<p>要使用 <code class=\"docutils literal notranslate\">LocaleMiddleware</code>，请在你的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 配置中添加 <code class=\"docutils literal notranslate\">'django.middleware.locale.LocaleMiddleware'</code>。因为中间件的顺序很重要，所以要遵循这些准则。</p>\n<ul class=\"simple\">\n<li><p>确保它是最先安装的中间件之一。</p></li>\n<li><p>它应该在 <code class=\"docutils literal notranslate\">SessionMiddleware</code> 之后，因为 <code class=\"docutils literal notranslate\">LocaleMiddleware</code> 使用会话数据。而且它应该在 <code class=\"docutils literal notranslate\">CommonMiddleware</code> 之前，因为 <code class=\"docutils literal notranslate\">CommonMiddleware</code> 需要激活的语言来解析请求的 URL。</p></li>\n<li><p>如果你使用 <code class=\"docutils literal notranslate\">CacheMiddleware</code>，把 <code class=\"docutils literal notranslate\">LocaleMiddleware</code> 放在它之后。</p></li>\n</ul>\n<p>例如，你的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 可能看起来像这样：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>MIDDLEWARE <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;django.contrib.sessions.middleware.SessionMiddleware&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.middleware.locale.LocaleMiddleware&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.middleware.common.CommonMiddleware&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>（关于中间件的更多信息，请参见 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/http/middleware/\"><span class=\"doc\">中间件文档</span></a>。）</p>\n<p><code class=\"docutils literal notranslate\">LocaleMiddleware</code> 试图通过以下算法来确定用户的语言偏好。</p>\n<ul>\n<li><p>首先，它在请求的URL中寻找语言前缀。 只有当你在你的根 URLconf 中使用 <code class=\"docutils literal notranslate\">i18n_patterns</code> 函数时，才会这样做。参见 <a class=\"reference internal\" href=\"#url-internationalization\"><span class=\"std std-ref\">国际化：在 URL 模式中</span></a> 了解更多关于语言前缀和如何国际化 URL 模式的信息。</p></li>\n<li><p>如果失败，它将查找 cookie。</p>\n<p>所使用的 cookie 的名称由 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_COOKIE_NAME\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_NAME</code></a> 设定。（默认名称是 <code class=\"docutils literal notranslate\">django_language</code>）。</p>\n</li>\n<li><p>如果失败了，它将查看 <code class=\"docutils literal notranslate\">Accept-Language</code> HTTP 头。这个头由你的浏览器发送，并告诉服务器你喜欢哪种语言，按优先级排序。Django 会尝试每一种语言，直到找到可用的翻译。</p></li>\n<li><p>如果不行，则使用全局 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> 设置。</p></li>\n</ul>\n<p id=\"locale-middleware-notes\">注意：</p>\n<ul>\n<li><p>在每一个地方，语言偏好都应该是标准的 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/i18n/#term-language-code\"><span class=\"xref std std-term\">语言格式</span></a>，作为一个字符串。例如，巴西葡萄牙语是 <code class=\"docutils literal notranslate\">pt-br</code>。</p></li>\n<li><p>如果基本语言可用，但指定的子语言不可用，Django 就使用基本语言。例如，如果用户指定了 <code class=\"docutils literal notranslate\">de-at</code> （奥地利德语），但 Django 只有 <code class=\"docutils literal notranslate\">de</code> 可用，Django 就使用 <code class=\"docutils literal notranslate\">de</code>。</p></li>\n<li><p>只有 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGES\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGES</code></a> 设置中列出的语言才能被选择。如果你想将语言选择限制在所提供的语言子集中（因为你的应用程序没有提供所有这些语言），请将 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGES\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGES</code></a> 设置为语言列表。例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>LANGUAGES <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">(</span><span class=\"s2\">&quot;de&quot;</span><span class=\"p\">,</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;German&quot;</span><span class=\"p\">)),</span>\n    <span class=\"p\">(</span><span class=\"s2\">&quot;en&quot;</span><span class=\"p\">,</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;English&quot;</span><span class=\"p\">)),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>这个例子将可供自动选择的语言限制为德语和英语（以及任何子语言，如 <code class=\"docutils literal notranslate\">de-ch</code> 或 <code class=\"docutils literal notranslate\">en-us</code>）。</p>\n</li>\n<li><p>如果你定义了一个自定义的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGES\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGES</code></a> 设置，就像上一弹所解释的那样，你可以将语言名称标记为翻译字符串——但要使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext_lazy\" title=\"django.utils.translation.gettext_lazy\"><code class=\"xref py py-func docutils literal notranslate\">gettext_lazy()</code></a> 而不是 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/utils/#django.utils.translation.gettext\" title=\"django.utils.translation.gettext\"><code class=\"xref py py-func docutils literal notranslate\">gettext()</code></a> 来避免循环导入。</p>\n<p>以下是一个实例配置文件:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\nLANGUAGES <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">(</span><span class=\"s2\">&quot;de&quot;</span><span class=\"p\">,</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;German&quot;</span><span class=\"p\">)),</span>\n    <span class=\"p\">(</span><span class=\"s2\">&quot;en&quot;</span><span class=\"p\">,</span> _<span class=\"p\">(</span><span class=\"s2\">&quot;English&quot;</span><span class=\"p\">)),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n</li>\n</ul>\n<p>一旦 <code class=\"docutils literal notranslate\">LocaleMiddleware</code> 确定了用户的偏好，它就会将这个偏好作为 <code class=\"docutils literal notranslate\">request.LANGUAGE_CODE</code> 提供给每一个  <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\">HttpRequest</code></a>。在你的视图代码中可以随意读取这个值。下面是一个例子：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n\n\n<span class=\"k\">def</span> <span class=\"nf\">hello_world</span><span class=\"p\">(</span>request<span class=\"p\">,</span> count<span class=\"p\">):</span>\n    <span class=\"k\">if</span> request<span class=\"o\">.</span>LANGUAGE_CODE <span class=\"o\">==</span> <span class=\"s2\">&quot;de-at&quot;</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span><span class=\"s2\">&quot;You prefer to read Austrian German.&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> HttpResponse<span class=\"p\">(</span><span class=\"s2\">&quot;You prefer to read another language.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>注意，静态（无中间件）翻译时，语言在 <code class=\"docutils literal notranslate\">settings.LANGUAGE_CODE</code> 中，而动态（中间件）翻译时，语言在 <code class=\"docutils literal notranslate\">request.LANGUAGE_CODE</code> 中。</p>\n</section>\n<section id=\"how-django-discovers-translations\">\n<span id=\"id6\"></span><h3>Django 如何发现翻译<a class=\"heading-anchor\" href=\"#how-django-discovers-translations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在运行时，Django 会在内存中建立一个统一的字面翻译目录。为了达到这个目的，它通过以下算法来查找翻译，关于它检查不同文件路径的顺序来加载编译的 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/i18n/#term-message-file\"><span class=\"xref std std-term\">消息文件</span></a> （<code class=\"docutils literal notranslate\">.mo</code>），以及同一字面意义的多个翻译的优先级。</p>\n<ol class=\"arabic simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> 中列出的目录优先级最高，先出现的比后出现的优先级高。</p></li>\n<li><p>然后，它会在 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\">INSTALLED_APPS</code></a> 中列出的每个已安装的应用程序中寻找并使用是否存在 <code class=\"docutils literal notranslate\">locale</code> 目录。 先出现的比后出现的优先级高。</p></li>\n<li><p>最后，Django 提供的位于 <a class=\"extlink-source reference external\" href=\"https://github.com/django/django/blob/stable/5.1.x/django/conf/locale\">django/conf/locale</a> 中的基本翻译将作为备用。</p></li>\n</ol>\n<aside class=\"admonition admonition-seealso\" role=\"note\">\n<p class=\"admonition-title\">See also</p>\n<p>JavaScript 资产中包含的字词的翻译是按照类似但不相同的算法来查找的。更多细节请参见 <a class=\"reference internal\" href=\"#django.views.i18n.JavaScriptCatalog\" title=\"django.views.i18n.JavaScriptCatalog\"><code class=\"xref py py-class docutils literal notranslate\">JavaScriptCatalog</code></a>。</p>\n<p>如果你还设置了 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">:set:`FORMAT_MODULE_PATH`</span></a>，你也可以把 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/i18n/formatting/#custom-format-files\"><span class=\"std std-ref\">自定义格式文件</span></a> 放在 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">:set:`LOCALE_PATHS`</span></a> 目录下。</p>\n</aside>\n<p>在所有情况下，包含译文的目录名称应使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/i18n/#term-locale-name\"><span class=\"xref std std-term\">locale name</span></a> 符号来命名，如 <code class=\"docutils literal notranslate\">de</code>、<code class=\"docutils literal notranslate\">pt_BR</code>、<code class=\"docutils literal notranslate\">es_AR</code> 等。未翻译的地域语言变体字符串使用通用语言的翻译。例如，未翻译的 <code class=\"docutils literal notranslate\">pt_BR</code> 字符串使用 <code class=\"docutils literal notranslate\">pt</code> 翻译。</p>\n<p>这样，你可以编写包含自己翻译的应用程序，你可以在你的项目中覆盖基础翻译。或者，你可以用几个应用程序构建一个大项目，并将所有翻译放到一个大的通用消息文件中，具体到你正在编写的项目。这是你的选择。</p>\n<p>所有的消息文件库的结构都是一样的。它们是：</p>\n<ul class=\"simple\">\n<li><p>配置文件的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> 中列出的所有路径都会被搜索到 <code class=\"docutils literal notranslate\">&lt;language&gt;/LC_MESSAGES/django.(po|mo)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">$APPPATH/locale/&lt;language&gt;/LC_MESSAGES/django.(po|mo)</code></p></li>\n<li><p><code class=\"docutils literal notranslate\">$PYTHONPATH/django/conf/locale/&lt;language&gt;/LC_MESSAGES/django.(po|mo)</code></p></li>\n</ul>\n<p>为了创建消息文件，你使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a> 工具。并使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages</code></a> 来生成二进制的 <code class=\"docutils literal notranslate\">.mo</code> 文件，这些文件被 <code class=\"docutils literal notranslate\">gettext</code> 使用。</p>\n<p>你也可以运行 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages --settings=path.to.settings</code></a> 使编译器处理你 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">:settings:`LOCALE_PATHS`</span></a> 设置中的所有目录。</p>\n</section>\n<section id=\"using-a-non-english-base-language\">\n<h3>使用非英语基础语言<a class=\"heading-anchor\" href=\"#using-a-non-english-base-language\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 一般假设可翻译项目中的原始字符串是用英语编写的。你可以选择其他语言，但你必须意识到某些限制。</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">gettext</code> 只为原始信息提供两种复数形式，所以如果基础语言的复数规则与英语不同，你还需要提供基础语言的翻译，以包括所有的复数形式。</p></li>\n<li><p>当英文变体被激活而英文字符串缺失时，后备语言将不是项目的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a>，而是原始字符串。例如，一个英语用户访问一个有 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> 设置为西班牙语的网站，而原来的字符串是用俄语写的，他看到的将是俄语文本而不是西班牙语。</p></li>\n</ul>\n</section>\n</section>","rootId":"translation","toc":[{"title":"概况","anchor":"overview","children":[]},{"title":"在 Python 代码中进行国际化","anchor":"internationalization-in-python-code","children":[{"title":"标准翻译","anchor":"standard-translation","children":[]},{"title":"为翻译者提供注释","anchor":"comments-for-translators","children":[]},{"title":"标记不用翻译的字符","anchor":"marking-strings-as-no-op","children":[]},{"title":"多元化","anchor":"pluralization","children":[]},{"title":"上下文标记","anchor":"contextual-markers","children":[]},{"title":"惰性翻译","anchor":"lazy-translation","children":[{"title":"模型字段和相关的 verbose_name 与 help_text 选项值","anchor":"model-fields-and-relationships-verbose-name-and-help-text-option-values","children":[]},{"title":"模型详细名称的值","anchor":"model-verbose-names-values","children":[]},{"title":"模型方法 description 参数用于 @display 装饰器。","anchor":"model-methods-description-argument-to-the-display-decorator","children":[]}]},{"title":"使用惰性翻译对象","anchor":"working-with-lazy-translation-objects","children":[{"title":"惰性翻译与复数","anchor":"lazy-translations-and-plural","children":[]},{"title":"格式化字符串：format_lazy()","anchor":"formatting-strings-format-lazy","children":[]},{"title":"延迟翻译中惰性(lazy)的其他用法","anchor":"other-uses-of-lazy-in-delayed-translations","children":[]}]},{"title":"语言的本地化名称","anchor":"localized-names-of-languages","children":[]}]},{"title":"在模板代码中国际化","anchor":"internationalization-in-template-code","children":[{"title":"translate 模板标签","anchor":"translate-template-tag","children":[]},{"title":"blocktranslate 模板标签","anchor":"blocktranslate-template-tag","children":[]},{"title":"传递字符串给标签和过滤器","anchor":"string-literals-passed-to-tags-and-filters","children":[]},{"title":"模板内对翻译的注释","anchor":"comments-for-translators-in-templates","children":[]},{"title":"在模板中选择语言","anchor":"switching-language-in-templates","children":[]},{"title":"其他标签","anchor":"other-tags","children":[{"title":"get_available_languages","anchor":"get-available-languages","children":[]},{"title":"get_current_language","anchor":"get-current-language","children":[]},{"title":"get_current_language_bidi","anchor":"get-current-language-bidi","children":[]},{"title":"i18n 上下文处理器","anchor":"i18n-context-processor","children":[]},{"title":"get_language_info","anchor":"get-language-info","children":[]},{"title":"get_language_info_list","anchor":"get-language-info-list","children":[]},{"title":"模板过滤器","anchor":"template-filters","children":[]}]}]},{"title":"国际化：在 JavaScript 代码里","anchor":"internationalization-in-javascript-code","children":[{"title":"JavaScriptCatalog 视图","anchor":"module-django.views.i18n","children":[]},{"title":"使用 JavaScript 翻译目录","anchor":"using-the-javascript-translation-catalog","children":[{"title":"gettext","anchor":"gettext","children":[]},{"title":"ngettext","anchor":"ngettext","children":[]},{"title":"interpolate","anchor":"interpolate","children":[]},{"title":"get_format","anchor":"get-format","children":[]},{"title":"gettext_noop","anchor":"gettext-noop","children":[]},{"title":"pgettext","anchor":"pgettext","children":[]},{"title":"npgettext","anchor":"npgettext","children":[]},{"title":"pluralidx","anchor":"pluralidx","children":[]}]},{"title":"JSONCatalog 视图","anchor":"the-jsoncatalog-view","children":[]},{"title":"性能说明","anchor":"note-on-performance","children":[]}]},{"title":"国际化：在 URL 模式中","anchor":"module-django.conf.urls.i18n","children":[{"title":"URL 模式中的语言前缀","anchor":"language-prefix-in-url-patterns","children":[]},{"title":"翻译URL模式","anchor":"translating-url-patterns","children":[]},{"title":"在模板中反向解析URL","anchor":"reversing-in-templates","children":[]}]},{"title":"本地化：如何创建语言文件","anchor":"localization-how-to-create-language-files","children":[{"title":"消息文件","anchor":"message-files","children":[]},{"title":"编译消息文件","anchor":"compiling-message-files","children":[]},{"title":"疑难解答: gettext() 在带有百分号的字符串中错误地检测 python-format","anchor":"troubleshooting-gettext-incorrectly-detects-python-format-in-strings-with-percent-signs","children":[]},{"title":"从 JavaScript 源码中创建消息文件","anchor":"creating-message-files-from-javascript-source-code","children":[]},{"title":"Windows 上的 gettext","anchor":"gettext-on-windows","children":[]},{"title":"自定义 makemessages 命令","anchor":"customizing-the-makemessages-command","children":[]}]},{"title":"杂项","anchor":"miscellaneous","children":[{"title":"set_language 重定向试图","anchor":"the-set-language-redirect-view","children":[]},{"title":"显式设置语言","anchor":"explicitly-setting-the-active-language","children":[]},{"title":"使用视图和模板外的翻译","anchor":"using-translations-outside-views-and-templates","children":[]},{"title":"Language cookie","anchor":"language-cookie","children":[]}]},{"title":"实施说明","anchor":"implementation-notes","children":[{"title":"Django 翻译的特性","anchor":"specialties-of-django-translation","children":[]},{"title":"Django 如何发现语言偏好","anchor":"how-django-discovers-language-preference","children":[]},{"title":"Django 如何发现翻译","anchor":"how-django-discovers-translations","children":[]},{"title":"使用非英语基础语言","anchor":"using-a-non-english-base-language","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/5.1/topics/"},{"docname":"topics/i18n/index","title":"国际化和本地化","url":"/zh-hans/5.1/topics/i18n/"}],"prev":{"docname":"topics/i18n/index","title":"国际化和本地化","url":"/zh-hans/5.1/topics/i18n/"},"next":{"docname":"topics/i18n/formatting","title":"本地格式化","url":"/zh-hans/5.1/topics/i18n/formatting/"},"formats":{"html":"/zh-hans/5.1/topics/i18n/translation/","markdown":"/zh-hans/5.1/topics/i18n/translation.md","json":"/zh-hans/5.1/topics/i18n/translation.json"},"source":"https://github.com/django/django/blob/stable/5.1.x/docs/topics/i18n/translation.txt","official":"https://docs.djangoproject.com/zh-hans/5.1/topics/i18n/translation/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}