Class: Interpret::Translation

Inherits:
I18n::Backend::ActiveRecord::Translation
  • Object
show all
Defined in:
app/models/interpret/translation.rb

Class Method Summary collapse

Class Method Details

.allowedObject



25
26
27
28
29
30
31
32
33
34
35
36
# File 'app/models/interpret/translation.rb', line 25

def allowed
  s = order("")
  if Interpret.wild_blacklist.any?
    black_keys = Interpret.wild_blacklist.map{|x| "#{CGI.escape(x)}%"}
    s = s.where(arel_table[:key].does_not_match_all(black_keys))
  end
  if Interpret.fixed_blacklist.any?
    black_keys = Interpret.fixed_blacklist.map{|x| "#{CGI.escape(x)}"}
    s = s.where(arel_table[:key].does_not_match_all(black_keys))
  end
  s
end

.dumpObject

Dump all contents from *.yml locale files into the database. If Interpret.soft is set to false, all existing translations will be removed



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'app/models/interpret/translation.rb', line 106

def dump
  files = Dir[Rails.root.join("config", "locales", "*.yml").to_s]
  delete_all unless Interpret.soft

  records = []
  files.each do |f|
    ar = YAML.load_file f
    locale = ar.keys.first
    records += parse_hash(ar.first[1], locale)
  end

  # TODO: Replace with activerecord-import bulk inserts
  transaction do
    records.each {|x| x.save(:validate => false)}
  end
end

.export(translations) ⇒ Object

Generate a hash from the given translations. That hash can be ya2yaml’ized to get a standard .yml locale file.



60
61
62
63
64
65
66
67
68
69
70
# File 'app/models/interpret/translation.rb', line 60

def export(translations)
  res = LazyHash.build_hash

  translations.each do |e|
    LazyHash.add(res, "#{e.locale}.#{e.key}", e.value)
  end
  if res.any? && res.keys.size != 1
    raise IndexError, "Generated hash must have only one root key. Your translation data in database may be corrupted."
  end
  res
end

.get_tree(lang = I18n.default_locale) ⇒ Object

Generates a hash representing the tree structure of the translations for the given locale. It includes only “folders” in the sense of locale keys that includes some real translations, or other keys.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'app/models/interpret/translation.rb', line 42

def get_tree(lang = I18n.default_locale)
  t = arel_table
  all_trans = locale(lang).select(t[:key]).where(t[:key].matches("%.%")).all

  tree = LazyHash.build_hash
  all_trans = all_trans.map{|x| x.key.split(".")[0..-2].join(".")}.uniq
  all_trans.each do |x|
    LazyHash.add(tree, x, {})
  end

  # Generate a new clean hash without the proc's from LazyHash.
  # Includes a root level for convenience, to be exactly like the
  # structure of a .yml file which has the "en" root key for example.
  {"index" => eval(tree.inspect)}
end

.import(file) ⇒ Object

Import the contents of the given .yml locale file into the database backend. If a given key already exists in database, it will be overwritten, otherwise it won’t be touched. This means that it won’t delete any existing translation, it only overwrites the ones you give in the file.

The language will be obtained from the first unique key of the yml file.

Raises:

  • (ArgumentError)


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'app/models/interpret/translation.rb', line 80

def import(file)
  hash = YAML.load file
  raise ArgumentError, "the YAML file must contain an unique first key representing the locale" unless hash.keys.count == 1

  lang = hash.keys.first

  unless lang.to_s == I18n.locale.to_s
    raise ArgumentError, "the language doesn't match"
  end

  records = parse_hash(hash.first[1], lang)
  transaction do
    records.each do |x|
      if tr = locale(lang).find_by_key(x.key)
        tr.value = x.value
        tr.save!
      else
        x.save!
      end
    end
  end
end

.updateObject

Run a smart update from the translations in .yml files into the databse backend. It issues a merging from both, comparing each key present in the db with the one from the yml file.

The use case beyond this arquitecture presuposes some things:

1) You’re working in development mode with the default I18n backend, that is with the translations in the config/locales/*.yml files.

2) Your application is deployed in production and running well. Also, it has support to modify it’s contents (from this very gem of course) on live, so its possible that your customer has changed a sentence or a title of the site. And you want to preserve that.

3) In general, from the very moment you choose to give the users (or admins) of your site the ability to change the contents, that contents are no longer part of the “project” (are checked in in git, to be specific), they are now part of the dynamic contents of the site just as if they were models in your db.

In development, you define a “content layout” in the sense of a specific locale keys hierarchy. How many paragraphs are in your views, how many titles, etc… But the real paragraphs are in the production database.

So, with this “update” action, you are updating that “contents layout” with the new one you just designed in development.

Also keep in mind that rails let you have a diferent locale key hierarchy for each language, and this behaviour is prohibited in interpret. Here, the I18n.default_locale configured in your app is considered the main one, that is, the only language that can be trusted to have all the required and correct locale keys. This will be used to check for inconsitent translations into other languages, knowing what you haven’t translated yet.

What does all that means?

  • First of all, get the locale keys for the main language from yml files.

  • For all of these locale keys, do:

    • If the key is not present in the db, it’s new. So, create a new

    entry for that key in the main language. If the key also exists in some other languages in yml files, also create the entry for that languages. But, do not create entries for the languages that does not have this key. Later you will be notified about that missing translations.

    • If the key already exists in the db, do nothing. Maybe somone has

    changed that content in production, and you don’t want to lose that. Or maybe you do want to change that content, because you just added the correct sentence in the yml files. It’s up to you to do the right thing. Also, if the key is missing in other languages in database but present in yml files, create the new entry for that language.

    • If a key is present in the db, but not in the new ones, remove

    it. You have removed it from the new content layout, so it’s no longer needed.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'app/models/interpret/translation.rb', line 181

def update
  files = Dir[Rails.root.join("config", "locales", "*.yml").to_s]

  @languages = {}
  files.each do |f|
    ar = YAML.load_file f
    lang = ar.keys.first
    if @languages.has_key?(lang.to_s)
      @languages[lang.to_s] = @languages[lang.to_s].deep_merge(ar.first[1])
    else
      @languages[lang.to_s] = ar.first[1]
    end
  end

  sync(@languages[I18n.default_locale.to_s])
end