Ruby on Rails i18n - Want To Translate Custom Messages in Models

前端 未结 4 1768
星月不相逢
星月不相逢 2020-12-13 09:19

I have attributes with special validation where I use the message clause to display a special message just for that validation. Here is one example:

validat         


        
相关标签:
4条回答
  • 2020-12-13 09:52

    Use a symbol for the message:

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

    then in the yaml file

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

    If there's a translation specific to this model, it will override the general one above:

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

    If you write custom validations, add_error(:email, :bad_email) will do the lookup above, but errors[:email] << :bad_email will not.

    0 讨论(0)
  • 2020-12-13 09:57

    The solution to this does not need to be custom; The format validator message already maps to the :invalid symbol. You need only set the invalid in translation.

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

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

    0 讨论(0)
  • 2020-12-13 10:00

    I just walked through all this and found the rails guides for custom validators too hard-coded... I'm posting this here even though it's not exactly what you asked, but the Q title fits perfectly (which is why I read this post for my problem).

    Custom validation with i18n message:

    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!"
    
    0 讨论(0)
  • 2020-12-13 10:10

    I will give a complete example.

    To make your models cleaner, you can create a custom validation helper method in an entirely new directory - app/validations, which will be autoloaded by Rails.

    I'll call my file time_validator.rb, located at app/validations/time_validator.rb

    My file has the following code, which validates user-entered time - that it is actually time.

    # 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
    

    You can read more about creating custom ActiveRecord validations here

    Our main point of concern is the record.errors line. Note that it's attribute and not :attribute, where attribute is the column in your model.

    :invalid_time is the key that retrieves your translated content from your locales file. In my case, this is the en file:

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

    Then in the home model:

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

    time automatically gets mapped to the class TimeValidator, and the methods therein get run.

    Incase this is violated, ActiveRecord will throw an error right below the column name.

    Hope this helps!

    0 讨论(0)
提交回复
热议问题