__I checked that...__
Add support for mkdocs-git-committers-plugin. In effect, when a user enables the plugin in mkdocs.yml, the latest revision date would automatically display under the page title.
Users can see clearly when pages where last updated -- without having to go to git.
It would look something like this:

If this is something that is considered useful I would be happy to work on the PR. Work to be done:
base.html with conditional statementsLooks useful to me, happy to collaborate on a PR.
How does the plugin handle L10N/I18N? Is the date string printed according to the environment locale? This also needs to be addressed in all other content that is automatically added to the template, i.e. "Last update:"
Good points!
The plugin outputs dates in YYYY-MM-DD format. We could use timeago which has localization, which we can map to mkdocs list of supported languages. Downside is this adds a 2kb dependency. That doesn't solve the "Last update:" part though. I realize now that this should be part of the mkdocs-git-committers-plugin plugin.
Is I18N a hard requirement for you? If so, I'll need to go and contribute to that plugin first & then re-open this issue here. Otherwise, we can start already with adding an english version.
The plugin outputs dates in YYYY-MM-DD format. We could use timeago which has localization, which we can map to mkdocs list of supported languages. Downside is this adds a 2kb dependency.
Solving this in the browser is actually too late. Material follows the idea of progressive enhancement, so the theme must work without any JavaScript, at least everything that is not interactive by design. For this reason this would need to be solved during build time.
That doesn't solve the "Last update:" part though. I realize now that this should be part of the mkdocs-git-committers-plugin plugin.
Ideally, the plugin should only provide the date object to the template without doing any formatting. We need to check whether there are datetime formatting functions available in the Jinja environment exposed by MkDocs. If there are, we could also put the date time format string in the language file (i.e. translation). The "Last update" could be translated by Material itself, so given the following file:
... we could add two new translations:
...
"last.update": "Last update",
"last.date: "%Y-%m-%d"
...
This could then easily be translated to all other languages with English being the fallback.
Is I18N a hard requirement for you? If so, I'll need to go and contribute to that plugin first & then re-open this issue here. Otherwise, we can start already with adding an english version.
Kind of. Adding a hard-coded string to the template I would want to provide a way to translate it easily.
I looked into it, and mkdocs offers no special datetime formatting, waylan refers to standard strftime functionality (see this issue), but the mkdocs-git-revision-date-plugin plugin returns a str and datetime is not imported by mkdocs.
If we accept the date is always in ISO-8610 format (the only right format anyway), we can move forward with an output like:
{% if git_revision_date is defined %}
# ...
{{ lang.t('last.update') }}: {{ git_revision_date }}
{% endif %}
Last updated: 2019-11-26
strftime would be perfect, or am I missing something? So if the date would be exposed as a date variable, we could use strftime in the template with a localized format string (with a reasonable default). MkDocs's build_date_utc is also exposed as a datetime object. So for reasons of consistency alone I would favor datetime over a string.
As much as I love XKCD – ISO-8610 is a very technical format. For my own docs I would prefer something more readable like _November 26, 2019_. Could we update the mentioned plugin that it outputs datetime objects? It could be implemented as an option to support both formats, string and datetime. If a datetime is encountered, Material will render it using the given format, otherwise it will just display the string.
Also see https://github.com/zhaoterryy/mkdocs-git-revision-date-plugin/issues/4, which is already a request for different date formats.
Yes let's do it proper then, will contribute to mkdocs-git-revision-date-plugin first so we get a datetime object, then get back here. Thanks so far!
Update: PR is awaiting review/approval, which will enable {{ git_revision_date.strftime('%d %B %Y') }}
Figured I could already start on this PR while I wait for the other one, so I started here: https://github.com/timvink/mkdocs-material/tree/1350-support-git-revision-date
I need some help with the scss, basically with a conditional margin on <h1>, if revision date is available no margin-bottom: -2em on h1:

