Frankie Roberto 给了你一个很好的答案。我将添加一些额外的信息。
首先是简单的部分:在模型中获取当前语言环境。
如果您将控制器中的语言设置为I18n.locale = something,那么您可以以相同的方式在模型中读取它。毕竟I18n 是一个全局常量。
现在关于搜索:
我通常更喜欢只有一个类别的设计,但该类别的名称被翻译成多种语言。一辆车属于“汽车”类别而另一辆车属于“车辆”的设计是有缺陷的恕我直言。在后一种情况下,将其设为单一站点是没有意义的 - 您可以创建一个单一语言的应用程序,并将其安装在多个实例中,每个实例都被翻译成一种语言。
如果您有一个简短的、静态的受支持语言列表,您可以为每种语言添加一列:name_en、name_fr、name_pl。
如果在设计应用程序时您的语言列表很大或未知,则将“名称”(作为示例)存储为序列化哈希会更容易。因此,您可以得到预期的翻译为name["fr"]、name["de"] 等等。
我已经了解到(困难的方法 :-)) 用户通常懒得提供所有的翻译(或者他们只是不知道所有的语言),因此您应该做好准备,您的某些模型将不包含您尝试显示或搜索的语言的数据。
对于每个“翻译”属性,您可能需要准备一种方法,该方法将为您提供最合适的翻译,以防所需的翻译丢失。
此方法的工作方式可能类似于:
def translated_name
([I18n.locale] + other_languages).each do |l|
return name[l] unless name[l].blank?
end
return "" # or some default value - possibly from I18n.t("some.static.default")
end
当然,您不需要使用 I18n.locale,您应该以(理想情况下)匹配用户语言偏好的方式定义 other_languages,可能通过分析“Accept-Language”标头。
我有时会使用方法名称name_for(lang) 或name_in(lang),如果我必须支持更多的数据语言而不是接口(我将翻译并放入 I18n 配置文件)。
啊,是的 - 搜索。 :)
如果您已将“名称”定义为单独的属性,则只需搜索相应的列即可。
如果您将“名称”作为单个序列化哈希,您可以将列作为简单文本搜索(但是我不确定 YAML 是否不会破坏非 ASCII 字符)或者创建另一个包含可搜索数据的列,然后(在模型级别,而不是在 SQL 级别) 将模型分成组:“搜索字符串已在您的语言中找到”,“The已找到其他语言的搜索字符串”。我相信多语言服务的用户会对以这种方式呈现的搜索结果感到满意。