Ruby on Rails 多语言多租户线程问题

问题描述 投票:0回答:1

我们有一个 Ruby on Rails 应用程序,它具有多品牌/多域的概念。外观和感觉会根据请求的域而变化。此外,该网站目前支持两种语言。默认英语,也可以选择法语。

在我们更新它以支持多个品牌之前,URL 要么是默认的(英文),

branddomain.com/page-slug
或者
branddomain.com/fr/page-slug
如果访客选择以法语查看。

We achieved this using the pattern 
scope '(:locale)', locale: /en|fr/ do
  # various URL handler definitions
end

routes.db

当我们开始支持多个品牌时,我们希望利用 Rails 的语言环境并使用诸如

brandone-en
brandtwo-en
brandone-fr
brandtwo-fr
等语言环境。

这使我们能够使用品牌定义的 ERB 文件以及依赖于后备的翻译文件。

为了防止 URL 显示品牌区域设置,我们对每个请求使用了以下方法

def set_locale(&action)
  original_locale = I18n.default_locale
  I18n.default_locale = "en-#{site.slug}"
  # set to locale in param if present otherwise provide language options
  # and set locale from set of options available best suited for the browser
  begin
    I18n.with_locale(params[:locale] || I18n.default_locale, &action)
  rescue I18n::InvalidLocale
    not_found
  end
ensure
  I18n.default_locale = original_locale
end

我们在部署到生产环境时发现的问题是 I18n.default_locale 不是线程安全的。它在所有线程之间共享,因此同时请求会将 default_locale 设置为其他访问者的错误品牌。为了解决这个问题,我们必须将 Puma 减少为高并发的单线程。不理想。

如果有人有此类设置的经验,我们将不胜感激。

ruby-on-rails ruby
1个回答
0
投票

我们使用会话来存储用户的区域设置首选项解决了这个问题

def override_locale
    session['locale_override'] = params.require 'locale'
end

def set_locale
  I18n.locale = ENV['default_locale']
  if current_domain.languages.length > 1
    compatible =http_accept_language.compatible_language_from(I18n.available_locales)
    I18n.locale = session['locale_override'] || compatible || ENV['default_locale']
  end
end
class ApplicationController < ActionController::Base
  before_action :set_locale
© www.soinside.com 2019 - 2024. All rights reserved.