And another more challenging issue: When you use a heading 1 (#) in a page it takes precedence over the navigation tree title (in mkdocs.yml), which means either the revision date is not shown (if within the title if block in base.html) or the ordering is wrong (when using separate if block below the title, see picture):
{% if not "\x3ch1" in page.content %}
<h1>{{ page.title | default(config.site_name, true)}}</h1>
{% endif %}
{% if page.meta.revision_date %}
<small>
{{ lang.t('last.update') }}: {{ page.meta.revision_date.strftime('%d %B %Y') }}
</small>
{% endif %}

Maybe you have some ideas or pointers in the right direction?
Placing it under the h1 will not work consistently, as the theme sets the page title as h1 if there's no h1 in the content as you already noticed. This behavior is not configurable. I think I would recommend to place it at the bottom after the content and footnotes and before the footer. This should also solve the spacing problems, which are tricky to get right in all possible combinations, as there are quite some rules for subsequent headlines, e.g. h1 + h2 etc.
That's not as nice but a lot more practical.
I also only now realize {{ page.meta.revision_date.strftime('%d %B %Y') }} does not respect the language option from mkdocs-material. It will default to the user's python locale.
Changing that is possible in python:
import locale
import datetime
date = datetime.datetime.now().date()
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
print(date.strftime('%A'))
#> Wednesday
locale.setlocale(locale.LC_ALL, 'nl_NL.UTF-8')
print(date.strftime('%A'))
#> woensdag
But not every user has every locale installed on his system. And it would also require a contribution to mkdocs. The alternative of exporting LC_ALL as an environment variable before building is not a failsafe method, and perhaps not user-friendly either.
Another way to do this is to use the python timeago package that has localization files:
import timeago
date = datetime.datetime.now().date()
print(timeago.format(date))
#> 9 hours ago
print(timeago.format(date, locale = "nl"))
#> 9 uren geleden
I could contribute to mkdocs a new custom jinja2 mkdocs template filter that uses timeago and takes locale as an argument, something like:
`{{ lang.t('last.update') }}: {{ page.meta.revision_date | totimeago( config.theme.language) }}`
So finally output would be something like:
Last update: 9 hours ago
Alternatively, the easiest route would be using YYYY-MM-DD format, e.g.:
Last update: 2019-11-27
Let me know what you prefer, or if you have any other good ideas ;)
@timvink thanks for the thorough research and experimentation! If opening the possibility to set locales opens yet another can of worms, I would also be fine with an English-only formatted date string which is adjustable through strftime. I guess it's possible to adjust the locale via LC_ALL as an environment variable in front of the mkdocs command, isn't it? We could add a hint in the documentation how to achieve this, e.g:
LC_ALL=nl_NL mkdocs build
@waylan could you maybe comment on this topic? Before we go down a specific path I would like to hear your opinion. I feel that localization is kind of an open and unresolved issue of MkDocs, which is also why Material went its own way with L10N based on template files / macros. Are there any plans for improving localization, maybe with a language parameter set in mkdocs.yml or via environment variables?
The current state of L10N is summarized in mkdocs/mkdocs#211 and the beginning of an implementation exists in mkdocs/mkdocs#1778. That PR adds a locale setting to the theme. In other words, the default language would be defined in mkdocs_theme.yml and could be overridden in mkdocs.yml:
theme:
locale: fr
@squidfunk Localization seems like the way to go then. I suggest I first propose & make a PR to mkdocs that implements the totimeago jinja2 filter. Then back here in addition to changes discussed we should also rename the language parameter to locale to be consistent with future versions of mkdocs. We can do this in a backwards compatible way with some jinja2 logic.
@waylan I skimmed through the PR and did not find a call to locale.setlocale. Could this be done and exposed to plugins, so they run in the context of the given locale?
Other than that to move forward with this PR I suggest:
YYYY-MM-DD stringen.html, which is the fallback if a key is not available for a specific language)Then back here in addition to changes discussed we should also rename the language parameter to locale to be consistent with future versions of mkdocs
We definitely need to provide backward-compatibility. Furthermore, we'll wait for a new MkDocs version to configure the locale for strftime, so there should be no necessity for timeago I guess.
I suggest I first propose & make a PR to mkdocs that implements the
totimeagojinja2 filter.
As this is all about supporting a third party plugin, I would suggest changes like this should be made to the plugin. As a reminder, plugins can alter the Jinja environment with the on_env event (to add filters, for example). I would expect a plugin which provides dates to a template to provide that date as a datetime object and also provide any date based filters needed to work with the datetime object. There is no need for MkDocs to change anything in that respect.
@waylan I skimmed through the PR and did not find a call to
locale.setlocale. Could this be done and exposed to plugins, so they run in the context of the given locale?
I'm not sure what you mean here. Plugins have access to the config, including config['theme']['locale'] so a plugin can, if it chooses, act on the locale. However, as it is currently implemented, the translation files are provided by the theme, so any translation should be done within the theme templates, not a plugin.
As an example, the only change to the search plugin in the PR is to the JS and all that does is obtain the "no results found" string from the HTML rather than hardcoding it in the JS. The string is now defined and translated in a template.
@waylan thanks! Do you have a rough estimate on when this will be released? Are we talking weeks or months? I'm asking because I have Material v5 in the making which will have some breaking changes and it would be great to push them out at once and not with a v6 some weeks after that.
I have no concrete timetable for this and can't commit to including it in a specific release. As it stands, the PR needs some more work: the readthedocs theme needs updated and the whole thing needs documented. I'm not sure when I'll have the time to get to it. In fact I haven't worked on MkDocs in months (aside from reviewing PRs by others). So if someone else completed the PR, it could get merged sooner, but the next release still has some other blockers so it will likely be a while. In other words, I wouldn't wait on it if I were you.
@waylan answers my question, thanks!
Update: made a PR for adding totimeago jinja2 filter to mkdocs-git-revision-date-plugin, pending review
@timvink pretty cool. Is it possible to format a date with a locale similar to strftime, like for example November 28, 2019?
timeago only has basic localization (see example for en).
Your remark made me think: dates don't require much translation. Then I found babel:
from datetime import date
from babel.dates import format_date
d = date(2007, 4, 1)
format_date(d, format='long', locale='en')
#> 'April 1, 2007'
I'll contribute a PR with a formatdate jinja2 filter to mkdocs-git-revision-date-plugin as well. Once it's merged I can come back here. We'll get there eventually!
Update: mkdocs-git-revision-date-plugin v.02 is now published on PyPi which enables the option of having the date as a datetime instead of str.
I'm currently writing my own mkdocs plugin in order to provide some jinja2 date filters (mkdocs-date-filters-plugin), because babel and timeago are dependencies that shouldn't be in mkdocs-git-revision-date-plugin. That way I can also make sure that the plugin uses theme.language or the future theme.locale as the default locale.
Then using all that in mkdocs-material should be relatively easy:
# mkdocs.yml
plugins:
- git-revision-date:
as_datetime: True
- date-filters
And in base.html, including a nice fall back to YYYY-MM-DD if you don't want to use date-filters:
{% if todateformat is defined %}
{{ page.meta.revision_date | todateformat }}
{% else %}
{{ page.meta.revision_date }}
{% endif %}
I tested this, but jinja throws an error if you don't have the new mkdocs-date-filters-plugin installed:
jinja2.exceptions.TemplateAssertionError: no filter named 'todateformat'
There's an open issue for this behaviour in jinja: (https://github.com/pallets/jinja/issues/842).
I'll need to think about a workaround, or take up the challenge of providing a PR to jinja first.
To be continued :)
Thanks for sharing your progress. I hope that in the end the configuration for this will not be too complicated with multiple possible scenarios that all need to be handled. There’s a reasonable amount of non tech-savvy people using this project.
As I understand there would be four cases that need to be addressed:
as_datetime: trueas_datetime: falseThat’s a lot of potential for breakage. Could we improve on the DX here?
Yes you're right. I didn't even think of the "both plugins set + as_datetime: false" case. Setup is too involved, implementation in mkdocs-material is not clean, and indeed too much potential for breakage.
Thought about it some more and I have a new idea: Fork and create a new plugin mkdocs-git-revision-date-localized-plugin that just makes the localized git revision dates available as normal jinja variables.
Usage:
# mkdocs.yml
plugins:
- git-revision-date-localized:
Implementation:
{% if git_revision_date_localized is defined %}
# ...
{{ lang.t('last.update') }}: {{ git_revision_date_localized }}
{% endif %}
(and we could also support the YYYY-MM-DD version of git_revision_date, prioritizing the localizated version over the normal one).
Should solve all the problems :)
Yes, that sounds like a reasonable plan! So the format is automatically handled by the plugin according to the selected locale. How is the locale determined? theme.lang? Later it's possible to use mkdocs.locale, but not for now I guess.
I published timvink/mkdocs-git-revision-date-localized-plugin this morning. It supports theme.language as well as the future mkdocs.locale.
I just opened a PR to add support for it. I included documentation & the translations I could find on google translate. Would appreciate a review!
Update: screenshot:

