How can I make my WordPress site show a certain “<html lang=>” tag without changing the frontend language (i.e. menus, buttons, and other stuff)? So, I’m not talking about picking a different language for the back-end user (or admin for that matter) – but about changing the language code shown in the page’s source.
Table Of Contents (T.O.C.):
- Introduction
- The problem
- My custom code solution
- Multilingual sites using Polylang
4.1. Custom country flags (optional)
4.2. Editing the Polylang language codes
4.2.1. What really worked in my case - Conclusion and SEO concerns
(Switzerland, Belgium etc)
1. Introduction
Don’t know about others, but this is a problem for us in the poor ex Yugoslav countries. Bosnia, Croatia, Montenegro, and Serbia all use the same language, but they call it by different names (it used to be just “Serbocroatian” before it all went to hell) – Bosnian, Croatian, Montenegrin, and Serbian – with different matching html language tags.
To make the matters worse, the litterate people used to read and write using either Cyrillic or Latin script (my name in both: Реља / Relja ). However, because of nationalism, my country (Serbia) now insists on only Cyrillic being the official alphabet. Latin script is by far most widely used here for writing (and, thus, reading what’s written), and it is a lot more practical to use with tech. related stuff.
Unfortunately, WordPress official translation team sticks to this technicality, ignoring the common sense! So, in order to set my site to a “Serbian” language tag, it must be in Cyrillic (see below for more details). And, there is no way to set a site to Serbocroatian – that language is officially treated worse than the (ancient) Latin.
I’m not the kind of guy who lets such nonsense get in the way without dealing with it. 🙂
2. The problem
If I want WordPress to show comment and other options in my native, in latin, I have two options:
- Set the site language to Serbian and use some transliteration plugin to rewrite Cyrillic into Latin alphabet (regardless of whether I write articles using Latin script right away).
The downside of this option is that I must install yet another plugin – more plugins, more potential problems. - Set the site (not the backent user!) language to “Croatian”.
The downside of this is that my site will show this language tag:
<!DOCTYPE html>
<html lang="hr">
<head>
I don’t want that! I am from Serbia and my site is, well, technically Serbian (the difference between Croatian and Serbian is like the difference between the UK and US English, very, very minor).
3. My custom code solution
So, I wanted to keep the frontend as “Croatian” to avoid using an extra transliteration plugin, but to have the appropriate language tag. To make it more accurate, I’ve decided to run with the “sh” langauge code which is for “Serbocroatian”. 🙂
To achieve that, I added some custom code to my child theme’s functions.php file:
// BEGIN BikeGremlin frontent langauge tag overriding
/// Change the lang attribute in the HTML tag
function custom_change_html_lang( $output ) {
// Set the desired language code
return 'lang="sh"';
// Replace 'sh' with your desired language code
}
add_filter( 'language_attributes', 'custom_change_html_lang' );
// END BikeGremlin frontent langauge tag overriding
4. Multilingual sites using Polylang
For multilingual sites using (the free version of) Polylang, this is how to fix it.
In a separate article, I explained how to translate footer and widgets with free Polylang.
4.1. Custom country flags (optional)
(Optional) Make a custom language country flag (if you use country flags and wish to change that) as a 16×11 .png file.
Name the file to match your chosen language “Code” – in this case it was “sh.png“.
Upload that image to:
/wp-content/polylang/
In this case that was:
/wp-content/polylang/sh.png
Note:
To get the new flag to be displayed, you must follow this article to the end of chapter 4.2. Briefly: you must edit the language you wish to change the flag for, choose any other flag, click update, then choose the language’s original flag back again (could be a bug, but that is required for the Polylang to load and display the new language flag). Don’t forget to purge any cache (what is website caching and why it matters)!
4.2. Editing the Polylang language codes
This is a general guide part – see chapter 4.2.1. for the nunaces!
Go to your Polylang language settings and click “Edit” for the language you wish to change the country code (or locale) for:
Now you can enter your desired language and locale code, and click update:
Note – You can also edit the “Full name” that will show as a tooltip on hover, in this case it says “Srpskohrvatski”.
Note:
If you want to change the country flag too (as explaind in chapter 4.1), you must now edit the language again, select some random country “Flag” (point 3 in picture 3 above), click Update, then edit again, switch back to your language’s flag (it will still show the old flag in the backend), and click “Update” again.
It sounds more complicated than it is. Basically, Polylang won’t update the frontend flag image until you switch to that flag from some other flag.
What you set for the “Language code” is what your country flag file should be named (en.png for en country code and so on).
4.2.1. What really worked in my case
This won’t work for translating comment and other WordPress-specific stuff!
For that to work, you need to select the langauge that Polylang supports, or make your own “.mo” file for that language. So, what I did in this case was use the “hr” language and locale code, and just add this PHP code to my child theme’s functions.php file (***we must change both the lang, and the hreflang tags when using multilingual sites):
// BEGIN BikeGremlin Polylang language code override
// Customize <html lang> attribute to change 'hr' to 'sh' for Croatian in Polylang
function custom_change_hr_lang_to_sh( $output ) {
// Get the current Polylang language code
$current_lang = pll_current_language();
// Check if the current language is Croatian ('hr')
if ( $current_lang == 'hr' ) {
// Replace 'hr' with 'sh' in the lang attribute
return 'lang="sh"';
}
// Return default language attributes for other languages
return $output;
}
add_filter( 'language_attributes', 'custom_change_hr_lang_to_sh' );
// Modify hreflang to replace 'hr' with 'sh'
function custom_change_hr_hreflang_to_sh( $hreflangs ) {
// Iterate through each hreflang entry
foreach ( $hreflangs as $lang_code => $hreflang_url ) {
// If 'hr' is detected, change it to 'sh'
if ( $lang_code == 'hr' ) {
// Add 'sh' hreflang and remove the original 'hr' entry
$hreflangs['sh'] = str_replace( 'hreflang="hr"', 'hreflang="sh"', $hreflang_url );
unset( $hreflangs['hr'] );
}
}
return $hreflangs;
}
add_filter( 'pll_rel_hreflang_attributes', 'custom_change_hr_hreflang_to_sh' );
// END BikeGremlin Polylang language code override
For this to work with the custom language flag, I had to upload a “hr.png” file instead of the “sh.png” file:
/wp-content/polylang/hr.png
Here is the screenshow of the Polylang settings that work with this (and edit to match your language accordingly):
Dont forget to purge cache!
5. Conclusion and SEO concerns
I hope this aritcle will help us Yugoslavs, and the Swiss and the Belgians. The latter two use several different languages in their countries, so they may face problems when making multilingual sites aimed for the locals.
For example, you may run a bicycle shop in Switzerland, make pages in both Italian, and German (OK, OK, French too… 🙂 ), but want it to be aimed for the local visitors, from Switzerland (not from Italy). To do that, you could set the country code to “CH” (for Switzerland), and locale to “it-CH“. And, if using Polylang, you could set different flags for different languages (make them even custom if you like).
I know – for my website(s) this is a shot in the foot in terms of SEO. It would probably be wiser to stick with the Serbian country code (instead of the Serbocroatian). However, my sites are non-profit and I do use Latin (so not officially “Serbian) – so common sense, technical correctness and not being a nationalist are more important for me. 🙂
Last updated:
Originally published: