You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Laravel服务提供者缓存翻译仅返回德语,期望获取德英双语

Laravel服务提供者缓存翻译时,英语(en)返回德语(de)内容的问题排查

我在Laravel中实现了一个服务提供者,用来读取lang目录下的德语(de)和英语(en)翻译文件,并把所有翻译内容缓存到文件里。目前功能能正常运行,但不管是德语还是英语的翻译结果,返回的全是德语内容,完全不符合我想要的双语预期。

我的服务提供者代码:

$minutes = 24 * 60;
Cache::remember('translations', $minutes, function () {
    $directories = array('de', 'en');
    $collection = new \stdClass;
    foreach ($directories as $directory) {
        $path = resource_path('lang/' . $directory);
        $allTranslations = collect(File::allFiles($path))->flatMap(function ($file, $directory) {
            return [
                ($translation = $file->getBasename('.php')) => trans($translation, array(), null, $directory),
            ];
        });
        $allModuleTranslations = collect(File::allFiles($path . '/modul'))->flatMap(function ($file, $directory) {
            return [
                ($translation = $file->getBasename('.php')) => trans('modul/' . $translation, array(), null, $directory),
            ];
        });
        $collection->$directory = $allTranslations->merge($allModuleTranslations);
    }
    return json_encode($collection);
});

当前返回的错误结果示例:

{
    "de": {
        "auth": {
            "failed": "Diese Zugangsdaten wurden nicht in unserer Datenbank gefunden.",
            "throttle": "Zu viele Login Versuche. Versuchen Sie es bitte in :seconds Sekunden."
        }
    },
    "en": {
        "auth": {
            "failed": "Diese Zugangsdaten wurden nicht in unserer Datenbank gefunden.",
            "throttle": "Zu viele Login Versuche. Versuchen Sie es bitte in :seconds Sekunden."
        }
    }
}

问题原因分析

问题出在flatMap的闭包参数和变量作用域上:

  1. flatMap的回调函数默认接收两个参数:当前文件对象数组的键值,你这里把第二个参数命名为$directory,这会直接覆盖外层循环的$directory变量(也就是当前遍历的语言目录:de/en)。
  2. 更关键的是,闭包默认无法访问外层的$directory变量,所以你在trans()方法里传入的$directory其实不是你想要的语言标识,而是flatMap遍历的数组键(通常是数字索引),最终trans()方法会 fallback 到应用的默认locale(德语),所以不管循环哪个语言目录,都返回德语翻译。

修复方案

修改flatMap的闭包,通过use ($directory)引入外层的语言目录变量,同时修改回调的第二个参数名避免冲突:

$minutes = 24 * 60;
Cache::remember('translations', $minutes, function () {
    $directories = array('de', 'en');
    $collection = new \stdClass;
    foreach ($directories as $directory) {
        $path = resource_path('lang/' . $directory);
        // 这里修改:用use($directory)引入外层变量,第二个参数改为$key避免冲突
        $allTranslations = collect(File::allFiles($path))->flatMap(function ($file, $key) use ($directory) {
            return [
                ($translation = $file->getBasename('.php')) => trans($translation, [], null, $directory),
            ];
        });
        // 同样修改模块翻译的闭包
        $allModuleTranslations = collect(File::allFiles($path . '/modul'))->flatMap(function ($file, $key) use ($directory) {
            return [
                ($translation = $file->getBasename('.php')) => trans('modul/' . $translation, [], null, $directory),
            ];
        });
        $collection->$directory = $allTranslations->merge($allModuleTranslations);
    }
    return json_encode($collection);
});

修复说明

  • use ($directory):让闭包可以访问外层循环的语言目录变量(de/en),确保trans()方法能拿到正确的locale参数。
  • 把回调的第二个参数从$directory改为$key:避免覆盖外层的语言变量,同时符合flatMap回调的参数定义(第二个参数是遍历的键)。

修改后,trans()方法会根据传入的$directory参数正确加载对应语言的翻译文件,最终缓存的结果就能同时包含德语和英语的正确翻译了。

内容的提问来源于stack exchange,提问作者dns_nx

火山引擎 最新活动