Repository: mkdocs/mkdocs
Pull request #3370 (2023-09-05 18:38:26)

Add zh_TW locale for built-in themes
😃 


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0e741aed..911cc6d0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -67,10 +67,10 @@ jobs:
           node-version: 16
       - name: Check with ruff
         if: always()
-        run: hatch run style:lint
+        run: hatch run style:fix
       - name: Check with black + isort
         if: always()
-        run: hatch run style:format && git diff --exit-code
+        run: hatch run style:format && git diff --color --exit-code
       - name: Check with mypy
         if: always()
         run: hatch run types:check
diff --git a/mkdocs/structure/nav.py b/mkdocs/structure/nav.py
index e6744190..018794eb 100644
--- a/mkdocs/structure/nav.py
+++ b/mkdocs/structure/nav.py
@@ -1,6 +1,7 @@
 from __future__ import annotations
 
 import logging
+import warnings
 from typing import TYPE_CHECKING, Iterator, TypeVar
 from urllib.parse import urlsplit
 
@@ -200,6 +201,22 @@ def _data_to_navigation(data, files: Files, config: MkDocsConfig):
                 f"A reference to '{file.src_path}' is included in the 'nav' "
                 "configuration, but this file is excluded from the built site.",
             )
+        page = file.page
+        if page is not None:
+            if isinstance(page, Page):
+                if type(page) is not Page:  # Strict subclass
+                    return page
+                warnings.warn(
+                    "A plugin has set File.page to an instance of Page and it got overwritten. "
+                    "The behavior of this will change in MkDocs 1.6.",
+                    DeprecationWarning,
+                )
+            else:
+                warnings.warn(  # type: ignore[unreachable]
+                    "A plugin has set File.page to a type other than Page. "
+                    "This will be an error in MkDocs 1.6.",
+                    DeprecationWarning,
+                )
         return Page(title, file, config)
     return Link(title, path)
 
diff --git a/mkdocs/themes/mkdocs/locales/zh_TW/LC_MESSAGES/messages.po b/mkdocs/themes/mkdocs/locales/zh_TW/LC_MESSAGES/messages.po
new file mode 100644
index 00000000..4b1f4c6b
--- /dev/null
+++ b/mkdocs/themes/mkdocs/locales/zh_TW/LC_MESSAGES/messages.po
@@ -0,0 +1,100 @@
+# Chinese (Traditional, Taiwan) translations for MkDocs.
+# Copyright (C) 2022 MkDocs
+# This file is distributed under the same license as the MkDocs project.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: MkDocs 1.3.1\n"
+"Report-Msgid-Bugs-To: \"https://github.com/mkdocs/mkdocs/issues\"\n"
+"POT-Creation-Date: 2022-08-15 17:05+0200\n"
+"PO-Revision-Date: 2023-09-06 02:13+0800\n"
+"Last-Translator: Peter Dave Hello <hsu@peterdavehello.org>\n"
+"Language: zh_Hant_TW\n"
+"Language-Team: zh_Hant_TW <hsu@peterdavehello.org>\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.6.0\n"
+
+#: mkdocs/themes/mkdocs/404.html:8
+msgid "Page not found"
+msgstr "找不到頁面"
+
+#: mkdocs/themes/mkdocs/base.html:116
+#: mkdocs/themes/mkdocs/keyboard-modal.html:31
+#: mkdocs/themes/mkdocs/search-modal.html:5
+msgid "Search"
+msgstr "搜尋"
+
+#: mkdocs/themes/mkdocs/base.html:126
+msgid "Previous"
+msgstr "上一頁"
+
+#: mkdocs/themes/mkdocs/base.html:131
+msgid "Next"
+msgstr "下一頁"
+
+#: mkdocs/themes/mkdocs/base.html:142 mkdocs/themes/mkdocs/base.html:144
+#: mkdocs/themes/mkdocs/base.html:146 mkdocs/themes/mkdocs/base.html:148
+#, python-format
+msgid "Edit on %(repo_name)s"
+msgstr "在 %(repo_name)s 上編輯"
+
+#: mkdocs/themes/mkdocs/base.html:150
+msgid "Edit"
+msgstr "編輯"
+
+#: mkdocs/themes/mkdocs/base.html:190
+#, python-format
+msgid "Documentation built with %(mkdocs_link)s."
+msgstr "使用 %(mkdocs_link)s 建立的文件"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:5
+msgid "Keyboard Shortcuts"
+msgstr "鍵盤快捷鍵"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:6
+#: mkdocs/themes/mkdocs/search-modal.html:6
+msgid "Close"
+msgstr "關閉"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:12
+msgid "Keys"
+msgstr "按鍵"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:13
+msgid "Action"
+msgstr "操作"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:19
+msgid "Open this help"
+msgstr "開啟這個說明"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:23
+msgid "Next page"
+msgstr "下一頁"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:27
+msgid "Previous page"
+msgstr "上一頁"
+
+#: mkdocs/themes/mkdocs/search-modal.html:9
+msgid "From here you can search these documents. Enter your search terms below."
+msgstr "從這裡您可以搜尋這些文件。請在下方輸入您要搜尋的內容。"
+
+#: mkdocs/themes/mkdocs/search-modal.html:12
+msgid "Search..."
+msgstr "搜尋..."
+
+#: mkdocs/themes/mkdocs/search-modal.html:12
+msgid "Type search term here"
+msgstr "在此輸入要搜尋的內容"
+
+#: mkdocs/themes/mkdocs/search-modal.html:15
+msgid "No results found"
+msgstr "沒有找到結果"
+
+#: mkdocs/themes/mkdocs/toc.html:3
+msgid "Table of Contents"
+msgstr "目錄"
diff --git a/mkdocs/themes/readthedocs/breadcrumbs.html b/mkdocs/themes/readthedocs/breadcrumbs.html
index 51ea9b91..29ab9086 100644
--- a/mkdocs/themes/readthedocs/breadcrumbs.html
+++ b/mkdocs/themes/readthedocs/breadcrumbs.html
@@ -1,12 +1,12 @@
 <div role="navigation" aria-label="breadcrumbs navigation">
   <ul class="wy-breadcrumbs">
