php – Yii2: How to force using fallback MessageFormatter method?-ThrowExceptions

Exception or error:

My website is with a hosting provider that has the MessageFormatter class available on the server (Linux, PHP 7.0.27) but it is an old ICU version (4.2.1) that doesn’t support my message {number,plural,=0{# available} =1{# available} other{# available}} and gives the error:

Message pattern is invalid: Constructor failed

msgfmt_create: message formatter creation failed: U_ILLEGAL_CHARACTER

…because of the =1 and =2 notation.

I’m not able to make changes to the server so how can I force using the fallback method provided by Yii2 which works just fine?

How to solve:

There is this hacky way you can try.

Copy the yii\i18n\MessageFormatter code to a new file. Name it MessageFormatter.php and place somewhere in your application (but not in vendor folder).

In this new file change the format() method to:

public function format($pattern, $params, $language)
{
    $this->_errorCode = 0;
    $this->_errorMessage = '';

    if ($params === []) {
        return $pattern;
    }

    return $this->fallbackFormat($pattern, $params, $language);
}

Don’t change anything else (including namespace).

Now let’s use Yii mapping.

Find a place in your application when you can put code that will be run every time in bootstrapping phase. Good place for this is common/config/bootstrap.php if you are using “Advanced Template”-like project.

Add there this line:

Yii::$classMap['yii\i18n\MessageFormatter'] = 'path/to/your/MessageFormatter.php';

Obviously change the path to the one you’ve chosen. Now Yii autoloader will load this class from your file instead of the original Yii vendor folder (as mentioned in Class Autoloading section of the Guide).

In the modified file MessageFormatter method presence of intl library is never checked so fallback is used as default.

The downside of this trick is that you need to update manually your file every time original Yii file is changed (so almost every time you upgrade Yii version).


Another approach is to configure I18N component in your application to use your custom MessageFormatter where you can extend the original file and just override format() method inside without modifying class map.

Leave a Reply

Your email address will not be published. Required fields are marked *