Why HTTP Statuses are not translated in core framework?

In an non-English Yii 2 application, I have every part of my site/error view perfectly translated… except for title. Which even in non-English application still says " Not Found (#404)".

Why is that? How to workaround this problem?

I have narrowed down the problem to the yii\web\Response::$httpStatuses property. Which for some weird reason does not use Yii:t, but a direct English messages:

/**
 * @var array list of HTTP status codes and the corresponding texts
 */
public static $httpStatuses = [
    100 => 'Continue',
    101 => 'Switching Protocols',
    102 => 'Processing',
    ...
    404 => 'Not Found',
    ...

Why? Is there a reasonable explanation for that?

What should I do in this case?

Shall I override httpStatuses property in application’s configuration?

'response' => [
    'format' => yii\web\Response::FORMAT_HTML,
    'charset' => 'UTF-8',
    'httpStatuses' => [
        100 => 'Kontinuita',
        101 => 'Prepínacie protokoly',
        102 => 'Spracovanie',
        ...
        404 => 'Nenájdené',
        ...
    ]
]

I am joking. This won’t work (Setting unknown property: yii\web\Response::httpStatuses).

Shall I override yii\web\Response to my own version to make httpStatuses property use Yii:t() like they should from the very beginning?

This also sounds like a crazy idea.

Is there any other approach to this?

It wouldn’t be that bad assuming you have proper tests in your app so you are prepared for any base class changes (which shouldn’t happened without proper notice anyway) which would break you code.

Thanks for sharing your thoughts on my idea. Fortunately, this is a low-level, far-milestone task, so I still have some time to consider resolution here.

I think there will be no class changes to Yii 2 anymore, except the ones to fix serious security issues (and I don’t think that there can be any serious security issue around table that returns some texts; this is the only thing that I am going to override, if I’ll go with this idea).

I think that the whole core team is 100% occupied with developing Yii 3 (minus those possible security issues found in Yii 2). And that Yii 2 is already or soon will be in security-maintainance mode, slowly being phased out.

As I said, solving this issue isn’t a problem. It much more bothers me, why it was done like that? I am waiting, if @samdark or someone else out of core team has a spare minute to shed a light on this? Was it simply omitted due to being forgotten? Or was it left as it is intentionally (i.e. 100% compatibility with core HTTP Statuses RFC)?

I haven’t traced the Response lifecycle but I’m betting on it is for performance reasons. If the array (67 elements) would be resolved with translations on every request, the process would be unnecessarily heavy.

Good point!

I made only basic tracing and, if I am correct, though yii\base\Request component is indeed used in every life-cycle or every request, the array itself is used only in erroneous conditions. Like using yii\web\ErrorAction or yii\web\NotFoundHttpException. I.e. in scenarios where you doesn’t get much attention to performance, because your application is already dying.

When I decide to follow this path, I’ll have to of course do much more tests on this. Thanks for pointing this out.

Note that these statuses are used in response header, so I would not advise to change them. If you want translated error messages, I suggest to process these exceptions in error action instead of changing anything in Request class.

2 Likes

Dump question: if I understand you correctly all that matters for you is your page title?
So why don’t you just translate that one instead of overwriting the class?
Somewhere in your error html you have to output the title - you could change that.

Thanks, you have finally explained why these errors are not traslated (are not using Yii:t() in first place.

Yes, you are correct. But it isn’t that easy.

The title is set like this (site/error route, so error action of the site controller):

<?php

/** @var yii\web\View $this */
/** @var string $name */
/** @var string $message */
/** @var Exception $exception */

use yii\helpers\Html;

$this->title = $name;

?>

<h1><?= Html::encode($this->title) ?></h1>

and the actual page title ($name) is set by framework itself, not me, because I am using the default solution from the Yii app:

public function actions()
{
    return [
        'error' => [
            'class' => \yii\web\ErrorAction::class,
        ],
        'captcha' => [
            'class' => \yii\captcha\CaptchaAction::class,
            'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
        ],
    ];
}

But, dropping the above idea, in favor of my own error action (as rob066 suggests) should solve the problem at all. Thanks.