gohugoio / hugoDocs

The source for https://gohugo.io/
Apache License 2.0
1.03k stars 1.47k forks source link

Unclear how i18n (lang.Translate) determines the target language #2619

Closed xlsigned closed 1 month ago

xlsigned commented 1 month ago

When I use {{ i18n "key" }} in a template, there appears to be no way to change/set the target language. E. g. if $page is a translated page (from $.AllTranslations), neither

{{ with $page }}
   {{ i18n "key" }}
{{ end }}

nor

{{ i18n "key" $page }}

has any effect on the target language, while {{ $page.Content }} clearly shows that I have indeed looked up a translated page.

The documentation should state how (or rather when) the language is determined and what the optional parameter [CONTEXT] actually means and if it is at all possible to change the target language within a template.


The scenario is a Multilingual Site where I want language specific pages that are still incomplete to show the content of the default language (or any other language).

For this I'm using a custom frontmatter value in the incomplete page which triggers the fallback when set, i. e. the template looks up the already completed/translated (default) $page and calls {{ $page.Content }} instead of {{ .Content }}.

jmooring commented 1 month ago

Thanks for logging this.

I'll add an admonition to https://gohugo.io/functions/lang/translate/ making it clear that the target language (a) is determined by Page.Language.Lang and (b) cannot be changed/specified when calling lang.Translate (aliases i18n and T).

I'll also add a section heading named "Context" to describe usage of the optional second argument. There are some examples of this on the page already, but they should be in own their section to make it clearer.

xlsigned commented 1 month ago

The issue here is mainly the word CONTEXT.

It's not a good choice for the optional parameter name. If it truly were the template context like when you call a partial with context and you pass a page as CONTEXT which has a different Language.Lang, it should use that as target language, but it doesn't.

So neither CONTEXT nor Page.Language.Lang is a good name or term for what is actually determining the target language of the i18n function. To me it seems like the language is determined once when hugo starts rendering the pages of a Site in Sites and stays the same for all pages of that Site. And this is really odd or at least quite unexpected behavior.

Having a site specific i18n (Site.Language.Translate) function/method like you were trying to implement in your PR is IMHO a workaround for this oddly behaving original function, but probably the only thing you can do, when you do not want to break existing sites by changing the original ì18n to actually honor the current page context.

As for the optional parameter it should be named [NUMBER] or [COUNT] or ... Something like this.

jmooring commented 1 month ago

We are not changing the name of the second argument. CONTEXT may be a number or a map, as described in the examples:

i18n/en.toml

[age]
  one = '{{ .name }} is {{ .count }} year old.'
  other = '{{ .name }} is {{ .count }} years old.'

template

{{ T "age" (dict "name" "Will" "count" 1) }} → Will is 1 year old.
{{ T "age" (dict "name" "John" "count" 3) }} → John is 3 years old.

The CONTEXT argument is in no way related to the current value of the dot in a template. This documentation has been in place for a very long time, and this is the first time someone has been confused by the argument name. We can revisit if the issue comes up again.

xlsigned commented 1 month ago

Honestly, this is rather surprising. I'd thought to the average hugo user CONTEXT would mean context aka the dot. But, if improving the documentation requires a higher number of confused user reports, so be it.