我们对于需要实施的功能存在困境。我们希望在我们的应用中支持n
种语言(0 < n < +infinity
)。
我们决定采用以下解决方案:
module TranslatedAttributes
def use_translated_attributes
has_many :translated_attributes, as: :owner
accepts_nested_attributes_for :translated_attributes
define_method :translate_attribute do |attribute, locale = I18n.locale|
TranslatedAttribute.where(attribute_name: attribute.to_s, owner_type: self.class.model_name, owner_id: self.id, locale: locale.to_s).first.try(:translation)
end
end
end
例如,用户应该能够为产品模型的实例定义X翻译。此外,根据用户在其个人资料中设置的区域设置,他将看到该属性的翻译版本。
示例:
Product
id: 12
TranslatedAttribute
attribute_name: 'name'
owner_id: 12
owner_type: 'Product'
locale: 'en'
translation: 'Magnificent shiny shoes'
TranslatedAttribute
attribute_name: 'name'
owner_id: 12
owner_type: 'Product'
locale: 'fr'
translation: 'Magnifiques chaussures brillantes'
在视图中,它将被称为:
product.translate_attribute(:name)
# or we will eventually define_method for each attribute to be translated
# so we could use the following
# product.name
这项工作已经过测试。
问题当我们尝试加载大量记录时,每个记录都需要查询数据库以了解要显示的正确翻译。
我的问题是:您如何处理CACHE?
我的另一个问题是:你看到的另一个问题是我到目前为止看不到的吗?另外,我考虑accepts_nested_attributes_for :translated_attributes
使用fields_for
构建翻译表单。你觉得像这样处理它是个坏主意吗?
谢谢!
答案 0 :(得分:2)
您可以使用globalize3 gem之类的内容来实现此功能。
答案 1 :(得分:1)
第一个优化可能是在第一次调用translate_attribute
时获取Product实例的所需语言环境[1]中的所有翻译,并将它们缓存在实例变量中。
这样,产品实例的翻译请求数量将减少到只有一个。
快速举例:
define_method :translate_attribute do |attribute, locale = I18n.locale|
locale = locale.to_s
@attributes_translations_cache ||= {}
@attributes_translations_cache[locale] ||= Hash[
self.translated_attributes
.where(locale: locale)
.map do |translated_attribute|
[translated_attribute.name, translated_attribute.translation]
end
]
@attributes_translations_cache[locale][attribute]
end
我认为也应该以{{1}}或至少join
以某种方式对产品进行翻译,但我还没有考虑过这个想法。我将尝试更新此答案。
[1]这假设您只在给定页面中使用单个区域设置,但您也可以同时获取所有区域设置,或者区域设置和属性的任意组合。