-    <li><a href="{{ nav.homepage.url|url }}" class="icon icon-home" aria-label="{% trans %}Docs{% endtrans %}"></a> &raquo;</li>
+    <li><a href="{{ nav.homepage.url|url }}" class="icon icon-home" aria-label="{% trans %}Docs{% endtrans %}"></a></li>
     {%- if page %}
       {%- for doc in page.ancestors[::-1] %}
-        {%- if doc.link %}
-          <li class="breadcrumb-item"><a href="{{ doc.link|e }}">{{ doc.title }}</a></li>
+        {%- if doc.url %}
+          <li class="breadcrumb-item"><a href="{{ doc.url|url }}">{{ doc.title }}</a></li>
         {%- else %}
-          <li>{{ doc.title }} &raquo;</li>
+          <li class="breadcrumb-item">{{ doc.title }}</li>
         {%- endif %}
       {%- endfor %}
       <li class="breadcrumb-item active">{{ page.title }}</li>
diff --git a/mkdocs/themes/readthedocs/locales/zh_TW/LC_MESSAGES/messages.po b/mkdocs/themes/readthedocs/locales/zh_TW/LC_MESSAGES/messages.po
new file mode 100644
index 00000000..3be1ac12
--- /dev/null
+++ b/mkdocs/themes/readthedocs/locales/zh_TW/LC_MESSAGES/messages.po
@@ -0,0 +1,108 @@
+# Chinese (Traditional, Taiwan) translations for MkDocs.
+# Copyright (C) 2022 MkDocs
+# This file is distributed under the same license as the MkDocs project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: MkDocs 1.3.1\n"
+"Report-Msgid-Bugs-To: \"https://github.com/mkdocs/mkdocs/issues\"\n"
+"POT-Creation-Date: 2022-08-15 17:05+0200\n"
+"PO-Revision-Date: 2023-09-06 02:19+0800\n"
+"Last-Translator: Peter Dave Hello <hsu@peterdavehello.org>\n"
+"Language: zh_Hant_TW\n"
+"Language-Team: zh_Hant_TW <hsu@peterdavehello.org>\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.6.0\n"
+
+#: mkdocs/themes/readthedocs/404.html:7
+msgid "Page not found"
+msgstr "找不到頁面"
+
+#: mkdocs/themes/readthedocs/base.html:97
+msgid "Logo"
+msgstr "Logo"
+
+#: mkdocs/themes/readthedocs/base.html:111
+msgid "Navigation menu"
+msgstr "導覽列"
+
+#: mkdocs/themes/readthedocs/base.html:140
+msgid "Mobile navigation menu"
+msgstr "行動裝置導覽列"
+
+#: mkdocs/themes/readthedocs/breadcrumbs.html:3
+msgid "Docs"
+msgstr "文件"
+
+#: mkdocs/themes/readthedocs/breadcrumbs.html:18
+#: mkdocs/themes/readthedocs/breadcrumbs.html:20
+#: mkdocs/themes/readthedocs/breadcrumbs.html:22
+#: mkdocs/themes/readthedocs/breadcrumbs.html:24
+#, python-format
+msgid "Edit on %(repo_name)s"
+msgstr "在 %(repo_name)s 上編輯"
+
+#: mkdocs/themes/readthedocs/breadcrumbs.html:26
+msgid "Edit"
+msgstr "編輯"
+
+#: mkdocs/themes/readthedocs/breadcrumbs.html:34
+msgid "Breadcrumb Navigation"
+msgstr "軌跡瀏覽"
+
+#: mkdocs/themes/readthedocs/breadcrumbs.html:36
+#: mkdocs/themes/readthedocs/footer.html:7
+#: mkdocs/themes/readthedocs/versions.html:17
+msgid "Previous"
+msgstr "上一頁"
+
+#: mkdocs/themes/readthedocs/breadcrumbs.html:39
+#: mkdocs/themes/readthedocs/footer.html:10
+#: mkdocs/themes/readthedocs/versions.html:20
+msgid "Next"
+msgstr "下一頁"
+
+#: mkdocs/themes/readthedocs/footer.html:5
+msgid "Footer Navigation"
+msgstr "頁尾導覽"
+
+#: mkdocs/themes/readthedocs/footer.html:25
+#, python-format
+msgid ""
+"Built with %(mkdocs_link)s using a %(sphinx_link)s provided by "
+"%(rtd_link)s."
+msgstr ""
+"使用 %(mkdocs_link)s 建置，並採用 %(rtd_link)s 所提供的 %(sphinx_link)s。"
+
+#: mkdocs/themes/readthedocs/search.html:5
+msgid "Search Results"
+msgstr "搜尋結果"
+
+#: mkdocs/themes/readthedocs/search.html:9
+msgid "Search the Docs"
+msgstr "搜尋文件"
+
+#: mkdocs/themes/readthedocs/search.html:9
+#: mkdocs/themes/readthedocs/searchbox.html:3
+msgid "Type search term here"
+msgstr "在此輸入要搜尋的內容"
+
+#: mkdocs/themes/readthedocs/search.html:12
+msgid "No results found"
+msgstr "沒有找到結果"
+
+#: mkdocs/themes/readthedocs/search.html:13
+msgid "Searching..."
+msgstr "搜尋中..."
+
+#: mkdocs/themes/readthedocs/searchbox.html:3
+msgid "Search docs"
+msgstr "搜尋文件"
+
+#: mkdocs/themes/readthedocs/versions.html:1
+msgid "Versions"
+msgstr "版本"
diff --git a/pyproject.toml b/pyproject.toml
index 07a4a70d..008ff1e0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -104,7 +104,7 @@ dependencies = [
 
 [tool.hatch.envs.default.scripts]
 all = [
-    "hatch run style:check",
+    "hatch run style:fix",
     "hatch run types:check",
     "hatch run test:test",
     "hatch run lint:check",


Test patch:
diff --git a/mkdocs/tests/structure/nav_tests.py b/mkdocs/tests/structure/nav_tests.py
index 3e4aba5f..44ae2adc 100644
--- a/mkdocs/tests/structure/nav_tests.py
+++ b/mkdocs/tests/structure/nav_tests.py
@@ -378,6 +378,34 @@ class SiteNavigationTests(unittest.TestCase):
         self.assertEqual(len(site_navigation.pages), 7)
         self.assertEqual(repr(site_navigation.homepage), "Page(title=[blank], url='/')")
 
+    def test_nav_page_subclass(self):
+        class PageSubclass(Page):
+            pass
+
+        nav_cfg = [
+            {'Home': 'index.md'},
+            {'About': 'about.md'},
+        ]
+        expected = dedent(
+            """
+            PageSubclass(title=[blank], url='/')
+            PageSubclass(title=[blank], url='/about/')
+            """
+        )
+        cfg = load_config(nav=nav_cfg, site_url='http://example.com/')
+        fs = [
+            File(list(item.values())[0], cfg.docs_dir, cfg.site_dir, cfg.use_directory_urls)
+            for item in nav_cfg
+        ]
+        files = Files(fs)
+        for file in files:
+            PageSubclass(None, file, cfg)
+        site_navigation = get_navigation(files, cfg)
+        self.assertEqual(str(site_navigation).strip(), expected)
+        self.assertEqual(len(site_navigation.items), 2)
+        self.assertEqual(len(site_navigation.pages), 2)
+        self.assertEqual(repr(site_navigation.homepage), "PageSubclass(title=[blank], url='/')")
+
     def test_active(self):
         nav_cfg = [
             {'Home': 'index.md'},