How to set parameters to yaml file in a Rails application? - ruby-on-rails

There is a yaml file in a Rails application which named 'notices.yml'.
notices:
content: "Notice 1."
Now want to set the notice content to dynamatic as:
content: "Notice 1. Good"
So should parse parameter to it in some logic.
I have thought about Rails' I18n. If use something like I18n.t("notices.content", "Good") may realize it. The yaml should be:
notices:
content: "Notice 1. %{data}"
But how to make the method? I am using a way to read yaml file like:
# config/application.rb
config.notices = YAML.load_file("#{Rails.root}/config/notices.yml")
# Some controller
content = Rails.configuration.notices['notices']['content']
It seems difficult to set parameter like that way.
I checked the I18n's translate method:
https://github.com/ruby-i18n/i18n/blob/master/lib/i18n.rb#L179
It use **options to set data. I have no idea to make a simple way to realize this case.

Related

I18n - locale file - use ruby - use translation()

In a I18n locale file (eg el.yml):
can I use translation method in order to use an already defined translation?
can I use ruby code inside?
For example, in the locale yml file, in several places I want to use the word "Invalid". So one approach is to translate the word "Invalid" each time
Another approach is to translate it once, at the top, and then in each translation inside the locale yml which contains this word I could use something like t(:invalid)..
eg:
el:
# global translations - in order to be used later in the file
locked: 'kleidomeno'
invalid: 'mi egiro'
password: 'kodikos'
devise:
failure:
invalid: "#{Invalid} %{authentication_keys} or #{password}."
locked: "Your account is #{locked}."
last_attempt: "You have one more attempt before your account is #{locked}."
not_found_in_database: "#{invalid} %{authentication_keys} ή #{password}."
can I use translation method in order to use an already defined translation?
Yes, that's what I18n translation comes for, e.g.
t 'something'
can I use ruby code inside?
No, it's a .yml file, which does not accept Ruby or any other programming languages.
Another approach is to translate it once
To translate once, you can write a new Rake task to generate the target yml for you.
Or maybe, wrap the official translation function with a new method, which can recognize your custom string syntax:
# custom translate
def ct(msg)
msg.gsub(/#\{\s*([^\}]+)\s*\}/) {|_| t $1}
end
Call it like:
ct 'Your account is #{locked}.'
I think you'd better remove these failure strings out of your yml file if so.

RAILS I18n: How to use # in translation key?

Here is in our yml file:
Or make up unique one like login#a.com : 'test'
But here is the error on view page for I18n.t("Or make up unique one like login#a.com"):
translation missing: zh-CN.Or make up unique one like login#a.com
What causes the missing translation of t()?
UPDATE:
Just verified that the problem was caused by # sign. Now the question becomes how to use # in translation key.
I highly recommend the Rails i18n guide for beginners.
It will help you understand how to structure your files, how to setup routes to support a locale param, how to set the locale, and other useful tips.
The t helper is not intended to take a string of text to translate. It takes a yaml key and outputs the translated text from a locale file.
You want to structure your yaml file as such:
config/locales/en.yml
en:
some_key: hello world
config/locales/cn.yml
cn:
some_key: hello in Chinese
Then using it in your views
<%= t :some_key %>
Based on the I18n.locale setting, the t helper will look up :some_key in the corresponding locale file and output the translated text.

Add Content Next to the line of a given search pattern in ruby

I'm making a custom rails 3 generator, I want to add some content after the attributes line in the following locale file, for example, inserting "user: 'User'"
es:
activerecord:
attributes:
user: 'User'
# some stuff
errors:
# some other stuff
how I can do that, considering that the attributes line could be in any position of the text?
There are a few options, each of them have drawbacks:
Inject with gsub_file: hard and error prone
Load the YAML, update the Hash and overwrite it: you may loose comments and other minor changes that won't affect the data
Create another YAML with only these new data (Rails loads all the locale files on startup): you may end up with many locale files

Internationalizing whole text with markup in Rails 3

What's the best practice for internationalizing, say, a Terms of Service document in Rails 3? I can think of two options:
Creating a partial for each locale and choosing which one to load according to the current user's locale.
<li><%= I18n.t :tos_paragraph_1 %></li><li><%= I18n.t :tos_paragraph_2 %></li>
None of these seems like a good solution. Any ideas?
There are a few solutions, but if I were doing this for a production project, I would probably do something like the following:
Create files for your translated Terms of Services in config/locales/terms/, naming them terms.en.html, replacing en with the locale for each translation and html with the format of the file (e.g. you could use Haml, Markdown, etc.).
Create the following helper methods (put them in app/helpers/application_helper.rb to use them everywhere, but you can put them in whatever helper file you need/want):
def localized_document_for(document, locale)
raise ArgumentError.new('nil is not a valid document') if document.nil?
raise I18n::InvalidLocale.new('nil is not a valid locale') if locale.nil?
localized_document = path_for_localized_document(document, locale)
raise MissingTranslationData unless File.exists?(localized_document)
# If you're using Markdown, etc. replace with code to parse/format your document
File.open(localized_document).readlines.join
end
def path_for_localized_document(document, locale)
"#{Rails.root}/config/locales/#{document}/#{document}.#{locale.to_s}.html"
end
Now, in your views, you can use localized_document_for('terms', I18n.locale) any time you need to get the contents of the Terms of Service in the user's language. Now the code you're using to fetch the document is DRY (you can easily fetch other documents by creating another directory in config/locales and changing the value of the document argument), and your translated documents are stored in their own directory and can easily be edited (and don't depend on YAML, which brings no value to storing a single document in a file).
Note that if you wanted to do it the "Rails 3 Way," you could use the I18n::Backend::Chain (see https://github.com/svenfuchs/i18n/blob/master/lib/i18n/backend/chain.rb), and pass in I18n::Backend::Simple.new along with a custom backend that reads the files as necessary, but for a one-off deal I believe the helpers work sufficiently.
Creating a partial for each language is definitly undry.
The Rails way is the second option you suggest with a .yml for each language.
The doc provides great examples to let you organize the yml according to each page. Thus you have shortcuts for all your variables.
See http://guides.rubyonrails.org/i18n.html

Is there any gem can dump the data from and to yml files?

I'm find such a gem a whole day, but not find a good one. I want to write one, but I'm not able to do it.
The data in my database may be English text, which will be dump to a yml file with plain text. And some are non-English text, which will be binary type.
And both of them may have such code:
<% xxx %>
When I use rake db:fixtures:load to load them into database, error may occur: method xxx not found.
I wan't to find a good gem can handle this problem. Thank for any help
UPDATE
I have gave up finding such a gem. At first, I think it's a easy task, but now, after some researchings, I have to say, it's much harder than I expected.
The reason you are having problems is because the Fixture loader will pass your fixture through erb before loading the data. This means that if you have <% xxx %> in your yaml file then Rails will see that as erb and try to run a method called xxx.
There does not seem to be an easy way to turn off erb processing of fixtures. I have tried replacing the fixtures with CSV fixtures and this still does ERB pre-processing.
Without a simple answer I have to ask the question Why do you have these strings in your file?
Do you want them to be expanded by erb?
Err...I'm not sure if you actually need a gem for this? Rails natively can turn any model into YAML.
Let's say you have a model called "Objects". You could hit a route that looks like:
/objects.yaml
and you would get a giant text file of all your Objects in YAML form.
Of course, you would want to have something like:
respond_to do |format|
format.yaml {render :yaml => #objects}
end
in your restful controller.
If you'd rather not hit a route to do this, you can always do
#yaml = []
#objects.each do |object|
#yaml.push object.to_yaml
end
anywhere in ruby, which will give you an array of yaml objects, that you can then write to a file at your leisure.
I imagine that if rails itself is generating the yaml, then it would be able to then later load it as a fixture?

Resources