PHP-Foundation
PHP-Foundation copied to clipboard
Problem with Internationalization (I18N)
I don't understand why but I can't get the i18n to work.
my .env
I18N_SUPPORTED_LOCALES=en-US,es-ES
in locale there are 2 folders:
en_US -> LC_MESSAGES
es_ES -> LC_MESSAGES
I purged the cache and rebuild the templates
$ sudo -u www-data php ./index.php clear-template-cache
$ sudo -u www-data php ./index.php precompile-templates
I extracted all translatable strings
$ bash ./i18n.sh en-US
Extracting and updating translations
* Creating PO (Portable Object) file for “en-US”
Created locale/en-US/LC_MESSAGES/messages.po.
* Creating MO (Machine Object) file for “en-US”
Done
$ bash ./i18n.sh es-ES
Extracting and updating translations
* Creating PO (Portable Object) file for “es-ES”
Created locale/es-ES/LC_MESSAGES/messages.po.
* Creating MO (Machine Object) file for “es-ES”
Done
NOTE -> After this operations in locale created me other 2 folders
en-US -> LC_MESSAGES -> messages.mo, messages.po
es-ES -> LC_MESSAGES -> messages.mo, messages.po
1 QUESTION: Why we have to create folder in locale en_US instead en-US maybe the documentation is wrong ?
https://github.com/delight-im/PHP-I18N#directory-and-file-names-for-translation-files
en-US messages.po
#
msgid ""
msgstr ""
"Language: en-US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Add"
msgstr ""
es-ES messages.po
#
msgid ""
msgstr ""
"Language: es-ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Add"
msgstr ""
I translated es-ES po
#
msgid ""
msgstr ""
"Language: es-ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Add"
msgstr "Añadir"
I updated the translations
$ bash ./i18n.sh es-ES
Extracting and updating translations
* Creating PO (Portable Object) file for “es-ES”
......................................................................................................................................................... done.
* Creating MO (Machine Object) file for “es-ES”
Done
Now in a file I tested
$app->i18n()->setLocaleManually('es-ES');
echo ('LANG: '. $app->i18n()->getLocale() .'<br>');
echo(_('Add'));
RESULT
LANG: es-ES Add -> INSTEAD -> Añadir
Hope that my process is clear and find the solution.
Thanks.
Your I18N_SUPPORTED_LOCALES looks fine. Purging the template cache and re-building it was a good idea as well.
Don’t create the language folders yourself. Maybe the documentation needs to be improved here.
When running the script, it should generate these for you, doesn’t it?
As for dash and underscore, just use what the script generates. If the translations are not picked up, try copying the folders to variants with the other symbol. But make sure these two are copies. The content of the dash variant must not be different from the content of the underscore variant.
Yes I tried to purge the template and rebuild after translation and I try to change the symbol too - _ I duplicate the directory. Anything seems work. I don't know what kind of debug I can make because don't give me any message just show always me the word in the principal language. :(
When running the script, it should generate these for you, doesn’t it?
What is strange is ... if Exist a directory as en_US the script generate the folder en-US but it's strange. If you check the i18n.sh file if the directory doesn't exist should to give error. And what happen if don't exist the folder en_US.
Well, you should follow some clearly defined steps and make sure to exclude all other possible reasons by resetting the translations:
- Remove the directories
en-US,en_US,es-ESandes_ES - Do not generate any of these directories manually again
- Use
i18n.sh en-USandi18n.sh es-ESinside WSL to extract the strings and generate these folders (and the files inside) - Fill in
msgstr ""where it’s empty and leavemsgid "…"as it is everywhere - Use
i18n.sh en-USandi18n.sh es-ESinside WSL again to compile the translations - Perhaps reload your web server or restart your machine
- Check if the translations show up
- Copy
en-UStoen_USandes-EStoes_ES(or the other way round) - Repeat steps 6 and 7
I make all the test that you wrote but nothing.
I tried to put as default en and es for don't have problem with score and underscore because something wrong with score and underscore there is but the same show always default word.
I said that there is something wrong with score and underscore because if you make a test and run the bash command with score the po generated is
msgid "add"
msgstr ""
Wrong because the default language should has both value
if you make with the underscore the result is
Correct
msgid "add"
msgstr "add"
Anyway later I'll try to make a new installation and just test the language because other idea over than to debug the i18n module I don't have.
Why do you think that
msgid "add"
msgstr ""
is wrong and
msgid "add"
msgstr "add"
is correct?
That would only be the case if you filled in the msgstr value already. Gettext doesn’t know about your default locale and shouldn’t automatically fill in translations after extracting strings. This is not the basis that we should evaluate the tool on.
It’s easy with the steps above: After step 3, please report the directory and file structure and the contents of the .po files. After step 5, please do the same.
Do you mean that I have to send you the zip of the folder en-US and es-ES after step 3 and after step 5 ?
The folder structure can be listed here in text form.
As for the files, you can either do that, or show small excerpts from the files here, e.g. with only the first two strings/translations.
Asked because at my first post already I show the file. Anyway this is the directory structure:
locale
- en-US
-- LC_MESSAGES
---- messages.mo
---- messages.po
- es-ES
-- LC_MESSAGES
---- messages.mo
---- messages.PO
- .gitignore
file en-US messages.po
#
msgid ""
msgstr ""
"Language: en-US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "%"
msgstr ""
msgid "100"
msgstr ""
msgid "200"
msgstr ""
msgid "Add"
msgstr ""
file es-ES messages.po
#
msgid ""
msgstr ""
"Language: es-ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "%"
msgstr ""
msgid "100"
msgstr ""
msgid "200"
msgstr ""
msgid "Add"
msgstr ""
AFTER STEP 4
file en-US messages.po
#
msgid ""
msgstr ""
"Language: en-US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "%"
msgstr ""
msgid "100"
msgstr ""
msgid "200"
msgstr ""
msgid "Add"
msgstr ""
file es-ES messages.po
#
msgid ""
msgstr ""
"Language: es-ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "%"
msgstr ""
msgid "100"
msgstr ""
msgid "200"
msgstr ""
msgid "Add"
msgstr "añadir"
Hope that I got your point and thanks.
The structure and the files look good after step 3. I’m just wondering why there aren’t any plural rules, as in the following example:
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
If en-US is your default locale, you don’t have to create (empty) translation files for it. Just leave it without its own folder. It will pick up the defaults from your code.
After step 4, the translation for msgid "Add" in es-ES is the only translation you’ve added, right?
So you didn’t share the file contents after step 5, which I asked for (and which is a little more interesting), but I guess it’s the same as after step 4.
Further, you may copy the *-* folders to *_*, but that shouldn’t make any difference if you’re on a Windows server.
After that, the only way to find out if everything is working is obviously switching your site to Spanish and checking whether “Add” is translated or not. Is it?
Next, as said above, and as the README states:
Translations are usually cached, so it may be necessary to restart the web server for any changes to take effect.
Finally, you should place the following code in a PHP file after having enabled the I18N component, ideally next to the echo(_('Add')); call:
\var_dump($app->i18n()->getLocale());
\var_dump($app->i18n()->getSystemLocale());
\var_dump($app->i18n()->getLocaleName());
\var_dump($app->i18n()->getLanguageName());
\var_dump($app->i18n()->getLocaleName('fr-BE'));
\var_dump($app->i18n()->getLanguageName('fr-BE'));
What’s the output?
Ok, I decided to make a new installation and just write this:
index.php
<?php
$i18n = new \Delight\I18n\I18n([
\Delight\I18n\Codes::EN,
\Delight\I18n\Codes::ES,
\Delight\I18n\Codes::IT
]);
$app->i18n()->setLocaleManually('en');
$app->get('/', [ '\App\HomeController', 'getIndex' ]);
Controller
<?php
namespace App;
use Delight\Foundation\App;
class HomeController {
public static function getIndex(App $app) {
$name = _('Hallo');
\var_dump($app->i18n()->getLocale());
\var_dump($app->i18n()->getSystemLocale());
\var_dump($app->i18n()->getLocaleName());
\var_dump($app->i18n()->getLanguageName());
\var_dump($app->i18n()->getLocaleName('fr-BE'));
\var_dump($app->i18n()->getLanguageName('fr-BE'));
// and return a view
echo $app->view('welcome.html.twig', [
'users' => $name
]);
}
}
template
{% include 'includes/header.html.twig' %}
<h1>{{_('Hello world')}}</h1>
{{users}}
{% include 'includes/footer.html.twig' %}
If I change in italian clean the cache and restart the web server work. BUT
If I change again in en clean the cache and restart the web server doesn't work and this is the result
Z:\wamp\www\phpfoundation\app\HomeController.php:13:string 'en' (length=2) Z:\wamp\www\phpfoundation\app\HomeController.php:14:string 'en.utf8' (length=7) Z:\wamp\www\phpfoundation\app\HomeController.php:15:string 'inglese' (length=7) Z:\wamp\www\phpfoundation\app\HomeController.php:16:string 'inglese' (length=7) Z:\wamp\www\phpfoundation\app\HomeController.php:17:string 'francese (Belgio)' (length=17) Z:\wamp\www\phpfoundation\app\HomeController.php:18:string 'francese' (length=8) Ciao Mondo Ciao
For let come back in english I need to delete in "it" folder the 2 file .mo and .po clear the cache and restart the web server.
I am frustrated :(
Thanks for doing the additional testing!
Don’t worry, I think we’re almost there, and after these initial setup problems on Windows, Gettext is an excellent system.
-
Don’t throw away and restart your projects anymore, please. The code and setup you have looks fine. This should be suitable for testing, and the problem is probably somewhere else, not in your code or setup.
-
Since you’re on Windows, can you please double check that you’re using the “Non Thread Safe (NTS)” version of PHP, and not the other one? Could you check your detailed PHP version? Since your version was probably bundled with WAMP, it’s highly likely that it’s the wrong one. This answer might help to install the correct one, which must use FastCGI instead of
mod_php. -
Please replace
setLocaleManually('en')in your code withsetLocaleAutomatically()and pass the language you want via GET parameters, e.g.lang=enorlang=it, which is easier during testing and avoids potential caching issues. -
Are you using the I18N component in that test setup with or without the framework? If using without the framework, using that constructor is fine. If using with the framework, you should define the supported languages in the configuration in
I18N_SUPPORTED_LOCALESinstead. -
If using it with the framework, please make sure that both
I18N_SESSION_FIELDandI18N_COOKIE_NAMEare empty. For easier testing, the language should only depend on your supplied GET parameter. -
As soon as a language has shown up successfully once (especially with its strings in the templates), there’s no need to clear and re-generate the template cache anymore.
-
In WSL, where you also extract the strings from code and templates, can you run
$ sudo locale-gen xx_XX $ sudo locale-gen xx_XX.UTF-8 $ sudo update-localeonce for every language (
xx_XX, e.g.it_IT) that you intend to support?