PHP: Translations with gettext not working in Apache mod_php but works on command line (caused by mod_perl)

Written by - 2 comments

Published on - Listed in Apache PHP Linux Coding


A very strange problem occurred recently on a Debian 10 (Buster, current stable release): PHP translations using gettext did not work. And to our big surprise this wasn't caused by a wrong usage of gettext or wrong translations files (po and mo), but rather by the Apache module mod_perl. But let's get into the details.

A simple PHP translation using gettext

Note: This article will not explain how po and mo files work in combination with gettext. For a good introduction visit this tutorial.

The following file translate.php was created with the following content:

$ cat translate.php
<?php
// Set locale
putenv("LC_ALL=de_CH.UTF-8");
setlocale(LC_ALL, 'de_CH.UTF-8');

// Select translation file
bindtextdomain("homepage", "./locale");
textdomain("homepage");

$results = gettext("Dedicated Hosting Description");
if ($results === "Dedicated Hosting Description") {
    echo "Original English was returned. Something wrong\n";
} else {
    echo $results;
}

?>

A few explanations concerning this code:

  • The environment variable LC_ALL and the locale of this PHP script are manually set to "de_CH" (language: German, country: Switzerland)
  • The bindtextdomain function defines where to load the translation file name (homepage) and path (here a sub-directory called locale)
  • The textdomain function defines the domain (easier: translation file name) as homepage
  • This means gettext will look for a translation file in the following path: ./locale/de_CH.UTF-8/LC_MESSAGES/homepage.mo
  • The English string "Dedicated Hosting Description" is looked up in the translation file
  • If gettext finds a translation, the translated string will be saved as $result variable - however if $result is still the same English text, return an error

gettext translation doesn't seem to work

But as soon as translate.php was opened in a browser, the text was not translated:

At this point we assumed a problem in the PHP code. Multiple changes to the code were applied, including:

  • Using absolute path in bindtextdomain function
  • Using a mix of $_SERVER['DOCUMENT_ROOT'] and relative locale path
  • Trying de_CH with and without .UTF-8 suffix
  • Renamed locale sub folder to "de_CH" and even a simple "de"
  • Changed the language to "de_DE"
  • Other little tweaks here and there

But nothing worked. We already prepared the text to ask a question on Stackoverflow (and be ready to get insulted) when the PHP script was also launched with the PHP command line (CLI).

Actually gettext translation works, but only on the CLI

To our big surprise, the German translation was returned, when the PHP script was called with the php7.3 cli:

$ php7.3 translate.php
Das ist der deutsche Text.

Wow. So the translation actually works; gettext is working just fine! To compare this again with a browser output, curl was used:

$ curl localhost/translate.php
Original English was returned. Something wrong

And again the translation doesn't work.

Fact now: The PHP translation works fine but as soon as the PHP script is opened via Apache (using mod_php), the translations don't work.

mod_perl is to blame

On the research why this happens, one hint was found on a question on Stackoverflow: Gettext not working through php-cli, but works in php-apache. The title itself was already intriguing enough although the problem description is the exact opposite of what we were running into.

Although not really relevant to the OP's question, one suggested answer was:

I just found a solution to the opposite problem: Gettext not working through php-apache, but working in php-cli. [...] Strangely, I just disabled the perl module in Apache and the problem disappeared.

Wait. What?! Why would mod_perl be interfering in a PHP code? We indeed had mod_perl enabled on this web server (for one particular Perl based web-application) so we decided to temporarily disable mod_perl - just for the sake of testing all possible workarounds.

# a2dismod perl
# systemctl restart apache2

And then, all of a sudden, the German translation was showing up in the curl response:

$ curl localhost/translate.php
Das ist der deutsche Text.

Is it really mod_perl or did a simple Apache restart fix something? Let's enable mod_perl and test again:

# a2enmod perl
# systemctl restart apache2

$ curl localhost/translate.php
Original English was returned. Something wrong

The problem is indeed caused by mod_perl. Mind. Blown.

Following up on (existing?) bugs

Now that we knew that mod_perl is causing this weird problem, there are two possible ways to solve this on this particular Apache web server:

  • Disable mod_perl for good
  • Switch from mod_php to PHP-FPM; as the root problem seems to be a locale issue within Apache (triggered by mod_perl), this problem should not happen if PHP is loaded outside of Apache, namely as a PHP-FPM daemon

More interestingly (for the geeks like us) is to find more information on this problem. The closest report to this bug can be found in Mageia Linux's Bugzilla: Bug 25411 Installing apache-mod_perl implies that setlocale has no effect in PHP. In fact, this does sound like the exact same behavior/bug. As Mageia is, according to Distrowatch, an independant Linux distribution and therefore not based on Debian, it does indicate that this is an upstream bug of the Apache mod_perl project.

To make sure this is handled in Debian and that Debian maintainers inform upstream, a new Debian bug report was created against the libapache2-mod-perl2 package: Bug #974922 mod_perl interferes with mod_php locales, unable to use gettext translations.

To complete the picture here, this issue happens on these versions and can be reproduced:

$ dpkg -l| egrep "(libapache2-mod-perl|libapache2-mod-php7.3|apache2-bin)" | awk '{print $2" "$3}'
apache2-bin 2.4.38-3+deb10u3
libapache2-mod-perl2 2.0.10-3
libapache2-mod-php7.3 7.3.19-1~deb10u1



Add a comment

Show form to leave a comment

Comments (newest first)

ck from Switzerland wrote on Nov 24th, 2020:

Thanks for your comment, Augusto. And thanks for referring back to this article as source of information. I am still curious what the exact bug in mod_perl is. No answer yet from the Debian bug report.


Augusto M Oliveira from MossorĂ³ - RN, Brazil wrote on Nov 24th, 2020:

I had an issue concerning frontend language in Zabbix application and it proved a fine solution. I was still afraid of undesirable implications as Mod_perl seems to have an important role and is praised for a lot of things but, up till now, everything has gone very well. To give you an idea of my struggle, you may view this topic at Zabbix forum https://www.zabbix.com/forum/zabbix-troubleshooting-and-problems/406728-problem-with-changing-the-language-debian . There I related my experience and gave due credit to your help.


RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder