Ruby on Rails i18n - 想要在模型中翻译自定义消息

Posted

技术标签:

【中文标题】Ruby on Rails i18n - 想要在模型中翻译自定义消息【英文标题】:Ruby on Rails i18n - Want To Translate Custom Messages in Models 【发布时间】:2013-07-29 22:12:33 【问题描述】:

我有带有特殊验证的属性,我使用消息子句来显示仅用于该验证的特殊消息。这是一个例子:

validates :email, presence:   true, length:  maximum: 60 ,
                format:      with: valid_email_regex, message: "is not a valid email address format." ,
                uniqueness:  case_sensitive: false  

我想在这里翻译消息,但我不知道该怎么做。

我见过他们输入如下内容的示例:message: t("some_value_here").我不确定这个名称。我试过这样的消息:t(:bad_email)。我在我的 yaml 文件中执行以下操作只是为了尝试。

activemodel:
  errors:
    bad_email: "is not a valid email address format."

当我尝试访问我的 Rails 应用程序时,出现以下错误:

ActionView::Template::Error (undefined method `t' for #<Class:0x007fefc1b709e0>)

我也在我的 yaml 文件中尝试过这个:

activemodel:
  errors:
    user:
      bad_email: "is not a valid email address format."

我整天都在研究这个问题。我能找到的只是替换内置的错误哈希,如空白或空。有没有办法让我拥有自定义错误哈希并在模型中替换它们?在这一点上,我无法让 t 按编码工作。我希望问题在于我如何设置我的 yaml 文件。我已经看到了如何设置它的不同版本。我不确定是否应该将它放在 activemodel 或 activerecord 下。我假设是 activemodel,因为那是我要翻译的自定义消息。

任何帮助将不胜感激。这是我在启动我的第一个应用程序翻译之前需要弄清楚的最后一部分。

更新 2013 年 7 月 29 日下午 7:30 CDT

bgates 为我提供了一个很好的开始,让我了解如何设置我的模型文件以接收 YAML 文件中的自定义消息。但是,我最终不得不在我的 yaml 文件中进行以下设置才能找到自定义消息。

activerecord:
  errors: 
    models: 
      user: 
        attributes: 
          bio: 
            no_links: "cannot contain email addresses or website links (URLs)."
          email: 
            bad_email: "is not a valid email address format."
          username: 
            bad_username: "can only contain numbers and letters.  No special characters or spaces."

【问题讨论】:

【参考方案1】:

使用符号表示消息:

validates :email, presence:   true, length:  maximum: 60 ,
            format:      with: valid_email_regex, message: :bad_email ,
            uniqueness:  case_sensitive: false  

然后在yaml文件中

[lang]:
  activerecord:
    errors:
      messages:
        bad_email: "just ain't right"

如果有特定于该模型的翻译,它将覆盖上面的通用翻译:

[lang]:
  activerecord:
    errors:
      models:
        model_name: # or namespace/model_name
          attributes:
            email:
              bad_email: "model-specific message for invalid email"

如果您编写自定义验证,add_error(:email, :bad_email) 将执行上述查找,但 errors[:email] &lt;&lt; :bad_email 不会。

【讨论】:

我设置了我的模型和 yaml 文件。我缺少 activerecord.errors.models.user.attributes.email.bad_email 的翻译。我将我在 yaml 文件中所做的更改放在我的描述中。它运作良好。非常感谢您帮助我入门。 我必须使用activemodel 而不是activerecord 作为我的***密钥。更多细节可以在错误source中找到。【参考方案2】:

我刚刚浏览了所有这些,发现 rails guides for custom validators 编码太硬了......我在这里发布了这个,即使它不是你所要求的,但 Q 标题非常适合(这就是我阅读这篇文章的原因为我的问题发帖)。

使用 i18n 消息进行自定义验证:

validate :something_custom?, if: :some_trigger_condition

def something_custom?
  if some_error_condition
    errors.add(:some_field_key, :some_custom_msg)
  end
end

# en.yml
activerecord: 
  errors:
    models:
      some_model:
        some_custom_msg: "This is i18n controlled. yay!"

【讨论】:

【参考方案3】:

这个问题的解决方案不需要定制; format 验证器消息已经映射到 :invalid 符号。您只需在翻译中设置无效即可。

en:
  activerecord:
    errors:
      models:
        some_model:
          attributes:
            email:
              invalid: "FOO"

参考:http://edgeguides.rubyonrails.org/i18n.html#error-message-interpolation

【讨论】:

【参考方案4】:

我会举一个完整的例子。

为了使您的模型更简洁,您可以在一个全新的目录 - app/validations 中创建一个自定义验证辅助方法,该方法将由 Rails 自动加载。

我将调用我的文件time_validator.rb,位于app/validations/time_validator.rb

我的文件有以下代码,用于验证用户输入的时间 - 实际上是时间。

# frozen_string_literal: true

class TimeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    Time.parse(value).strftime('%H:%M')
  rescue ArgumentError 
    record.errors.add(attribute, :invalid_time)
  end
end

您可以阅读有关创建自定义 ActiveRecord 验证的更多信息here

我们的主要关注点是record.errors 行。请注意,它是 attribute 而不是 :attribute,其中 attribute 是模型中的列。

:invalid_time 是从您的语言环境文件中检索翻译内容的键。就我而言,这是en 文件:

en
  activerecord:
    errors:
      models:
        home:
          attributes:
            check_in_time:
              invalid_time: Please enter valid time
            check_out_time:
              invalid_time: Please enter valid time

然后在home 模型中:

validates :check_in_time, time:  allow_blank: true 
validates :check_out_time, time:  allow_blank: true 

time 自动映射到TimeValidator 类,并运行其中的方法。

如果违反此规定,ActiveRecord 将在列名下方抛出错误。

希望这会有所帮助!

【讨论】:

以上是关于Ruby on Rails i18n - 想要在模型中翻译自定义消息的主要内容,如果未能解决你的问题,请参考以下文章

思考Ruby On Rails的底层代码(Ruby on Rails 開發秘籍 | Ruby on Rails 快速入門)

新手入门 Ruby On Rails 必备的知识体系

Ruby on Rails Installation(Learn Rails5.2)

Ruby on Rails - 控制器子目录

覆盖Ruby on Rails中的保存

如果 Ruby on Rails 中有设置限制,如何显示特定的 div 元素