Symfony 6中DoctrineBehaviors多默认Locale回退方案问询
实现双重Locale回退的优雅方案
1. 重写实体的getTranslation方法
DoctrineBehaviors的TranslatableTrait默认只支持单Locale回退,我们可以在实体中重写getTranslation()方法,自定义多优先级回退逻辑:
use Knp\DoctrineBehaviors\Contract\Entity\TranslatableInterface; use Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait; class YourEntity implements TranslatableInterface { use TranslatableTrait; /** * 自定义翻译获取逻辑:优先目标locale,依次回退到en、fr */ public function getTranslation(?string $locale = null): YourEntityTranslation { $targetLocale = $locale ?? $this->getCurrentLocale(); // 先尝试目标语言翻译 if ($this->hasTranslation($targetLocale)) { return $this->translations[$targetLocale]; } // 按优先级检查回退语言列表 $fallbackLocales = ['en', 'fr']; foreach ($fallbackLocales as $fallbackLocale) { if ($this->hasTranslation($fallbackLocale)) { return $this->translations[$fallbackLocale]; } } // 极端兜底:返回任意现有翻译或抛出异常 if (!empty($this->translations)) { return reset($this->translations); } throw new \RuntimeException('该实体无可用翻译'); } }
2. 全局统一回退逻辑(可选)
如果需要在所有实体中统一应用该回退规则,可以自定义TranslatableSubscriber替换默认监听器:
步骤1:创建自定义监听器
namespace App\EventListener; use Knp\DoctrineBehaviors\EventSubscriber\TranslatableSubscriber; use Knp\DoctrineBehaviors\Model\Translatable\TranslatableInterface; class CustomTranslatableSubscriber extends TranslatableSubscriber { protected function getFallbackLocale(TranslatableInterface $translatable): string { // 按优先级检查回退语言 foreach (['en', 'fr'] as $locale) { if ($translatable->hasTranslation($locale)) { return $locale; } } // 最终回退到Symfony默认配置 return $this->localeProvider->getLocale(); } }
步骤2:替换默认服务
在config/services.yaml中覆盖默认监听器:
services: Knp\DoctrineBehaviors\EventSubscriber\TranslatableSubscriber: class: App\EventListener\CustomTranslatableSubscriber arguments: $localeProvider: '@Knp\DoctrineBehaviors\Provider\LocaleProvider' tags: - { name: doctrine.event_subscriber }
3. 验证路由Locale切换
确保控制器中正确处理Locale切换逻辑:
// 基类控制器中统一设置Locale public function setLocale(Request $request): void { $locale = $request->attributes->get('_locale'); if (in_array($locale, ['en', 'fr', 'de'])) { $request->setLocale($locale); $this->get('session')->set('_locale', $locale); } }
以上方案完全满足需求:当目标语言无翻译时,自动按en > fr的优先级回退;若实体无en翻译,所有语言路由均显示fr内容;若实体仅存en翻译,所有路由都显示en内容。
内容的提问来源于stack exchange,提问作者Ryierth
相关产品推荐
相关产品推荐

