[i18n] Theme translations

Hello people, it’s been almost two years and the situation hasn’t changed so i figured it’s time for a revival of this topic! To me the question is how can we empower themes to empower users while retaining user capability to override any part of the theme?

The topic was originally about theme translations specifically, but there’s a number of other concerns (related to themeing and i18n) i’d like to discuss. I’m willing to try and make patches for the first three problems outlined if other people agree they are actual problems, about the fourth i’m not sure what the best course of action is and would like more feedback.

Problem #1: themes can’t package translation strings

It’s common for a theme to have translatable strings, for example for “next/previous page” buttons, or for the date format. If the theme is not able to provide/query those, it means it’s not really i18n-friendly and the user will have to rewrite parts of the theme to support localization. However, it’s important that the user retains the possibility to use different wording if they so please, and that they can add new translation strings for their own widgets/shortcodes.

Currently, the only way to achieve that is to use the [extra] section from config/theme.toml, because they are properly merged recursively when the build starts. However, it means templates can’t use the trans function, which sort of defeats its purpose. Instead, you have to explicitly call config.extra.translations|get(key=lang)|get(key="myTranslation").

Proposal: i’d like to have some mechanism for translations to inherit from themes but allow site-wide override. The simplest form of that would be supporting a [translations] or [languages] section in theme.toml, although i would see an interest in supporting other translation mechanisms (per-lang locale files using TOML or po)

Problem #2: missing translations cause build to fail

Currently, if a translation is missing in a language, the build will fail. This is a good default setting as it prevents many stupid mistakes. However, it can happen for volunteer-run sites that translations are out of sync. In this case, erroring is not a solution because it will incentivize users to place placeholders in their actual translation strings just to have their site built, at which point missing translations will go unnoticed unless there is a manual review.

Proposal: have a configuration switch to determine how to act on missing translations:

  • error and abort (default for build mode)
  • print a warning a use a placeholder containing the name of the missing key (default for serve mode)
  • print a warning and fallback to the translation in the default_language

Printing a warning during build (but allowing to build) may prove useful to get the stuff translated in the long run.

Problem #3: site/theme inheritence rules are not intuitive

This is a different issue but since we’re talking about site/theme inheritance, it’s worth mentioning here: extending a theme from your site is not as easy as it could be. Having to spell out the theme path in extends is not intuitive. Changing your customized templates in order to try a different theme is in my view an antipattern, because as soon as you start customizing a theme you’re “stuck” and every other theme you want to try (just to get a quick overview, even if your customizations aren’t relevant anymore) takes you several minutes of adjusting your templates just to get the site to build and display anything.

Also very relevant: supporting theme extensions that are not tied to a theme name enables interoperability between theme. So if a single person maintaining several themes, or several theme maintainers want to “standardize” the blocks you can override, it would make it possible to retain customizations across themes.

Proposal: template lookup rules should support a magic string like THEME so you would extends "THEME/templateName.html" without having to spell out the theme name (which may change in the future). Related: it would be nice to be able to print warnings when the site overrides a block which does not exist in the theme.

Problem #4: sites can’t override theme-provided macros

Still unrelated to the original problem, but worth discussing: the only way for a site to override a theme-provided macro is if the macros each live in a separate file (like shortcodes), which creates an “import hell”.

Proposal 1: Reuse HTML shortcodes as site/template-provided macros. It’s already possible to import them one-by-one, but that’s not desirable. A default shortcodes:: would be more handy, although loading it by default in every template might create a resource overhead, especially since some of these shortcodes are only supposed to be called from markdown and will never be used in themes. Alternatively, providing a shortcode function with a reserved keyword for the shortcode name looks like a fair alternative. If supported by the tera templating engine, having a shortcode function which returns the macro itself (shortcode(name="mything")(param1=foo, param2=bar)) would be more convenient as it would not reverse a special keyword in shortcodes.

Proposal 2: Allow to override macros from templates. This can take place on a macro level or on a block level. On a macro level, it appears macros are not properly inherited by the extends directive and in any case tera would prevent it (with Macro `mymacro` is duplicated error):

Reason: Failed to render 'page.html'
Reason: Macro `widgets::theme_macro` not found in template `page.html`

(where theme_macro is defined in the theme’s widgets.html, and the site’s widgets.html extends the theme’s widgets.html)

On a block level (defining a block macro_t in the theme’s widgets and overriding it in the site’s widgets) there’s also some shenanigans:

* Failed to parse "/REDACTED/themes/water/templates/widgets.html"
   --> 138:1
    |
138 | {%- macro t(key) -%}␊
    | ^---
    |
    = unexpected tag; expected an endblock tag (`{% endblock block_name %}` or some content
1 Like