Backward Compatibility Questions

I was just thinking about another possibility:

Rename that method in YiiBase to “translate”, only support the whole load of parameters and let people define their own shorthand helper method in Yii. Looking into the code, I see there already is a method named “translate” and “t” actually is a shorthand helper method. :D

Now, what I also saw is, "translate" uses the same signature as "t" does. May I suggest to remove the string mangling at least from the "translate" method (I18N component)?

I’m not so picky about the shorthand methods in YiiBase. No problem with taking a pragmatic approach there. If someone doesn’t like it, he can quickly write a wrapper of his own, or use the l18n component directly.

I’m open to suggestions. Note that we should also consider the message extraction tool. The new syntax shouldn’t cause too much difficulty for creating such a tool.

Yeah, was also thinking about that. Will it be based on scanning the source using regular expressions? The only other thing I can think of is collecting strings at runtime. Runtime extraction might be more accurate, because it would cover variables being passed to the translation methods. The downside is, that you first have to run the code and to reach every bit of it…

Idea… Why not use your namespace name as "category" ?

What I did in Yii 1.1:

Created a class named T with some methods msg, atr, act. In Yii2 would look something like:

Class:




namespace yii;


class T {

	public static function msg($message, $context = null, $params = array(), $language = null) {

		return self::translate($message, $context, $params, $language);

	}


	public static function translate($message, $context = null, $params = array(), $language = null) {

		if (Yii::$app !== null) {

			return Yii::$app->getI18N()->translate($message, $context, $params, $language);

		} else {

			return is_array($params) ? strtr($message, $params) : $message;

		}

	}

}



Usage:




namespace myApplication;


use yii\T;


T::msg('name'); // default context [category]


T::msg('name', Person::className()); // name in the Person context


T::msg('name', __NAMESPACE__); // name in myApplication context



As you can see I’m also proposing to rename the “category” parameter to “context” as I think it fits better in the context of translating.

I think its better to introduce another class where the developers can extend from it and customize it as they judge it better. The default method (T::msg) is as short as (Yii::t) and if all translations method are in the same class, it’s easier to create the regex for the message extraction tool.

I can agree with that.

By doing this you’ve only made it more simpler for a very small percentage of users and not actually benefited the end user. This will mostly benefit the core framework and extensions and even in extensions most people have custom categories.

I do and don’t agree with the array method - it solves the problem but isn’t great programming methodology as the parameters aren’t obvious to the user and their IDE.

I would purpose something like:




public static function t($category, $message = null, $params = array(), $language = null)

{

	if ( is_null( $message ) )

	{

		$message = $category;

		$category = 'app';

	}

}


Yii::t('my message');

Yii::t('category', 'my message');



Yes its not the prettiest code you’ll ever see but is just an example and it will require some further code to make sure message is set if params are but solves the problem and practically no overhead.

Also looking at the current method it adds overhead of the strpos and preg_match which it does twice. Once in the t() function and again in the translate() function.

Of course we could just leave it how it is as another option.

For your information, in other frameworks:

  • ZF1 and ZF2: $this->translate($string, $category = ‘’)

  • Symfony2: $translator->trans($string, interpolationArgs = array(), $category = ‘’)

  • Drupal7: t($string, $interpolationArgs = array(), $options = array())

  • Moodle: get_string($string, $category=’’, $interpolationArgs…)

Moodle is not a generic framework, but a popular Learning Management System coded in PHP.

So, with these PHP frameworks the l10n string is the first parameter, and the translation category is an optional second or third parameter.

PHP callbacks use the same format though, a string for a plain function and an array for a class method. I think with proper documentation people will pick it up quickly.

The unfortunate thing about all of those solutions is that, as qiang said, the message command should still be able to easily parse these messages. Right now it uses a single regular expression, so the only format that’s easy to parse is


Yii::t($message, $category = '', $params = array())

which means that if there are parameters but no category, you always have to pass ‘’. I think all of the solutions given in the previous posts, including the array method would probably make it a lot more complicated for parsing.

I have to say at first I also didn’t like the pipe format, but on the other hand, it’s already used for plural forms in Yii 1.

Edit: what would be nice is a property on the i18n component, to configure the default category, instead of it always defaulting to ‘app’. For some (public) apps I prefer to use the name of the app instead. But maybe that’s a discussion for a different topic.

Question is if we need to provide a custom message command. We could as well use some existing solution like xgettext. It doesn’t support javascript out of the box though. And even if there will be a custom message command, I don’t really mind if it is bit more complicated or if it uses a bunch of regular expressions instead of only a single one. As long as it does its job, I’m fine with it. ;)

@Müller & @François Gannaz:

I think it’s more common to use parameterized messages than to use different message contexts or the necessity to specify a target language. That’s why imo the method should allow to skip those two rarely used parameters, even when $params are present.

I prepared a variadic version of the method, providing similar functionality to @Jaggi’s suggestion. You can hava a look at it on my variadic-yii-t branch. I’m not really happy with its parameter naming though…

I think category/context is more common than parameters. Think about modules/extensions, they are required to define the category/context.

If its not backwards compatible and a totally new framework, don’t call it Yii 2 then, give it a new name. Creating a "new"framework what is not backward compatible is completely idiotic. The argument that when you use Yii(1) you don’t need to upgrade because its so good and stable doesn’t pass. If it was so good etc, you didnt need a new designed framework. Its for us a major reason to drop Yii all together.

Zend Framework 2, Symfony2, Laravel 4, CakePHP 3 (and probably others) followed this "idiotic" route too, which reduces your choices significantly…

It’s not totally new framework. The spirit of Yii is still there and concepts are alike. Lots of components code (and sometimes design) are used etc.

Daaamn, people… Do you complain as well that you can not put 1966 Chevrolet Camaro I throttle in the 2009 Chevrolet Camaro V? Well, the same name just different version number, should be backward compatible!