Avoid WordPress’ gettext functionality

This is part 23 of my article series 25+ Tutorials on How to boost the performance of your WooCommerce store. Although it's a practical feature, a major reason for the success of Wordpress, and yet PHP's gettext is slow, because with each of your plugins, the number of slow physical file reads increases. Here we talk about avoiding the internationalisation and localisation features of Wordpress to speed up site performance.

In most WordPress installations that I have worked on, most of the processing time that PHP needs to render the HTML is used to translate strings. This is especially true when you use many plugins, which all come with their own .mo files. For each request to a certain page, WordPress looks for the translation files in multiple locations (for example in a child theme and it’s parent theme), if it finally finds the file reads it from disk, loads it into memory then finds the string and returns the translation. And all that is done for each and every call to the _e('Translate me'); and __('Translate this, too.'); functions.

Single language sites

If your WooCommerce online store is available in one single language, you don’t need that feature and should not have WordPress waste your customers time. Instead you want to hardcode text in your desired language.

Let’s create a must use plugin in order to achieve this:

wp-content/mu-plugins/disable-gettext.php
<?php /** Plugin Name: Disable Gettext */ add_filter('override_load_textdomain','__return_true');

By returning true from the override_load_textdomain filter, we will prevent all .mo files from loading.

This turns off the translation feature and you should see your site in English now. If you’re site isn’t in English, then you want to replace all the calls to the gettext functions in your theme files:

Take these two example calls, where one echoes out a translated string and the second returns one:


<?php
_e('This is an example.'); /* this is echoed */
$message = __('Another translated string.'); /* this is returned */

You want to replace it, this way (for example in Spanish):


Esto es un ejemplo.
<?php $message = 'Otra cadena traducida.'; ?>

Once you have done this with all occurrences of these function calls in your theme, you are left with notices, form validation, and other texts coming dynamically from within the plugins you use. For that matter one can hook into a filter, which receives the English string:

wp-content/themes/storefront/functions.php
add_filter('gettext', 'translate_without_gettext', 10, 3); function translate_without_gettext($translation, $text, $domain) { switch ($text) { case 'Cart updated.': return 'Carrito actualizado.'; break; default: return $text; } }

Multilingual sites

Multilingual sites are managed differently. Some people use plugins, others code their own solution. This is why it’s hard to give a one-fits-all solution here.

In case you are using multiple domains, to serve your site for different markets & countries, you could choose to use a different, pre-translated child theme for each domain. One very lightweight way of doing this is to use the WP Theme Test Plugin. You simply enable the Parameter Function and by appending theme $_GET Parameter ?theme=theme-name-es or ?theme=theme-name-fr you preselect the corresponding theme. Since you don’t want your visitors to append a GET parameter, let’s modify the plugin a bit to use a environment variable instead.

We only change this section around line 57:

wp-content/plugins/wp-theme-test/wp-theme-test.php
/** from this: */ if (isset($_GET['theme']) && $this->get_parameter()) { $theme_object = wp_get_theme(esc_html($_GET['theme'])); return $theme_object; } /** to this: */ if (isset($_SERVER['THEME']) && $this->get_parameter()) { $theme_object = wp_get_theme(esc_html($_SERVER['THEME'])); return $theme_object; }

For this to work, all that’s missing is to tell each virtual host, which theme to use. In your Nginx php location block simply add fastcgi_param THEME theme-name-es; or fastcgi_param THEME theme-name-fr;. Relaod Nginx and it should automatically chose the correct theme, based on your domain. A complete location block would look like this:

/etc/nginx/sites-available/domain.es.conf
... location ~ \.php$ { try_files $uri /index.php =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php8.0-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param THEME theme-name-es; include fastcgi_params; }

Et voilá! You now successfully got rid of WordPress’ gettext functions and instead use “hardcoded” language in your themes and plugins. Using an APM (application performance monitor) of your choice should allow you to verify that get text is no longer used and give you important feedback on the actual saving in processing times of your pages.

Continue to part 24 of this tutorial series: Use Cloudflare with proxy caching enabled (work in progress).