Searching for hours but cannot find the solution.
I have a translation key:
en:
welcomes
index:
welcome: Hello World!
Using I18n's "lazy loading" I can use <%= t('.welcome') %> which works perfectly fine.
However, when I do something like:
# in welcomes/index.html.erb
<%= t('.welcome_abc') %>
I expect a "translation missing" to be presented but instead it translates to "Welcome Abc".
I cannot find a setting at https://guides.rubyonrails.org/i18n.html that creates this behaviour.
How do I get the "translation missing" error here?
SOLUTION!
Apparently there still is a missing key.
According to https://apidock.com/rails/v6.1.3.1/ActionView/Helpers/TranslationHelper/translate when there is a MissingTranslation it will render an inline span that contains "the missing key as the value of the title attribute"
Welcome Abc
Related
I am trying to perform a simple customization on all of the validation error messages on a form in my rails app. Simply, I want to go from: can't be blank and is invalid to Can't be blank, Is invalid, etc. Is there a way to do this in my translations that won't require customizing every single individual error message?
If you have a class or some way of creating a css selector you can use:
.error-msg:first-letter{
text-transform: capitalize
}
Another option is you could change your config/locales/en.yml file like so:
en:
errors:
messages:
blank: "Can't be blank"
invalid: "Is invalid"
...
You could try changing it in your view using the capitalize method.
In your view:
<% m.errors.each do |attr, msg| %>
<%= msg.capitalize %>
<% end %>
I've got a set of locales, as listed below. When an error message is triggered, it will pull in the name of the attribute and prepends it before the error message.
The error result for the points value being blank on submit is, "value points value can't be blank".
How do I remove the {%attribute} name in the error message?
en:
activerecord:
attributes:
referral:
email: The email address you entered
errors:
models:
answer:
attributes:
value:
blank: points value can't be blank
I've also tried to add the message in the model, but to no avail (it still prepends the attribute name).
validates_presence_of :value, :message => "points value can't be blank"
Thanks in advance!
I would do this by localizing the attribute name, rather than prevent it from being added to the message:
en:
activerecord:
attributes:
answer:
value: "points"
You could try accessing each message value from the errors in the object you're trying to create, and within each message, to access it's first value (as it's an array), something like:
<% answer.errors.messages.values.each do |message| %>
<li><%= message.first %></li>
<% end %>
This might be I18n-ception but lets say I have an en.yml file as below
en:
my_var: Foo
my_message: "This is a message where I'd like to interpolate I18n's %{my_var}"
Is there a way to indicate to I18n that %{my_var} should be the my_var key in en.yml?
I know I could accomplish it by doing something like
I18n.t 'my_message', :my_var => I18n.t('my_var')
but I was hoping I18n has a way to self reference keys.
This is actually a pretty common question, but the short answer is no, this isn't possible unfortunately :(
Currently I struggle for it... And finally I create a custom yaml type.
in init section.
Psych.add_builtin_type('i18n') { |_type, value|
->(_key, _options) do
value.gsub(/%\{([\w.]+)\}/) do |match|
key = $1.to_sym
if I18n.exists?(key)
I18n.t(key)
else
match
end
end
end
}
I18n.reload!
in en.yml
en:
my_var: Foo
my_message: !!i18n "This is a message where I'd like to interpolate I18n's %{my_var}"
!!i18n apply custom builtin type.
As you said, maybe it is not a so straight solution to call twice from the view to the translation
<%= t("my_message", my_var: t("my_var") ) %>
but gives you the flexibility to call with a variable
<%= t("my_message", my_var: t("my_#{$item[:slug]}") ) %>
I have user.errors which gives all errors in my controller. So, i have the field :user_login which has its error(s). How can i get full error messages from user.errors ONLY for that field?
I can get just text of this field like that:
user.errors[:user_login] # Gives that 'can't be empty'
But i really want to do something like that
user.errors.get_full_message_for_field[:user_login] # 'Your login can't be empty'
Well, I know this question was explicitly posted for Rails 3.x, one and a half years ago, but now Rails 4.x seems to have the very method you were wishing, full_messages_for.
user.errors.full_messages_for(:user_login) #=> return an array
# if you want the first message of all the errors a specific attribute gets,
user.errors.full_messages_for(:user_login).first
# or
user.errors.full_messages_for(:user_login)[0]
It's less verbose than the previously used user.errors.full_message(:user_login, user.errors[:user_login].first).
Have a look at full_message here:
http://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-full_message
A bit verbose but you may be able to do something like:
user.errors.full_message(:user_login, user.errors[:user_login])
We can get the error message of particular field by using
<%= resource.errors.full_messages_for(:email).join("") %>
output : Email cant be blank
If you want to check the particular field has error or not then check it by using
resource.errors.include?(:email)
output : true/false
Here is the code snippet for displaying only the first error for each field.
<!-- Display only first error for each field --->
<% entity.attributes.keys.each do |key| %>
<% if entity.errors.full_messages_for(key.to_sym).length > 0 %>
<li><%= entity.errors.full_messages_for(key.to_sym).first %></li>
<% end %>
<% end %>
I have partial view that displays model-specific flash messages. The partial looks like:
app/views/mymodel/_flashpartial.erb
<% flash.each do |key, value| %>
<% if model_key = myModelFlash(key) then %>
<%= content_tag(:div, value, :class => "flash #{model_key}") %>
<% end %>
<% end %>
The myModelFlash method simply takes the key and checks for a particular prefix using a simple regex. It's located in
app/helpers/mymodelhelper.rb
module MyModelHelper
def myModelFlash( key )
m = /^_mymodel_(.*)/.match(key)
m[1] unless m.nil?
end
end
This works perfectly fine in my development and test environments. As soon as it goes onto Heroku, I get an error saying (ActionView::Template::Error) "can't convert Symbol into String" pointing to the call to match.
If I remove the call to myModelFlash from the view and simply display the key and value, that works just fine in terms of not erroring out, so at the very least the key and value are getting into the partial view just fine. For some reason the helper method thinks that the key being passed into it is a symbol and not a String.
Any ideas as to why this might be happening?
I suggest you just use key.to_s as a quick workaround.
The reason for your problem may be that some version of some component differs between your testing server and the production server.
If your tests pass, and your production environment crashes, that is a very bad situation.
You should compare the versions of ruby and all of the gems you are using. If you use 'bundler' then 'bundle list' gives a nice summary.
If you find out that all the versions are the same... Well, we will be looking for another reason.
Update
As it seems that the problem is caused not by the version differences, but by unexpected data in flash, which obviously in production environment may be different than in testing.
I suggest you change the myModelFlash method a little.
def myModelFlash( key )
if m = /^_mymodel_(.*)/.match(key.to_s)
return m[1]
end
end
The flash may contain different keys, some of them may be Symbols or really anything, so you must be prepared to handle all of them.
Converting the key parameter with .to_s should be a safe choice, but if you are sure that you always set the flash keys (I mean the keys related to this "_mymodel" issue) as Strings, you may change the first line of this method:
def myModelFlash( key )
if key.is_a?(String) && m = /^_mymodel_(.*)/.match(key.to_s)
return m[1]
end
end
And in your test, add a few other keys to your flash, and then test how the action handles them.