How to `ExecuteAsTemplate` a global resource per language

Am I right in the assumption that there is currently no way to generate a global, say JS, resource that differs per language?[1]

Because

  • Hugo’s asset pipeline around global resources is not meant to produce output that differs per page; instead, everything gets aggressively cached, which means a template under assets/ is built only for the first (default) language and recycled afterwards.
  • Global resources can only be loaded from the assets/ dir, thus we can’t resort to a regular layout file – only resources can be fed to js.Build.
  • Page resources are also not what we’re looking for since the resource would need to exist in every page bundle (but we want to use a global resource).

I had also no success with trying to duplicate the global resource for every language and suffixing it with the respective language identifier.

Any plans on lifting this limitation?


  1. The actual issue this came up with is found here. ↩︎

I’m not aware of any limitation in this area, but perhaps I don’t understand your question.

assets/
├── js/
│   ├── de/
│   │   └── greeting.js
│   ├── en/
│   │   └── greeting.js
│   ├── shared/
│   │   └── foo.js
│   ├── main.de.js
│   └── main.en.js
└── jsconfig.json

Then stick this wherever…

{{ with resources.Get (printf "js/main.%s.js" .Language.Lang) }}
  {{ if eq hugo.Environment "development" }}
    {{ with . | js.Build }}
      <script src="{{ .RelPermalink }}"></script>
    {{ end }}
  {{ else }}
    {{ $opts := dict "minify" true }}
    {{ with . | js.Build $opts | fingerprint }}
      <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script>
    {{ end }}
  {{ end }}
{{ end }}

Here’s a working example. Open the browser console and switch back and forth between the two languages.

git clone --single-branch -b hugo-forum-topic-46212 https://github.com/jmooring/hugo-testing hugo-forum-topic-46212
cd hugo-forum-topic-46212
hugo server

The public directory will look like this:

public/
├── de/
│   └── index.html
├── en/
│   └── index.html
├── js/
│   ├── main.de.552aa6f469ae3e35c2fdc430f23828d273288abba92a5041e4204a807853cdcd.js
│   └── main.en.f72224f44803232d5645520a334b1aef36fd75040381979ae1d2355496639ab2.js
├── favicon.ico
└── index.html
1 Like

Your answers are awesome, as always—Thanks a lot!

Initially I thought language-suffixed assets wouldn’t be acceptable for my use case since I would need to know all the languages in advance, i.e. create the assets by hand.

Now I realized that I can accomplish what I want indirectly with

  • a sentinel like REPLACE-ME-WITH-LANG-PREFIX in assets/js/flexsearch.js

  • template code à la

    {{- $jsPath := "" -}}
    {{- if site.LanguagePrefix -}}
      {{- $jsPath = printf "js/flexsearch.%s.js" site.Language.Lang -}}
    {{- else -}}
      {{- $jsPath = "js/flexsearch.js" -}}
    {{- end -}}
    {{-
      os.ReadFile "/assets/js/flexsearch.js" |
        replaceRE "REPLACE-ME-WITH-LANG-PREFIX" site.LanguagePrefix |
        resources.FromString $jsPath |
        resources.ExecuteAsTemplate $jsPath .
    -}}
    

This works regardless of whether defaultContentLanguageInSubdir is true or not.

Since the above is quite an unintuitive way (one might call it “workaround”) to convince Hugo to cache an asset file per language instead of per whole site, I wonder:

Are there any plans on allowing more control over assets resource caching behaviour? So I could put the lang-specific template logic directly in the asset file instead of the template that calls resources.ExecuteAsTemplate on it?

I think this would be a bit easier…

{{ with resources.Get "js/flexsearch.js" }}
  {{ with resources.ExecuteAsTemplate (printf "js/flexsearch.%s.js" $.Language.Lang) $ . }}
    <script src="{{ .RelPermalink }}"></script>
  {{ end }}
{{ end }}

assets/js/flexsearch.js

console.log({{ site.LanguagePrefix}} + 'or' + {{ whatever else you want to do}});
1 Like

Damn, this is almost what I tried first, but I was muddled enough to not vary the target path for the resource created by ExecuteAsTemplate. Only the english version was generated (with a long hash in the filename), so I (falsely) assumed that it would get executed only once and used from cache for subsequent langs and there would nothing I could do about it. It was indeed executed only once (or at least only a single file was generated instead of one per language), but simply because I’m a fool.

Thanks a million! :heart:

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.