We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

How can I realize specific multi-lingual support?

I think, that reasonable to use this directories structure:

// Languages Dirs, English lang
app/langs/en/
- Session_Index.php        | Language file for SessionController and IndexAction
- Session_Login.php        | Language file for SessionController and LoginAction
- Index_Index.php          | Language file for IndexController   and IndexAction

// Controller Dirs
app/controllers/
- SessionController.php
- IndexController.php

Language-files set langs for Actions in controllers including forms and other files. It must be set in the public/Index.php (services) file and be universal. I think it soulds be like this.

The real multi-language support is until not necessary but will be useful in the future.

I just want to make the website's text in the files.

Thank you!



12.2k

How about using phalcon's native translation support:

https://docs.phalcon.io/en/latest/reference/translate.html



11.1k
edited May '16

How about using phalcon's native translation support:

https://docs.phalcon.io/en/latest/reference/translate.html

Yes, I have read this already)) But I think: it would be right to put the Translate as component in /public/index.php file... And interact with controller automaticly. Yes, I'll can register function getTranslation () { ... } in each controller, and require the languages-files but it's irrational. Is it possible to do this automatically?



12.2k
Accepted
answer

Actually, you register translation service in $di.

I am using GetText as my translation adapter:


/*
 * Using Gettext adapter from Incubator, otherwise ctxtmsg isn't available
 * but you can use Phalcon\Translate\Adapter\Gettext
 */
use Library\Translate\Adapter\Gettext as TranslationService;

/**
 * Translation service
 *
 * @return array
 */
$di->setShared('translation', function () use ($di) {

    if (!function_exists('gettext')) {
        throw new \Phalcon\Exception('Please install gettext extension');
    }

    $request = $di->get('request');
    $session = $di->get('session');

    $browser_language = $request->getBestLanguage();

    /**
     * If possible get the $language from the browser
     */
    if (false === strpos($browser_language, '_')) {
        $language = $browser_language . '_' . strtoupper($browser_language) . '.utf8';
    }
    else {
        $language = $browser_language . '.utf8';
    }

    /**
     * If we have $language in the session, use that
     * instead of the browser $language
     */
    // TODO mraspor Add cookie check for locale
    if ($session->has('language') && null !== $session->get('language')) {
        $language = $session->get('language') . '.utf8';
    }

    /**
     * Set up the default $language
     * Here I am using websiteConfig service to retrieve default language from my config file
     */
    $default_language = $di->get('websiteConfig')->defaultLanguage;

    /**
     * Check if the translation directory exists
     */
    $translation_exists = file_exists(APP_PATH . '/app/languages/' . $language)
        ?
        true
        :
        false;

    /**
     * Return gettext for the language
     * (Fall back to the default $language if $language isn't found)
     */
    $translate = new TranslationService(array(
        'locale'        => $translation_exists
            ?
            $language
            :
            $default_language,
        'defaultDomain' => 'messages',
        'file'          => 'messages',
        'directory'     => APP_PATH . '/app/languages/',
        'category'      => LC_MESSAGES,
    ));

    return $translate;

});

And then in whatever controller, I just use:


$this->translation->_("string I am translating");

or in model:


$this->getDi()->translation->_('string I am translating');
#OR
$this->getDI()->get('translation')->_('string I am translating');


11.1k
edited May '16

Oh! Thanks! You give me enough food for reflection))) And the last (I hope) question: is the Phalcon has some method to get names of the Controller or Action, depending on the using controller? Yes, I can get the address of the web-page, and manipulate with them, but I can't be sure, that the chousing part of url exactly will be the Controller or the Action.



12.2k

Sure:


$this->dispacher->getControllerName();
$this->dispacher->getActionName();
#OR
$this->router->getControllerName();
$this->router->getActionName();


11.1k
edited May '16

I was founded, but... How should be look the lang.php file, if I'll be use the GetText Adapter?

With NativeArray everything is clear:

en.php

<?php

// ...

$lang = [
    'text' => 'The Text!'
];

// ...
<?php

// ...

require "../app/languages/en.php";

$translation = new NativeArray([
    "content" => $lang
]);

// ...

But what about the GetText? How does the "en.php" look here?



12.2k
edited May '16

This is my relevant directory tree


├── app
│   ├── languages
│   │   └── hr_HR.utf8
│   │       └── LC_MESSAGES
│   │           ├── messages.mo
│   │           └── messages.po

So, let's imagine you want to create a translation for German language (along side the above Croatian), you would then add/have


├── app
│   ├── languages
│   │   └── hr_HR.utf8              # Croatian
│   │       └── LC_MESSAGES
│   │           ├── messages.mo
│   │           └── messages.po
│   │   └── de_DE.utf8              # German
│   │       └── LC_MESSAGES
│   │           ├── messages.mo
│   │           └── messages.po

Let's imagine that your default language is English (which will be shown if no translation is found).

So, your German messages.po file looks like this:


msgid "yes"
msgstr "ja"

msgid "no"
msgstr "nein"

msgid "Sign-in"
msgstr "Anmelden"

And your Croatian messages.po file looks like this:


msgid "yes"
msgstr "da"

msgid "no"
msgstr "ne"

msgid "Sign-in"
msgstr "Prijava"

.po files cannot be used as it is. You need to convert them to binary .mo files. I use a tool called Virtaal (https://virtaal.translatehouse.org/) for that. Basicly I load a .po file into Virtaal and export a .mo file. This could be of course automated.

And in a controller I use it like this:


$variable = $this->translation->_('Sign-in');

$this->view->setVars([
    'variable' => $variable # or directly $this->translation->_('Sign-in')
]);

And then use the above $variable in your view file.

If you want to do translations directly in volt file you can first pass the translation service as a variable (from controller or better from the base controller):


$this->view->setVars([
    't' => $this->translation
]);

And then use it in .volt file like this:


{{ t._('Sign-in') }}

Hopefully this will set you on a right track.