开发主题

创建和分发自定义主题的指南。


注意: 如果你在寻找现有的第三方主题,它们列在社区维基页面和MkDocs项目目录中。如果你想分享你创建的主题,你应该在那里列出它。

在创建新主题时,你可以按照本指南的步骤从头开始创建,或者你可以下载mkdocs-basic-theme作为一个基础但完整的主题,其中包含了所有必需的样板代码。你可以在GitHub上找到这个基础主题。它包含了详细的代码注释,描述了不同的功能及其用法。

创建自定义主题

自定义主题的最低要求是一个main.html[Jinja2模板]文件,该文件放置在一个不是docs_dir子目录的目录中。在mkdocs.yml中,将theme.custom_dir选项设置为包含main.html的目录路径。路径应相对于配置文件。例如,给定以下示例项目布局:

mkdocs.yml
docs/
    index.md
    about.md
custom_theme/
    main.html
    ...

... 你可以在mkdocs.yml中包含以下设置以使用自定义主题目录:

theme:
  name: null
  custom_dir: 'custom_theme/'

注意: 通常,在构建自己的自定义主题时,theme.name配置设置会被设置为null。然而,如果theme.custom_dir配置值与现有主题结合使用,theme.custom_dir可以用来仅替换内置主题的特定部分。例如,使用上述布局,如果你设置name: "mkdocs",那么theme.custom_dir中的main.html文件将替换mkdocs主题中同名文件,但其他部分保持不变。如果你只想对现有主题进行小的调整,这很有用。

有关更具体的信息,请参阅自定义你的主题

警告: 主题的配置mkdocs_theme.yml文件中定义,不会从theme.custom_dir加载。当整个主题存在于theme.custom_dir中且theme.name设置为null时,那么整个主题配置必须在mkdocs.yml文件的theme配置选项中定义。

然而,当一个主题被打包用于分发,并使用theme.name配置选项加载时,那么需要一个mkdocs_theme.yml文件来定义主题。

基础主题

最简单的main.html文件如下:

<!DOCTYPE html>
<html>
  <head>
    <title>{% if page.title %}{{ page.title }} - {% endif %}{{ config.site_name }}</title>
    {%- for path in config.extra_css %}
      <link href="{{ path | url }}" rel="stylesheet">
    {%- endfor %}
  </head>
  <body>
    {{ page.content }}

    {%- for script in config.extra_javascript %}
      {{ script | script_tag }}
    {%- endfor %}
  </body>
</html>

mkdocs.yml中指定的每个页面的主体内容使用{{ page.content }}标签插入。样式表和脚本可以像普通HTML文件一样引入到这个主题中。导航栏和目录也可以通过navtoc对象自动生成并包含。如果你希望编写自己的主题,建议从内置主题之一开始并进行相应修改。

注意: 由于MkDocs使用Jinja作为其模板引擎,你可以访问Jinja的所有功能,包括模板继承。你可能会注意到,MkDocs附带的主题大量使用了模板继承和块,允许用户轻松地从主题custom_dir中覆盖模板的小部分。因此,内置主题是在base.html文件中实现的,main.html扩展了它。虽然不是必需的,但第三方模板作者鼓励遵循类似的模式,并可能希望定义与内置主题中使用的一致的块。

从配置中获取CSS和JavaScript

MkDocs 定义了顶级配置 extra_cssextra_javascript。这些是文件列表。

主题必须包含链接这些配置项的 HTML,否则这些配置将无法生效。你可以在 上面的基础示例 中看到渲染它们的推荐方式。

新功能:在版本 1.5 中更改:

config.extra_javascript 列表中的项目过去是简单的字符串,但现在变成了具有 pathtypeasyncdefer 这些字段的对象。

在该版本中,MkDocs 还增加了 script_tag 过滤器

? 示例:过时的样式:

  {%- for path in extra_javascript %}
    <script src="{{ path }}"></script>
  {%- endfor %}

这个旧样式示例甚至使用了过时的顶级 extra_javascript 列表。请始终使用 config.extra_javascript 代替。

