Multi-language, not only in the Viewer but also in the Controllers and Models

I think the way of multi-language in the manual $t->_("something") is only can work in the Viewer~~ How to achieve the multi-language in the whole site?

You can use them anywhere you want. Just docs dont have all the examples.

Usually in my projects i have a BaseController which other controllers extend. in getTranslations() you can use Phalcon docs example for detecting language or you can make custom logic. For exmaple i get the language from the url, but its up to you.

Sample code:

// Base Controller
class BaseController extends \Phalcon\Mvc\Controller
{ 
    public function initialize()
    { 
        // Set them as SHARED service so you can use them anywhere. Note: you can change variable name from T to anything you like. 
        $this->di->setShared('t', $this->getTranslation());
    } 
}

Usage

// Volt 
{{ t._('hi') }}

// Model
$this->getDI()->getT()->_('hi');

// Controller
$this->t->_('hi')

// Custom library / Helper classes
$di = \Phalcon\DI::getDefault();  
$di['t']->_t('hi');


8.1k

Thanks!

My code can't work properly

use \Phalcon\Mvc\Controller;
use Phalcon\Translate\Adapter\NativeArray;

class Base extends Controller
{
    protected function getTranslation()
    {
        $language = "en";

        require APP_DIR . "/lang/" . $language . "/main.php";

        return new NativeArray(array("content" => $messages));
    }

    public function initialize()
    {
        $this->di->setShared('t', $this->getTranslation());
    }
}

it says Notice: Undefined variable: t

Show us the code where you call t?



8.1k
// Base.php is shown above
//ControllerBase.php
class ControllerBase extends Base
{
    public function initialize()
    {
        $this->view->setTemplateBefore("main");
    }
}
//UsersController.php
class UsersController extends ControllerBase
{
}

just in the volt of /view/users/index.volt, I code {{ t._('hi') }}, and it shows the error like above.



34.7k

Hey man

I recommned you add the translate to service to call any where, for example

//Translation application use gettext
$di->set(
    'translation',
    function () use ($di) {
        $language = $di->get('siteLang');
        // if (!file_exists(ROOT_DIR . 'common/messages/' . $language . '.php"')) {
        //     throw new \Exception("You must specify a language file for language '$language'");
        // }
        require ROOT_DIR . 'common/messages/' . $language . '.php';

        //Return a translation object
        return new NativeArray([
           'content' => $messages
        ]);
    },
    true
);

/**
 * Translation function call anywhere
 *
 * @param $string
 *
 * @return mixed
 */
if (!function_exists('t')) {
    function t($string, $params = [])
    {
        $translation = DI::getDefault()->get('translation');
        return $translation->_($string, $params);
    }
}

After that just call {{t('your need to trans')}} in volt

edited Feb '16

An elegant way to use translations in view or volt is through Tag extension (need translate service registered), I use code like this

class Tag extends \Phalcon\Tag
{
    public static function _($translateKey, $placeholders = NULL)
    {
        return self::getDI()->get('translate')->_($translateKey, $placeholders);
    }
}

then in volt you call it as

{{ _('localized text') }}


8.1k

How to call it in Models and Controllers?

An elegant way to use translations in view or volt is through Tag extension (need translate service registered), I use code like this

``` class Tag extends \Phalcon\Tag { public static function ($translateKey, $placeholders = NULL) { return self::getDI()->get('translate')->($translateKey, $placeholders); } } ```

then in volt you call it as

``` {{ _('localized text') }} ```

edited Feb '16

I've done it in my lib :
https://github.com/corentin-begne/phalconTool/
So i use a controller base class :
https://github.com/corentin-begne/phalconTool/blob/master/src/ControllerBase.php
then you can access to the translation in controllers action with $this->__() and $this-> _() and in view with $t->__() and $t->_()
if you need some tranlations inside models then pass the value in params from controller or use model base class and add this functionality.

edited Feb '16

As I wrote, you need to to register "translate" service to DI. Thien gave you an example a few posts ago. By my meaning its the cleanest solution, because your code will be more maintainable and testable. You can pass this service via DI pattern and are not hardcoding it anywhere.

How to call it in Models and Controllers?

An elegant way to use translations in view or volt is through Tag extension (need translate service registered)



8.1k

Could you please show me a more detailed example?

As I wrote, you need to to register "translate" service to DI. Thien gave you an example a few posts ago. By my meaning its the cleanest solution, because your code will be more maintainable and testable. You can pass this service via DI pattern and are not hardcoding it anywhere.

How to call it in Models and Controllers?

An elegant way to use translations in view or volt is through Tag extension (need translate service registered)



8.1k
edited Feb '16

Thanks a lot!

According to your way, is there anyway to load a defferent language file according to the defferent page? like the offical demo PHP alternative site

In this demo, for example, if we visit the index page, it will load messages/en/index.php for language strings, and if we visite the download page, it will load messages/en/download.php for language strings.

here is the function.

Hi

First you need add to DI see here https://github.com/phanbook/phanbook/blob/master/core/config/services.php#L374, then you defined the function t to call anywhere see at https://github.com/phanbook/phanbook/blob/master/core/config/services.php#L460

After that you just using it ,see at https://github.com/phanbook/phanbook/blob/master/core/modules/frontend/controllers/PostsController.php#L171

You can use dispatcher and methods like getModuleName(), getControllerName() and getActionName()



8.1k

Hi, @Thien

define the following function in service.php

if (!function_exists('t')) {
    function t($string, $params = [])
    {
        $translation = DI::getDefault()->get('translation');
        return $translation->_($string, $params);
    }
}

It can work : <?php echo t(&#039;.....&#039;)?>

But I can't user {{ t(&#039;......&#039;) }}!, It says: Macro 't' does not exist, and in php file, it render callMacro('t', Array(...))

why?

edited Apr '16

You need to register it to Volt compiler

$volt = new Volt($view, $di);

$compiler = $volt->getCompiler();
$compiler->addFunction(
    't', function ($resolvedArgs, $exprArgs) {
        return 't(' . $resolvedArgs . ')';
    }
);

https://docs.phalconphp.com/en/latest/reference/volt.html#extending-volt



8.1k

Thanks, @davihu

  1. Is it registered in service.php, like following?
// Setting up the view component
$di->set('view', function() use ($config) {
    $view = new View();
    $view->setViewsDir($config->application->viewsDir);
    $view->registerEngines(array(
        '.volt' => function($view, $di) use ($config) {
            $volt = new VoltEngine($view, $di);
            $volt->setOptions(array(
                'compiledPath' => $config->application->cacheDir . 'volt/',
                'compliedSeparator' => '_'
            ));

            // register here is correct?
            $volt->getCompiler()->addFunction('__', function ($resolvedArgs, $exprArgs){
                return '__(' . $resolvedArgs . ')';
            });


            return $volt;

        },
        '.phtml' => 'Phalcon\Mvc\View\Engine\Php' //// Generate Template files uses PHP itself as the template engine
    ));
    return $view;
}, true);
  1. how to register the function with two params? like the function '__':
if (! function_exists('__')) {
    function __($string, array $placeholder = null)
    {
        $translation = \Phalcon\Di::getDefault()->get('translation');
        return $translation->_($string, $placeholder);
    }
}