3

I've checked on the questions regarding this issue, they did not help (see what I tried below).

I setup a multi-container app on docker with a httpd:2.4 (apache) container acting as reverse-proxy forwarding requests to php files to my php-fpm container.

Everything in this setup works perfectly, with the exception of gettext translations. I simply cannot get the Docker container to return a gettext translation in the locale en_GB.

Setup:

  • The .mo files are present in a folder successfully mounted into my php-fpm container, at /var/www/php/translations, with the structure:
en_GB.utf8
   LC_MESSAGES
      first.mo
      second.mo
  • In my php code copied into my container, I call this before trying to fetch a gettext translation via _() or dgettext():
 bindtextdomain('first', '/var/www/php/translations');
 bindtextdomain('second', '/var/www/php/translations');

What I've tried:

  • Runnig locale -a in the running php-fpm container returns:
C 
C.utf8 
POSIX 
en_GB.utf8
  • I tried to change the language folders to e.g. en_GB.UTF-8
  • I tried to additionally call:
bind_textdomain_codeset('first', 'UTF-8');
bind_textdomain_codeset('second', 'UTF-8');

var_dumps() of each of the following methods when run in the container echo:

  • setlocale(LC_ALL, "en_GB.UTF-8") > en_GB.UTF-8
  • setlocale(LC_ALL, "en_GB.utf8") > en_GB.utf8
  • textdomain('first') > first
  • textdomain('second') > second

Still, it is not working (I've also double-checked that the msgid is properly setup and translated, and even re-generated .mo files over and over again).

Note: Nothing in relation to locales is done on the apache container, but that should be fine, as it is a completely separate container?

Note: This exact setup works when deployed on an actual VM with apache as reverse proxy with php running as fastcgi behind it. So I am totally clueless what I am missing.

Dockerfile of my php-fpm container (relevant parts) :

FROM php:8.2-fpm

RUN <<EOF
apt-get update
apt-get install -y locales gettext libgettextpo-dev
docker-php-ext-install gettext
apt-get install -y libzip-dev unzip
docker-php-ext-install zip
docker-php-ext-install pdo_mysql
EOF

# Generate the locale(s) you need
RUN echo "en_GB.utf8 utf8" >> /etc/locale.gen && \
    echo "de_CH.UTF-8 UTF-8" >> /etc/locale.gen && \
    locale-gen

# Set environment variables so PHP uses the locale
ENV LANG=en_GB.utf8
ENV LANGUAGE=en_GB:en
ENV LC_ALL=en_GB.utf8

More details:

PHP Code with which I'm trying to load the translations ATM:

$locale_value = 'en_GB';

putenv("LANGUAGE=$locale_value.utf8");
putenv("LC_LANGUAGE=$locale_value.utf8");
putenv("LANG=$locale_value.utf8");
putenv("LC_LANG=$locale_value.utf8");
putenv("LC_ALL=$locale_value.utf8");
setlocale(
LC_ALL,
"$locale_value.utf8"
);

// Load text domains
bindtextdomain(
domain   : 'first',
directory: '/var/www/php/translations'
);

bindtextdomain(
domain   : 'second',
directory: '/var/www/php/translations'
);

// Set default textdomain to first textdomain
textdomain('first');

I then try to access my gettext translations via:

_('Hallo')

... for first, or:

dgettext('second','Hallo')

... for second.

The result is that simply the msgid is always returned, in the gettext default language (so Hallo instead of Hello, no matter if all of the calls succeed as explained in my var_dumps shown above).

I've initially only tried to load the language via:

putenv("LC_ALL=$locale_value.utf8");
setlocale(
LC_ALL,
"$locale_value.utf8"
);

... but am so done with this issue patience wise that I simply set pretty much each global variable I'm reading about in relation to this issue.

I've then also tried to replace the /var/www/php/translations directory in the calls above with /usr/lib/locale, as that appears to be php-fpms native locale directory for LC_MESSAGES for the docker image I'm pulling. No effect though, same outcome.

PS: If that matters, the php-fpm image is built on top of Debian, as you can see in the link of the image my dockerfile uses.

Then, if this matters, the way I am implementing the reverse-proxy logic over apache is by using the following in the apache config that is copied into my apache docker container:

<FilesMatch \.php$>

    ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/var/www/html%{reqenv:SCRIPT_NAME}"

    SetHandler "proxy:fcgi://php-fpm:9000"

</FilesMatch>

(With the name of the php-fpm container being php-fpm, and the port the image exposes being 9000).

Again everything works, the entire php application, except from the gettext thing, as mentioned above.

2
  • You say: "it's not working", or more precise, you cannot get it to: "return a gettext translation in the locale en_GB", but you never told us what actually happens. Do you get an error? An empty string? Do you do _("Hello") and it returns "Hello"? What's in your .mo file? What does your PHP code look like? I would leave out the docker stuff and concentrate on what you're doing in PHP first. Commented Oct 21 at 21:41
  • Added further details which should help you, and no the Docker thing is the important part as the exact same code works if deployed on a VM running php as fast CGI (not apache module) behind an apache reverse proxy. The fact that it does not work in Docker is precisely the issue. But if my error has something to do with my PHP code, be my guest. Commented Oct 21 at 21:50

1 Answer 1

1

Got it!

The reason why this failed is that the php-fpm container's default worker:

www-data

... was not able to actually access the .mo files. All I had to do to make this work is add the following into my Dockerfile (after the step that copy-pastes the .mo files into my container at /var/www/php/translations) :

RUN chown -R www-data:www-data /var/www/php/translations

It would have saved me hours of work if gettext would have logged any kind of permission denied error or whatsoever, but I guess that's part of the game. Anyways, hopefully you will not lose as much time as I did with this.

And just to be clear here, not all the environment variable calls mentioned above were necessary to get this working. Doing only the calls below:

putenv("LC_ALL=en_GB.utf8");
setlocale(LC_ALL,"en_GB.utf8");

... was enough to get things working properly.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.