因此,稍微现代一点的方法如下,但它仍然是过时的,因为它忽略了脚本的额外属性:

  {%- for path in config.extra_javascript %}
    <script src="{{ path | url }}"></script>
  {%- endfor %}
? 示例:新样式:

  {%- for script in config.extra_javascript %}
    {{ script | script_tag }}
  {%- endfor %}

如果你希望在保持主题与旧版本 MkDocs 兼容的同时能够获取新的自定义功能,请使用以下代码片段:

! 示例:向后兼容的样式:

  {%- for script in config.extra_javascript %}
    {%- if script.path %}  {# 检测到 MkDocs 1.5+,具有 `script.path` 和 `script_tag` #}
      {{ script | script_tag }}
    {%- else %}  {# 回退 - 直接检查文件名 #}
      <script src="{{ script | url }}"{% if script.endswith(".mjs") %} type="module"{% endif %}></script>
    {%- endif %}
  {%- endfor %}

主题文件

主题以某种特殊方式处理各种文件。任何其他文件在构建站点时都会从主题目录复制到 site_dir 中的相同路径。例如,图像和 CSS 文件没有特殊意义,会原样复制。但请注意,如果用户在其 docs_dir 中提供了相同路径的文件,则用户的文件将替换主题文件。

模板文件

任何具有 .html 扩展名的文件都被视为模板文件,不会从主题目录或任何子目录中复制。此外,static_templates 中列出的任何文件,无论其文件扩展名如何,都被视为模板。

主题元文件

打包主题所需的各种文件也会被忽略。具体来说,mkdocs_theme.yml 配置文件和任何 Python 文件。

点文件

主题作者可以通过以点开头的文件或目录名称显式强制 MkDocs 忽略文件。以下任何文件都将被忽略:

.ignored.txt
.ignored/file.txt
foo/.ignored.txt
foo/.ignored/file.txt

文档文件

所有文档文件都会被忽略。具体来说,任何 Markdown 文件(使用 MkDocs 支持的任何文件扩展名)。此外,主题目录中可能存在的任何 README 文件也会被忽略。

模板变量

主题中的每个模板都是使用模板上下文构建的。这些是可用于主题的变量。上下文因正在构建的模板而异。目前,模板要么使用全局上下文,要么使用页面特定的上下文构建。全局上下文用于不表示单个 Markdown 文档的 HTML 页面,例如 404.html 页面或 search.html。

全局上下文

以下变量在任何模板中都可用。

config

config 变量是根据 mkdocs.yml 配置文件生成的 MkDocs 配置对象实例。虽然你可以使用任何配置选项,但一些常用的选项包括:

nav 变量用于为文档创建导航。 nav 对象是根据 nav 配置设置定义的 导航对象 的可迭代对象。

除了 导航对象 的可迭代对象外,nav 对象还包含以下属性:

homepage: Page | None instance-attribute

The page object for the homepage of the site.

pages: list[Page] instance-attribute

A flat list of all page objects contained in the navigation.

此列表不一定包含所有站点页面的完整列表,因为它不包含未包含在导航中的页面。此列表确实与用于所有“下一页”和“上一页”链接的页面列表和顺序相匹配。要获取所有页面的列表,请使用 pages 模板变量。

导航示例

以下是一个基本用法示例,它将第一级和第二级导航输出为嵌套列表。

{% if nav|length > 1 %}
    <ul>
    {% for nav_item in nav %}
        {% if nav_item.children %}
            <li>{{ nav_item.title }}
                <ul>
                {% for nav_item in nav_item.children %}
                    <li class="{% if nav_item.active %}current{% endif %}">
                        <a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
                    </li>
                {% endfor %}
                </ul>
            </li>
        {% else %}
            <li class="{% if nav_item.active %}current{% endif %}">
                <a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
            </li>
        {% endif %}
    {% endfor %}
    </ul>
{% endif %}

base_url

base_url 提供了 MkDocs 项目根目录的相对路径。虽然可以直接将其前置到本地相对 URL,但最好使用 url 模板过滤器,它更智能地应用 base_url

mkdocs_version

包含当前 MkDocs 版本。

build_date_utc

一个 Python datetime 对象,表示文档在 UTC 时间构建的日期和时间。这对于显示文档最近更新的时间很有用。

pages

项目中所有页面的 File 对象的扁平列表。此列表可能包含未包含在全局 navigation 中的页面,并且可能与该导航中的页面顺序不匹配。每个 Filepage 对象可以通过 file.page 访问。

page

在不是从 Markdown 源文件渲染的模板中,page 变量为 None。在从 Markdown 源文件渲染的模板中,page 变量包含一个 page 对象。相同的 page 对象在全局 navigationpages 模板变量中用作 page 导航对象

Bases: StructureItem

所有 page 对象包含以下属性:

title() -> str | None

Returns the title for the current page.

Before calling read_source(), this value is empty. It can also be updated by render().

Checks these in order and uses the first that returns a valid title:

  • value provided on init (passed in from config)
  • value of metadata 'title'
  • content of the first H1 in Markdown content
  • convert filename to title
content: str | None instance-attribute

The rendered Markdown as HTML, this is the contents of the documentation.

Populated after .render().

toc: TableOfContents instance-attribute

An iterable object representing the Table of contents for a page. Each item in the toc is an AnchorLink.

以下示例将显示页面的前两级目录。

<ul>
{% for toc_item in page.toc %}
    <li><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
    {% for toc_item in toc_item.children %}
        <li><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
    {% endfor %}
{% endfor %}
</ul>
meta: MutableMapping[str, Any] instance-attribute

A mapping of the metadata included at the top of the markdown page.

在此示例中,我们在页面标题上方定义了一个 source 属性:

source: generics.py
        mixins.py

# 页面标题

内容...

模板可以通过 meta.source 变量访问此页面元数据。然后可以将其用于链接到与文档页面相关的源文件。

{% for filename in page.meta.source %}
  <a class="github" href="https://github.com/.../{{ filename }}">
    <span class="label label-info">{{ filename }}</span>
  </a>
{% endfor %}
url: str property

The URL of the page relative to the MkDocs site_dir.

建议将其与 url 过滤器一起使用,以确保 URL 相对于当前页面。

<a href="{{ page.url|url }}">{{ page.title }}</a>
file: File instance-attribute

The documentation File that the page is being rendered from.

abs_url: str | None instance-attribute

The absolute URL of the page from the server root as determined by the value assigned to the site_url configuration setting. The value includes any subdirectory included in the site_url, but not the domain. base_url should not be used with this variable.

        show_root_full_path: false
        heading_level: 5

例如,如果 `site_url: https://example.com/`,那么页面 `foo.md` 的 `page.abs_url` 值将是 `/foo/`。然而,如果 `site_url: https://example.com/bar/`,那么页面 `foo.md` 的 `page.abs_url` 值将是 `/bar/foo/`。

::: mkdocs.structure.pages.Page.canonical_url
    options:
        show_root_full_path: false
        heading_level: 5

::: mkdocs.structure.pages.Page.edit_url
    options:
        show_root_full_path: false
        heading_level: 5

::: mkdocs.structure.pages.Page.is_homepage
    options:
        show_root_full_path: false
        heading_level: 5

这可以与其他 `page` 对象的属性结合使用以改变行为。例如,在主页上显示不同的标题:

```django
{% if not page.is_homepage %}{{ page.title }} - {% endif %}{{ site_name }}
previous_page: Page | None instance-attribute

The page object for the previous page or None. The value will be None if the current page is the first item in the site navigation or if the current page is not included in the navigation at all.

next_page: Page | None instance-attribute

The page object for the next page or None. The value will be None if the current page is the last item in the site navigation or if the current page is not included in the navigation at all.

parent: Section | None = None class-attribute instance-attribute

The immediate parent of the item in the site navigation. None if it's at the top level.

children: None = None class-attribute instance-attribute

Pages do not contain children and the attribute is always None.

active: bool property writable

When True, indicates that this page is the currently viewed page. Defaults to False.

is_section: bool = False class-attribute instance-attribute

Indicates that the navigation object is a "section" object. Always False for page objects.

is_page: bool = True class-attribute instance-attribute

Indicates that the navigation object is a "page" object. Always True for page objects.

Indicates that the navigation object is a "link" object. Always False for page objects.

A single entry in the table of contents.

title: str instance-attribute

The text of the item, as HTML.

url: str property

The hash fragment of a URL pointing to the item.

level: int instance-attribute

The zero-based level of the item.

children: list[AnchorLink] instance-attribute

An iterable of any child items.

导航对象

nav 模板变量中包含的导航对象可以是 section 对象、page 对象和 link 对象之一。虽然 section 对象可能包含嵌套的导航对象,但页面和链接不会。

页面对象是当前 page 使用的完整页面对象,所有相同的属性都可用。Section 和 Link 对象包含以下定义的属性子集:

Section

section 导航对象定义了导航中的命名部分,并包含一个子导航对象列表。请注意,部分不包含 URL,也不是任何类型的链接。然而,默认情况下,MkDocs 将索引页面排在顶部,如果主题选择这样做,第一个子项可能用作部分的 URL。

Bases: StructureItem

以下属性在 section 对象上可用:

title: str instance-attribute

The title of the section.

parent: Section | None = None class-attribute instance-attribute

The immediate parent of the item in the site navigation. None if it's at the top level.

children: list[StructureItem] instance-attribute

An iterable of all child navigation objects. Children may include nested sections, pages and links.

active: bool property writable

When True, indicates that a child page of this section is the current page and can be used to highlight the section as the currently viewed section. Defaults to False.

is_section: bool = True class-attribute instance-attribute

Indicates that the navigation object is a "section" object. Always True for section objects.

is_page: bool = False class-attribute instance-attribute

Indicates that the navigation object is a "page" object. Always False for section objects.

Indicates that the navigation object is a "link" object. Always False for section objects.

link 导航对象包含一个指向非内部 MkDocs 页面的链接。

Bases: StructureItem

以下属性在 link 对象上可用:

title: str instance-attribute

The title of the link. This would generally be used as the label of the link.

url: str instance-attribute

The URL that the link points to. The URL should always be an absolute URLs and should not need to have base_url prepended.

parent: Section | None = None class-attribute instance-attribute

The immediate parent of the item in the site navigation. None if it's at the top level.

children: None = None class-attribute instance-attribute

Links do not contain children and the attribute is always None.

active: bool = False class-attribute instance-attribute

External links cannot be "active" and the attribute is always False.

is_section: bool = False class-attribute instance-attribute

Indicates that the navigation object is a "section" object. Always False for link objects.

is_page: bool = False class-attribute instance-attribute

Indicates that the navigation object is a "page" object. Always False for link objects.

Indicates that the navigation object is a "link" object. Always True for link objects.

```markdown
        show_root_full_path: false
        heading_level: 5

### 额外上下文

可以通过[`extra`](../user-guide/configuration.md#extra)配置选项将其他变量传递给模板。这是一个键值对集合,可以使自定义模板更加灵活。

例如,这可以用于在所有页面上包含项目版本和与项目相关的链接列表。可以通过以下`extra`配置实现:

```yaml
extra:
  version: 0.13.0
  links:
    - https://github.com/mkdocs
    - https://docs.readthedocs.org/en/latest/builds.html#mkdocs
    - https://www.mkdocs.org/

然后在自定义主题中使用以下HTML显示:

{{ config.extra.version }}

{% if config.extra.links %}
  <ul>
  {% for link in config.extra.links %}
      <li>{{ link }}</li>
  {% endfor %}
  </ul>
{% endif %}

模板过滤器

除了[Jinja的默认过滤器],以下自定义过滤器可用于MkDocs模板:

url

规范化URL。绝对URL保持不变。如果URL是相对的且模板上下文包含页面对象,则返回相对于页面对象的URL。否则,返回带有base_url前缀的URL。

<a href="{{ page.url|url }}">{{ page.title }}</a>

tojson

安全地将Python对象转换为JavaScript脚本中的值。

<script>
    var mkdocs_page_name = {{ page.title|tojson|safe }};
</script>

script_tag

新功能: 在版本1.5中新增。

extra_javascript中的项目转换为<script>标签,该标签考虑了所有此配置的自定义,并内置了与|url行为等效的功能。

请参阅如何在基本示例中使用它

搜索和主题

从MkDocs版本0.17开始,通过search插件为MkDocs添加了客户端搜索支持。主题需要提供一些内容才能与插件一起工作。

虽然search插件默认激活,但用户可以禁用该插件,主题应考虑到这一点。建议主题模板将搜索特定标记包装在对插件的检查中:

{% if 'search' in config.plugins %}
    在此处搜索内容...
{% endif %}

在其最基本的功能中,搜索插件将简单地提供一个索引文件,该文件只是一个包含所有页面内容的JSON文件。主题需要实现自己的客户端搜索功能。然而,通过一些设置和必要的模板,插件可以提供一个基于lunr.js的完整客户端搜索工具。

需要在主题中添加以下HTML,以便提供的JavaScript能够正确加载搜索脚本,并从当前页面生成相对链接的搜索结果。

<script>var base_url = {{ base_url|tojson }};</script>

通过正确配置的设置,以下HTML模板将向您的主题添加完整的搜索实现。

<h1 id="search">搜索结果</h1>

<form action="search.html">
  <input name="q" id="mkdocs-search-query" type="text" >
</form>

<div id="mkdocs-search-results">
  抱歉,页面未找到。
</div>

插件中的JavaScript通过查找上述HTML中使用的特定ID来工作。用户输入搜索查询的表单输入必须标识为id="mkdocs-search-query",放置结果的div必须标识为id="mkdocs-search-results"

插件支持在主题的配置文件mkdocs_theme.yml中设置以下选项:

include_search_page

确定搜索插件是否期望主题通过位于search/search.html的模板提供专用搜索页面。

include_search_page设置为true时,搜索模板将被构建并可在search/search.html中使用。此方法由readthedocs主题使用。

include_search_page设置为false或未定义时,预期主题提供其他显示搜索结果的机制。例如,mkdocs主题通过模态在任何页面上显示结果。

search_index_only

确定搜索插件是仅生成搜索索引还是完整的搜索解决方案。

search_index_only设置为false时,搜索插件通过添加其自己的templates目录(优先级低于主题)并将其脚本添加到extra_javascript配置设置来修改Jinja环境。

search_index_only设置为true或未定义时,搜索插件不会对Jinja环境进行任何修改。使用提供的索引文件实现完整解决方案是主题的责任。

搜索索引被写入位于search/search_index.json的JSON文件中。

[site_dir]。文件中包含的 JSON 对象可能包含最多三个对象。

```json
{
    config: {...},
    docs: [...],
    index: {...}
}

如果存在,config 对象包含用户在 mkdocs.yml 配置文件中为插件定义的配置选项键值对,位于 plugings.search 下。config 对象在 MkDocs 版本 1.0 中新增。

docs 对象包含文档对象的列表。每个文档对象由 location(URL)、titletext 组成,可用于创建搜索索引和/或显示搜索结果。

如果存在,index 对象包含一个预构建的索引,这为较大站点提供了性能改进。请注意,仅当用户显式启用 prebuild_index 配置选项时,才会创建预构建索引。主题应预期索引可能不存在,但可以选择在索引可用时使用它。index 对象在 MkDocs 版本 1.0 中新增。

打包主题

MkDocs 使用 Python 打包 来分发主题。这带来了一些要求。

要查看包含一个主题的包的示例,请参见 MkDocs Bootstrap 主题,要查看包含多个主题的包的示例,请参见 MkDocs Bootswatch 主题

注意: 严格来说,打包主题并不是必须的,因为整个主题可以包含在 custom_dir 中。如果你创建了一个“一次性主题”,这应该足够了。然而,如果你打算将你的主题分发给其他人使用,打包主题有一些优势。通过打包你的主题,你的用户可以更轻松地安装它,他们可以依赖默认的 配置 定义,并且他们可以利用 custom_dir 对你的主题进行调整,以更好地满足他们的需求。

包布局

推荐的主题布局如下。在包含主题目录的顶级目录中有两个文件,分别是 MANIFEST.insetup.py,主题目录中包含一个空的 __init__.py 文件、一个主题配置文件 (mkdocs_theme.yml) 以及你的模板和媒体文件。

.
|-- MANIFEST.in
|-- theme_name
|   |-- __init__.py
|   |-- mkdocs_theme.yml
|   |-- main.html
|   |-- styles.css
`-- setup.py

MANIFEST.in 文件应包含以下内容,但需要更新 theme_name 并添加任何额外的文件扩展名到 include 中。

recursive-include theme_name *.ico *.js *.css *.png *.html *.eot *.svg *.ttf *.woff
recursive-exclude * __pycache__
recursive-exclude * *.py[co]

setup.py 应包含以下文本,并根据以下描述进行修改。

from setuptools import setup, find_packages

VERSION = '0.0.1'

setup(
    name="mkdocs-themename",
    version=VERSION,
    url='',
    license='',
    description='',
    author='',
    author_email='',
    packages=find_packages(),
    include_package_data=True,
    entry_points={
        'mkdocs.themes': [
            'themename = theme_name',
        ]
    },
    zip_safe=False
)

填写 URL、许可证、描述、作者和作者电子邮件地址。

名称应遵循 mkdocs-themename 的约定(如 mkdocs-bootstrapmkdocs-bootswatch),以 MkDocs 开头,使用连字符分隔单词,并包含你的主题名称。

文件的其余部分大部分可以保持不变。我们需要更改的最后一部分是 entry_points。这是 MkDocs 如何找到你包含在包中的主题的方式。左侧的名称是用户将在他们的 mkdocs.yml 中使用的名称,右侧的名称是包含你的主题文件的目录。

在本节开始时创建的包含 main.html 文件的目录应包含所有其他主题文件。最低要求是它包含一个 main.html 用于主题。它必须还包括一个 __init__.py 文件,该文件应为空,此文件告诉 Python 该目录是一个包。

主题配置

打包的主题必须包含一个名为 mkdocs_theme.yml 的配置文件,该文件位于模板文件的根目录中。该文件应包含主题的默认配置选项。然而,如果主题不提供配置选项,该文件仍然是必需的,并且可以留空。未打包的主题不需要 mkdocs_theme.yml。 文件,因为该文件不是从 theme.custom_dir 加载的。

主题作者可以自由定义任何被认为必要的任意选项,这些选项将在模板中可用以控制行为。例如,一个主题可能希望使侧边栏成为可选的,并在 mkdocs_theme.yml 文件中包含以下内容:

show_sidebar: true

然后在模板中,可以引用该配置选项:

{% if config.theme.show_sidebar %}
<div id="sidebar">...</div>
{% endif %}

用户可以在其项目的 mkdocs.yml 配置文件中覆盖默认设置:

theme:
  name: themename
  show_sidebar: false

除了主题定义的任意选项外,MkDocs 还定义了一些特殊选项,这些选项会改变其行为:

Block

locale

此选项与 theme 配置选项同名。如果在 mkdocs_theme.yml 文件中未定义此值,并且用户未在 mkdocs.yml 中设置它,则它将默认为 en(英语)。该值应与主题提供的文本(如“下一页”和“上一页”链接)所使用的语言匹配,并应作为 <html> 标签的 lang 属性的值使用。有关更多信息,请参阅 支持主题本地化/翻译

请注意,在配置验证期间,提供的字符串会被转换为 Locale 对象。该对象包含 Locale.languageLocale.territory 属性,并且会在模板中解析为字符串。因此,以下内容将正常工作:

<html lang="{ config.theme.locale }">

如果将区域设置为 fr_CA(加拿大法语),则上述模板将呈现为:

<html lang="fr_CA">

如果你不希望包含区域属性,则直接引用 language 属性:

<html lang="{ config.theme.locale.language }">

这将呈现为:

<html lang="fr">

static_templates

此选项与 theme 配置选项同名,并允许主题设置一些默认值。请注意,虽然用户可以向此列表添加模板,但用户无法删除主题配置中包含的模板。

extends

定义此主题继承自的父主题。值应为父主题的字符串名称。正常的 Jinja 继承规则 适用。

插件还可以定义一些选项,允许主题通知插件它期望的插件选项集。请参阅你希望在主题中支持的任何插件的文档。

分发主题

通过上述更改,你的主题现在应该可以安装了。这可以通过 pip 完成,如果你仍在 setup.py 所在的目录中,可以使用 pip install .

大多数 Python 包,包括 MkDocs,都分发在 PyPI 上。为此,你应该运行以下命令。

python setup.py register

如果你还没有设置账户,系统会提示你创建一个。

有关更详细的指南,请参阅官方 Python 打包文档中的 打包和分发项目

支持主题本地化/翻译

虽然内置主题提供了对 本地化/翻译 模板的支持,但自定义主题和第三方主题可能选择不提供。无论如何,theme 配置选项的 locale 设置始终存在,并被系统的其他部分所依赖。因此,建议所有第三方主题使用相同的设置来指定语言,无论它们使用何种翻译系统。这样,无论用户选择何种主题,他们都将体验到一致的行为。

管理翻译的方法由主题开发者决定。然而,如果主题开发者选择使用内置主题所使用的相同机制,以下部分概述了如何启用并利用 MkDocs 所使用的相同命令。

使用本地化/翻译命令

警告: 由于 pybabel 不是默认安装的,大多数用户不会安装 pybabel,因此主题开发者和/或翻译人员应确保安装了必要的依赖项(使用 pip install 'mkdocs[i18n]'),以便可以使用这些命令。

翻译命令应从主题工作树的根目录调用。

有关 MkDocs 用于翻译内置主题的工作流程的概述,请参阅贡献指南中的适当 [部分] 和 [翻译指南]。

自定义主题本地化/翻译工作流程示例

注意:如果你的主题继承自已经提供翻译目录的现有主题,你的主题翻译将在 MkDocs 构建期间与父主题的翻译合并。

这意味着你只需要专注于新增的翻译。然而,你仍然可以受益于父主题的翻译。同时,你也可以覆盖父主题的任何翻译!

假设你正在开发自己的 [mkdocs-basic-theme][basic theme] 分支,并希望为其添加翻译。

通过在 HTML 源码中使用 {% trans %}{% endtrans %} 包裹文本来编辑模板,如下所示:

--- a/basic_theme/base.html
+++ b/basic_theme/base.html
@@ -88,7 +88,7 @@

 <body>

-  <h1>This is an example theme for MkDocs.</h1>
+  <h1>{% trans %}This is an example theme for MkDocs.{% endtrans %}</h1>

   <p>
     It is designed to be read by looking at the theme HTML which is heavily

然后,你可以像往常一样遵循 Translation Guide 来运行你的翻译。

将翻译与你的主题打包

虽然 extract_messages 命令创建的 Portable Object Template (pot) 文件和 init_catalogupdate_catalog 命令创建的 Portable Object (po) 文件对于创建和编辑翻译很有用,但 MkDocs 并不直接使用它们,也不需要在主题的打包版本中包含它们。当 MkDocs 使用翻译构建站点时,它只使用指定语言环境的二进制 mo 文件。因此,在 [打包主题] 时,请确保将其包含在“wheels”中,使用 MANIFEST.in 文件或其他方式。

然后,在构建你的 Python 包之前,你将希望确保每个语言环境的二进制 mo 文件是最新的,为此你需要为每个语言环境运行 compile_catalog 命令。MkDocs 期望二进制 mo 文件位于 locales/<locale>/LC_MESSAGES/messages.mocompile_catalog 命令会自动为你完成这一点。详情请参阅 [测试主题翻译]。

注意: 正如我们在 Translation Guide 中概述的那样,MkDocs 项目选择在代码仓库中包含 potpo 文件,但不包含 mo 文件。这要求我们在打包新版本之前始终运行 compile_catalog,无论是否对翻译进行了任何更改。然而,你可以为你的主题选择一个替代的工作流程。至少,你需要确保在每个版本中包含位于正确位置的最新 mo 文件。不过,如果你选择这样做,你可以使用不同的流程来生成这些 mo 文件。