Open tombreit opened 8 months ago
Hello @tombreit I think you can take inspiration from : https://github.com/ultrabug/mkdocs-static-i18n/blob/main/mkdocs_static_i18n/custom_i18n_sitemap/sitemap.xml
Hi @ultrabug, thanks for your prompt reply and the sitemap-hint! But in my case, there must be something wrong with my project setup - even i18n_alternates
is not defined:
# requirements.txt
mkdocs 1.5.3
mkdocs-static-i18n 1.2.2
# mkdocs.yml
site_name: Testsite
strict: true
plugins:
- i18n:
docs_structure: suffix
languages:
- locale: en
default: true
name: English
build: true
- locale: de
name: Deutsch
build: true
theme:
name: null
custom_dir: 'theme/'
# project layout
.
├── docs
│ ├── page1.de.md
│ └── page1.en.md
├── mkdocs.yml
├── theme
│ ├── base.html
│ ├── main.html
│ └── mkdocs_theme.yml
└── upload.sh
<!-- theme/base.html -->
i18n_page_locale: {{ i18n_page_locale }}
i18n_languages: {{ i18n_languages }}
i18n_alternates: {{ i18n_alternates.items() }}
→ mkdocs serve
→
File "project/theme_csl/main.html", line 1, in top-level template code
{% extends "base.html" %}
File "project/theme_csl/base.html", line 86, in top-level template code
{{ i18n_alternates.items() }}
^^^^^^^^^^^^^^^^^^^^^^^^^
File "project/.venv/lib/python3.11/site-packages/jinja2/environment.py", line 485, in getattr
return getattr(obj, attribute)
^^^^^^^^^^^^^^^^^^^^^^^
jinja2.exceptions.UndefinedError: 'i18n_alternates' is undefined
Do you have any other tips or ideas?
The i18n_alternates
are set only in the template context:
https://github.com/ultrabug/mkdocs-static-i18n/blob/0b492e11fa0cd8c716bb2e570a8fb4cc93765cf1/mkdocs_static_i18n/plugin.py#L145
For sitemap.xml and perhaps 404.html as well, as it's included in static_templates.
The page context has only those values: https://github.com/ultrabug/mkdocs-static-i18n/blob/0b492e11fa0cd8c716bb2e570a8fb4cc93765cf1/mkdocs_static_i18n/plugin.py#L182-L188
Based on this excerpt from the material theme, the templates can access the config
:
https://github.com/squidfunk/mkdocs-material/blob/cc78979185dfca30ad6657192174733f702d86f5/src/templates/base.html#L63-L65
So try:
{% if "i18n" in config.plugins %}
{% set i18n_alternates = config.plugins["i18n"].i18n_files_per_language %}
{% else %}
{% set i18n_alternates = {} %}
{% endif %}
{{ i18n_alternates.items() }}
I haven't tested it ✌️
Sorry, but I don't get it. You put me on the right track - but
<!-- mytheme/base.html -->
{% for locale, i18n_files in config.plugins["i18n"].i18n_files_per_language.items() %}
- locale: {{ locale }}
i18n_files: {{ i18n_files }}
{% endfor %}
only works for my secondary language pages - it does not list alternate de
pages for en
pages - but lists en
and de
pages for de
pages:
# page: docs/index.en.md
- locale: en
i18n_files: [File(src_uri='index.en.md', dest_uri='index.html', name='index', url='./')]
# page: docs/index.de.md
- locale: en
i18n_files: [File(src_uri='index.en.md', dest_uri='index.html', name='index', url='./')]
- locale: de
i18n_files: [File(src_uri='index.de.md', dest_uri='de/index.html', name='index', url='de/')]
Hard to explain, so I have put together a demo page:
Didn't run the demo, your comment explained the situation quite well:
https://github.com/ultrabug/mkdocs-static-i18n/blob/0b492e11fa0cd8c716bb2e570a8fb4cc93765cf1/mkdocs_static_i18n/plugin.py#L76-L78
It turned out that the i18n_files_per_language
is a mapping that gets updated after each language build, and the sitemap uses the data from the last build to save the information, once all languages are built.
Going back to your OP:
I would like to build a language selector in a custom (non-mkdocs-material) theme, but I do not know how to access the alternate language versions of a given page:
As far as I know, the i18n plugin requires or assumes that the file tree is the same in each language, so every file path is the same too only the .en.md
file suffix or /en/...
folder prefix changes.
Given this information you don't need to access the files from other languages, you only need the language identifier. https://github.com/ultrabug/mkdocs-static-i18n/blob/0b492e11fa0cd8c716bb2e570a8fb4cc93765cf1/mkdocs_static_i18n/reconfigure.py#L85 https://github.com/ultrabug/mkdocs-static-i18n/blob/0b492e11fa0cd8c716bb2e570a8fb4cc93765cf1/mkdocs_static_i18n/reconfigure.py#L110-L114
You should be able to access the data with:
you have access to the current locale already:config.plugins["i18n"].current_language
get current language
context["i18n_file_locale"] = page.file.locale
context["i18n_page_locale"] = self.current_language
config.plugins["i18n"].build_languages
loop over that to get alternates
page.url | replace(current_language, alternate, 1)
replace the current with the alternate once inside the url 🤔
accessing page
might crash on 404.html
, so add a safety check if that happens if page
That would work if all pages exists in all configured languages. Looping over config.plugins["i18n"].all_languages
seems to get same resuts.
But neither config.plugins["i18n"].build_languages
nor config.plugins["i18n"].all_languages
seem to return only the actually existing alternates. Instead these return all possible alternates according to the languages
config key.
Given the following docs
layout:
docs/
├── enonly.en.md
├── index.de.md
└── index.en.md
this would work for index.en.md
↔index.de.md
- but not for enonly.en.md
.
Perhaps I implement this language switcher in Javascript;-) And thank you very much for taking the time to look at my issue.
Well, both build_languages
and all_languages
are global containers for the whole build, and aren't "resolved" for each page separately.
I always use the https://ultrabug.github.io/mkdocs-static-i18n/setup/controlling-your-builds/#fallbacking-to-default setting, so I never even considered a non-translated page alternate as an issue 😅
Perhaps I implement this language switcher in Javascript;-)
So that after a page load, the JavaScript fetches the urls to check if the page is available and returns a status 200? I advise against this, as this would just create unnecessary requests.
This is the code that reconfigures the context and configures the alternates:
https://github.com/ultrabug/mkdocs-static-i18n/blob/0b492e11fa0cd8c716bb2e570a8fb4cc93765cf1/mkdocs_static_i18n/reconfigure.py#L424-L442
There is the page.file.alternates
list, but I don't think it will limit the alternates to only existent ones, still worth a try.
I would like to build a language selector in a custom (non-mkdocs-material) theme,
Also the Material theme uses the extra.alternate
config, which later is modified by the plugin. So why not copy the logic from the material theme? The licence is MIT, so you can reuse it, just provide attribution.
I already tried to hijack the language switcher from mkdocs-material. But, again, I'm unable to use the provided "integration" via reconfigure_material_theme
. To me it looks like this functionality is strongly coupled with/for the material theme and it is not clear to me how I could use this functionality with my theme:
This integration actually sounds perfect and I would love to use it - but the static-i18n plugin only seems to provide/expose this for "mkdocs-material"?
True, my bad, I forgot about the config.theme.name
validation. The i18n plugin makes the assumption that extra.alternate
is only used by the mkdocs-material theme, which for now it was, and has merged the alternate handling with the reconfiguration logic.
The code responsible for the alternate deepcopy could be moved out into another function reconfigure_extra_alternate
:
https://github.com/ultrabug/mkdocs-static-i18n/blob/0b492e11fa0cd8c716bb2e570a8fb4cc93765cf1/mkdocs_static_i18n/reconfigure.py#L306-L356
and later it can be called inside the reconfigure_material_theme
like before, and in an elif "alternate" in config.extra
statement after that whole material
validation:
https://github.com/ultrabug/mkdocs-static-i18n/blob/0b492e11fa0cd8c716bb2e570a8fb4cc93765cf1/mkdocs_static_i18n/reconfigure.py#L127
I think it's a valid proposition to support that feature in other themes, one issue might be that other themes use extra.alternate
in a different way from the material theme. You could do some market research with the more popular themes, and built-in themes, and make sure there won't be any conflict. if there is a conflict additional validation would be required for that extra.alternate
to make sure it has valid values.
IMO that logic is not that coupled with material, that it can't be taken out 🤔However, I won't be developing anything for at least a week+ so can't make a PR myself. Once the market research is done ping ultrabug, maybe he'll have the time if you don't want to dabble with Python directly.
I would like to build a language selector in a custom (non-mkdocs-material) theme, but I do not know how to access the alternate language versions of a given page:
i18n_page_locale
gives me the expected language code for the current language version.But the variable
i18n_languages
seem to be undefined.How do I access the alternate language versions of a given page in a custom template?