{"title":"翻译","version":"3.0","locale":"zh-hans","docname":"topics/i18n/translation","url":"/zh-hans/3.0/topics/i18n/translation/","canonical":"https://djangodocs.dev/zh-hans/3.0/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/3.0/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/3.0/topics/i18n/#term-message-file\"><span class=\"xref std std-term\">message file</span></a> 中。这个文件让翻译者方便地提供翻译字符串。一旦翻译者填写了 message file ，就必须编译它。这个过程依赖 GNU gettext 工具集。</p>\n<p>完成后，Django 会根据用户的语言偏好，使用每种可用语言对网页进行即时翻译。</p>\n<p>Django 的国际化钩子默认是开启的，这意味着在框架的某些位置存在一些 i18n 相关的开销。如果你不使用国际化，你应该在配置文件里设置 <a class=\"reference internal\" href=\"/zh-hans/3.0/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/3.0/ref/settings/#std-setting-USE_L10N\"><code class=\"xref std std-setting docutils literal notranslate\">USE_L10N</code></a> 的设置，用来控制 Django 是否应该实现格式本地化。查看 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/i18n/formatting/\"><span class=\"doc\">本地格式化</span></a> 获取更多细节。</p>\n</aside>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>确保你的项目已经激活了翻译（最快的办法是检查 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 是否包含 <a class=\"reference internal\" href=\"/zh-hans/3.0/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\">How Django discovers language preference</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/3.0/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/3.0/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> 的工作方式，只有带有单一字符串参数的函数才能当做 <code class=\"docutils literal notranslate\">_</code> 引入：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.0/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/3.0/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<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<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=\"s1\">&#39;Welcome&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;to&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;my&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;site.&#39;</span><span class=\"p\">]</span>\n    output <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s1\">&#39; &#39;</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=\"s1\">&#39;Welcome to my site.&#39;</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/3.0/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/3.0/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=\"s1\">&#39;Today is </span><span class=\"si\">%(month)s</span><span class=\"s1\"> </span><span class=\"si\">%(day)s</span><span class=\"s1\">.&#39;</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span><span class=\"s1\">&#39;month&#39;</span><span class=\"p\">:</span> m<span class=\"p\">,</span> <span class=\"s1\">&#39;day&#39;</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/3.0/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/3.0/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<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=\"s1\">&#39;there is </span><span class=\"si\">%(count)d</span><span class=\"s1\"> object&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;there are </span><span class=\"si\">%(count)d</span><span class=\"s1\"> objects&#39;</span><span class=\"p\">,</span>\n    count<span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;count&#39;</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=\"s1\">&#39;There is </span><span class=\"si\">%(count)d</span><span class=\"s1\"> </span><span class=\"si\">%(name)s</span><span class=\"s1\"> available.&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;There are </span><span class=\"si\">%(count)d</span><span class=\"s1\"> </span><span class=\"si\">%(name)s</span><span class=\"s1\"> available.&#39;</span><span class=\"p\">,</span>\n    count\n<span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;count&#39;</span><span class=\"p\">:</span> count<span class=\"p\">,</span>\n    <span class=\"s1\">&#39;name&#39;</span><span class=\"p\">:</span> name\n<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=\"s1\">&#39;There is </span><span class=\"si\">%(count)d</span><span class=\"s1\"> </span><span class=\"si\">%(name)s</span><span class=\"s1\"> object available.&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;There are </span><span class=\"si\">%(count)d</span><span class=\"s1\"> </span><span class=\"si\">%(name)s</span><span class=\"s1\"> objects available.&#39;</span><span class=\"p\">,</span>\n    count\n<span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;count&#39;</span><span class=\"p\">:</span> count<span class=\"p\">,</span>\n    <span class=\"s1\">&#39;name&#39;</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=\"s1\">&#39;There is </span><span class=\"si\">%(count)d</span><span class=\"s1\"> </span><span class=\"si\">%(name)s</span><span class=\"s1\"> available.&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;There are </span><span class=\"si\">%(count)d</span><span class=\"s1\"> </span><span class=\"si\">%(plural_name)s</span><span class=\"s1\"> available.&#39;</span><span class=\"p\">,</span>\n    count\n<span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;count&#39;</span><span class=\"p\">:</span> Report<span class=\"o\">.</span>objects<span class=\"o\">.</span>count<span class=\"p\">(),</span>\n    <span class=\"s1\">&#39;name&#39;</span><span class=\"p\">:</span> Report<span class=\"o\">.</span>_meta<span class=\"o\">.</span>verbose_name<span class=\"p\">,</span>\n    <span class=\"s1\">&#39;plural_name&#39;</span><span class=\"p\">:</span> Report<span class=\"o\">.</span>_meta<span class=\"o\">.</span>verbose_name_plural\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>当正在运行 <a class=\"reference internal\" href=\"/zh-hans/3.0/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=\"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>a <span class=\"nb\">format</span> specification <span class=\"k\">for</span> argument <span class=\"s1\">&#39;name&#39;</span><span class=\"p\">,</span> <span class=\"k\">as</span> <span class=\"ow\">in</span> <span class=\"s1\">&#39;msgstr[0]&#39;</span><span class=\"p\">,</span> doesn<span class=\"s1\">&#39;t exist in &#39;</span>msgid<span class=\"s1\">&#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/3.0/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/3.0/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<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>pgettext_lazy<span class=\"p\">(</span>\n        <span class=\"s1\">&#39;help text for MyThing model&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;This is the help text&#39;</span><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>Contextual markers are also supported by the <a class=\"reference internal\" href=\"#std-templatetag-trans\"><code class=\"xref std std-ttag docutils literal notranslate\">trans</code></a> and\n<a class=\"reference internal\" href=\"#std-templatetag-blocktrans\"><code class=\"xref std std-ttag docutils literal notranslate\">blocktrans</code></a> template tags.</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/3.0/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<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=\"s1\">&#39;This is the help text&#39;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>你可以通过使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/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/3.0/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/3.0/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/3.0/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=\"s1\">&#39;kinds&#39;</span><span class=\"p\">,</span>\n        verbose_name<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s1\">&#39;kind&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>就像你在 <a class=\"reference internal\" href=\"/zh-hans/3.0/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/3.0/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/3.0/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<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=\"s1\">&#39;name&#39;</span><span class=\"p\">),</span> help_text<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s1\">&#39;This is the help text&#39;</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=\"s1\">&#39;my thing&#39;</span><span class=\"p\">)</span>\n        verbose_name_plural <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s1\">&#39;my things&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"model-methods-short-description-attribute-values\">\n<h4>模型方法 <code class=\"docutils literal notranslate\">short_description</code> 的属性值<a class=\"heading-anchor\" href=\"#model-methods-short-description-attribute-values\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>对于模型方法，可以使用 <code class=\"docutils literal notranslate\">short_description</code> 属性来为 Django 和 admin管理后台提供翻译：</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<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=\"s1\">&#39;kinds&#39;</span><span class=\"p\">,</span>\n        verbose_name<span class=\"o\">=</span>_<span class=\"p\">(</span><span class=\"s1\">&#39;kind&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">)</span>\n\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    is_mouse<span class=\"o\">.</span>short_description <span class=\"o\">=</span> _<span class=\"p\">(</span><span class=\"s1\">&#39;Is it a mouse?&#39;</span><span class=\"p\">)</span>\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=\"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=\"s1\">&#39;https://example.com/send&#39;</span><span class=\"p\">,</span> data<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;body&#39;</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=\"s1\">&#39;https://example.com/send&#39;</span><span class=\"p\">,</span> data<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;body&#39;</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<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=\"s1\">&#39;This is the help text&#39;</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.utils.translation</span> <span class=\"kn\">import</span> ngettext_lazy\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><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> <span class=\"s1\">&#39;num&#39;</span><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> forms<span class=\"o\">.</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=\"s1\">&#39;num&#39;</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> forms<span class=\"o\">.</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/3.0/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<span class=\"o\">...</span>\nname <span class=\"o\">=</span> gettext_lazy<span class=\"p\">(</span><span class=\"s1\">&#39;John Lennon&#39;</span><span class=\"p\">)</span>\ninstrument <span class=\"o\">=</span> gettext_lazy<span class=\"p\">(</span><span class=\"s1\">&#39;guitar&#39;</span><span class=\"p\">)</span>\nresult <span class=\"o\">=</span> format_lazy<span class=\"p\">(</span><span class=\"s1\">&#39;</span><span class=\"si\">{name}</span><span class=\"s1\">: </span><span class=\"si\">{instrument}</span><span class=\"s1\">&#39;</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.safestring</span> <span class=\"kn\">import</span> mark_safe\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\nmark_safe_lazy <span class=\"o\">=</span> lazy<span class=\"p\">(</span>mark_safe<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> mark_safe_lazy<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s2\">&quot;&lt;p&gt;My &lt;strong&gt;string!&lt;/strong&gt;&lt;/p&gt;&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><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=\"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=\"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=\"s1\">&#39;fr&#39;</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=\"s1\">&#39;de&#39;</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=\"s1\">&#39;name&#39;</span><span class=\"p\">],</span> li<span class=\"p\">[</span><span class=\"s1\">&#39;name_local&#39;</span><span class=\"p\">],</span> li<span class=\"p\">[</span><span class=\"s1\">&#39;name_translated&#39;</span><span class=\"p\">],</span> li<span class=\"p\">[</span><span class=\"s1\">&#39;bidi&#39;</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/3.0/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=\"trans-template-tag\">\n<span id=\"std-templatetag-trans\"></span><h3><code class=\"docutils literal notranslate\">trans</code> 模板标签<a class=\"heading-anchor\" href=\"#trans-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\">{% trans %}</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\">trans</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\">trans</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\">trans</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/3.0/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\">{% trans %}</code> 的字符串内混合模板变量。如果你的翻译需要带有变量的字符串，可以使用 <a class=\"reference internal\" href=\"#std-templatetag-blocktrans\"><code class=\"xref std std-ttag docutils literal notranslate\">{% blocktrans %}</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\">trans</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\">trans</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\">trans</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\">trans</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\">blocktrans</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\">endblocktrans</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\">{% trans %}</code> 也支持使用 <code class=\"docutils literal notranslate\">context</code> 的 <a class=\"reference internal\" href=\"#contextual-markers\"><span class=\"std std-ref\">contextual markers</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\">trans</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=\"blocktrans-template-tag\">\n<span id=\"std-templatetag-blocktrans\"></span><h3><code class=\"docutils literal notranslate\">blocktrans</code> 模板标签<a class=\"heading-anchor\" href=\"#blocktrans-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-trans\"><code class=\"xref std std-ttag docutils literal notranslate\">trans</code></a> 相反，<code class=\"docutils literal notranslate\">blocktrans</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\">blocktrans</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\">endblocktrans</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\">blocktrans</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\">endblocktrans</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">blocktrans</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\">endblocktrans</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>可以在单个 <code class=\"docutils literal notranslate\">blocktrans</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\">blocktrans</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\">endblocktrans</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\">{% blocktrans with book|title as book_t and author|title as author_t %}</code></p>\n</aside>\n<p>其他块标签（比如 <code class=\"docutils literal notranslate\">{% for %}</code> 或 <code class=\"docutils literal notranslate\">{% if %}</code>）不允许包含在 <code class=\"docutils literal notranslate\">blocktrans</code> 标签里。</p>\n<p>如果解析其中一个块参数失败，<code class=\"docutils literal notranslate\">blocktrans</code> 将通过使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/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\">{% blocktrans %}</code> 和 <code class=\"docutils literal notranslate\">{% endblocktrans %}</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\">blocktrans</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\">endblocktrans</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\">blocktrans</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\">endblocktrans</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>当你同时使用复数特性和将值绑定给除了计数器值之外的局部变量时，要记住 <code class=\"docutils literal notranslate\">blocktrans</code> 构造在内部转换为 <code class=\"docutils literal notranslate\">ngettext</code> 调用。这意味着有关ngettext变量的注意事项（<a class=\"reference internal\" href=\"#pluralization-var-notes\"><span class=\"std std-ref\">notes regarding ngettext variables</span></a>）同样适用于此。</p>\n<p>反向 URL 查找不能在 <code class=\"docutils literal notranslate\">blocktrans</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\">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\">blocktrans</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\">endblocktrans</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\">blocktrans</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\">endblocktrans</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\">{% blocktrans %}</code> 也支持使用 <code class=\"docutils literal notranslate\">context</code> 的 <a class=\"reference internal\" href=\"#contextual-markers\"><span class=\"std std-ref\">contextual markers</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\">blocktrans</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\">endblocktrans</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">{% blocktrans %}</code> 支持的另一个特性是 <code class=\"docutils literal notranslate\">trimmed</code> 选项。这个选项将删除从 <code class=\"docutils literal notranslate\">{% blocktrans %}</code> 标签开头到结尾的换行符，替换所有的行首和行位的空格，并且使用空格将所有行合并为一行。这对缩进 <code class=\"docutils literal notranslate\">{% blocktrans %}</code> 标签的内容非常有用，而且缩进字符不会出现在 PO 文件的相应条目中，这会让翻译过程变得容易。</p>\n<p>例如，下面的 <code class=\"docutils literal notranslate\">{% blocktrans %}</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\">blocktrans</span> <span class=\"nv\">trimmed</span> <span class=\"cp\">%}</span>\n  First sentence.\n  Second paragraph.\n<span class=\"cp\">{%</span> <span class=\"k\">endblocktrans</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>如果没有 <code class=\"docutils literal notranslate\">trimmed</code> 选项，那么 PO 文件中的条目 <code class=\"docutils literal notranslate\">&quot;First sentence. Second paragraph.&quot;</code> 成为 <code class=\"docutils literal notranslate\">&quot;\\n First sentence.\\n Second sentence.\\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/3.0/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\">trans</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\">blocktrans</span> <span class=\"cp\">%}</span>A multiline translatable\nliteral.<span class=\"cp\">{%</span> <span class=\"k\">endblocktrans</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\">trans</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\">blocktrans</span> <span class=\"cp\">%}</span>Ambiguous translatable block of text<span class=\"cp\">{%</span> <span class=\"k\">endblocktrans</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\">trans</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\">trans</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\">How Django discovers language preference</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/3.0/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/3.0/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/3.0/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=\"s1\">&#39;available_languages&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;en&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;es&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;fr&#39;</span><span class=\"p\">]}</span>\n<span class=\"k\">return</span> render<span class=\"p\">(</span>request<span class=\"p\">,</span> <span class=\"s1\">&#39;mytemplate.html&#39;</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/3.0/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/3.0/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=\"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><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=\"s1\">&#39;jsi18n/&#39;</span><span class=\"p\">,</span> JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;javascript-catalog&#39;</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=\"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>urlpatterns <span class=\"o\">=</span> <span class=\"p\">[</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;jsi18n/myapp/&#39;</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=\"s1\">&#39;your.app.label&#39;</span><span class=\"p\">]),</span>\n         name<span class=\"o\">=</span><span class=\"s1\">&#39;javascript-catalog&#39;</span><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=\"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><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=\"s1\">&#39;jsi18n/&#39;</span><span class=\"p\">,</span> JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">(),</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;javascript-catalog&#39;</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\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;text/javascript&quot;</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=\"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\">gettext</span><span class=\"p\">(</span><span class=\"s1\">&#39;this is to be translated&#39;</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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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=\"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\">gettext_noop</span><span class=\"p\">(</span><span class=\"s1\">&#39;this will not be translated&#39;</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/3.0/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=\"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\">pgettext</span><span class=\"p\">(</span><span class=\"s1\">&#39;month name&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;May&#39;</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/3.0/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/3.0/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/3.0/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=\"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><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><span class=\"s1\">&#39;jsi18n/&#39;</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=\"s1\">&#39;js18n-</span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> get_version<span class=\"p\">())(</span>JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">()),</span>\n         name<span class=\"o\">=</span><span class=\"s1\">&#39;javascript-catalog&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>客户端缓存将节省带宽并让网站加载速度变快。如果你正在使用 ETags（<a class=\"reference internal\" href=\"/zh-hans/3.0/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/3.0/topics/conditional-view-processing/#conditional-decorators\"><span class=\"std std-ref\">conditional decorators</span></a>）。在下面的例子中，当你重启应用程序服务时，缓存将失效。</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><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><span class=\"s1\">&#39;jsi18n/&#39;</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>JavaScriptCatalog<span class=\"o\">.</span>as_view<span class=\"p\">()),</span>\n         name<span class=\"o\">=</span><span class=\"s1\">&#39;javascript-catalog&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>你甚至可以在部署过程中预先生成JavaScript目录，并将其作为静态文件。该技术已在 <a class=\"reference external\" href=\"https://django-statici18n.readthedocs.io/en/latest/\">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/3.0/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/3.0/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/3.0/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 设置中包含 <a class=\"reference internal\" href=\"/zh-hans/3.0/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/3.0/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=\"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><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=\"s1\">&#39;sitemap.xml&#39;</span><span class=\"p\">,</span> sitemap<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;sitemap-xml&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n\nnews_patterns <span class=\"o\">=</span> <span class=\"p\">([</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;&#39;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>index<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;index&#39;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;category/&lt;slug:slug&gt;/&#39;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>category<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;category&#39;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;&lt;slug:slug&gt;/&#39;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>details<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">],</span> <span class=\"s1\">&#39;news&#39;</span><span class=\"p\">)</span>\n\nurlpatterns <span class=\"o\">+=</span> i18n_patterns<span class=\"p\">(</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;about/&#39;</span><span class=\"p\">,</span> about_views<span class=\"o\">.</span>main<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;about&#39;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;news/&#39;</span><span class=\"p\">,</span> include<span class=\"p\">(</span>news_patterns<span class=\"p\">,</span> namespace<span class=\"o\">=</span><span class=\"s1\">&#39;news&#39;</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=\"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><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=\"s1\">&#39;en&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s1\">&#39;sitemap-xml&#39;</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=\"s1\">&#39;news:index&#39;</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=\"s1\">&#39;nl&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s1\">&#39;news:detail&#39;</span><span class=\"p\">,</span> kwargs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;slug&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;news-slug&#39;</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> ，URLs 将会是：</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><span class=\"gp\">&gt;&gt;&gt; </span>activate<span class=\"p\">(</span><span class=\"s1\">&#39;en&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s1\">&#39;news:index&#39;</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=\"s1\">&#39;nl&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s1\">&#39;news:index&#39;</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/3.0/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/3.0/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=\"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><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=\"s1\">&#39;sitemap.xml&#39;</span><span class=\"p\">,</span> sitemap<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;sitemap-xml&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n\nnews_patterns <span class=\"o\">=</span> <span class=\"p\">([</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;&#39;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>index<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;index&#39;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s1\">&#39;category/&lt;slug:slug&gt;/&#39;</span><span class=\"p\">),</span> news_views<span class=\"o\">.</span>category<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;category&#39;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span><span class=\"s1\">&#39;&lt;slug:slug&gt;/&#39;</span><span class=\"p\">,</span> news_views<span class=\"o\">.</span>details<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">],</span> <span class=\"s1\">&#39;news&#39;</span><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=\"s1\">&#39;about/&#39;</span><span class=\"p\">),</span> about_views<span class=\"o\">.</span>main<span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;about&#39;</span><span class=\"p\">),</span>\n    path<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s1\">&#39;news/&#39;</span><span class=\"p\">),</span> include<span class=\"p\">(</span>news_patterns<span class=\"p\">,</span> namespace<span class=\"o\">=</span><span class=\"s1\">&#39;news&#39;</span><span class=\"p\">)),</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>然后你可以创建翻译，<a class=\"reference internal\" href=\"/zh-hans/3.0/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=\"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><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=\"s1\">&#39;en&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s1\">&#39;news:category&#39;</span><span class=\"p\">,</span> kwargs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;slug&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;recent&#39;</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=\"s1\">&#39;nl&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>reverse<span class=\"p\">(</span><span class=\"s1\">&#39;news:category&#39;</span><span class=\"p\">,</span> kwargs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;slug&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;recent&#39;</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\">trans</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/3.0/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/3.0/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=\"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>django<span class=\"o\">-</span>admin makemessages <span class=\"o\">-</span>l de\n</code></pre></div>\n<p>...其中 <code class=\"docutils literal notranslate\">de</code> 是你要创建的消息文件的 <a class=\"reference internal\" href=\"/zh-hans/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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> or <code class=\"docutils literal notranslate\">.py</code> 为后缀的文件。如果想覆盖默认值，需使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/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=\"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>django<span class=\"o\">-</span>admin makemessages <span class=\"o\">-</span>l de <span class=\"o\">-</span>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=\"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>django<span class=\"o\">-</span>admin makemessages <span class=\"o\">-</span>l de <span class=\"o\">-</span>e html<span class=\"p\">,</span>txt <span class=\"o\">-</span>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/3.0/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=\"http://babel.pocoo.org/\">Babel</a> 的 <a class=\"reference external\" href=\"http://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=\"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><span class=\"c1\"># Extraction from Python source files</span>\n<span class=\"p\">[</span>python<span class=\"p\">:</span> <span class=\"o\">**.</span>py<span class=\"p\">]</span>\n\n<span class=\"c1\"># Extraction from Jinja2 templates</span>\n<span class=\"p\">[</span>jinja2<span class=\"p\">:</span> <span class=\"o\">**.</span>jinja<span class=\"p\">]</span>\nextensions <span class=\"o\">=</span> jinja2<span class=\"o\">.</span>ext<span class=\"o\">.</span>with_\n</code></pre></div>\n<p>确保列出所有正在使用的扩展名。否则Babel不会识别这些扩展名定义的标签，并会完全忽略包含它们的Jinja2模板。</p>\n<p>Babel提供了与 <a class=\"reference internal\" href=\"/zh-hans/3.0/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=\"http://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/3.0/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/3.0/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=\"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>_<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/3.0/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 内核以及你的项目中允许 non-ASCII 源字符串，你 <strong>必须</strong> 使用 UTF-8作为你的PO文件的编码。这意味着每个人将使用相同的编码，这在 Django 处理PO文件时很重要。</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>要重新检查新翻译字符串的源代码和模板并更新所有语言的所有消息，运行这行：</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>django<span class=\"o\">-</span>admin makemessages <span class=\"o\">-</span>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/3.0/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> 使用而优化的二进制文件。</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>django<span class=\"o\">-</span>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/3.0/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\">.po files: Encoding 和 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=\"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><span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext <span class=\"k\">as</span> _\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=\"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><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>使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a> ，你可以像其他Django消息文件一样创建并更新消息文件。唯一的区别是，你需要提供一个 <code class=\"docutils literal notranslate\">-d djangojs</code> 参数，明确指定gettext术语中的域，本例中是 <code class=\"docutils literal notranslate\">djangojs</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>django<span class=\"o\">-</span>admin makemessages <span class=\"o\">-</span>d djangojs <span class=\"o\">-</span>l de\n</code></pre></div>\n<p>这会创建或更新德语的JavaScript 消息文件。更新消息文件后，像执行普通 Django 消息文件那样运行  <a class=\"reference internal\" href=\"/zh-hans/3.0/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> 命令工作正常即可。如果在命令行下输入 <code class=\"docutils literal notranslate\">xgettext --version</code> ，会导致报错：&quot;xgettext.exe 生成错误，并将被 Windows 关闭。&quot;，所以请不要试图使用带有 <code class=\"docutils literal notranslate\">gettext</code> 包的 Django 翻译工具。</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/3.0/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=\"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><span class=\"kn\">from</span> <span class=\"nn\">django.core.management.commands</span> <span class=\"kn\">import</span> makemessages\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=\"s1\">&#39;--keyword=mytrans&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>如果需要更多的灵活性，也可以给自定义的 <a class=\"reference internal\" href=\"/zh-hans/3.0/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=\"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><span class=\"kn\">from</span> <span class=\"nn\">django.core.management.commands</span> <span class=\"kn\">import</span> makemessages\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\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=\"s1\">&#39;--extra-keyword&#39;</span><span class=\"p\">,</span>\n            dest<span class=\"o\">=</span><span class=\"s1\">&#39;xgettext_keywords&#39;</span><span class=\"p\">,</span>\n            action<span class=\"o\">=</span><span class=\"s1\">&#39;append&#39;</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=\"s1\">&#39;xgettext_keywords&#39;</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> <span class=\"p\">(</span>\n                makemessages<span class=\"o\">.</span>Command<span class=\"o\">.</span>xgettext_options<span class=\"p\">[:]</span> <span class=\"o\">+</span>\n                <span class=\"p\">[</span><span class=\"s1\">&#39;--keyword=</span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> kwd <span class=\"k\">for</span> kwd <span class=\"ow\">in</span> xgettext_keywords<span class=\"p\">]</span>\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=\"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>path<span class=\"p\">(</span><span class=\"s1\">&#39;i18n/&#39;</span><span class=\"p\">,</span> include<span class=\"p\">(</span><span class=\"s1\">&#39;django.conf.urls.i18n&#39;</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/3.0/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>对于 AJAX 请求，仅在设置了 <code class=\"docutils literal notranslate\">next</code> 参数时执行回退。否则会返回 204 状态码（无内容）。</p></li>\n<li><p>对于非AJAX请求，回退将会一直执行。</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/3.0/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/3.0/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=\"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><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\nuser_language <span class=\"o\">=</span> <span class=\"s1\">&#39;fr&#39;</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/3.0/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<aside class=\"version-note version-changed\" data-version=\"3.0\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 3.0</p><p>在老版本中，你可以在当前会话中设置语言。</p>\n</aside>\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=\"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><span class=\"kn\">from</span> <span class=\"nn\">django.utils</span> <span class=\"kn\">import</span> translation\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=\"s1\">&#39;welcome&#39;</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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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=\"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><span class=\"kn\">from</span> <span class=\"nn\">django.utils</span> <span class=\"kn\">import</span> translation\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=\"s1\">&#39;welcome&#39;</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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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/3.0/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>Implementation notes<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>Specialties of Django translation<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's translation machinery uses the standard <code class=\"docutils literal notranslate\">gettext</code> module that comes\nwith Python. If you know <code class=\"docutils literal notranslate\">gettext</code>, you might note these specialties in the\nway Django does translation:</p>\n<ul class=\"simple\">\n<li><p>The string domain is <code class=\"docutils literal notranslate\">django</code> or <code class=\"docutils literal notranslate\">djangojs</code>. This string domain is\nused to differentiate between different programs that store their data\nin a common message-file library (usually <code class=\"docutils literal notranslate\">/usr/share/locale/</code>). The\n<code class=\"docutils literal notranslate\">django</code> domain is used for Python and template translation strings\nand is loaded into the global translation catalogs. The <code class=\"docutils literal notranslate\">djangojs</code>\ndomain is only used for JavaScript translation catalogs to make sure\nthat those are as small as possible.</p></li>\n<li><p>Django doesn't use <code class=\"docutils literal notranslate\">xgettext</code> alone. It uses Python wrappers around\n<code class=\"docutils literal notranslate\">xgettext</code> and <code class=\"docutils literal notranslate\">msgfmt</code>. This is mostly for convenience.</p></li>\n</ul>\n</section>\n<section id=\"how-django-discovers-language-preference\">\n<span id=\"id5\"></span><h3>How Django discovers language preference<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>Once you've prepared your translations -- or, if you want to use the\ntranslations that come with Django -- you'll need to activate translation for\nyour app.</p>\n<p>Behind the scenes, Django has a very flexible model of deciding which language\nshould be used -- installation-wide, for a particular user, or both.</p>\n<p>To set an installation-wide language preference, set <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a>.\nDjango uses this language as the default translation -- the final attempt if no\nbetter matching translation is found through one of the methods employed by the\nlocale middleware (see below).</p>\n<p>If all you want is to run Django with your native language all you need to do\nis set <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> and make sure the corresponding <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/i18n/#term-message-file\"><span class=\"xref std std-term\">message\nfiles</span></a> and their compiled versions (<code class=\"docutils literal notranslate\">.mo</code>) exist.</p>\n<p>If you want to let each individual user specify which language they\nprefer, then you also need to use the <code class=\"docutils literal notranslate\">LocaleMiddleware</code>.\n<code class=\"docutils literal notranslate\">LocaleMiddleware</code> enables language selection based on data from the request.\nIt customizes content for each user.</p>\n<p>To use <code class=\"docutils literal notranslate\">LocaleMiddleware</code>, add <code class=\"docutils literal notranslate\">'django.middleware.locale.LocaleMiddleware'</code>\nto your <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> setting. Because middleware order matters, follow\nthese guidelines:</p>\n<ul class=\"simple\">\n<li><p>Make sure it's one of the first middleware installed.</p></li>\n<li><p>It should come after <code class=\"docutils literal notranslate\">SessionMiddleware</code>, because <code class=\"docutils literal notranslate\">LocaleMiddleware</code>\nmakes use of session data. And it should come before <code class=\"docutils literal notranslate\">CommonMiddleware</code>\nbecause <code class=\"docutils literal notranslate\">CommonMiddleware</code> needs an activated language in order\nto resolve the requested URL.</p></li>\n<li><p>If you use <code class=\"docutils literal notranslate\">CacheMiddleware</code>, put <code class=\"docutils literal notranslate\">LocaleMiddleware</code> after it.</p></li>\n</ul>\n<p>For example, your <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> might look like this:</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>MIDDLEWARE <span class=\"o\">=</span> <span class=\"p\">[</span>\n   <span class=\"s1\">&#39;django.contrib.sessions.middleware.SessionMiddleware&#39;</span><span class=\"p\">,</span>\n   <span class=\"s1\">&#39;django.middleware.locale.LocaleMiddleware&#39;</span><span class=\"p\">,</span>\n   <span class=\"s1\">&#39;django.middleware.common.CommonMiddleware&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>(For more on middleware, see the <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/http/middleware/\"><span class=\"doc\">middleware documentation</span></a>.)</p>\n<p><code class=\"docutils literal notranslate\">LocaleMiddleware</code> tries to determine the user's language preference by\nfollowing this algorithm:</p>\n<ul>\n<li><p>First, it looks for the language prefix in the requested URL.  This is\nonly performed when you are using the <code class=\"docutils literal notranslate\">i18n_patterns</code> function in your\nroot URLconf. See <a class=\"reference internal\" href=\"#url-internationalization\"><span class=\"std std-ref\">国际化：在 URL 模式中</span></a> for more information\nabout the language prefix and how to internationalize URL patterns.</p></li>\n<li><p>Failing that, it looks for a cookie.</p>\n<p>The name of the cookie used is set by the <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGE_COOKIE_NAME\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_COOKIE_NAME</code></a>\nsetting. (The default name is <code class=\"docutils literal notranslate\">django_language</code>.)</p>\n</li>\n<li><p>Failing that, it looks at the <code class=\"docutils literal notranslate\">Accept-Language</code> HTTP header. This\nheader is sent by your browser and tells the server which language(s) you\nprefer, in order by priority. Django tries each language in the header\nuntil it finds one with available translations.</p></li>\n<li><p>Failing that, it uses the global <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> setting.</p></li>\n</ul>\n<p id=\"locale-middleware-notes\">注意：</p>\n<ul>\n<li><p>In each of these places, the language preference is expected to be in the\nstandard <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/i18n/#term-language-code\"><span class=\"xref std std-term\">language format</span></a>, as a string. For example,\nBrazilian Portuguese is <code class=\"docutils literal notranslate\">pt-br</code>.</p></li>\n<li><p>If a base language is available but the sublanguage specified is not,\nDjango uses the base language. For example, if a user specifies <code class=\"docutils literal notranslate\">de-at</code>\n(Austrian German) but Django only has <code class=\"docutils literal notranslate\">de</code> available, Django uses\n<code class=\"docutils literal notranslate\">de</code>.</p></li>\n<li><p>Only languages listed in the <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGES\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGES</code></a> setting can be selected.\nIf you want to restrict the language selection to a subset of provided\nlanguages (because your application doesn't provide all those languages),\nset <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGES\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGES</code></a> to a list of languages. For example:</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>LANGUAGES <span class=\"o\">=</span> <span class=\"p\">[</span>\n  <span class=\"p\">(</span><span class=\"s1\">&#39;de&#39;</span><span class=\"p\">,</span> _<span class=\"p\">(</span><span class=\"s1\">&#39;German&#39;</span><span class=\"p\">)),</span>\n  <span class=\"p\">(</span><span class=\"s1\">&#39;en&#39;</span><span class=\"p\">,</span> _<span class=\"p\">(</span><span class=\"s1\">&#39;English&#39;</span><span class=\"p\">)),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>This example restricts languages that are available for automatic\nselection to German and English (and any sublanguage, like <code class=\"docutils literal notranslate\">de-ch</code> or\n<code class=\"docutils literal notranslate\">en-us</code>).</p>\n</li>\n<li><p>If you define a custom <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGES\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGES</code></a> setting, as explained in the\nprevious bullet, you can mark the language names as translation strings\n-- but use <a class=\"reference internal\" href=\"/zh-hans/3.0/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> instead of\n<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/utils/#django.utils.translation.gettext\" title=\"django.utils.translation.gettext\"><code class=\"xref py py-func docutils literal notranslate\">gettext()</code></a> to avoid a circular import.</p>\n<p>以下是一个实例配置文件:</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><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=\"s1\">&#39;de&#39;</span><span class=\"p\">,</span> _<span class=\"p\">(</span><span class=\"s1\">&#39;German&#39;</span><span class=\"p\">)),</span>\n    <span class=\"p\">(</span><span class=\"s1\">&#39;en&#39;</span><span class=\"p\">,</span> _<span class=\"p\">(</span><span class=\"s1\">&#39;English&#39;</span><span class=\"p\">)),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n</li>\n</ul>\n<p>Once <code class=\"docutils literal notranslate\">LocaleMiddleware</code> determines the user's preference, it makes this\npreference available as <code class=\"docutils literal notranslate\">request.LANGUAGE_CODE</code> for each\n<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\">HttpRequest</code></a>. Feel free to read this value in your view\ncode. Here's an example:</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><span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\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=\"s1\">&#39;de-at&#39;</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>Note that, with static (middleware-less) translation, the language is in\n<code class=\"docutils literal notranslate\">settings.LANGUAGE_CODE</code>, while with dynamic (middleware) translation, it's\nin <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>At runtime, Django builds an in-memory unified catalog of literals-translations.\nTo achieve this it looks for translations by following this algorithm regarding\nthe order in which it examines the different file paths to load the compiled\n<a class=\"reference internal\" href=\"/zh-hans/3.0/topics/i18n/#term-message-file\"><span class=\"xref std std-term\">message files</span></a> (<code class=\"docutils literal notranslate\">.mo</code>) and the precedence of multiple\ntranslations for the same literal:</p>\n<ol class=\"arabic simple\">\n<li><p>The directories listed in <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> have the highest\nprecedence, with the ones appearing first having higher precedence than\nthe ones appearing later.</p></li>\n<li><p>Then, it looks for and uses if it exists a <code class=\"docutils literal notranslate\">locale</code> directory in each\nof the installed apps listed in <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\">INSTALLED_APPS</code></a>.  The ones\nappearing first have higher precedence than the ones appearing later.</p></li>\n<li><p>Finally, the Django-provided base translation in <code class=\"docutils literal notranslate\">django/conf/locale</code>\nis used as a fallback.</p></li>\n</ol>\n<aside class=\"admonition admonition-seealso\" role=\"note\">\n<p class=\"admonition-title\">See also</p>\n<p>The translations for literals included in JavaScript assets are looked up\nfollowing a similar but not identical algorithm. See\n<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> for more details.</p>\n<p>You can also put <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/i18n/formatting/#custom-format-files\"><span class=\"std std-ref\">custom format files</span></a> in the\n<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> directories if you also set\n<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-FORMAT_MODULE_PATH\"><code class=\"xref std std-setting docutils literal notranslate\">FORMAT_MODULE_PATH</code></a>.</p>\n</aside>\n<p>In all cases the name of the directory containing the translation is expected to\nbe named using <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/i18n/#term-locale-name\"><span class=\"xref std std-term\">locale name</span></a> notation. E.g. <code class=\"docutils literal notranslate\">de</code>, <code class=\"docutils literal notranslate\">pt_BR</code>, <code class=\"docutils literal notranslate\">es_AR</code>,\netc. Untranslated strings for territorial language variants use the translations\nof the generic language. For example, untranslated <code class=\"docutils literal notranslate\">pt_BR</code> strings use <code class=\"docutils literal notranslate\">pt</code>\ntranslations.</p>\n<p>This way, you can write applications that include their own translations, and\nyou can override base translations in your project. Or, you can build a big\nproject out of several apps and put all translations into one big common\nmessage file specific to the project you are composing. The choice is yours.</p>\n<p>All message file repositories are structured the same way. They are:</p>\n<ul class=\"simple\">\n<li><p>All paths listed in <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> in your settings file are\nsearched for <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>To create message files, you use the <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-makemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin makemessages</code></a>\ntool. And you use <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages</code></a>\nto produce the binary <code class=\"docutils literal notranslate\">.mo</code> files that are used by <code class=\"docutils literal notranslate\">gettext</code>.</p>\n<p>You can also run <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-compilemessages\"><code class=\"xref std std-djadmin docutils literal notranslate\">django-admin compilemessages\n--settings=path.to.settings</code></a> to make the compiler process all\nthe directories in your <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOCALE_PATHS\"><code class=\"xref std std-setting docutils literal notranslate\">LOCALE_PATHS</code></a> setting.</p>\n</section>\n<section id=\"using-a-non-english-base-language\">\n<h3>Using a non-English base language<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 makes the general assumption that the original strings in a translatable\nproject are written in English. You can choose another language, but you must be\naware of certain limitations:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">gettext</code> only provides two plural forms for the original messages, so you\nwill also need to provide a translation for the base language to include all\nplural forms if the plural rules for the base language are different from\nEnglish.</p></li>\n<li><p>When an English variant is activated and English strings are missing, the\nfallback language will not be the <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> of the project,\nbut the original strings. For example, an English user visiting a site with\n<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\">LANGUAGE_CODE</code></a> set to Spanish and original strings written in\nRussian will see Russian text rather than Spanish.</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":"模型方法 short_description 的属性值","anchor":"model-methods-short-description-attribute-values","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":"trans 模板标签","anchor":"trans-template-tag","children":[]},{"title":"blocktrans 模板标签","anchor":"blocktrans-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":"Implementation notes","anchor":"implementation-notes","children":[{"title":"Specialties of Django translation","anchor":"specialties-of-django-translation","children":[]},{"title":"How Django discovers language preference","anchor":"how-django-discovers-language-preference","children":[]},{"title":"Django 如何发现翻译","anchor":"how-django-discovers-translations","children":[]},{"title":"Using a non-English base language","anchor":"using-a-non-english-base-language","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/3.0/topics/"},{"docname":"topics/i18n/index","title":"国际化和本地化","url":"/zh-hans/3.0/topics/i18n/"}],"prev":{"docname":"topics/i18n/index","title":"国际化和本地化","url":"/zh-hans/3.0/topics/i18n/"},"next":{"docname":"topics/i18n/formatting","title":"本地格式化","url":"/zh-hans/3.0/topics/i18n/formatting/"},"formats":{"html":"/zh-hans/3.0/topics/i18n/translation/","markdown":"/zh-hans/3.0/topics/i18n/translation.md","json":"/zh-hans/3.0/topics/i18n/translation.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/topics/i18n/translation.txt","official":"https://docs.djangoproject.com/zh-hans/3.0/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","pt-br","ko","es","el","pl"]}