We are moving our forum in GitHub Discussions. For questions about Phalcon v3/v4 you can visit here and for Phalcon v5 here.

Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

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.1k

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.1k
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.1k

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.1k
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 (http://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.