dongsanhu4784 2019-07-23 14:38
浏览 97
已采纳

禁用给定请求的翻译(laravel)

I'm currently building a Vue.js SPA with laravel as the backend where I need to support multiple locales. I'm therefore considering using Lang.js alongside laravel's built-in translation system to manage the translated stings. I basicly want to manage all the strings in laravel (on the backend) but let the frontend handle the actual translations, to allow the user to switch language dynamicly with a language switcher ui component.

The problem is that when I submit a form request that is validated on the server, the error messages are already translated, thus not allowing the frontend to pick a language on-the-fly.

My question is how I can disable the translation for a given request (preferably using headers in middleware or something like that) and instead print the raw translation keys

For example for the given validation

<?php
function store() {
    request()->validate(['test' => 'required'])
}

The server returns

{
    'message': 'The given data was invalid',
    'errors': {
        'test': 'The test field is required'
    }
}

instead of

{
    'message': 'The given data was invalid',
    'errors': {
        'test': 'validation.required',
    }
}

I have already tried using \App::setLocale('somethinginvalidandrandom') which should technically try to translate the key into a language that doesn't exist, thus returning the key, but besides feeling wrong and hacky, this approach won't work if I want to preserve the fallback language funcionality of laravel, since the key would be found in the fallback language (en).

  • 写回答

2条回答 默认 最新

  • duana1021 2019-07-26 12:04
    关注

    I actually just solved it myself, and thought to reply here in case others where trying to solve the same problem as me in the future.

    Solution

    I added an invalidJson method to my App\Exceptions\Handler class, that Laravel will automaticly call whenever an ValidationException is thrown and $request->wantsJson() is true.

    In that method i just checked if my custom header (X-WITH-UNTRANSLATED-VALIDATION) is present in the request with the value of "yes". If that is the case i get the validator instance from the exception, and grab all the rules.

    However laravel represent these rules internally in "studly caps case" (StartsWith) and we want to get them in a snake case format ("starts_with"). To fix this I used the laravel collection helpers to map over the nested array and convert the rule keys to snake case.

    Code

    Here is the code from app\Exceptions\Handler.php.

    /**
     * Convert a validation exception into a JSON response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Validation\ValidationException  $exception
     * @return \Illuminate\Http\Response
     */
    protected function invalidJson($request, ValidationException $exception)
    {
        //If the header is not present in the request 'no' wil be provided as the fallback value, thus not being equal with "yes"
        if($request->header('X-WITH-UNTRANSLATED-VALIDATION', 'no') === "yes") {
            $failed = $this->makeUntranslatedMessagesIntoSnakeCase($exception);
    
            return response([
                // Get the original exception message
                'message' => $exception->getMessage(),
                'errors' => $failed,
                // Add the original translated error messages under a diffrent key to help with debugging
                'translated_errors' => $exception->errors(),
            ], $exception->status);
        }
    
        //If the header is not present (with the right value) we return the default JSON response instead
        return parent::invalidJson($request, $exception);
    }
    
    /**
     * Convert the untranslated rule names of a validation exception into snake case.
     * 
     * @param \Illuminate\Validation\ValidationException  $exception
     * @return array
     */
    protected function makeUntranslatedMessagesIntoSnakeCase(ValidationException $exception) : array
    {
        return collect($exception->validator->failed())->map(function ($item) {
            return collect($item)->mapWithKeys(function ($values, $rule) {
                return [Str::snake($rule) => $values];
            });
        })->toArray();
    }
    

    Further improvements

    If you need to disable translation for normal "non-json" requests, you can also override the invalid method in the Handler.php and do a similar thing, but just add the messages to the session instead. Likewise you could also add the translated messages alongside the untranslated messages.

    Edit

    I also added 'translated_errors' => $exception->errors(), to the response to help with debugging

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误
  • ¥30 最小化遗憾贪心算法上界
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