Rails own config/initializers updated and doesn't display changes - ruby-on-rails

I work on a web app that was already coded, and I have to bring some new features to improve it. I have to add 2 field in the rails admin, and there are some file type that I have never work with like .yml files.
I have a file called : simple_form.fr.yml, that permit to use on the view : human_attribute_name on a class. but I made a modification on a line (change "hello" to "hello world" for example) and I can't see the modification on the view ...
Should I did a command line to make modifications available ?
Thank ! (don't hesitate to ask if you need more precisions / code, I'll update my question)
EDIT
The yml document :
fr:
simple_form:
labels:
school:
code_online_access: "Accès code en ligne"
the line that I change is code_online_access, I juste change the content of the string and in the view I have this line :
<%= School.human_attribute_name("code_online_access") %>

The problem is that you're changing a label for simple_form, but expect the change to show up in human_attribute_name. This method does not look in simple_form's section.
Take a look at this section of I18n rails guide to learn correct place to put your translations to.
en:
activerecord:
models:
user: Dude
attributes:
user:
login: "Handle"
# will translate User attribute "login" as "Handle"
then
User.human_attribute_name("login") # => 'Handle'

Related

Rails I18n switch key based on user permissions

I have a namespace in my routes:
namespace :fruit do
resources :apple, only [:create, :destroy]
resources :banana, only [:show]
end
and also the same key in my translation file:
en:
fruit:
apple:
name: apple
banana:
name: banana
This works just fine, what I want to do is to be able to use a completely new key for the namespace part if my user has particular permissions (user.is_a_vendor?). So for a vendor I would like the translations to be t('vendor.apple.name') instead of t('fruit.apple.name') for example but I don't want to have to conditionally do this in all of my views. Is there a way to centrally switch the keys based on the user? This seems like there should be a simple solution but I can't seem to figure it out.
I have a lot of views that already have their keys set and they use lazy loading so I was wondering if there's a way to conditionally change the lazy loading to use a different key in the top.
EDIT:
I don't want to use my own custom locale since I might want to have translations for these in other languages other than English and if I do that, this solution would lead to problems. I also don't want to use a helper since that would check the conditional every single time, I'd rather have it just select a locale key automatically. Some more research lead me down the path of i18n custom backends: https://guides.rubyonrails.org/i18n.html#using-different-backends, https://www.rubydoc.info/github/svenfuchs/i18n/master/I18n/Backend/Base#eager_load!-instance_method and it might be what I need to use to do this?
I would write a helper that did the switch for you. You then use your custom helper everywhere in your views, and within the helper decide which parent namespace you want to concatenate with the requested translation.
I think you can create a vendor locale (eg. en_vendor) then switch locale base on user type, so both cases you can keep the key t('fruit.apple.name') or lazy lookup t('.apple.name') on views, no need to change any views or replace(switch) keys at all.
# controller
around_action :switch_locale
def switch_locale(&action)
locale = current_user.is_a_vendor? ? :en_vendor : :en #"#{I18n.locale}_vendor"?
I18n.with_locale(locale, &action)
end
# en.yml
en:
fruit:
apple:
name: apple
banana:
name: banana
en_vendor:
fruit:
apple:
name: apple vendor
banana:
name: banana vendor
In case you already had locale file for vendor, i think you can copy/paste to or organize like en.yml file above and switch locale, it takes less effort than switch keys.

Rails admin views' titles & views' links

I'm working with a RESTful Rails App since long time ago.
But this week I received a requirement to change the titles for a Rails App. I think it could be easy. But I'm reading the views (in hamlet)
And found the titles are not written and come from other place. I found they use things like:
label: t("common.email")
f.input :password_confirmation,
ep.check_box :followed_issues
link_to t('common.profile'), csn_profile_path
I wrote a lote of code in rails' controllers but this is the first time I'm trying to understand rails views. Is this standard? Where can I find all this information? is this the way to do?
I think what you are looking for is Rails internationalization.
The internationalization allows use the same views but with different languages. You can find the translations in config/local/, there you will find one yml file per language.
So, when you use t("common.email") it will search the translation in config/local/[language_abbreviation].yml
For example en.yml should look like:
common:
welcome: "Welcome to my page"
email: "Email"
bye: "Bye bye"
And, at the same time es.yml:
common:
welcome: "Bienvenido a mi pagina"
email: "Correo electronico"
bye: "Adios"
Thus, you only need to find the translation and change it for each language and it will change the titles in the views.

I18n to call different Model Attribute depending on Locale?

