Language switcher in menu

I’m trying to set up a language switcher that fulfils these requirements:

  • the order of the languages should be permanent
  • if there isn’t a translation for that piece of content in the alternate language the button should be disabled or show the result of the Lang.Merge

So far, I came up with this:

{{ if .IsHome }}
	<li><a href="/pt" class="{{- if eq (string .Lang) "pt" -}}active{{- end -}}">Portuguese</a></li>
	<li><a href="/en" class="{{- if eq (string .Lang) "en" -}}active{{- end -}}">English</a></li>
{{ else }}
<li><a href="/pt{{ .Permalink | relURL }}" class="{{- if eq (string .Lang) "pt" -}}active{{- end -}}">Portuguese</a></li>
<li><a href="/en{{ .Permalink | relURL }}" class="{{- if eq (string .Lang) "en" -}}active{{- end -}}">English</a></li>
{{ end }}

But of course, this breaks when there isn’t a translation and is too hard coded. I also tried to range through the translations, but that had two problems:

  • the order of languages would change
  • if there wasn’t an available translation, it would only show one button.

I’m a bit lost as to how to cycle through all the available languages and set the href appropriately.

Is there something I’m missing?

Not sure if it answers your question but, this is what I am doing in my work-in-progress site.

This assumes two languages. It ranges through the translations of the page it’s on, and shows the other one. If there is no translation, it gives a link to the root depending on which language the site is in. In this case, the site is two domains, but in the case a language is in a subfolder, just hard-code the href accordingly.

Side note: I’m using the “bulma” css lib this time around, and while I mostly like it, the way it uses color, is to assign a color to a class with some meaning, like is-primary, is-info, is-danger etc. The color I selected happens to be called is-danger but, it’s semantically meaningless, so it can be ignored. (I need to make some color classes that simply are what they are).

1 Like

Thanks @RickCogley it helped ! Here’s how the final code turned out:

{{ if .Site.IsMultiLingual }}
	{{ range .Site.Languages }}
	{{ if eq . $.Site.Language }}
		<li><a href="#" class="active language">{{ .LanguageName }}</a></li>
	{{ else }}
		{{ range $.Translations }}
		<li><a href="{{ .Permalink }}" class="">{{ .Language.LanguageName }}</a></li>
		{{ end }}
	{{ end }}
	{{ end }}
{{ end }}

I’m not sure how it would work for sites with 3 or more languages, but in this use case it seems to do the trick.

2 Likes

Here is one example (home page only):

This does not take any “lang merge” into account, though. But it should be stable.

1 Like

I do it this way:

6 Likes

Just wanted to say thank you for these answers. I wanted a flag based switcher, so I ended up with something like this code below. I’m not sure if using emoji like that is recommended, or if I should use an SVG or other image(?):

  {{ if .IsTranslated }}
    {{ range .Translations }}
      {{ if eq .Site.Language.Lang "en" }}
    <li><a title="English" href="{{ .RelPermalink }}">&#x1F1EC;&#x1F1E7;</a></li>
      {{ else }}
    <li><a title="Norsk" href="{{ .RelPermalink }}">&#x1F1F3;&#x1F1F4;</a></li>
      {{ end }}
    {{ end }}
  {{ else }}
    {{ if eq .Site.Language.Lang "no" }}
    <li><a title="English" href="/en">&#x1F1EC;&#x1F1E7;</a></li>
    {{ else }}
    <li><a title="Norsk" href="/">&#x1F1F3;&#x1F1F4;</a></li>
    {{ end }}
  {{ end }}
</ul>

(Also not sure if re-opening old threads like this is considered good or bad … :thinking: :innocent:)

1 Like

generally, new support questions should get their own thread. But yours is more adding to the possibilities. There has been some discussion about using flags for this elsewhere in the forum; it could be considered problematic since flags are nation-based whereas languages are not.

@flips i saw your code, but you had to hard code language cases.

In the spirit (or did I stole it here, can’t remember :-)) of @martignoni example this is what I have for my multilingual site. The partial is universal. I just have to add some entries to config.toml


{{ $siteLanguages := site.Languages}}
{{ $pageLang := .Page.Lang}}
{{- range .Page.AllTranslations }}
    {{ $translation := . }}
    {{- range sort $siteLanguages "Weight" "asc" }}
        {{- if eq $translation.Lang .Lang }}
            {{ if eq $pageLang .Lang}}
                <a class="flagselect" href="{{ $translation.Permalink | relURL }}">{{ .Params.languageNameShort }}{{ .Params.languageFlag }}</a>
            {{ else }}
                <a class="flagnoselect" href="{{ $translation.Permalink | relURL }}">{{ .Params.languageNameShort }}{{ .Params.languageFlag }}</a>
            {{ end }}
        {{- end }}
    {{- end }}
{{- end }}

and on config.toml I have a language subsection for each language

[languages]
    [languages.fr]
        languageName = "Français"
        languageNameShort = "fr"
        languageFlag = "🇫🇷"
        weight = 1
    [languages.en]
        languageName = "English"
        languageNameShort = "en"
        languageFlag = "🇬🇧"
        weight = 3
/* Flags navigation */
.flagselect {
  border: 1px solid #333333;
  padding: 0px;
  margin: 0px;
  font-weight: bold;
  color: black;
  font-size: 90%;
}
.flagnoselect {
  padding: 0px;
  margin: 0px;
  color: #333333;
  font-size: 90%;
}

3 Likes

A post was split to a new topic: How can I switch the language of the current page

Here is my take on a language switcher. I put some work in to getting proper markup and attributes, setting rel as alternative and setting hreflang etc.

<h2 class="visually-hidden">{{ i18n "lang_select_title" }}</h2>
<nav class="language-selector layout__language-selector">
<ul class="navbar">
{{ if .IsTranslated -}}
{{ range .Translations }}
<li><a rel="alternate" href="{{ .RelPermalink }}" hreflang="{{ .Lang }}" lang="{{ .Lang }}">{{ .Language.LanguageName }}</a></li>
{{ end -}}
{{ else -}}
{{ range .Site.Languages -}}
{{ if ne $.Site.Language.Lang .Lang }}
<li><a rel="alternate" href="{{ .Lang | relURL }}" hreflang="{{ .Lang }}" lang="{{ .Lang }}">{{ .LanguageName }}</a></li>
{{ end -}}
{{ end -}}
{{ end -}}
</ul>
</nav>

This switcher will switch to a translated version of the page if it exist and the front page if it doesn’t.

Wrote about it at https://xdeb.org/post/2018/04/05/go-multilingual-with-hugo/

1 Like

I have inserted the code at layouts/partials/language-selector.html

In config.

This is my main-menu.html

<div id="main-menu" class="main-menu">
  <ul>
    {{ $currentPage := . }}
    {{ range .Site.Menus.main }}
    <li class="menu-item-{{ .Name | lower }}{{ if $currentPage.IsMenuCurrent "main" . }} active{{ end }}">
      <a href="{{.URL}}">
        {{ .Pre }}
        <span>{{ .Name }}</span>
      </a>
    </li>
    {{end}}
  </ul>
</div>

what I have prepared so far is:

  1. setting names for all folders for both languages in the menu bar
  2. moved content to /en/ and /de/

how can I create the link in the menu?
If I create a menu entry like this it jumps to the defined URL instead of only translating

[[languages.en.menu.main]]
name = "DE"
url = "/"
weight = 6

Do NOT double post.

I have moved your post from the other topic here. Please keep this support request in one place.