How to control RoR I18n texts stored in database? - ruby-on-rails

I'm using the I18n Gem from Sven Fuchs in my Ruby on Rails 3.2 Application and while the gem works great I came across a situation, which I don't know the solution to:
I have a seed file, which contains the basic translation for my MVC's and is seeded, when I install my application on a new machine. The problem is that when one of these translations changes, I have to go to my seed file, edit it, delete in the database and reseed it. Which is problem not the best way to do this.
Furthermore, my application can create complete MVC's on the fly, which of course need translations as well. These translations get only stored in the database. But it would be nice to store them in a real file, keep them under version control and import or export them if I need to.
So, basically what I'm looking for, is an intelligent connection between the translations in my database and the ones in my files. So I can populate one from the other or vica verca and keep them in sync.
And also I looked at solutions like Globalize3 or localeapp, but they don't seem to fit.
Summarized, what I have is:
The I18n Gem from Sven Fuchs with a Backend I created myself
A Seed File which changes sometimes and has to be edited manually but seeds the basic translations
A database which contains translations that are created on the fly and are not under version control, nor stored in some file
What I want:
A sync between translations in my seed file and my database
A way to put my translations under version control
I'm sure I can't be the only one who needs this...
Thanks in regards!

Here is how I solved a problem closer to the question asked:
task :task_name => [:environment] do
file = "db/file_name.txt"
counter = 0
CSV.foreach(file, :headers => true, :col_sep => "^", :quote_char => "~") do |row|
identifier = row[0].to_i
model_name = ModelName.find_or_create_by_identifier(identifier)
I18n.locale = row[1]
model_name.name = row[3]
model_name.save!
end
end
Note that identifier needs to be a unique identifier that doesn't change and exists in the file and in the database. In this example, the columns are separated by "^" and quores are "~"
As #tigrish said in the comments, it is not a good idea to insert in the file and in the database, so it is important to restrict this.
These links may also help:
http://railscasts.com/episodes/396-importing-csv-and-excel
http://jasonseifer.com/2010/04/06/rake-tutorial
As the question is a little old, I hope it can help somebody else.

Related

Creating devise users from a CSV file - Rails - PG

I have been given a CSV file that contains emails and passwords.
My task is to go through this CSV file and create users using the devise gem.
You will probably wonder why I hace been given peoples emails and passwords (I am as well), but I've been told not to worry about it.
My csv file looks like this:
Email,Password,Password_confirmation,,
email1#email.com ,password1,password1,,
email2#email.com ,password2,password2,,
email3#email.com ,password3,password3,,
I wrote the following code in my seeds.rb file:
require 'csv'
CSV.foreach("db/fixtures/users.csv", :col_sep => ",", :headers => true) do |row|
User.create(email: row['email'], password: row['password'], password_confirmation: row['password_confirmation'])
end
I run rails db:seed to create the users, but nothing happens, no error messaged either.
Any support would be welcomed.
First of all, it's a really bad idea to put that file with actual passwords under version control and to import it in seeds.rb. Would be much better to add a rake task for that purpose accepting csv file path as an argument and perform it once in a suitable environment.
About the code, the headers in CSV import are case sensitive, so it would work if you get the row value via row['Email'], row['Password'] etc.
Also, make sure that filling in those fields are enough to save the user, there may be some other required fields in your particular model.

How can I find out what locale-files are loaded by rails (including gems)?

I am introducing a new locale to my application, and copy all existing files in config/locales/.locale1.yml to config/locales/.locale2.yml.
At first I expect that I18n.backend.send(:translations)['locale1'] would equal I18n.backend.send(:translations)['locale2'], but when I diff both hashes I realise that my new new 'locale2' is missing a bunch of translations.
I figure that for locale1 additional translations have been loaded from gems like for instance the popular rails-i18n gem.
As there is no (easy) way to find out in which .yml file a translation was defined, I want to get a list of all locale-files loaded from any gems.
Any suggestions how to get that information?
Even more interesting would be if I could actually implement a way to figure out from which file a translation was loaded, but I guess that would require writing a custom i18n backend that somehow stores where each key was loaded from.
After phrasing the question, it became quite clear what I need to search for: 'rails i18n load paths'.
By using:
Rails.configuration.i18n.load_path.select { |path| path.match('bundle/gems') }
I get close to what I need. Still not a list of what files are actually loaded or containing translations for the locale of interest, but at least a list of all gems that are considered by i18n.

How to manage Rails 2.3.x i18n locales programatically?

I would like to know if there is a way to insert, alter and remove i18n locale keys programatically (I guess I could use the DB, but I like Rails i18n and want to stay as close to it as possible).
Basically I want to know if there's a way (native, gem, plugin, whatever) to do things like:
I18n.add_locale_key("en", "application.messages.submit_message", "Submit message!")
I18n.add_locale_key("es", "application.messages.submit_message", "Enviar mensaje!")
I18n.remove_locale_key("en", "application.messages.submit_message")
I18n.remove_locale_key("es", "application.messages.submit_message")
As packaged, the Rails I18n API only support defining locale terms via the local .yaml or .rb files. Short of dynamically editing those files at runtime, your best bet is to use the DB functionality of a gem gem like FastGetText.
You could also roll your own solution, of course, but the DB method will likely work for your use case and will result in a smaller time investment.
Here's one way to do it:
>> I18n.backend.store_translations :en, :hello_world => "Hello, world."
=> {:hello_world=>"Hello, world."}
>> I18n.t :hello_world
=> "Hello, world."

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?

Plugin to use Ruby on Rails Simple I18n backend with translations overridable in the database?

Hoping some learned Rails developers here can recommend an existing Ruby on Rails plugin or gem that allows you to continue using the Simple I18n backend whilst allowing you to optionally specify translations in the database.
Here's why:
I have one Rails app used for many websites. For the example I'll just use 2 websites:
Website 1: Leprechauns R Us
Website 2: Unicorns R Us
Most translations are the same for both websites, but occassionally I want to override a translation. For example, in my en-US.yml file I have the following translation:
view_all: View all
And for most websites this translation is fine, including for website 1 (Leprechauns) where I'm happy to use "View all".
However, for website 2, I'd like to use "View all Unicorns" as the view_all translation and I'd like to specify this in the database. For maintenance reasons I don't want to specify this override in a YAML file.
Many thanks,
Eliot
In the end I opted to take advantage of Rails' I18n::Backend::Simple's ability to process both .yml files and .rb files as locale dictionaries.
Artifacts created:
DB migration to create a translations table with columns: locale, key, text
Translation model to map to the translations table
Class method to_locale_hash on Translation model that returns a locale keyed hash as required by I18n::Backend::Simple.load_rb
A single-line file located at config/translations.rb with the line 'Translation.to_locale_hash'
For the source code see the Spree extension (sorry not in a Rails plugin structure, it will be easy to move over to a plugin should you require it) here:
http://github.com/eliotsykes/spree-i18n-db/tree/master

Resources