How to use $this->_() in zend framework views?

2019-05-18 04:56发布

问题:

In my ZF 1.11 application I'm storing my translator in registry like this:

Zend_Registry::set('Zend_Translate', $translator);

So in my view scripts I can access the translator this way:

$this->translate('abc');

Is there any clever way to be able to use this call instead:

$this->_('abc');

Using $this->translate clutters the views, and lot's of people are used to seeing _() anyway.

回答1:

Whereas I generally agree with the notion that function/method names should be meaningful, I also agree that the _() for translations is a widely used standard and therefore acceptable.

You can do this by adding wrappers to your intermediate layers. For example the following would make the method available to all your controllers derived from MyProject_Controller_Action:

class MyProject_Controller_Action extends Zend_Controller_Action 
{
    protected $translator;

    public function init()
    {
        $this->translator = Zend_Registry::get('Zend_Translate');
    }



   /**
    * Translator wrapper
    * 
    * @param string $string The string to be translated
    * @return string $translated The translated string
    */
    protected function _($string)
    {
        $translated = $this->translator->translate($string);
        return $translated;
    }
}

Of course the same can be done with Zend_View.

Disclaimer: It is not the best practice to clutter your code with direct calls to the registry. Actually it's an anti-pattern which should be replaced by DI. Zend Framework 2 will make it much easier for us to avoid the registry. This code could be improved by actually injecting the translation object into the class via constructor.



回答2:

No, not that I know of. There are several implicit issues related to that anyway. First, you should always give functions (and variables for that matter) meaningful names. That said, __() is not a meaningful name at all. Quite the opposite, in fact, it has no meaning. Second of all, it is considered best practice to prefix only private and protected functions (and, again, variables for that matter) with an underscore.

Finally, with the way zend view helpers work, you would pretty much have to sorta "trick" the system into locating your view helper if it was named __(). You would have to name it something like Zend_View_Helper___ and that wouldn't work. Not to mention, that would entail having to name your file __.php.

I suppose you could name your helper Zend_View_Helper_T, in which case you could translate stuff using $this->t($string); (I tested this and it works), but again you should always use meaningful names.


Edit

Having not realized that you wanted to call this from within the controller until now, I decided to revise my answer and give a little feedback about the comment I received from the down voter..

It's hard to recommend that you create a wrapper class for Zend_Controller_Action in which to create a function _() for the following reason:

  • Because regardless it being an "accepted standard" or not, I reiterate that that all methods and variables should have a meaningful name. I must assert this because I am a firm believer in following explicit coding standards (as opposed to those "hearsay" or "recently-adopted" practices that don't directly correspond to a known - and thereby trusted - paradigm). That said, should PEAR, or even Zend, decide to adopt such a radical change some day, I will resign my disposition. NOTE: It could be argued that credible companies like Drupal and their self-proclaimed best practices could be considered explicit coding standards but I disagree. Why? Because PEAR is...well...it's PEAR. And Zend is "The PHP Company." It's hard to get more credible than that. If anyone disagrees with that last statement please state why or correct me instead of down voting. Regardless, standards are merely a suggestion not required; therefore, they should be treated as such. So, I guess as long as you're following some standard then that's good! These are not rules after all.

Nevertheless, markus' solution was good other than the function name (for reasons stated previously). The only thing I would change is the call to Zend_Registry::get() in the _() function. If you plan to call that function as much as you alluded to, then something like this might work better:

class MyProject_Controller_Action extends Zend_Controller_Action 
{
    /**
     * the translator object
     * @var Zend_Translate
     */
    protected $_translator;

    public function init()
    {
        $this->_translator = Zend_Registry::get('Zend_Translate');
    }

    /**
     * note my new method name, you don't have to use it but I still
     * recommend it. the name is just a suggestion, if you prefer something
     * like _translate() or _trnslte() then by all means (although I don't
     * recommend abbreviations unless they're super obvious I guess).
     */
    protected function _trans($string)
    {
        return $this->_translator->translate((string) $string);
    }
}