Thanks for all the support on this issue @squidfunk. I realize now even more how much effort has gone into mkdocs-material. Thanks for all your work and the awesome theme! Glad I could contribute back a little bit.
Thanks for your contributions! Pleasure to work with you. The changes were just released with 4.6.0.
Hey @timvink, I tried it out but got:
Exception in callback <bound method LiveReloadHandler.poll_tasks of <class 'livereload.handlers.LiveReloadHandler'>>
Traceback (most recent call last):
File "/home/gitpod/.pyenv/versions/3.7.4/lib/python3.7/site-packages/tornado/ioloop.py", line 907, in _run
return self.callback()
File "/workspace/.pip-modules/lib/python3.7/site-packages/livereload/handlers.py", line 69, in poll_tasks
filepath, delay = cls.watcher.examine()
File "/workspace/.pip-modules/lib/python3.7/site-packages/livereload/watcher.py", line 105, in examine
func()
File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocs/commands/serve.py", line 107, in builder
site_dir=site_dir
File "/workspace/.pip-modules/lib/python3.7/site-packages/mkdocs/config/base.py", line 210, in load_config
"Aborted with {0} Configuration Errors!".format(len(errors))
mkdocs.exceptions.ConfigurationError: Aborted with 1 Configuration Errors!
Any idea why? I really want to use it.
mkdocs.yml:
site_name: RDIL Web Docs
theme:
name: 'material'
palette:
primary: 'cyan'
accent: 'cyan'
feature:
tabs: false
favicon: /favicon.ico
logo: assets/34555510.png
repo_name: 'rdilweb/docs'
repo_url: 'https://github.com/rdilweb/docs'
markdown_extensions:
- markdown.extensions.admonition
- markdown.extensions.codehilite:
guess_lang: false
- markdown.extensions.def_list
- markdown.extensions.footnotes
- markdown.extensions.meta
- markdown.extensions.toc:
permalink: true
- pymdownx.arithmatex
- pymdownx.betterem:
smart_enable: all
- pymdownx.caret
- pymdownx.critic
- pymdownx.details
- pymdownx.emoji:
emoji_generator: !!python/name:pymdownx.emoji.to_svg
- pymdownx.inlinehilite
- pymdownx.keys
- pymdownx.magiclink
- pymdownx.mark
- pymdownx.smartsymbols
- pymdownx.superfences
- pymdownx.tasklist:
custom_checkbox: true
- pymdownx.tilde
- git-revision-date-localized:
type: timeago
site_description: Documentation for RDIL's services and libraries.
site_url: https://docs.rdil.rocks
site_author: Reece Dunham
copyright: Copyright (©) Reece Dunham 2019-present
remote_branch: master
extra:
social:
- type: 'github'
link: 'https://github.com/rdilweb'
- type: 'twitter'
link: 'https://twitter.com/rdil_pickle'
nav:
- Home: index.md
- API: api.md
- Libraries:
- area4: libraries/area4.md
- filehandlers: libraries/filehandlers.md
- intutils: libraries/intutils.md
- lcpy: libraries/lcpy.md
- LiquidBT:
- Introduction: libraries/liquidbt/intro.md
- "Getting Started": libraries/liquidbt/getting-started.md
- Plugins: libraries/liquidbt/plugins.md
- "Code of Conduct": CODE_OF_CONDUCT.md
- "Docs License": LICENSE.md
Hi @RDIL
Happy to hear you'd like to use it!
You have an error in your config, as you added a plugin under markdown-extensions. Instead, add a new section with:
plugins:
- git-revision-date-localized
type: timeago
and if you use search, you need to explictly enable it under plugins as well, i.e.:
plugins:
- search
- git-revision-date-localized
type: timeago
If you have any issues with the plugin you can open an issue at mkdocs-git-revision-date-localized-plugin
Ohhh thanks @timvink, didn't notice that. 😄
Most helpful comment
Hi @RDIL
Happy to hear you'd like to use it!
You have an error in your config, as you added a plugin under
markdown-extensions. Instead, add a new section with:and if you use search, you need to explictly enable it under plugins as well, i.e.:
If you have any issues with the plugin you can open an issue at mkdocs-git-revision-date-localized-plugin