xgettext won't scan plural form - php

I use Poedit for my gettext i18n and that works fine. I use ZF2 where there are view helpers to integrate the translations. One is translate, the other translatePlural.
Usage:
<?php echo $this->translate('Welcome') ?>
<?php echo $this->translatePlural('Item', 'Items', $number) ?>
In Poedit I add the keywords translate and translatePlural. The normal translations work fine, but for the plural forms, only the "Item" is found (and not the "Items"). Just for testing purposes, I replaced the $this->translatePlural() call with ngettext(), but I end up with the same result. My conclusion: (my version of) Poedit is unable to scan plural forms.
What should I enter as keyword to let Poedit scan the second string as well?

After some further search, I stumbled upon the syntax [function]:1,2. That did the trick for me. I have now identified these two functions as keywords for Poedit as follows:
translate
translatePlural:1,2
And now my second argument is scanned.

Related

Is using echo rather than printf a trouble maker for string translation using .pot file and Poedit?

I was wondering could the use of echo in php code rather than the use of printf() be the cause of a .mo file or in general the reason why the translation files do not work at all?
For Example:
In my php code I have this line of code:
echo __('Twinkle Twinkle little star');
Which has the double underscore identifier __().
When using Poedit, I get my string displayed in the translatable strings column, so that's not an issue.
Sum up:
Could echo cause a problem with the translation even thought Poedit can index and understand that the string is there?
Thanks in advance for your time.
echo and printf are not related to translations. They are merely ways to output a string.
The translating is performed by the __() function. So assuming you have your locale set to French with the proper files loaded:
echo "Hello";
// Hello
echo __("Hello");
// Bonjour
printf("Hello");
// Hello
printf(__("Hello"));
// Bonjour

How to make PoEdit recognize plural strings from Symfony Translator component

I have a non-Symfony PHP project in which I want to use Symfony Translate component with MoFileLoader. I have setup PoEdit so it recognizes trans("string") function when parsing file looking for translations.
This part of code <?php echo $translator->trans("Welcome"); ?> is parsed as it should be.
Problem is I can't make PoEdit to recognize this as plural string <?php echo $translator->trans('Found {result} search result', ['{result}' => 1]); ?>
1 is clearly number of results and with that data I want to be able to use correct plural string.
Big issue is that my main language is Croatian which plural form ‪nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); is way more complex than English one nplurals=2; plural=(n!=1)
I have added this Sources keywords in PoEdit
trans
trans:1,2
I already tried to use PHP and gettext to accomplish this but it is just not working for me due to server restrictions and other problems with gettex, Apache and PHP.
This is the way I'm using Symfony Translate component:
<?php
require_once __DIR__.'/vendor/autoload.php';
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Loader\MoFileLoader;
$lang = "hr";
$translator = new Translator($lang, new MessageSelector());
$translator->setFallbackLocales(['en']);
$translator->addLoader('mo', new MoFileLoader());
$translator->addResource('mo', "locale/$lang/LC_MESSAGES/messages.mo", $lang);
echo $translator->trans("Welcome");
echo $translator->trans('Found {result} search result', ['{result}' => 1]);
?>
Is there a way to make PoEdit recognize this as plural string:
<?php echo $translator->trans('Found {result} search result', ['{result}' => 1]); ?>
trans
trans:1,2
You gave two conflicting instructions there - one to treat trans as singular, one as plural. Additionally, the plural one, trans:1,2 doesn't make sense: you're asking to extract 1st parameter as singular and 2nd as plural, but you don't even have two string parameters. See documentation for the syntax.
$translator->trans('Found {result} search result', ['{result}' => 1]);
There's no way trans() could work like this — how would it know what number to use to determine the plural version to choose? And how would it know what to use for plural version in English if it's nowhere to be found in the code?
You need to use transChoice() instead, as documented in Symfony docs. Plurals are always a moderately complicated subject, you absolutely must read the documentation to understand the concepts before writing any code.

Using Drupal, how do I force t('') to populate the string?

I am trying to make sure that all of the translatable strings are present in the database. Some of them appear very rarely (various form validation errors), therefore it would be a pain to reproduce them all.
Instead, I've created an admin module that, once called, goes through an array of all translatable strings and executes echo t('[the string from the array]').
After this, I expect to be able to translate those strings using admin/config/regional/translate/translate. But not all of them are there.
What am I missing?
If that's for some reason not possible, is there any function that would force entry?
Install and use "Translation template extractor" module as suggested by Vlad Stratulat.
The module let you parse all of your modules and themes and extract all the strings that are used in t() function.
The result is a .po file with all the original/translation string pairs.
You can open the .po (it's a plain text file, so use your favorite text-editor or POEdit software) and check and translate the missing strings.
Finally re-upload the complete .po in Drupal.
Try the following.
foreach(array(t('foo'), t('bar')) as $t) {
echo $t;
}
You should never use t() to translate variables, such as calling t($text). Read about t() function.
But anyway, the best way is to create .po file from your module and export it to Drupal using Translation template extractor.
This module will extract all your translatable strings and will save it into language specific file which you can then use in any other sites where you would like to use your module.

Website Language translation in php

Hi i am devloping site in php i need to translate whole website in other language like german,spanish etc... how can it possible in php i have tried using some csv but it all goes static i mean i can not convert the whole website ..
if you have any csv or api information ..
please help..
-Div
<?php
$GLOBAL['langs']=array(
'en'=>array(
'Welcome to my site!'=>'Welcome to my site!'
),
'it'=>array(
'Welcome to my site!'=>'Benvenuto sul mio sito web!'
)
);
function _($text){
$lang=$_COOKIE['lang'];
return $GLOBAL['langs'][$text];
}
?><html><head><?php
echo '<title>'._('Welcome to my site!').'</title>';
?></head><body>
....
</body></html>
While Christian's answer will do the trick there's a more cleaner and efficient way to achieve your needs: gettext is PHP's built-in function for internationalization.
Zend Translate is a library exactly build for this.
Gettext is not thread-safe. PHP supports only gettext and native array. Zend_Translate supports several source formats, including those supported by PHP, and other formats including TMX and CSV files.
If you want to translate 'a whole page' to any language, you could use Google Translate.

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