Reputation: 33348
I'm on CakePHP 2.6.x
My app is localized in French and English. English is the default.
My translation files currently look like this:
/app/Locale/eng/LC_MESSAGES/default.po
/app/Locale/fra/LC_MESSAGES/default.po
In my views, I normally can show localized text for the current language like this:
echo __("Foo");
However, in a few situations I need to override the current language and return a translation for a specific language. My understanding is __d() is meant for exactly this. However, the following does NOT work for me:
echo __d("fra", "Foo");
[Correction: __d
is NOT meant for this.]
This seems to always return the translation of the current language. Basically acting just link __()
.
After a lot of trial-and-error I renamed the French .PO file...
/app/Locale/fra/LC_MESSAGES/fra.po
...and then __d("fra", "Foo");
DOES work as expected. But then __()
DOESN'T work anymore. After I change the file name, all instances of __()
return text in the default language.
What am I doing wrong? How do I get BOTH __d()
and _()
to work at the same time? Or another way of asking the same question: How can I change the language used by __()
within the same request?
Update
My first instinct was to try something like what Lars suggests below. But for some reason it doesn't work. I'm doing the following in an email view:
Configure::write("Config.language", "fra");
$this->log(Configure::read("Config.language")); //'fra'
$this->log( __("yes") ); //'yes'
Notice that the Config language is correctly set. But __()
ignores it and echos the current language anyway. (Btw I checked and yes/oui is in the PO file)
Upvotes: 2
Views: 4564
Reputation: 33348
Following @ndm's suggestion, I wrote a little utility for "toggling" the language mid-request.
Here's how I use it:
App::uses('L10nTool', 'Lib');
$L10n = new L10nTool();
$L10n->startToggleLg("fra");
...
//Bonjour, mon ami
...
$L10n->stopToggleLg();//Back to initial language
Later I might add another method, similar Lars's answer, for doing one quick string in a single method. But right now I'm doing some email logic in the "toggled" language, so it's easier for me to do it this way.
Here's the code:
<?php
App::uses('AppHelper', 'View/Helper');
App::uses('CakeSession', 'Model/Datasource');
class L10nTool {
public $start_lg;
public $use_session = FALSE;
public function startToggleLg($lg) {
if (CakeSession::check("Config.language")) {
$this->start_lg = CakeSession::read("Config.language");
$this->use_session = TRUE;
} else {
$this->start_lg = Configure::read("Config.language");
}
if ( $this->use_session ) {
CakeSession::write("Config.language", $lg);
} else {
Configure::write("Config.language", $lg);
}
}
public function stopToggleLg($lg = NULL) {
$lg = ($lg) ? $lg : $this->start_lg;
if ( $this->use_session ) {
CakeSession::write("Config.language", $lg);
} else {
Configure::write("Config.language", $lg);
}
}
}
Upvotes: 3
Reputation: 3537
Your best bet would be to change the set language prior the call and change it back later:
$before = Configure::read('Config.language');
Configure::write('Config.language', 'fra');
echo __('Your String');
Configure::write('Config.language', $before);
You could even put that into a function:
function __lang($string, $language) {
$before = Configure::read('Config.language');
Configure::write('Config.language', $language);
echo __($string);
Configure::write('Config.language', $before);
}
As mdm explained in the comments, that is basically what the I18N::translate function does.
If this (and my function) does not work, I would guess that there is something wrong with your translation files. Have you tried switching to the target language globally? Does that print the correct string?
To circumvent all configuration and session values, you could simply rely on the I18N::translate function:
function __lang($string, $language) {
echo I18N::translate($string, null, null, I18n::LC_MESSAGES, null, $language);
}
Upvotes: 3