您可以将includes
员工 + 他们的 job_function 翻译,这是n+2 查询
这是我的演示,产品模型包含许多版本模型,这些模型已经为名称属性设置了移动性,分别对应于您的公司、员工、工作职能。
class Version < ApplicationRecord
belongs_to :product
extend Mobility
translates :name, locale_accessors: [:en, :ja], backend: :table
end
class Product < ApplicationRecord
has_many :versions
has_many :translation_versions, -> {
i18n{name.not_eq(nil)}
.select("versions.*,
version_translations_#{Mobility.locale}.name AS translate_name")
}, class_name: "Version"
end
使用默认语言环境:en
Product.includes(:translation_versions).first.translation_versions
.map(&:translate_name)
# SELECT "products".* FROM "products" ...
# SELECT versions.*, version_translations_en.name AS translate_name
# FROM "versions" LEFT OUTER JOIN "version_translations" "version_translations_en"
# ON "version_translations_en"."version_id" = "versions"."id"
# AND "version_translations_en"."locale" = 'en'
# WHERE "version_translations_en"."name" IS NOT NULL AND "versions"."product_id" = ? ...
# => ["v1", "v2"]
使用语言环境:ja
Mobility.locale = :ja
Product.includes(:translation_versions).first.translation_versions
.map(&:translate_name)
# ...
# => ["ja v1", "ja v2"]
所以只有一个查询。
如果您的backend
设置是 KeyValue,翻译表不仅会分隔locale
(type
字符串,文本,...),而且您已经决定了属性的类型,对吗?例如:名称:字符串。这样您仍然只需要设置动态语言环境。
class Product < ApplicationRecord
has_many :translation_versions, -> {
i18n{name.not_eq(nil)}
.select("versions.*,
Version_name_#{Mobility.locale}_string_translations.value AS translate_name")
}, class_name: "Version"
end
查询与上述相同。
当然,您可以translation_versions
更一般地通过将其分成一个模块,用Version
类名,name
目标属性替换并制作一个类似于translation_#{table_name}
.