Make translations in multiple languages - php

I have my php gettext default language in English let's say
I would like in one of my controller, to translate some words in 2 other languages and put them all in an array.
ideally I could do
$word_sv = gettext($word, 'sv_SV');
$word_fi = gettext($word, 'fi_FI');
but it doesn't exist.
Is the only way to change the overall gettext settings each time?
function setLang($lang){
putenv("LC_ALL=$lang");
setlocale(LC_ALL, $lang);
bindtextdomain("myPHPApp", "./locale");
textdomain("myPHPApp");
}
setLang('sv_SV');
$word_sv = gettext($word);
setLang('fi_FI');
$word_fi = gettext($word);
related: saw it on Google after : i18n with gettext but without the locale hassle?
Edit
here are the proposed answered solutions:
https://github.com/Philipp15b/php-i18n (seems best solution)
http://glotpress.trac.wordpress.org/browser/trunk/pomo (could use it if I find a good doc or tuto ;))
change locale on the fly, probably not good

I know the pains of using gettext, but its performance is what keeps me with it !
In your case, you might want to look at this little project ? i'm pretty sure this might help you !
this simply uses .ini files with translations, you can freely switch between files and echo the different languages for the same word.
https://github.com/Philipp15b/php-i18n

If you are bound to gettext here, Let the computer do the work for you.
You either have a list of words you then want to check against all languages, the do the wordlist for each language first. That will spare you some overhead to call the setlanguage function between each word and language.
If you want to go each language, each word, write the functions that way:
function gettext_by_lang($lang, $word) {
putenv("LC_ALL=$lang");
setlocale(LC_ALL, $lang);
bindtextdomain("myPHPApp", "./locale");
textdomain("myPHPApp");
return gettext($word);
}
$word_sv = gettext_by_lang('sv_SV', $word);
$word_fi = gettext_by_lang('fi_FI', $word);
This would at least make your code more compact. Another idea that comes to mind is using a a parser for PO and MO files so that you can check for the data.
In PHP one of that is shipping with Wordpress / Glotpress:
http://glotpress.trac.wordpress.org/browser/trunk/pomo
Maybe this helps. That library is being maintained.

I guess an obvious answer is to roll your own global function:
function getLocalText($string, $lang)
{
putenv("LC_ALL=$lang");
setlocale(LC_ALL, $lang);
bindtextdomain("myPHPApp", "./locale");
textdomain("myPHPApp");
return gettext($string);
}
$word_fi = getLocalText($word, 'fi_FI');

Related

Gettext php, idea ?

I installed gettext on a server and want to use for a php script..
I use with 3 languages. The original website is written in english..
Other are french and Italian.
I can without problem change language to French or Italian.. But when I want load the en_EN.mo file to replace the origine text of the php file, the translation are not loaded.
I try many things.. Remove file, replace name.. restart apache..
Nothing.. it work perfectly with all other langage, but impossible to use a english file.
I create new language.. it work too.. but never the en_EN..
All my files langage are in the same tree style
locale
en_EN
LC_MESSAGES
en_EN.mo
fr_FR
LC_MESSAGES
fr_FR.mo
...
if I force to use..
$directory = './locale';
$domain ='en_EN';
$locale ='en_EN';
putenv('LC_ALL='.$locale);
setlocale(LC_ALL, $locale);
bindtextdomain($domain, $directory);
textdomain($domain);
bind_textdomain_codeset($domain, 'UTF-8');
no result..
My problem is that I have no idea how to debug it ? Where can I find a log or something to help ? Where see errors ?
It's strange that it work with all lang, but not english.. I use Poedit to create my file, I have create the file many time.. in the same way that other..
Please share your idea :)
I create new language.. it work too.. but never the en_EN..
You misunderstand what the locale string means. It is not “2 language code letters followed by the same letters in uppercase” (that wouldn’t make any sense, would it), it is “language code followed by country code” per ISO 3166. And “EN” is not only not a valid country code for any country that speaks English, it’s not a valid country at all. You’re asking WordPress to run under the English locale (presumably), but only providing it translation files for “English in a made-up country” locale that WP is never going to look for.
You’re thinking of en_US.

CakePHP Localization issue

