xiaoyi xiaoyi - 3 months ago 79
PHP Question

How to clear php's gettext cache without restart Apache nor change domain?

This is a little code snippet from php manual:

putenv('LC_ALL=zh_CN');
setlocale(LC_ALL, 'zh_CN');

bindtextdomain('domain', './locale');
textdomain('domain');

echo gettext('Hello');


Which will output 你好 as defined in
domain.mo
file, but the problem is as long as the Apache is running,
gettext()
always return the cached result.

If I change the translation of Hello to 您好 in
domain.mo
, it will still output 你好.

However there is a fix for this by changing the
domain
argument of
bindtextdomain()
and
textdomain()
to a new name. Like from
"domain"
to
"domain2"
. But this is really painful to edit the php file every time I updated the
.mo
file.

Is there a better way for doing this, like remove some folders or calling some php functions to do the job? So that I can write a little script for this purpose.

Answer

Every solution (1, 2, 3) suggests changing the domain to get rid of the cache problem, but this will create lots of out-of-date cache in memory.

So I dug into the gnu-gettext source for details on the cache strategy (bindtextdom.c:78.)

When bindtextdomain(domain, dirname) is called, it will check whether domain exists in the cache; if so, it will then check if dirname is the same with the one in the cache. If this fails, it will force a cache flush for the same domain, instead of creating a new one in memory.

The fix is incredibly simple, first create a dummy link to the locale folder where your .mo file is stored:

cd locale
ln -s . nocache

Then add one single line before bindtextdomain()

bindtextdomain('domain', './locale/nocache');
bindtextdomain('domain', './locale');

Now the cache is forced to flush every time.


Updates:

This hack may not works in some cases (Can't figure out the exact conditions.) This solution is NOT something you should use in production environment, but only for those who need to fix something while keeping httpd running!

Whenever you can, please avoid using gettext from very beginning, this is really something ancient and should be deprecated for good.