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

Rails 6应用路由Locale约束配置:实现仅匹配指定语言并拦截非法路径

Rails 6 路由Locale约束失效问题解决

嘿,我之前也踩过类似的Rails路由Locale匹配的坑,你的问题其实是路由优先级+未约束的全局路由在搞鬼,我来给你理清楚整个过程:

问题场景

你在Rails 6应用里配置了带Locale的路由,初衷是让不同语言加载特定路由:

scope '(/:locale)' do
  resources :posts
end

这个配置原本能正常工作:支持/it/posts/de/posts,以及默认语言为it的/posts路径。但麻烦的是,不存在的URL(比如website.com/fakepath)会被错误解析成Locale,而不是返回404。你尝试了两种约束配置都没生效:

# 尝试1:直接在scope里指定locale正则
scope '(/:locale)', locale: /it|de/, defaults: { locale: "it" }
# 尝试2:用constraints参数
scope '(/:locale)', constraints: { locale: /it|de/ }

问题根源

后来你发现了关键:在scope外部还有一条未加约束的路由

get '/:locale', to: 'pages#index'

这条路由没有任何Locale限制,会接收所有匹配/:locale格式的请求——不管这个路径是不是合法的Locale值。而且因为路由匹配是从上到下的,这条全局路由的优先级会覆盖你在scope里设置的约束,导致非法路径被这条路由“接住”,自然不会返回404。

解决方案

给这条全局的/:locale路由加上Locale约束就搞定了!推荐直接用I18n的可用语言列表生成正则,这样不用硬编码语言代码,后续新增语言也不用改路由:

get '/:locale', to: 'pages#index', constraints: { locale: Regexp.union(I18n.available_locales.map(&:to_s)) }

现在只有匹配I18n.available_locales里的语言代码(比如it、de)的路径才会被这条路由处理,非法路径就会正常返回404错误啦。

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

火山引擎 最新活动