i18n missing keys to gengo export/import
namespace :translator do | |
desc "Export missing translations for a specific locale" | |
task :export_keys => :environment do | |
from = ENV['FROM'] | |
to = ENV['TO'] | |
if from.present? and to.present? | |
translator = Translator.new( | |
from: from.to_sym, | |
to: to.to_sym | |
) | |
missing = translator.export_keys | |
if missing.length > 0 | |
filename = "translate_#{from}_to_#{to}.txt" | |
File.open(filename, 'w') do |file| | |
file.write missing | |
end | |
puts "Created export file: #{filename}" | |
else | |
puts "There are no missing translations from #{from} to #{to}" | |
end | |
else | |
puts "Please provide locale to translate for example:" | |
puts "rake translator FROM=en TO=fr" | |
end | |
end | |
desc "Import missing translations for a specific locale" | |
task :import_keys => :environment do | |
if ENV['FROM'].present? and ENV['TO'].present? and ENV['FILE'].present? | |
translator = Translator.new( | |
from: ENV['FROM'].to_sym, | |
to: ENV['TO'].to_sym | |
) | |
file = File.open(ENV['FILE']) | |
translator.import_keys(file.read) | |
translator.write_locale_file | |
else | |
puts "Please provide the following arguments:" | |
puts "rake translator FROM=en TO=fr FILE=en_to_fr.translate" | |
end | |
end | |
end |
require 'yaml' | |
class Translator | |
def initialize(options = {}) | |
@from = options[:from] | |
@to = options[:to] | |
@dir = options[:dir] || "config/locales/multilingual" | |
end | |
def prepare_translations_for_missing_keys | |
I18n.with_locale(@from) do | |
result = {} | |
find_missing_keys.each do |key| | |
result[key] = I18n.t(key.gsub("#{@to}.", '')).to_s | |
end | |
result | |
end | |
end | |
def export_keys | |
prepare_translations_for_missing_keys.map do |key, value| | |
"[[[#{key}]]] #{value}" | |
end.join("\n") | |
end | |
def import_keys(import) | |
matches = import.scan %r{ | |
\[\[\[ # key start brackets | |
([^\]]+) # key | |
\]\]\] # key end brackets | |
((.(?!\[\[\[))*) # value until brackets | |
}xm | |
@import = {} | |
matches.each do |match| | |
@import[match[0]] = match[1].to_s.lstrip | |
end | |
@import | |
end | |
def write_locale_file | |
old_yaml = yaml(@to) | |
new_yaml = deflatten_keys(@import) | |
merged_yaml = old_yaml ? old_yaml.deep_merge(new_yaml) : new_yaml | |
File.open(path(@to), 'w') do |file| | |
file.write merged_yaml.to_yaml | |
end | |
end | |
def find_missing_keys | |
yaml_1 = yaml(@from) | |
yaml_2 = yaml(@to) | |
keys_1 = yaml_1.present? ? flatten_keys(yaml_1[yaml_1.keys.first]) : [] | |
keys_2 = yaml_2.present? ? flatten_keys(yaml_2[yaml_2.keys.first]) : [] | |
(keys_1 - keys_2).map {|k| "#{@to}.#{k}" } | |
end | |
private | |
def yaml(locale) | |
YAML.load((File.open(path(locale)) rescue '')) | |
end | |
def path(locale) | |
File.expand_path("#{@dir}/#{locale}.yml") | |
end | |
def deflatten_keys(hash) | |
new_hash = {} | |
hash.each do |k,v| | |
new_hash.deep_merge!( | |
k.split('.').reverse.inject(v) {|a,n| { n => a } } | |
) | |
end | |
new_hash | |
end | |
def flatten_keys(hash, prefix="") | |
keys = [] | |
hash.keys.each do |key| | |
if hash[key].is_a? Hash | |
current_prefix = prefix + "#{key}." | |
keys << flatten_keys(hash[key], current_prefix) | |
else | |
keys << "#{prefix}#{key}" | |
end | |
end | |
prefix == "" ? keys.flatten : keys | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
thermistor commentedOct 20, 2014
FYI, I made a few changes in my fork. In my 'from' or starting locale I generally break things into multiple files for easier maintenance, so I load all translations differently and then pick that locale instead of just loading from a single file. Thanks again!