Common pitfalls and challenges with the translation plugin Weglot on the way to more traffic and visitors
Experience report after two years: Read what customizations we have made to our WordPress Website and the Weglot Plugin.
Weglot translates your WordPress website into more than 100 other languages within seconds. What sounds like magic at first, has the potential to save an incredible amount of time. Instead of having to translate sentence by sentence or paragraph by paragraph, Weglot combines different translation engines like Google Translate and DeepL to deliver texts that don’t look like they were translated by a computer. The translation is so fast that it is done directly when the web page is opened the first time.
If you want to know more about how Weglot has helped us increase our traffic and visitors, I recommend you take a look at my blog article: Weglot on Seatable.io: our experience with the translation plugin for WordPress.
This text, however, will focus specifically on the technical challenges we have had to overcome with Weglot over the past two years.
I hope that if you have the same or similar problems, you will stumble across this article and I may be able to present you with a solution. The good news is that thanks to the good documentation and helpful support from Weglot, we have been able to solve all the problems so far.
The following solutions are all used on the website https://seatable.io, which we write in German and let Weglot translate automatically to English, French, Spanish, and Russian. As WordPress theme we use Enfold-Child and as web server we use nginx with fastcgi cache.
Auto-switcher and caching
The problem
Weglot offers the function that visitors are automatically redirected to the (browser)-language that suits them the first time they visit the home page. However, you should not use this function if you cache your website. Thanks to the cache, the first visitor sets the language to which all subsequent website visitors will be redirected.
Our solution
Weglot appears to be compatible with various caching plugins in wordpress. With nginx fastcgi cache, this auto-redirect defined does not work. You don’t want under any circumstances that by an unfortunate coincidence all website visitors are redirected to the Russian version.
That’s why we disabled the auto-redirect in the Weglot account and built a function compatible with fastcgi caching ourselves. Thanks to functions.php this function is loaded when the start page is opened.
(function() { if (!document.querySelectorAll) {
return;
} var nullStorage = {};
nullStorage.getItem = function (name) {return null};
nullStorage.setItem = function (name, value) {}; var localStorage = window.localStorage || nullStorage;
var sessionStorage = window.sessionStorage || nullStorage; document.addEventListener("DOMContentLoaded", function(event) {
document.querySelectorAll('.country-selector li a').forEach(function(a) {
a.addEventListener("click", function (event) {
localStorage.setItem('langSelect', a.parentElement.dataset.codeLanguage);
});
})
});/* break if the url is not the main page or an url parameters exist */
if (window.location.pathname !== "/" || window.location.pathname.indexOf('?') !== -1) {
return;
} var userLang = navigator.language || navigator.userLanguage;
var browserLang = userLang.split('-')[0].toLowerCase(); if (!browserLang || browserLang === "de") {
return;
} var langSelect = localStorage.getItem('langSelect');
var langRedirect = sessionStorage.getItem('langRedirect'); if (langRedirect && !langSelect) {
return;
} sessionStorage.setItem('langRedirect', browserLang); var urlLang;
switch (browserLang) {
case 'en':
case 'fr':
case 'ru':
case 'es':
urlLang = browserLang;
break;
default:
urlLang = 'en';
break;
} if (langSelect) {
urlLang = langSelect;
} if (urlLang === 'de') {
return;
} window.location.replace('https://seatable.io/' + urlLang + '/');})();
Link boxes ignore the current language selection
The problem
Weglot normally detects the current language and ensures that links on the web page are updated to include the current language. Thus, https://seatable.io/blog becomes https://seatable.io/en/blog if the visitor is currently visiting the English version of the website. However, the Enfold-Child theme we use also offers link boxes, which we use on our help page, for example. These are not recognized by Weglot, and the links always lead to the original German language.
The problem arises because these link boxes are not controlled by the normal <a href> tag, but instead use a “data-link-column-url”.
<div class="flex_column ..." data-link-column-url="https://seatable.io/en/docs/">
<a href="https://seatable.io/docs/">...</a>
</div>
Our solution
Through a separate function, these data-link-column-urls can also be registered for Weglot. As soon as one inserts the following code in the functions.php, the links of the link boxes are adapted reliably.
/**
* data-link-column-url ignoriert weglot
*
* https://developers.weglot.com/wordpress/use-cases/linkedin-share-post-translate-oembed-wp-url
*/
function seatable_weglot_localise_data_link_url($html)
{
$url = get_site_url();
$search = "data-link-column-url=\"$url/";
$current_language = weglot_get_current_language();
$default_language = weglot_get_original_language();
if ($current_language !== $default_language) {
$html = str_replace($search, "data-link-column-url=\"$url/$current_language/", $html);
}
return $html;
}
add_filter('weglot_html_treat_page', 'seatable_weglot_localise_data_link_url');
Anchor texts jump to the wrong place
The problem
In our user guide https://seatable.io/docs/handbuch/ we increasingly use links with anchor texts. Unfortunately, these links do not work in languages translated by Weglot because the headline that the anchor text points to is translated, but the link remains the same.
Here is an example:
The following link <a href=”/docs/handbuch/#deutsche-ueberschrift”> has an /en/ added to it accordingly by Weglot. Unfortunately, however, the target of the anchor text has been translated and is now no longer “German Headline” but “German Headline”.
Our solution
This problem can be solved without programming by adding an additional tag like id=”deutsche-ueberschrift” to the respective headlines. id-tags are not translated by Weglot and the anchor texts work again.
Hide language switcher on scroll down
The problem
By default, Weglot displays a language switcher at the bottom right of the screen. Unfortunately, on mobile devices with small resolutions, this toggle covered the navigation points in the footer when scrolling to the bottom of the page.
Our solution
We built a small JavaScript function that makes the language switcher disappear when you scroll down a bit. So, you can now always click on all links in the footer on mobile devices. As soon as you scroll up again, the language switcher appears again.
// in functions.php: hide weglot dropdown on scrolldown
function hide_weglot()
{
wp_enqueue_script('customjs', '/wp-content/themes/enfold-child/hideWeglotDropdown.js', array('jquery'), 2, true);
}
add_action('wp_enqueue_scripts', 'hide_weglot', 100);
The code below has to be added to the functions.php of WordPress and loads the following JavaScript.
jQuery(window).scroll(function(){
var weglotdropdown = jQuery(".weglot-dropdown");
scroll = jQuery(window).scrollTop();
if (scroll >= 1000) weglotdropdown.fadeOut();
else weglotdropdown.fadeIn();
});
The original language cannot be the fallback language
The problem
We write the website https://seatable.io in German. Thus, for Weglot, German is also the fallback language for all visitors for whom none of the offered languages is suitable. However, we would prefer to always use English as the fallback language. Furthermore, on some pages, the hreflang-tags were not always reliably implemented. Here we wanted to have more control.
Our solution
Thanks to the following code in functions.php we make sure that all translations and default tags are always set correctly. In addition, we prevent the Chrome browser from offering an automatic translation from the browser.
Crawler to prevent Weglot API errors
The problem
Occasionally, we need to clear the entire cache at once after a code or style adjustment to our website. This leads to many pages having to be re-cached at the same time and thus retrieved by Weglot. Sporadically, we had the problem that the API of Weglot then did not translate the web pages and thus untranslated pages ended up in the cache. Since all further accesses were served from the cache, it looked to the visitors as if some parts of the website were simply not translated.
These incorrect translations could be recognized if the following tag occurs at the end of the source code:
<!--Weglot error API : "Exception too many calls"-->
Our solution
In order to automatically detect and fix such incorrect translations, we have written a small website crawler. This retrieves the complete sitemap once an hour and then rattles off all pages. If the page is not already cached, it generates the page and caches it. If the API error is found, this page is deleted from the cache and called again.
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 'On');$sitemaps = [
'https://seatable.io/sitemap_index.xml',
];$crawler = new BJ_Crawler($sitemaps);
$crawler->run();
class BJ_Crawler
{
protected $_sitemaps = null;
protected $_urls = null; public function __construct($sitemaps = null)
{
$this->_sitemaps = [];
$this->_urls = []; if (! is_null($sitemaps)) {
if (! is_array($sitemaps)) {
$sitemaps = [ $sitemaps ];
} foreach ($sitemaps as $sitemap) {
$this->add_sitemap($sitemap);
}
}
} public function add_sitemap($sitemapurl)
{
if (in_array($sitemapurl, $this->_sitemaps)) {
return;
} $this->_sitemaps[] = $sitemapurl; $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $sitemapurl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
$http_return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ('200' != $http_return_code) {
return false;
} $xml = new SimpleXMLElement($content, LIBXML_NOBLANKS); if (! $xml) {
return false;
} switch ($xml->getName()) {
case 'sitemapindex':
foreach ($xml->sitemap as $sitemap) {
$this->add_sitemap(reset($sitemap->loc));
}
break; case 'urlset':
foreach ($xml->url as $url) {
$this->add_url(reset($url->loc));
}
break; default:
break;
}
} public function add_url($url)
{
if (! in_array($url, $this->_urls)) {
$this->_urls[] = $url;
$url_parse = parse_url($url);
$this->_urls[] = $url_parse['scheme'] ."://". $url_parse['host'] ."/en". $url_parse['path'];
$this->_urls[] = $url_parse['scheme'] ."://". $url_parse['host'] ."/fr". $url_parse['path'];
$this->_urls[] = $url_parse['scheme'] ."://". $url_parse['host'] ."/es". $url_parse['path'];
$this->_urls[] = $url_parse['scheme'] ."://". $url_parse['host'] ."/ru". $url_parse['path'];
}
} public function run()
{
$i = 0;
require_once 'vendor/autoload.php';
$httpClient = new \GuzzleHttp\Client(); $purged_urls = [];
foreach ($this->_urls as $url) { $response = $httpClient->get($url);
$htmlString = (string) $response->getBody();
$cacheStatus = $response->getHeaderLine('X-FastCGI-Cache'); if ($cacheStatus === "HIT" and strpos($htmlString, 'Weglot error API') !== false) { // <!--Weglot error API : "Exception too many calls"--> was found.
echo " - PURGE!";
$purged_urls[] = $url;
$url_parse = parse_url($url);
$purge_url = $url_parse['scheme'] ."://". $url_parse['host'] ."/purge". $url_parse['path'];
$response = $httpClient->get($purge_url);
usleep(500000); // 0.5 sec.
$response = $httpClient->get($url);
} elseif ($cacheStatus === "HIT") {
usleep(1000);
} elseif ($cacheStatus === "MISS" or $cacheStatus === "EXPIRED") {
// usleep(1*1000000); // 1 sec.
}
echo "\n";
}
}
}
With Weglot, multilingual websites are a breeze.
We have been using Weglot for two years now, and we are still very convinced. Weglot is a great tool to make your website international in a very short time. All technical problems could be solved thanks to the support and the good documentation.
Try out Weglot. You will be amazed.