Repository: mkdocs/mkdocs
Pull request #3024 (2022-10-26 14:53:05)

Translate mkdocs theme to Norwegian (nb and nn)
I also reordered the locale list alphabetically (except for English).


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b533af12..27c0b0dc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,7 +7,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        python-version: [3.7, 3.8, 3.9, '3.10', pypy-3.7-v7.x]
+        python-version: [3.7, 3.8, 3.9, '3.10', '3.11', pypy-3.7-v7.x]
         os: [ubuntu-latest, windows-latest, macos-latest]
         include:
           - python-version: 3.7
@@ -18,6 +18,8 @@ jobs:
             py: py39
           - python-version: '3.10'
             py: py310
+          - python-version: '3.11'
+            py: py311
           - python-version: pypy-3.7-v7.x
             py: pypy3
         # Just to slim down the test matrix:
@@ -28,6 +30,10 @@ jobs:
             os: windows-latest
           - python-version: 3.9
             os: ubuntu-latest
+          - python-version: 3.10
+            os: macos-latest
+          - python-version: 3.10
+            os: windows-latest
     runs-on: ${{ matrix.os }}
     steps:
       - uses: actions/checkout@v3
@@ -98,7 +104,7 @@ jobs:
       - name: Setup Python
         uses: actions/setup-python@v4
         with:
-          python-version: '3.9'
+          python-version: '3.10'
       - name: Install Hatch
         run: |
           python -m pip install -U hatch
diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yml
index 4f07eef4..d1aedce2 100644
--- a/.github/workflows/deploy-release.yml
+++ b/.github/workflows/deploy-release.yml
@@ -13,7 +13,7 @@ jobs:
       - name: Setup Python
         uses: actions/setup-python@v4
         with:
-          python-version: '3.9'
+          python-version: '3.10'
       - name: Install Hatch
         run: |
           python -m pip install -U hatch
diff --git a/docs/user-guide/choosing-your-theme.md b/docs/user-guide/choosing-your-theme.md
index 24bf1a70..30492e24 100644
--- a/docs/user-guide/choosing-your-theme.md
+++ b/docs/user-guide/choosing-your-theme.md
@@ -108,17 +108,19 @@ supports the following options:
     The following locales are supported by this theme:
 
     * `en`: English (default)
-    * `fr`: French
-    * `es`: Spanish
-    * `ja`: Japanese
-    * `pt_BR`: Portuguese (Brazil)
-    * `zh_CN`: Simplified Chinese
     * `de`: German
+    * `es`: Spanish
     * `fa`: Persian (Farsi)
+    * `fr`: French
     * `it`: Italian
-    * `tr_TR`: Turkish (Turkey)
+    * `ja`: Japanese
+    * `nb`: Norwegian Bokmål
+    * `nn`: Norwegian Nynorsk
+    * `pt_BR`: Portuguese (Brazil)
     * `ru`: Russian
+    * `tr_TR`: Turkish (Turkey)
     * `uk`: Ukrainian
+    * `zh_CN`: Simplified Chinese
 
     See the guide on [localizing your theme] for more information.
 
diff --git a/mkdocs/livereload/__init__.py b/mkdocs/livereload/__init__.py
index c2e52ab8..e136ff05 100644
--- a/mkdocs/livereload/__init__.py
+++ b/mkdocs/livereload/__init__.py
@@ -246,7 +246,7 @@ class LiveReloadServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGISe
                         self._epoch_cond.wait_for(condition, timeout=self.poll_response_timeout)
                     return [b"%d" % self._visible_epoch]
 
-        if path.startswith(self.mount_path):
+        if (path + "/").startswith(self.mount_path):
             rel_file_path = path[len(self.mount_path) :]
 
             if path.endswith("/"):
diff --git a/mkdocs/structure/files.py b/mkdocs/structure/files.py
index e469c9e4..91679f82 100644
--- a/mkdocs/structure/files.py
+++ b/mkdocs/structure/files.py
@@ -230,10 +230,7 @@ class File:
         url = self.dest_uri
         dirname, filename = posixpath.split(url)
         if use_directory_urls and filename == 'index.html':
