Use PHP Gettext without having to install locales
Asked Answered
D

3

15

I've been looking at options for internationalizing an open source project:

  • Gettext, which everyone seems to recommend, apparently needs locales to be "installed on your system" to be used. See this note on the PHP manual, which reflects exactly my situation. This SO question also asks about the same problem. This isn't suitable for an open source project because I can't trust that the end users have the appropriate locales installed on their system. Besides, it's very very weird that you have to install locales just to use strings that you've translated (IMO).

  • Zend_Translate is also recommended in favour of gettext sometimes, but I'm not using the Zend framework so I don't think it's an option for me. Some people have said you can split it from the Zend framework, but I'd have no clue how. If anyone can tell me what files I need (I've downloaded a tarball of the Zend framework) to pick out, I would be open to using Zend_Translate.

  • Arrays. That's what I'm doing now, but it's not ideal because:

    • It will be using up lots of memory to define every translation, when most won't be used by the current page.
    • I am having problems with finding myself duplicating the keys in the array, which has already become 1000 lines of code long and I've barely added anything yet...
    • It means non-programmers can't really translate, whereas POedit is the standard that everyone expects to use.

Can I somehow read .mo files without Gettext or Zend_Translate, or must I use Gettext? If so, how can I make all locales work, like in the question I linked to above?

EDIT: I'm now willing to use Zend_Translate. I just need to work out what files I need (it would be great if they could be combined into one file) - I don't want the entire Zend Framework in my project.


Update: I was interested to see how big open source projects handle i18n:

So none of those three random projects use Zend_Translate, nor gettext directly, as far as I can see.

Maybe it's a good idea to use the C locale, store the name of the language in the text domain name, and go from there.


So here's as far as I've got with that:

$lang = 'de'; //debug
setlocale( LC_ALL, 'C' );
bindtextdomain( 'default', PATH . "/locale/$lang" );
bind_textdomain_codeset( 'default', 'UTF-8' );
textdomain( 'default' );

var_dump( file_exists( PATH . "/locale/$lang/C/LC_MESSAGES/default.mo" ) ); //bool(true)

But I still just get the English string, even though I've used poedit, msgfmt etc. to make the appropriate files. I've also tried restarting Apache.

Dissatisfied answered 21/3, 2013 at 7:29 Comment(8)
Install locales? What do you mean? You just include the specific .mo files and set the appropriate locale. Its really not as scary as you make it out to be.Finnigan
It'd be great if that was the case, but I don't think it is... see the link at the top of the question. User notes on the PHP manual also say this, and that you need to run locale -a to see what locales are available to use (and run sudo apt-get install language-pack-langcode-base to install extra language packs). My own tests also reflect this. This isn't suitable for an open source project as I can't expect users to do this.Dissatisfied
Simple key => value arrays are hardly sufficient for a complete translation system. Do they support plurals? Context? Categories? Domains? Comments? These are all features you should be using, maybe you just don't know it yet. If you're averse to gettext, give Zend_Translate a shot. Your reasons against it are really non-reasons.Antefix
Yeah, that's why I want to switch from arrays to something else. I guess I'd be willing to use Zend_Translate if I needed to, but how? People on SO have said that they can split it from the rest of the Zend framework, but I don't know how to.Dissatisfied
Just put the Zend Framework somewhere and load the Zend_Translate class, done.Antefix
But can I put just Zend_Translate in my project, not the entire Zend framework? I've downloaded a tarball and I've found the Translator folder, but I'm not sure what other parts of Zend it needs.Dissatisfied
@DuncanNZ what @Antefix said is the easiest way to go. It may seem overkill, but really it will only waste some space in your hard disk, but as the rest of the framework won't be used, won't eat any memory or load for each request, etc... Once you have the Zend_Translate working, go removing classes/folders and see if it still works... until you end with a small enough (for you) set of classes.Domesday
@Antefix sorry for my noobishness but I can't even work out how to "load" Zend. I just get "class Zend_Translate not found". I've got the entire Zend framework in there (to start with). I'm not sure which file I should be including - is it Zend/I18n/Translator/Translator.php, or Zend Loader or something...?Dissatisfied
D
4

Here is the solution:

$lang = 'de'; //debug
setlocale( LC_ALL, 'C.UTF-8' );
bindtextdomain( 'default', PATH . "/locale/$lang" );
bind_textdomain_codeset( 'default', 'UTF-8' );
textdomain( 'default' );

The only difference between that and the example I posted at the bottom of my answer is that it uses C.UTF-8 not just C.

I'll be doing more testing of this, and if it works cross-platform, and will update this answer if I find out anything else.

Dissatisfied answered 22/3, 2013 at 22:38 Comment(3)
Congratulations, it seems to work for me, too. But it seems to be really hacky and I cannot believe that this is the common way to solve this. I do not understand what the language "C.UTF-8" is but it seems to be installed on every environment. Since your post is 2 years ago i would kindly ask you if you found any better solution in the meantime.Decade
Sorry @steven, I haven't really used PHP since. However nowadays I am less bothered by best practice and would probably go straight for an array-based solution knowing the frustrations of gettext.Dissatisfied
Do you know how to install locales on xampp for windows?Chantress
A
4

Try gettext-php. It is a drop-in replacment for gettext written in PHP. It was originally done for WordPress, I think, because WP needs to run on shared hosts which are not always configured for every locale. This seems to me to be your issue as well.

It has a bit of performance hit, but it has not been an issue for me at all.

Antrorse answered 22/3, 2013 at 22:44 Comment(1)
Thanks for the suggestion. Now that I've (finally) got Gettext going I think I'll stick with it for now, but I'll bear that in mind incase I have any more problems.Dissatisfied
A
0

For anyone still having some problem with this, you can try the code below, which i get from here: http://php.net/manual/en/function.gettext.php#58310

It solved me on freebsd server, having no extra locale install (fr_FR and my_MY) This code is also useful when you have some problem with the gettext cache.

<?php
function initialize_i18n($locale) {
  $locales_root="/app/php/locale"; // change This to where you locale folder at
  putenv('LANG='.$locale);
  setlocale(LC_ALL,"");
  setlocale(LC_MESSAGES,$locale);
  setlocale(LC_CTYPE,$locale);
  $domains = glob($locales_root.'/'.$locale.'/LC_MESSAGES/*.mo');
  $current = basename($domains[0],'.mo');
  $timestamp = preg_replace('{messages-}i','',$current);
  bindtextdomain($current,$locales_root);
  textdomain($current);
}
?>
Asthenic answered 1/8, 2018 at 8:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.