mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2026-08-04 19:45:08 -04:00
Added hook to automatically compute and update translations
This commit is contained in:
@@ -134,6 +134,51 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Language list
|
||||
.mdx-flags {
|
||||
margin: 2em auto;
|
||||
|
||||
// Language list
|
||||
ol {
|
||||
list-style: none;
|
||||
|
||||
// Language list item
|
||||
li {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
// Language item
|
||||
&__item {
|
||||
display: flex;
|
||||
gap: px2rem(12px);
|
||||
}
|
||||
|
||||
// Language content
|
||||
&__content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
// Language name
|
||||
span {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
// Language link
|
||||
> span:nth-child(2) {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
// Language code
|
||||
code {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blog author
|
||||
.mdx-author {
|
||||
display: flex;
|
||||
|
||||
54
src/.overrides/hooks/translations.html
Normal file
54
src/.overrides/hooks/translations.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!--
|
||||
Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- Render translation language -->
|
||||
{% macro render_language(language) %}
|
||||
<div class="mdx-flags__item" markdown>
|
||||
:flag_{{ language.flag }}:{ .lg .middle }
|
||||
<span class="mdx-flags__content">
|
||||
<span>
|
||||
<strong>{{ language.name }}</strong>
|
||||
<code>{{ language.code }}</code>
|
||||
</span>
|
||||
{% if language.miss %}
|
||||
<span>
|
||||
<a href="{{ language.link }}">
|
||||
{{ language.miss | length }} translations missing
|
||||
</a>
|
||||
</span>
|
||||
{% else %}
|
||||
<small>Complete</small>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
<!-- Render translations -->
|
||||
{% macro render(translations, start = 1) %}
|
||||
<div class="mdx-columns mdx-flags" markdown>
|
||||
<ol markdown>
|
||||
{% for language in translations %}
|
||||
<li markdown>{{ render_language(language) }}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
185
src/.overrides/hooks/translations.py
Normal file
185
src/.overrides/hooks/translations.py
Normal file
@@ -0,0 +1,185 @@
|
||||
# Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com>
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from glob import glob
|
||||
from mkdocs.config.defaults import MkDocsConfig
|
||||
from mkdocs.structure.pages import Page
|
||||
from urllib.parse import urlencode, urlparse
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Hooks
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Determine missing translations and render language overview in the setup
|
||||
# guide, including links to provide missing translations.
|
||||
def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files):
|
||||
issue_url = "https://github.com/squidfunk/mkdocs-material/issues/new"
|
||||
if page.file.src_uri != "setup/changing-the-language.md":
|
||||
return
|
||||
|
||||
# Collect all existing languages
|
||||
names: dict[str, str] = dict()
|
||||
known: dict[str, dict[str, str]] = dict()
|
||||
for path in glob("src/partials/languages/*.html"):
|
||||
with open(path, "r", encoding = "utf-8") as f:
|
||||
data = f.read()
|
||||
|
||||
# Extract language code and name
|
||||
name, = re.findall(r"<!-- Translations: (.+) -->", data)
|
||||
code, _ = os.path.splitext(os.path.basename(path))
|
||||
|
||||
# Map names and available translations
|
||||
names[code] = name
|
||||
known[code] = dict(re.findall(
|
||||
r"^ \"([^\"]+)\": \"([^\"]+)\"(?:,|$)?", data,
|
||||
re.MULTILINE
|
||||
))
|
||||
|
||||
# Remove technical stuff
|
||||
for key in [
|
||||
"direction",
|
||||
"search.config.pipeline",
|
||||
"search.config.lang",
|
||||
"search.config.separator"
|
||||
]:
|
||||
if key in known[code]:
|
||||
del known[code][key]
|
||||
|
||||
# Traverse all languages and compute missing translations
|
||||
languages = []
|
||||
reference = set(known["en"])
|
||||
for code, name in names.items():
|
||||
miss = reference - set(known[code])
|
||||
|
||||
# Check each translations
|
||||
translations: list[str] = []
|
||||
for key, value in known["en"].items():
|
||||
if key in known[code]:
|
||||
translations.append(
|
||||
f" \"{key}\": \"{known[code][key]}\""
|
||||
)
|
||||
else:
|
||||
translations.append(
|
||||
f" \"{key}\": \"{value} ⬅️\""
|
||||
)
|
||||
|
||||
# Assemble GitHub issue URL
|
||||
link = urlparse(issue_url)
|
||||
link = link._replace(query = urlencode({
|
||||
"template": "translate.yml",
|
||||
"title": f"Update {name} translations",
|
||||
"translations": "\n".join([
|
||||
"{% macro t(key) %}{{ {",
|
||||
",\n".join(translations),
|
||||
"}[key] }}{% endmacro %}"
|
||||
])
|
||||
}))
|
||||
|
||||
# Add translation
|
||||
languages.append({
|
||||
"flag": countries[code],
|
||||
"code": code,
|
||||
"name": name,
|
||||
"link": link.geturl(),
|
||||
"miss": miss
|
||||
})
|
||||
|
||||
# Load template and render translations
|
||||
env = config.theme.get_env()
|
||||
template = env.get_template( "hooks/translations.html")
|
||||
translations = template.module.render(
|
||||
sorted(languages, key = lambda language: language["name"])
|
||||
)
|
||||
|
||||
# Replace translation marker
|
||||
return markdown.replace(
|
||||
"<!-- hooks/translations.py -->", "\n".join(
|
||||
[line.lstrip() for line in translations.split("\n")
|
||||
]
|
||||
))
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Data
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Map ISO 639-1 (languages) to ISO 3166 (countries)
|
||||
countries = dict({
|
||||
"af": "za",
|
||||
"ar": "ae",
|
||||
"bg": "bg",
|
||||
"bn": "bd",
|
||||
"ca": "es",
|
||||
"cs": "cz",
|
||||
"da": "dk",
|
||||
"de": "de",
|
||||
"el": "gr",
|
||||
"en": "us",
|
||||
"eo": "eu",
|
||||
"es": "es",
|
||||
"et": "ee",
|
||||
"fa": "ir",
|
||||
"fi": "fi",
|
||||
"fr": "fr",
|
||||
"gl": "es",
|
||||
"he": "il",
|
||||
"hi": "in",
|
||||
"hr": "hr",
|
||||
"hu": "hu",
|
||||
"hy": "am",
|
||||
"id": "id",
|
||||
"is": "is",
|
||||
"it": "it",
|
||||
"ja": "jp",
|
||||
"ka": "ge",
|
||||
"ko": "kr",
|
||||
"lt": "lt",
|
||||
"lv": "lv",
|
||||
"mk": "mk",
|
||||
"mn": "mn",
|
||||
"ms": "my",
|
||||
"my": "mm",
|
||||
"nb": "no",
|
||||
"nl": "nl",
|
||||
"nn": "no",
|
||||
"pl": "pl",
|
||||
"pt-BR": "br",
|
||||
"pt": "pt",
|
||||
"ro": "ro",
|
||||
"ru": "ru",
|
||||
"sh": "rs",
|
||||
"si": "lk",
|
||||
"sk": "sk",
|
||||
"sl": "si",
|
||||
"sr": "rs",
|
||||
"sv": "se",
|
||||
"th": "th",
|
||||
"tl": "ph",
|
||||
"tr": "tr",
|
||||
"uk": "ua",
|
||||
"ur": "pk",
|
||||
"uz": "uz",
|
||||
"vi": "vn",
|
||||
"zh": "cn",
|
||||
"zh-Hant": "cn",
|
||||
"zh-TW": "tw"
|
||||
})
|
||||
Reference in New Issue
Block a user