【问题标题】:Rails 4 multidomain application with locale set for each domain i18n localeRails 4 多域应用程序,为每个域 i18n 语言环境设置了语言环境
【发布时间】:2014-04-22 06:23:32
【问题描述】:

在 Rails 4 多域应用程序中,我需要为每个域(总共 3 个域)提供 4 种语言的一组语言环境文件。

一些翻译在域之间重叠,但其中一些非常具体,所以我正在考虑一个有点像这样的结构:

config/locales/en.yml ..fr.yml ..de.yml ..it.yml  #is picked up by all domains
config/locales/domain1/en.yml ..fr.yml ..de.yml ..it.yml  #is picked up by domain 1
config/locales/domain2/en.yml ..fr.yml ..de.yml ..it.yml  #is picked up by domain 2
config/locales/domain3/en.yml ..fr.yml ..de.yml ..it.yml  #is picked up by domain 3

这在 Rails 4 中可行吗?如果是这样,那么进行此设置的最佳方法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 rails-i18n


    【解决方案1】:

    config/application 中你会:

    some_domain = Rails.root.basename.to_s # this will give us "myapp.com" if the app is in "/var/www/myapp.com"
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', some_domain, '*.{rb,yml}').to_s]
    

    这将只加载所需的文件并且应该用后面的数据覆盖任何重复的键,但我还没有测试那个位。

    【讨论】:

    • Basename 将只返回 Rails 应用程序名称而不是域名。
    • 域名将由request.domain返回,但在初始化时application.rb当然不可用。
    • 我需要采取不同的方法,因为域总是只有在提出请求时才可用......这是一个鸡蛋问题
    • 另请注意:这是一个提供 3 个不同域名的多域应用程序。
    • 所以你有一个应用程序为 3 个域运行一次?您可能需要考虑部署到不同的路径,以便您可以提前预编译这样的东西。这就是我对这三个所做的:absave.comlabsave.combiosave.com
    【解决方案2】:

    请尝试使用i18n-active_record。因为我们可以将所有locales 存储在database 中。

    在这个 gem 中,他们使用没有关系的 translation 模型,在您的情况下,您可以在 relationdomain 之间创建关系,然后您可以使用 domain 存储所有区域设置,基于获取区域设置时您可以覆盖默认 gem 方法。

    ==> 您的密钥应包含用于查找域的使用域名,或者您可以使用其他方式获取域名,例如 threadenv,您可以保存您的值。

    # 我的猜测键应该是 login-label-test.com domain = Domain.where(:name => namespace.split("-").last).first

    在 gem 中找到translation 时,只需覆盖该方法,请尝试一下。

    我不确定,请尝试一次

    首先将您的locale 文件迁移到db

    require 'yaml'
    
    namespace :locale do
     desc "Copy translations from yml yo db. Non-overwriting."
      task :yml_to_db, [:environment, :locale,:domain] => :environment do |t, args|
        info = YAML::load(IO.read("#{Rails.root}/config/locales/#{args[:locale]}-#{args[:domain]}.yml"))
        domain = Domain.where(:name => args[:domain]).first
        info["#{args[:locale]}"].each do |key, value|
        translation = domain.translations.where(:key => key)
        domain.translations.create!(:key => key, :value => value, :locale => args[:locale]) if translation.blank?
       end
      end
     end
    

    我试图覆盖 gem 中的一种方法:

    require 'active_record'
    
      module I18n
       module Backend
       class ActiveRecord
        class Translation < ::ActiveRecord::Base
    
        belongs_to :domain
    
        TRUTHY_CHAR = "\001"
        FALSY_CHAR = "\002"
    
        self.table_name = 'translations'
    
        serialize :value
        serialize :interpolations, Array
    
          def lookup(keys, *separator)
            # in your keys should contain use domain name for find the domain or you can use some other way to get the domain name like in thread or env you can save your value.
    
            column_name = connection.quote_column_name('key')
            keys = Array(keys).map! { |key| key.to_s }
    
            unless separator.empty?
              warn "[DEPRECATION] Giving a separator to Translation.lookup is deprecated. " <<
                "You can change the internal separator by overwriting FLATTEN_SEPARATOR."
            end
    
            namespace = "#{keys.last}#{I18n::Backend::Flatten::FLATTEN_SEPARATOR}%"
            # my guess key should be login-label-test.com
            domain =  Domain.where(:name => namespace.split("-").last).first
            where("#{column_name} IN (?) OR #{column_name} LIKE ?", keys, namespace).where(:id => domain.id)
           end
       end
      end
     end
    

    请像这样尝试。

    【讨论】:

    • 是的,这可能是一种方法,但我发现它过于复杂。我想将我的翻译保存在 .yml 文件中,以便于访问和编辑。所以这不是我想采取的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2013-12-02
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    相关资源
    最近更新 更多