So I am building an on-line shop and I want two language options, English and Spanish.
I am using I18n as you would normally do for all my static text and headings ect.
But, I have a products Model that can have new Products created for listing on the site. This has fields like :name_en and :name_es, :description_en and :description_es ect.
When the admin uploads a new product they obviously need to add the English and the Spanish text.
Because I have only 2 locales what I would like to do i think is call something like
<%= Product.name_"#{I18n.locale.downcase}" %>
But obviously this does not work. How can i, or just can I, interpolate a method or Attribute?
Have I missed something obvious here and just going about it the wrong way or is there a way to do this along the lines of my thinking?
Any Help massively appreciated.
Thanks
You can use send method. Try something like:
<%= Product.send("name_#{I18n.locale.downcase}") %>
Just a word of explanation, the following are equal:
string = "Hello"
string.upcase
# => "HELLO"
string.send("upcase")
# => "HELLO"
Hope that puts you in proper direction!
Good luck!

Hook into Rails' I18n

I've written a little library to hold translated content in model attributes. All you have to do is add the following to a model:
class Page < ActiveRecord::Base
i18n_attributes :title, :content
end
By convention, the data is written to the real attributes i18n_title and i18n_content as a hash (or hstore hash for Postgres). And a number of getters and setters give you access to "localized virtual attributes":
page = Page.new
page.title_en = 'Hello'
page.title_es = 'Hola'
page.i18n_title # => { en: "Hello", es: "Hola" }
I18n.locale = :es
page.title # => "Hola"
page.title_en # => "Hello"
You can use these virtual attributes in forms as well, but there's a downside: The form builder uses I18n to get the label and translate attribute validation errors. And it does of course look for keys such as activerecord.attributes.page.title_en if you use title_enin the form.
It would be very cumbersome to replicate the same translation for every available_locale in the locales/en.yml etc files:
activerecord:
attributes:
page:
title_en: "Title"
title_es: "Title"
...
What I'd like to do is execute some code after Rails has loaded all locales in the boot process and then clone translations for these keys. Is there a way to do this? Maybe a hook which gets called after the translations have been loaded from the YAML files? (The translations are not yet loaded when my lib loads.)
Or do you see another way to tackle this problem? (I've tried to alias I18n.translate, but I'm afraid this might cause major headache in the future.)
Thanks for your hints!
Although you dropped this approach, please let me share my thoughts:
I don't think it is incredible useful to add other locale strings into a translation file for a specific localization. Since a config/locales/$locale.yml usually starts (at least in my case) with
$locale:
...
there is no need for activerecord.attributes.page.title_es in an English localization file. I'd just put it in es.yml as activerecord.attributes.page.title.
I mean: isn't that the whole purpose of separate localization files? (Or from the developer/translator point of view: In which file should I search for .title_es, in en.yml, es.yml or both?)

Overriding model attribute names using I18n - can't get this working

I'm trying to override the string used to describe the 'login' attribute of my User model to be "User name" instead. I thought that this was set in vendor/rails/activerecord/lib/active_record/locale/en.yml. I've tried changing it here and in my config/locales/en.yml file, and in neither case does it work (i restart the server after every change).
In both cases it's done like this:
en:
...
activerecord:
attributes:
user:
login: User Name
When i test it out, eg having f.label :login in my new user form, it comes out as "Login" not "User Name". Am i labouring under some fundamental error about how this stuff works, or is it genuinely not working? Either way, can anyone tell me how to fix it? thanks, max
In case if any of you have trouble the translation aren't loaded, I debugged like this:
First I use the script in https://stackoverflow.com/a/10211540/474597 to setup logging.
Then as I run the server and render the pages, I can see in that log the keys used to get the translations. Then I can check if the keys I use are correct or not.
One pitfall is that, the first key isn't necessarily the key they will use. I have seen cases where it loads the correct key, and then looks for another key which does not have translation, resulting in the English translation. I had to put the translation in those two keys.
For example: my Foo has_many Bar, and Bar has_many Duu, and Duu has a price column.
In order to translate that price column, I have to have the following for it to work:
activerecord:
attributes:
'foo/bar/duu':
price: "price"
Even though the log has this:
:duu
:"activerecord.attributes.duu.text"
:"activerecord.errors.models.duu.attributes.text.blank"
:"activerecord.errors.models.duu.blank"
:"activerecord.errors.messages.blank"
:"errors.attributes.text.blank"
:"errors.messages.blank"
:"activerecord.attributes.foo/bars/duus.text"
I'm answering this here on request of someone... I did fix this and didn't update my question, sorry. I was on the right lines in my question but didn't have the right "path" down to the keys: the names of fields, as they are displayed, are called "labels" and they have their own section outside of the :activerecord part of the yaml tree.
The correct way to do it is
en:
user:
labels:
login: "User Name"
email: "Email Address"
where "user" is a lowercased model name and login and email are fields.
I think you can find what you are looking for here:
http://guides.rubyonrails.org/i18n.html#translations-for-active-record-models
You may store your "User Name" string under any name in your en.yml file:
en:
user:
user_name: User Name
and in your view
<%= f.label :login, t('user.user_name') %>

Resources