What is the best way to make custom language switcher to the site. My problem is that I have a site with two language versions and my custom language switcher is a bit problematic I would say. It doesn’t work in all pages for some reason and in my opinion is it coded in very complicated way. In our site the language versions are changed via url. For example mycompany.fi/ is the main language version and the mycompany.fi/en/ is for the english version of the site. Here is the code how I switch language currently by just changing the url. In the code it checks the url and also if the page has translated_content. After that I put the site_language and other_language to links so by pressing the link it changes the language.
{% if absolute_url is string_containing "/en-us/" %}
{% set site_language = 'en' %}
{% set other_language = 'fi' %}
{% if content.translated_content['fi-fi'] %}
{% set other_language_url = '/' + content.translated_content['fi-fi'].slug %}
{% elif content.translated_content['fi'] %}
{% set other_language_url = '/' + content.translated_content['fi'].slug %}
{% else %}
{% set other_language_url = '#' %}
{% endif %}
{% elif absolute_url is string_containing "/en/" %}
{% set site_language = 'en' %}
{% set other_language = 'fi' %}
{% if content.translated_content['fi-fi'] %}
{% set other_language_url = '/' + content.translated_content['fi-fi'].slug %}
{% elif content.translated_content['fi'] %}
{% set other_language_url = '/' + content.translated_content['fi'].slug %}
{% else %}
{% set other_language_url = '#' %}
{% endif %}
{% else %}
{% set site_language = 'fi' %}
{% set other_language = 'en' %}
{% if content.translated_content['en-us'] %}
{% set other_language_url = '/' + content.translated_content['en-us'].slug %}
{% elif content.translated_content['en'] %}
{% set other_language_url = '/' + content.translated_content['en'].slug %}
{% else %}
{% set other_language_url = '#' %}
{% endif %}
{% endif %}
I’m wondering is there any other way to make this happen because for me this seems very complicated solution. I would like to know if there is some global variable or something what defines the current language used in the page.
Actually my version of the custom language switcher is just a modified version from the post you mentioned. Because our site has a content in language versions (‘en’, ‘en-us’ and ‘fi’) it had to be modified a little bit. And what I would like to know is that is there any quicker or would I say “less code” version of doing this. Because to my eye this is very complicated solution to just change the language of the page.
The company I’m at has six languages to switch between, but just add/remove in the “codes” array as necessary.
This is for a dropdown menu, which displays the current language with the flag of that language (but you can delete that) as the item to hover on to show the dropdown. It then adds as many list items as you have languages to the dropdown, with the appropriate href, language name, and flag generated.
*Edit: was able to cut a line out of this:
{% if content.translated_content|length %}
<ul class="dropdown menu" data-dropdown-menu>
<li>
{% set currLang = locale_name(locale) %}
{% set codes = {'English': 'en', 'Español': 'es', 'Deutsch': 'de', 'Français': 'fr' ,'Italiano': 'it' , 'Nederlands' :'nl'} %}
<a class="lang-select" href="#"><img class="lang-flag" src="[our assets url]/{{codes[currLang]}}-flag.png">{{ currLang }}</a>
<ul class="menu desktop-lang">
{% for key, val in codes.items() %} {% set URL = "/"~content.translated_content[val].slug || val %} <li><a class="lang-option" href="{{ URL }}"><img class="lang-flag" src="[our assets url]/{{val}}-flag.png">{{key}}</a></li> {% endfor %}
</ul>
</li>
</ul>
{% endif %}
Biggest problem with the languages on our site is that we have content on four different language versions (fi, fi_fi, en, en_us) even whe have only two languages (fi, en) on our site. This is because we have lots of content creators and we didn’t inform them at the beginning to use only ‘fi’ and ‘en’ language versions of hubspot. That is the reason why your solution is not working on our site. Also we want that both ‘fi’ and ‘en’ are visible all time in the language switcher even when there is no content in one of the language options. We want that there is both language options in the switcher for example in the case that blog post has only finnish version of the post but not english.
@SuperHolde Ah I see. It seems like you’re only ever using fi or fi_fi, and en or en_us as the language versions, i.e. never both options for one language at a time?
Also it seems like your code above isn’t actually using the site_language and other_language variables (unless you’re using them outside the if statement).
The only operation you’re doing is getting the slug of the translated content and adding that to the other_language_url variable. In which case, you could do:
{# the below grabs the language code for your translated content, whatever it is, and gets the slug for that code, so you don't have to check for specific codes e.g. 'fi-fi'/'fi', 'en-us'/'en' #}{% for key, val in content.translated_content.items() %} {% set other_language_url = '/' + content.translated_content[key].slug %} {# use the other_language_url here, as you can't use a variable set within a for loop outside of that loop #}{% endfor %}
Which can replace both operations you’re doing to set the other_language_url. If you’re not using the site_language and other_language variables outside of your if statement, then the above could replace all of your code.
If you do need the site_language and other_language variables you could try:
{# grab the first 3 characters of the request path, so it will return '/en' for both '/en-us/' or '/en/' #}{% set path = request.path|truncate(3, true, '') %}{% if path is string_containing 'en' %}
{% set site_language = 'en' %}
{% set other_language = 'fi' %}{% else %} {% set site_language = 'fi' %} {% set other_language = 'en' %}{% endif %}{# the below grabs the language code for your translated content, whatever it is, and gets the slug for that code, so you don't have to check for specific codes e.g. 'fi-fi'/'fi', 'en-us'/'en' #}{% for key, val in content.translated_content.items() %} {% set other_language_url = '/' + content.translated_content[key].slug %} {# use the other_language_url here, as you can't use a variable set within a for loop outside of that loop #}{% endfor %}
{% set path = request.path|truncate(3, true, '') %}
{% if path is string_containing 'en' %} {% set site_language = 'en' %}
{% set other_language = 'fi' %}{% else %} {% set site_language = 'fi' %} {% set other_language = 'en' %}{% endif %}{% if content.translated_content %} {% for item in content.translated_content %} {% set other_language_url = "/"~item.slug %} {% endfor %}{% else %} {% set other_language_url = '#' %} {% endif %}
This gets the first 3 characters of the request path i.e. if the path is /en-us/ or /en/ it’ll return ‘/en’ so you don’t have to check for both of those.
You can do the below if you want to sort these alphabetically
{% for item in content.translated_content|sort(False, False, 'language') %}
It then gets the language code for whatever translated content you have, if it exists, and grabs the associated slug so you again don’t have to check for specific codes. You do have to use the other_language_url in the for loop though, can’t use a variable set inside a loop outside of said loop. Just add your list items/whatever you’re using to display your languages there.
You wouldn’t be able to use the logic above though. Start with this and see what item gives you
{% if content.translated_content|length %}
{% for item in content.translated_content|sort(False, False, 'language') %}
{% set date = content_by_id(item.id).publish_date %}
{% if date != '1970-01-01 00:00:00' %} // makes sure the page is published and not in draft, remove if you don't need to test for that
{{ item }}
{% endif %}
{% endfor %}
{% endif %}
@piersgI have the subdomains set up and selected in the translated page I just couldn’t get your previous mark-up to get the URL set in the page settings. I’ll give the above code a try and see what I get.
EDIT - output given is About us nl, id: 40617517899, slug: over-ons
URL on selected option doesn’t change.
I have to admit, I have never tested this, but the code @piersg presented looks sound.
I guess it is time I get a new domain with a different TLD to test things like this
One problem I am seeing in that knowledgebase article that you linked to is that it looks it is mistaking subdomains for top level domains which I will make sure this language gets updated in the doc.
@dennisedson@piersg The default HubSpot language switcher works how my client wants it to but they want to be able to add their own coutry flags and be able to manage the text that displays, for instance. Instead of English - United States they want to show USA plus the flag icon for it.
I can’t see anywhere on the default HS language switcher that allows for that hence me needing to build a custom LS. But with the translated page having a different URL I can’t get the switcher to work.
@ScottD22 Here’s the code for my langauge switcher (with what I put above added in for you), which allows you to change the name displayed and flag. Just make the en.svg (or whatever file format) flag the US flag
<ul class="lang-menu">
{% if content.translated_content|length %}
{% for item in content.translated_content|sort(False, False, 'language') %}
{% if item.language == 'de' %}{% set name = 'Deutsch' %}{% elif item.language == 'en' %}{% set name = 'USA' %}{% elif item.language == 'es' %}{% set name = 'Español' %}{% elif item.language == 'fr' %}{% set name = 'Français' %}{% elif item.language == 'nl' %}{% set name = 'Nederlands' %}{% endif %}
{% set date = content_by_id(item.id).publish_date %}
{% if date != '1970-01-01 00:00:00' %}
{% set url = '' %}
{% if request.domain is string_containing 'us' %}
{% set url = 'www.domain.nl' %}
{% else %}
{% set url = 'www.domain.us' %}
{% endif %}
<li>
<a class="lang-option" href="{{url}}/{{ item.slug }}">
<img class="lang-flag" src="https://f.hubspotusercontent10.net/hubfs/[portal id]/[path to icons]/{{item.language}}.svg" alt="{{name}} flag">
{{name}}
</a>
</li>
{% endif %}
{% endfor %}
{% endif %}
</ul>
Hey @piersg thank you so much for helping me out. I’ve added in the above code and it’s nearly there. I now have the URL switching, but I can’t figure out how to show the current language you are on like in the below code. Any help with that would be much appreciated. Thank you.
{% set currLang = locale_name(locale) %} {% set codes = {‘English’: ‘en’, ‘Español’: ‘es’, ‘Deutsch’: ‘de’, ‘Français’: ‘fr’ ,‘Italiano’: ‘it’ , ‘Nederlands’ :‘nl’} %} <a class=“lang-select” href=“#”><img class=“lang-flag” src=“[our assets url]/{{codes[currLang]}}-flag.png”>{{ currLang }}</a>
If my client starts to add additional languages how would I enable them to add more in the code provided? Obviously this works great with the us / nl domains we have ATM but what if they add German for example? How would I get the URL to switch?
So the way I have set it up is an item in my nav with the flag (added language name for you) of the current language that opens up the full list of languages when clicked (using JS).
// in nav
<ul>
// ...other nav items
{% set currLang = content.language.languageTag %}
{% if content.translated_content|length %}
<li role="menuitem" class="is-dropdown-submenu-parent">
<a class="main-nav-link nav-swipe-link" id="languages"><img class="lang-flag" src="[path to flags]/{{currLang}}.svg">{{locale_name(locale)}}</a>
</li>
{% endif %}
</ul>
Hmmm… off the top of my head the only reason I can think of for the double domain in the url is that your href has a / at the beginning of it, i.e. href=“/{{url}}/{{ item.slug }}” instead of href=“{{url}}/{{ item.slug }}”. Or maybe you need to add the protocol either in the {% set url = 'https://www.domain.us" %} or href=“https://{{url}}/{{ item.slug }}”
@piersgAwesome, you have helped me out massively. If I could upvote this 1000 times I would.
Just on my point above, if my client starts to add additional languages how would I enable them to add more in the code provided? Obviously this works great with the us / nl domains we have ATM but what if they add German for example?
Maybe instead of using the domain and the slug from item you could use the content id from item. This should avoid having to update the if statement with alternatives and will automatically update with new translated pages when they’re published
That won’t work for blog homepages though. This is what I do for switching between blogs (on the blog homepage) if you need that:
{% if content.translated_content|length %}
// ... languages for website pages and blog posts as above
{% elif group.translations %}
// languages for blog home page
{% for item in group.translations|sort(False, False, 'language') %}
{% if item.language == 'de' %}{% set name = 'Deutsch' %}{% elif item.language == 'en' %}{% set name = 'English' %}{% elif item.language == 'es' %}{% set name = 'Español' %}{% elif item.language == 'fr' %}{% set name = 'Français' %}{% elif item.language == 'it' %}{% set name = 'Italiano' %}{% elif item.language == 'nl' %}{% set name = 'Nederlands' %}{% endif %}
<li>
<a class="lang-option" href="{{ item.absolute_url }}">
<img class="lang-flag" src="[path to icons]/{{item.language}}.svg" alt="{{name}} flag">
{{name}}
</a>
</li>
{% endfor %}
{% endif %}