I follow the cakePHP book to config the i18n and l10n of my site. Suppose I have English, Spanish, German.
Browsers usually have a list of languages ordered by priority. If at the first position of the list appears a language that is configured on my site all works fine. But if, for example, the list is this: French, German, Spanish, English; localization fails and shows the i18n identifiers that I used in my code.
I would like that in this case the page appears translated in German, because in the list is the first language that my site can provide. This would be the perfect solution but at least I would like that I can configure a default language (for example, English) if the first language of the browser list is unknown by my page.
What I can do to achieve this and where should put the code?
Thank you in advance.
Well, I did the next in app/Config/bootstrap.php:
$browserLangs = explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']);
$find = 'eng';
foreach($browserLangs as $browserLang) {
$lang = substr($browserLang,0,2);
var_dump($lang);
if ($lang == 'en') {
$find = 'eng';
break;
} else if ($lang == 'es') {
$find = 'spa';
break;
} else if ($lang == 'ca') {
$find = 'cat';
break;
}
}
Configure::write('Config.language', $find);
In Accept Language header we have a string with all the list of languages of the browser. Then I define English as default, and try to find other language in the list, breaking the bucle when I get one.
I put this as an answer because it works, but its dirty because:
I don't know if this is the best way and the best place,
this is very static, you have to put the languages one by one and when you add another language you have to update the algorithm. The best solution will check automatically for the locales defined on the cake application, which I don't know how to ask for.
Perhaps this code should be defined as a plugin, component or something like that.
Perhaps someone can improve this or post another better solution as a new answer.
You will have to open the created .po file, with an editor (for example: http://poedit.net) there you can create multiple language versions.
Dont forget to change the plural forms for every language, for german it's nplurals=2; plural=(n != 1), here a list: http://translate.sourceforge.net/wiki/l10n/pluralforms.
After that, you'll have to save the language file in app/Locale/deu/LC_MESSAGES/...
You should have a default.mo and default.po file in that folder at the end.

PHP Language Converter

I have a script I'm using to convert English text to other spoken languages, and I have a php code handling it like so.
ini_set("max_execution_time", "300");
header('Content-Type: text/html; charset=utf-8');
require_once('googleTranslate.class.php');
$gt = new Google_Translate_API();
$title = $gt->translate($title, "en", $lang);
$keywords = $gt->translate($keywords, "en", $lang);
$body = $gt->translate($body, "en", $lang);
Anyways, when I run this script, it times out before it can translate much text at all, so I was wondering if we could run one piece at a time somehow?
Also, note that the googleTranslate.class.php can be freely downloaded from Google Code.
Cheers
Hm, well I think you shoulde cache results at first. Make some script witch caches translated content for needed languages. Else you fast will reach querys limit.
Got it. Turns out Google Translate API wasn't the way to go. Instead, I'm using the Bing Translate service. It also doesn't restrict me to certain lengths of text. Thanks for the help. (:

Permanently write variables to a php file with php

I need to be able to permanently change variables in a php file using php.
I am creating a multilanguage site using codeigniter and using the language helper which stores the text in php files in variables in this format:
$lang['title'] = "Stuff";
I've been able to access the plain text of the files using fopen() etc and I it seems that I could probably locate the areas I want to edit with with regular expressions and rewrite the file once I've made the changes but it seems a bit hacky.
Is there any easy way to edit these variables permanently using php?
Cheers
If it's just an array you're dealing with, you may want to consider var_export. It will print out or return the expression in a format that's valid PHP code.
So if you had language_foo.php which contained a bunch of $lang['title'] = "Stuff"; lines, you could do something along the lines of:
include('language_foo.php');
$lang['title2'] = 'stuff2';
$data = '$lang = ' . var_export($lang, true) . ';';
file_put_contents('language_foo.php', '<?PHP ' . $data . ' ?>');
Alternatively, if you won't want to hand-edit them in the future, you should consider storing the data in a different way (such as in a database, or serialize()'d, etc etc).
It looks way easier to store data somewhere else (for instance, a database) and write a simple script to generate the *.php files, with this comment on top:
#
# THIS FILE IS AUTOGENERATED - DO NOT EDIT
#
I once faced a similar issue. I fixed it by simply adding a smarty template. The way I did it was as follows:
Read the array from the file
Add to the array
Pass the array to smarty
Loop over the array in smarty and generate the file using a template (this way you have total control, which might be missing in reg-ex)
Replace the file
Let me know if this helps.
Assuming that
You need the dictionary file in a human-readable and human-editable form (no serializing etc.)
The Dictionary array is an one-dimensional, associative array:
I would
Include() the dictionary file inside a function
Do all necessary operations on the $lang array (add words, remove words, change words)
Write the $lang array back into the file using a simple loop:
foreach ($lang as $key => $value)
fwrite ($file, "\$lang['$key'] = '$value';\n";
this is an extremely limited approach, of course. I would be really interested to see whether there is a genuine "PHP source code parser, changer and writer" around. This should be possible to do using the tokenizer functions.
If it also is about a truly multilingual site, you might enjoy looking into the gettext extension of PHP. It falls back to a library that has been in use for localizing stuff for many years, and where tools to keep up with the translation files have been around for almost quite as long. This makes supporting all the languages in later revisions of the product more fun, too.
In other news, I would not use an array but rather appropriate definitions, so that you have a file
switch ($lang) {
case 'de':
define('HELLO','Hallo.');
define('BYE','Auf wiedersehen.');
break;
case 'fr':
define('HELLO','Bonjour');
define('BYE','Au revoir.');
break;
case 'en':
default:
define ('HELLO','Hello.');
define ('BYE','Bye.');
}
And I'd also auto-generate that from a database, if maintenance becomes a hassle.
Pear Config will let you read and write PHP files containing settings using its 'PHPArray' container. I have found that the generated PHP is more readable than that from var_export()

How does gettext handle dynamic content?

In php (or maybe gettext in general), what does gettext do when it sees a variable to dynamic content?
I have 2 cases in mind.
1) Let's say I have <?=$user1?> poked John <?=$user2?>. Maybe in some language the order of the words is different. How does gettext handle that? (no, I'm not building facebook, that was just an example)
2) Let's say I store some categories in a database. They rarely, but they are store in a database. What would happen if I do <?php echo gettext($data['name']); ?> ? I would like the translators to translate those category names too, but does it have to be done in the database itself?
Thanks
Your best option is to use sprintf() function. Then you would use printf notation to handle dynamic content in your strings. Here is a function I found on here a while ago to handle this easily for you:
function translate()
{
$args = func_get_args();
$num = func_num_args();
$args[0] = gettext($args[0]);
if($num <= 1)
return $args[0];
return call_user_func_array('sprintf', $args);
}
Now for example 1, you would want to change the string to:
%s poked %s
Which you would input into the translate() function like this:
<?php echo translate('%s poked %s', $user1, $user2); ?>
You would parse out all translate() functions with poEdit. and then translate the string "%s poked %s" into whatever language you wanted, without modifying the %s string placeholders. Those would get replace upon output by the translate() function with user1 and user2 respectively. You can read more on sprintf() in the PHP Manual for more advanced usages.
For issue #2. You would need to create a static file which poEdit could parse containing the category names. For example misctranslations.php:
<?php
_('Cars');
_('Trains');
_('Airplanes');
Then have poEdit parse misctranslations.php. You would then be able to output the category name translation using <?php echo gettext($data['name']); ?>
To build a little on what Mark said... the only problem with the above solution is that the static list must be always maintained by hand and if you add a new string before all the others or you completely change an existing one, the soft you use for translating might confuse the new strings and you could lose some translations.
I'm actually writing an article about this (too little time to finish it anytime soon!) but my proposed answer goes something like this:
Gettext allows you to store the line number that the string appears in the code inside the .po file. If you change the string entirely, the .po editor will know that the string is not new but it is an old one (thanks to the line number).
My solution to this is to write a script that reads the database and creates a static file with all the gettext strings. The big difference to Mark's solution is to have the primary key (let's call it ID) on the database match the line number in the new file. In that case, if you completely change one original translation, the lines are still the same and your translator soft will recognize the strings.
Of course there might be newer and more intelligent .po editors out there but at least if yours is giving you trouble with newer strings then this will solve them.
My 2 cents.
If you have somewhere in your code:
<?=sprintf(_('%s poked %s'), $user1, $user2)?>
and one of your languages needs to swap the arguments it is very simple. Simply translate your code like this:
msgid "%s poked %s"
msgstr "%2$s translation_of_poked %1$s"

Categories