-            if dirname == '':
-                url = '.'
-            else:
-                url = dirname + '/'
+            url = (dirname or '.') + '/'
         return urlquote(url)
 
     def url_relative_to(self, other: File) -> str:
diff --git a/mkdocs/structure/pages.py b/mkdocs/structure/pages.py
index f24ad967..6592495b 100644
--- a/mkdocs/structure/pages.py
+++ b/mkdocs/structure/pages.py
@@ -88,7 +88,7 @@ class Page:
     @property
     def url(self) -> str:
         """The URL of the page relative to the MkDocs `site_dir`."""
-        return '' if self.file.url == '.' else self.file.url
+        return '' if self.file.url in ('.', './') else self.file.url
 
     file: File
     """The documentation [`File`][mkdocs.structure.files.File] that the page is being rendered from."""
@@ -133,7 +133,7 @@ class Page:
     @property
     def is_homepage(self) -> bool:
         """Evaluates to `True` for the homepage of the site and `False` for all other pages."""
-        return self.is_top_level and self.is_index and self.file.url in ['.', 'index.html']
+        return self.is_top_level and self.is_index and self.file.url in ('.', './', 'index.html')
 
     previous_page: Optional[Page]
     """The [page][mkdocs.structure.pages.Page] object for the previous page or `None`.
diff --git a/mkdocs/themes/mkdocs/locales/nb/LC_MESSAGES/messages.po b/mkdocs/themes/mkdocs/locales/nb/LC_MESSAGES/messages.po
new file mode 100644
index 00000000..ad9e9699
--- /dev/null
+++ b/mkdocs/themes/mkdocs/locales/nb/LC_MESSAGES/messages.po
@@ -0,0 +1,101 @@
+# Norwegian Bokmål 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: 2022-10-26 11:10+0200\n"
+"Last-Translator: Per Christian Gaustad <pcgaustad@mailbox.org>\n"
+"Language: nb\n"
+"Language-Team: nb <LL@li.org>\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.10.3\n"
+
+#: mkdocs/themes/mkdocs/404.html:8
+msgid "Page not found"
+msgstr "Fant ikke siden"
+
+#: mkdocs/themes/mkdocs/base.html:116
+#: mkdocs/themes/mkdocs/keyboard-modal.html:31
+#: mkdocs/themes/mkdocs/search-modal.html:5
+msgid "Search"
+msgstr "Søk"
+
+#: mkdocs/themes/mkdocs/base.html:126
+msgid "Previous"
+msgstr "Forrige"
+
+#: mkdocs/themes/mkdocs/base.html:131
+msgid "Next"
+msgstr "Neste"
+
+#: 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 "Rediger på %(repo_name)s"
+
+#: mkdocs/themes/mkdocs/base.html:150
+msgid "Edit"
+msgstr "Rediger"
+
+#: mkdocs/themes/mkdocs/base.html:190
+#, python-format
+msgid "Documentation built with %(mkdocs_link)s."
+msgstr "Dokumentasjonen bygget med %(mkdocs_link)s."
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:5
+msgid "Keyboard Shortcuts"
+msgstr "Tastatursnarveier"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:6
+#: mkdocs/themes/mkdocs/search-modal.html:6
+msgid "Close"
+msgstr "Lukk"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:12
+msgid "Keys"
+msgstr "Taster"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:13
+msgid "Action"
+msgstr "Handling"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:19
+msgid "Open this help"
+msgstr "Åpne denne hjelpen"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:23
+msgid "Next page"
+msgstr "Neste side"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:27
+msgid "Previous page"
+msgstr "Forrige side"
+
+#: mkdocs/themes/mkdocs/search-modal.html:9
+msgid "From here you can search these documents. Enter your search terms below."
+msgstr "Her kan du søke i disse dokumentene. Skriv søketeksten nedenfor."
+
+#: mkdocs/themes/mkdocs/search-modal.html:12
+msgid "Search..."
+msgstr "Søk ..."
+
+#: mkdocs/themes/mkdocs/search-modal.html:12
+msgid "Type search term here"
+msgstr "Skriv søketeksten her"
+
+#: mkdocs/themes/mkdocs/search-modal.html:15
+msgid "No results found"
+msgstr "Fant ingen resultater"
+
+#: mkdocs/themes/mkdocs/toc.html:3
+msgid "Table of Contents"
+msgstr "Innholdsfortegnelse"
+
diff --git a/mkdocs/themes/mkdocs/locales/nn/LC_MESSAGES/messages.po b/mkdocs/themes/mkdocs/locales/nn/LC_MESSAGES/messages.po
new file mode 100644
index 00000000..66992e7f
--- /dev/null
+++ b/mkdocs/themes/mkdocs/locales/nn/LC_MESSAGES/messages.po
@@ -0,0 +1,101 @@
+# Norwegian Nynorsk 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: 2022-10-26 11:10+0200\n"
+"Last-Translator: Per Christian Gaustad <pcgaustad@mailbox.org>\n"
+"Language: nn\n"
+"Language-Team: nn <LL@li.org>\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.10.3\n"
+
+#: mkdocs/themes/mkdocs/404.html:8
+msgid "Page not found"
+msgstr "Fann ikkje sida"
+
+#: mkdocs/themes/mkdocs/base.html:116
+#: mkdocs/themes/mkdocs/keyboard-modal.html:31
+#: mkdocs/themes/mkdocs/search-modal.html:5
+msgid "Search"
+msgstr "Søk"
+
+#: mkdocs/themes/mkdocs/base.html:126
+msgid "Previous"
+msgstr "Førre"
+
+#: mkdocs/themes/mkdocs/base.html:131
+msgid "Next"
+msgstr "Neste"
+
+#: 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 "Rediger på %(repo_name)s"
+
+#: mkdocs/themes/mkdocs/base.html:150
+msgid "Edit"
+msgstr "Rediger"
+
+#: mkdocs/themes/mkdocs/base.html:190
+#, python-format
+msgid "Documentation built with %(mkdocs_link)s."
+msgstr "Dokumentasjonen bygd med %(mkdocs_link)s."
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:5
+msgid "Keyboard Shortcuts"
+msgstr "Tastatursnarvegar"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:6
+#: mkdocs/themes/mkdocs/search-modal.html:6
+msgid "Close"
+msgstr "Lukk"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:12
+msgid "Keys"
+msgstr "Tastar"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:13
+msgid "Action"
+msgstr "Handling"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:19
+msgid "Open this help"
+msgstr "Opn denne hjelpa"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:23
+msgid "Next page"
+msgstr "Neste side"
+
+#: mkdocs/themes/mkdocs/keyboard-modal.html:27
+msgid "Previous page"
+msgstr "Førre side"
+
+#: mkdocs/themes/mkdocs/search-modal.html:9
+msgid "From here you can search these documents. Enter your search terms below."
+msgstr "Her kan du søke i desse dokumenta. Skriv søketeksta nedanfor."
+
+#: mkdocs/themes/mkdocs/search-modal.html:12
+msgid "Search..."
+msgstr "Søk ..."
+
+#: mkdocs/themes/mkdocs/search-modal.html:12
+msgid "Type search term here"
+msgstr "Skriv søketeksta her"
+
+#: mkdocs/themes/mkdocs/search-modal.html:15
+msgid "No results found"
+msgstr "Fann ingen resultat"
+
+#: mkdocs/themes/mkdocs/toc.html:3
+msgid "Table of Contents"
+msgstr "Innhaldsliste"
+
diff --git a/pyproject.toml b/pyproject.toml
index b3ee8718..9c32c949 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -23,6 +23,7 @@ classifiers = [
     "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3 :: Only",
     "Programming Language :: Python :: Implementation :: CPython",
     "Programming Language :: Python :: Implementation :: PyPy",


Test patch:
diff --git a/mkdocs/tests/structure/file_tests.py b/mkdocs/tests/structure/file_tests.py
index 7f5fd1ee..8d8257f0 100644
--- a/mkdocs/tests/structure/file_tests.py
+++ b/mkdocs/tests/structure/file_tests.py
@@ -168,7 +168,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
         self.assertPathsEqual(f.abs_src_path, '/path/to/docs/index.md')
         self.assertEqual(f.dest_uri, 'index.html')
         self.assertPathsEqual(f.abs_dest_path, '/path/to/site/index.html')
-        self.assertEqual(f.url, '.')
+        self.assertEqual(f.url, './')
         self.assertEqual(f.name, 'index')
         self.assertTrue(f.is_documentation_page())
         self.assertFalse(f.is_static_page())
@@ -182,7 +182,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
         self.assertPathsEqual(f.abs_src_path, '/path/to/docs/README.md')
         self.assertEqual(f.dest_uri, 'index.html')
         self.assertPathsEqual(f.abs_dest_path, '/path/to/site/index.html')
-        self.assertEqual(f.url, '.')
+        self.assertEqual(f.url, './')
         self.assertEqual(f.name, 'index')
         self.assertTrue(f.is_documentation_page())
         self.assertFalse(f.is_static_page())
@@ -446,7 +446,7 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
         ]
 
         to_file_urls = [
-            '.',
+            './',
             'foo/',
             'foo/bar/',
             'foo/bar/baz/',
@@ -493,18 +493,18 @@ class TestFiles(PathAssertionMixin, unittest.TestCase):
 
         from_file = File('index.html', '/path/to/docs', '/path/to/site', use_directory_urls=True)
         expected = [
-            '.',  # . relative to .
-            '..',  # . relative to foo/
-            '../..',  # . relative to foo/bar/
-            '../../..',  # . relative to foo/bar/baz/
-            '..',  # . relative to foo
-            '../..',  # . relative to foo/bar
-            '../../..',  # . relative to foo/bar/baz
+            './',  # . relative to .
+            '../',  # . relative to foo/
+            '../../',  # . relative to foo/bar/
+            '../../../',  # . relative to foo/bar/baz/
+            '../',  # . relative to foo
+            '../../',  # . relative to foo/bar
+            '../../../',  # . relative to foo/bar/baz
         ]
 
         for i, filename in enumerate(to_files):
             file = File(filename, '/path/to/docs', '/path/to/site', use_directory_urls=True)
-            self.assertEqual(from_file.url, '.')
+            self.assertEqual(from_file.url, './')
             self.assertEqual(file.url, to_file_urls[i])
             self.assertEqual(from_file.url_relative_to(file.url), expected[i])
             self.assertEqual(from_file.url_relative_to(file), expected[i])
diff --git a/mkdocs/tests/structure/page_tests.py b/mkdocs/tests/structure/page_tests.py
index 24b17a01..9ccd9ff8 100644
--- a/mkdocs/tests/structure/page_tests.py
+++ b/mkdocs/tests/structure/page_tests.py
@@ -659,7 +659,7 @@ class RelativePathExtensionTests(unittest.TestCase):
     def test_relative_html_link_index(self):
         self.assertEqual(
             self.get_rendered_result(['non-index.md', 'index.md']),
-            '<p><a href="..">link</a></p>',
+            '<p><a href="../">link</a></p>',
         )
 
     @mock.patch('mkdocs.structure.pages.open', mock.mock_open(read_data='[link](sub2/index.md)'))
@@ -696,7 +696,7 @@ class RelativePathExtensionTests(unittest.TestCase):
     def test_relative_html_link_parent_index(self):
         self.assertEqual(
             self.get_rendered_result(['sub2/non-index.md', 'index.md']),
-            '<p><a href="../..">link</a></p>',
+            '<p><a href="../../">link</a></p>',
         )
 
     @mock.patch(