I’m encountering a challenging issue with translations and localization in CakePHP 5.1.1, and I’d greatly appreciate any guidance. Normally, clearing the cache resolves any minor issues I’ve had with translations appearing, but this time, the problem seems different. Here’s what I’m currently doing:
I generate .pot files using bin/cake i18n extract, placing them in /resources/locales/fr_FR/.
I rename the .pot files to .po, and then translate the necessary messages.
Issue
Despite this setup, none of my translations are being applied—except for one, but inconsistently. In my form inputs, all required fields display the English message “This field cannot be left empty” except for one, which shows the French translation “Veuillez compléter ce champ.” However, even when a translation is displayed correctly, it doesn’t match the exact text provided in cake.po.
When I inspect the cake.po file, I find the following:
#: ./vendor/cakephp/cakephp/src/Validation/Validator.php:3036
#: ./vendor/cakephp/cakephp/src/View/Form/ArrayContext.php:232
msgid "This field cannot be left empty"
msgstr "Ce champ ne peut être vide."
This suggests that the translation should be applied globally, yet it isn’t reflected as expected in the application.
I’ve also tried forcing the locale to French in the initialize() method of AppController.php using I18n::setLocale('fr_FR'); but the issue persists.
Any insights or recommendations from the community would be highly valued! Thank you all in advance for any help you can offer.
Unless I’ve missed something significant—always a possibility!—I’ve ensured the following setup:
Both the cake.po and default.po files exist in the resources/locales/fr_FR directory.
The cake.po file indeed contains the exact string “This field cannot be left empty”.
The .po file structure follows the correct syntax, as shown here:
msgid "This field cannot be left empty"
msgstr "Ce champ ne peut être vide"
I tested that code in AppController
/**
* Initialization hook method.
*
* Use this method to add common initialization code like loading components.
*
* e.g. `$this->loadComponent('FormProtection');`
*
* @return void
*/
public function initialize(): void {
parent::initialize();
debug(I18n::getLocale());
I18n::setLocale('fr_FR');
debug(__('This field cannot be left empty'));
debug(__d('cake', 'This field cannot be left empty'));
debug(__d('default', 'This field cannot be left empty'));
die();
$this->loadComponent('Flash');
/* Removed in CakePHP 5 ! $this->loadComponent('RequestHandler'); */
/* Ajoutez cette ligne pour vérifier le résultat de l'authentification et verrouiller votre site */
$this->loadComponent('Authentication.Authentication');
/*
* Enable the following component for recommended CakePHP form protection settings.
* see https://book.cakephp.org/4/en/controllers/components/form-protection.html
*/
//$this->loadComponent('FormProtection');
}
and got that in my browser
APP/Controller/AppController.php (line 79)
'fr_FR'
APP/Controller/AppController.php (line 81)
'This field cannot be left empty'
APP/Controller/AppController.php (line 82)
'This field cannot be left empty'
APP/Controller/AppController.php (line 83)
'This field cannot be left empty'
Yet, as seen in the debug output, the translation isn’t being applied as expected, and I continue seeing the English message “This field cannot be left empty.”
Would you have any other suggestions for further troubleshooting?
I don’t know much about the internals of any of this. I do see a few places where what you’re doing is different from what I do. I have no idea whether they affect things.
I don’t rename my pot files, I leave them in place and use PoEdit to manage the po files. At least two differences from this are that the pot file then still exists (don’t know if that’s important or not), and there’s a line reading "Language: fr_FR\n" in the header of my po file (again, don’t know if that’s important).
Also, you said you cleared the cache, but didn’t say how. I expect you did it correctly, but seems useful to double check that tmp/cache/persistent is empty after you do it.
Seems most likely that there’s some issue in your process. You know that i18n extract updates the pot file, not the po? And you then need a second process to merge that most recent pot file into your existing po file, to preserve existing translations but also add new ones?
I always generate .po files from .pot files via PoEdit
Indeed, the management and generation of .pot and .po files has always worked “automagically”.
The command bin/cake i18n extract only generates the .pot file, NOT the .po file which actually contains the translated strings for your desired language.
I am on CakePHP 5.1.1 as well without any problems.
You already made sure that Cake knows its set to fr_FR via doing debug(I18n::getLocale());
Therefore there is no problem with setting the language in your config/environment.
I’d guess you have a permission problem reading the file or - as mentioned before - the .po file is not in the correct format because its just a renamed .pot file which may not be 100% intercompatible
I come here to indicate that I found an answer to my problem.
first of all,
the inconsistency of the translation of the same case was due to the fact that the requisition of a field was not done in the same way depending on the field. When the requisition, (CANNOT BE NULL) of a field is defined in the database schema then everything happens as expected. The second field was not defined as required (CAN BE NULL) in the database but in the input form via the option (“required” => true then the message ‘this field cannot be left empty’ is intercepted and translated by the browser (client side) and no longer server side.
Second point,
I confirm the fact that it is optional to transcribe via poedit the .pot files generated via “bin/cake i18n extract”. This works very well by copying them, renaming them into .po files in the appropriate directory. POedit is useless to me because I have very little language to translate. From English to French, this is sufficient in most of the applications I am asked for.
Third point,
you actually have to clear the cache in the tmp directory (tmp/cache/persistent…) but this has never caused me a problem.
Finally, the crux, the core of my problem
was that my .po file had the wrong format. I have no more information, I ended up in desperation, starting my translation procedure from the beginning by deleting my .po file and everything is back to normal.
Thank you both for spending the time to answer me and give me some lines of research.