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的闭包参数和变量作用域上:
flatMap的回调函数默认接收两个参数:当前文件对象和数组的键值,你这里把第二个参数命名为$directory,这会直接覆盖外层循环的$directory变量(也就是当前遍历的语言目录:de/en)。- 更关键的是,闭包默认无法访问外层的
$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




