translations_sync 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README +66 -0
- data/Rakefile +67 -0
- data/bin/translations_sync +15 -0
- data/init.rb +2 -0
- data/lib/tasks/translations_sync.rake +69 -0
- data/lib/translations_sync.rb +245 -0
- data/spec/spec_helper.rb +6 -0
- metadata +88 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2010 [name of plugin creator]
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
TranslationsSync
|
|
2
|
+
================
|
|
3
|
+
|
|
4
|
+
This plugin is intended to help the developer to synchronize the different locales for
|
|
5
|
+
the project that uses yaml based locales, in particular, I18n.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Requirements
|
|
9
|
+
============
|
|
10
|
+
|
|
11
|
+
gem 'ya2yaml'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Installation
|
|
15
|
+
============
|
|
16
|
+
|
|
17
|
+
1. As plugin
|
|
18
|
+
rails plugin install http://github.com/dima4p/translations_sync/
|
|
19
|
+
|
|
20
|
+
2. As gem
|
|
21
|
+
sudo gem install translations_sync
|
|
22
|
+
translations_sync
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
Description
|
|
26
|
+
===========
|
|
27
|
+
|
|
28
|
+
There are two rake tasks implemented in the plugin.
|
|
29
|
+
|
|
30
|
+
1. rake translations:sync
|
|
31
|
+
|
|
32
|
+
This task generates the files with missing translations in the directory
|
|
33
|
+
config/locales. One file per a locale is created with the name missing_#{locale}.yml
|
|
34
|
+
Each file contains the text of one of the existing locales, namely the first one
|
|
35
|
+
existing. The order to check is defined by the LIST parameter. This parameter
|
|
36
|
+
can also be used to add a new locale.
|
|
37
|
+
The parameter EXCLUDE may be used to extract one or more locales from the participation
|
|
38
|
+
in the process. If any locale is mentioned in both lists, it will not participate in the
|
|
39
|
+
calculation of the missing translations but it's value may be used in the sample
|
|
40
|
+
translation.
|
|
41
|
+
The parameter NAME allows you to write the missing translations to the specified
|
|
42
|
+
files instead of default 'missing'.
|
|
43
|
+
The parameter SOURCE allows you to restrict the synchronization to be done within
|
|
44
|
+
only one file name. Only the files for all the locales that meet the given name
|
|
45
|
+
will be loaded for the synchronization.
|
|
46
|
+
The parameter IN sets both NAME and SOURCE to its value.
|
|
47
|
+
|
|
48
|
+
2. rake translations:singles
|
|
49
|
+
|
|
50
|
+
This task generates a single file config/locales/singles.yml that contains the
|
|
51
|
+
translations occuring only in one locale.
|
|
52
|
+
|
|
53
|
+
3. rake translations:move KEY=key.to.move TO=where.to.move
|
|
54
|
+
|
|
55
|
+
This task moves the given KEY under the TO. Please note, that the TO
|
|
56
|
+
must not have the last part of the KEY at the end.
|
|
57
|
+
You can use all the parameters available for the translations:sync task with the default
|
|
58
|
+
value for the NAME equal to 'moved'.
|
|
59
|
+
In order to overwrite the existing file both NAME and SOURCE should be given
|
|
60
|
+
with the same value. For that there is the parameter IN that sets both values.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
So far it works only for rails applications. Suggestions for others are welcome.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
Copyright (c) 2010-2011 Dmitri Koulikoff, released under the MIT license
|
data/Rakefile
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'rake/rdoctask'
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'rake/gempackagetask'
|
|
4
|
+
# require 'spec/rake/spectask'
|
|
5
|
+
require 'rubygems/specification'
|
|
6
|
+
require 'date'
|
|
7
|
+
|
|
8
|
+
GEM = "translations_sync"
|
|
9
|
+
GEM_VERSION = "0.2.0"
|
|
10
|
+
AUTHOR = "Dmitri Koulikoff"
|
|
11
|
+
EMAIL = "koulikoff@gmail.com"
|
|
12
|
+
HOMEPAGE = "http://github.com/dima4p/translations_sync/"
|
|
13
|
+
SUMMARY = "Synchronizes the different locales represeinted in yaml, in particular, for I18n"
|
|
14
|
+
|
|
15
|
+
spec = Gem::Specification.new do |s|
|
|
16
|
+
s.name = GEM
|
|
17
|
+
s.version = GEM_VERSION
|
|
18
|
+
s.platform = Gem::Platform::RUBY
|
|
19
|
+
s.has_rdoc = true
|
|
20
|
+
s.extra_rdoc_files = ["README", "MIT-LICENSE"]
|
|
21
|
+
s.summary = SUMMARY
|
|
22
|
+
s.description = s.summary
|
|
23
|
+
s.author = AUTHOR
|
|
24
|
+
s.email = EMAIL
|
|
25
|
+
s.homepage = HOMEPAGE
|
|
26
|
+
|
|
27
|
+
s.add_dependency "ya2yaml"
|
|
28
|
+
|
|
29
|
+
s.executables = 'translations_sync'
|
|
30
|
+
s.default_executable = 'translations_sync'
|
|
31
|
+
s.require_path = 'lib'
|
|
32
|
+
s.files = %w(MIT-LICENSE README Rakefile init.rb) +
|
|
33
|
+
Dir.glob("{bin,lib,spec}/**/*") -
|
|
34
|
+
Dir.glob("{bin,lib,spec}/**/*~")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
desc 'Generate documentation for the translations_sync plugin.'
|
|
38
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
39
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
40
|
+
rdoc.title = 'TranslationsSync'
|
|
41
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
42
|
+
rdoc.rdoc_files.include('README')
|
|
43
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
|
47
|
+
pkg.gem_spec = spec
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# task :default => :spec
|
|
51
|
+
# desc "Default: Run specs"
|
|
52
|
+
# Spec::Rake::SpecTask.new do |t|
|
|
53
|
+
# t.spec_files = FileList['spec/**/*_spec.rb']
|
|
54
|
+
# t.spec_opts = %w(-fs --color)
|
|
55
|
+
# end
|
|
56
|
+
|
|
57
|
+
desc "install the gem locally"
|
|
58
|
+
task :install => [:package] do
|
|
59
|
+
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
desc "create a gemspec file"
|
|
63
|
+
task :make_spec do
|
|
64
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
|
65
|
+
file.puts spec.to_ruby
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
from = File.join(File.split(Gem.bin_path('translations_sync')).first,
|
|
6
|
+
'..', 'lib', 'tasks', '*.rake')
|
|
7
|
+
to = File.expand_path('.', File.join('lib', 'tasks'))
|
|
8
|
+
environment = File.expand_path('.', File.join('config', 'environment.rb'))
|
|
9
|
+
|
|
10
|
+
if File.directory? to and File.exists? environment
|
|
11
|
+
FileUtils.cp Dir.glob(from), to
|
|
12
|
+
puts "Rake file are copied to #{to}"
|
|
13
|
+
else
|
|
14
|
+
puts 'You must run it from within the rails directory'
|
|
15
|
+
end
|
data/init.rb
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
namespace :translations do
|
|
3
|
+
|
|
4
|
+
PARAMS = '. LIST=locales,to,use EXCLUDE=locales,to,ignore'
|
|
5
|
+
|
|
6
|
+
desc "Synchronizes the existing translations" + PARAMS + ' NAME=file_name_prefix'
|
|
7
|
+
task :sync => :environment do
|
|
8
|
+
source = ENV['SOURCE'] || ENV['IN']
|
|
9
|
+
ts = TranslationsSync.new ENV['LIST'], ENV['EXCLUDE'], source
|
|
10
|
+
name = ENV['NAME'] || ENV['IN'] || 'missing'
|
|
11
|
+
ts.missing.keys.sort.each do |lang|
|
|
12
|
+
filename = File.join Rails.root, 'config', 'locales', "#{name}_#{lang}.yml"
|
|
13
|
+
print filename + ' ... '
|
|
14
|
+
if File.exist? filename
|
|
15
|
+
hash = YAML::load(File.open(filename))
|
|
16
|
+
File.open(filename, "w") do |file|
|
|
17
|
+
file.write(TranslationsSync.to_yaml(hash.deep_merge!(ts.missing.slice(lang))))
|
|
18
|
+
end
|
|
19
|
+
puts 'updated'
|
|
20
|
+
else
|
|
21
|
+
File.open(filename, "w") do |file|
|
|
22
|
+
file.write(TranslationsSync.to_yaml(ts.missing.slice lang))
|
|
23
|
+
end
|
|
24
|
+
puts 'created'
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
puts "All is synchronized" if ts.missing.size == 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
desc "Detects the translations existing only in one locale" + PARAMS
|
|
31
|
+
task :singles => :environment do
|
|
32
|
+
ts = TranslationsSync.new ENV['LIST'], ENV['EXCLUDE']
|
|
33
|
+
filename = File.join Rails.root, 'config', 'locales', "singles.yml"
|
|
34
|
+
if ts.singles.size > 0
|
|
35
|
+
File.open(filename, "w") do |file|
|
|
36
|
+
file.write(TranslationsSync.to_yaml ts.singles)
|
|
37
|
+
end
|
|
38
|
+
puts filename + ' <= ' + ts.singles.keys.join(', ')
|
|
39
|
+
else
|
|
40
|
+
puts 'No singles were found'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
desc "Moves the key in the translations" + PARAMS + " KEY=key.to.move TO=where.to.move IN=filespec"
|
|
45
|
+
task :move => :environment do
|
|
46
|
+
source = ENV['SOURCE'] || ENV['IN']
|
|
47
|
+
name = ENV['NAME'] || ENV['IN'] || 'moved'
|
|
48
|
+
key = ENV['KEY'] or raise "Parameter KEY must be given"
|
|
49
|
+
ts = TranslationsSync.new ENV['LIST'], ENV['EXCLUDE'], source
|
|
50
|
+
if ts.move key, ENV['TO']
|
|
51
|
+
ts.moved.keys.sort.each do |lang|
|
|
52
|
+
filename = File.join Rails.root, 'config', 'locales', "#{name}_#{lang}.yml"
|
|
53
|
+
print filename + ' ... '
|
|
54
|
+
if File.exist? filename
|
|
55
|
+
status = 'updated'
|
|
56
|
+
else
|
|
57
|
+
status = 'created'
|
|
58
|
+
end
|
|
59
|
+
File.open(filename, "w") do |file|
|
|
60
|
+
file.write(TranslationsSync.to_yaml(ts.moved.slice lang))
|
|
61
|
+
end
|
|
62
|
+
puts status
|
|
63
|
+
end
|
|
64
|
+
else
|
|
65
|
+
puts "The key \"#{key}\" was not found"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'ya2yaml'
|
|
3
|
+
require 'i18n'
|
|
4
|
+
|
|
5
|
+
class Hash
|
|
6
|
+
def stringify_keys!
|
|
7
|
+
keys.each do |key|
|
|
8
|
+
self[key.to_s] = delete(key)
|
|
9
|
+
end
|
|
10
|
+
self
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class TranslationsSync
|
|
15
|
+
|
|
16
|
+
attr_accessor :translations, :list
|
|
17
|
+
DEFAULT_LIST = 'ru,en'
|
|
18
|
+
EXCLUDE_LIST = ''
|
|
19
|
+
TAIL = '=TODO'
|
|
20
|
+
PKORDER = {'zero' => 0, 'one' => 1, 'two' => 2, 'few' => 3, 'many' => 5, 'other' => 9}
|
|
21
|
+
PKLIST = PKORDER.keys
|
|
22
|
+
RE = Regexp.new ' \d(' + PKORDER.keys.join('|') + '):'
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
def to_yaml(hash)
|
|
26
|
+
translate_keys(hash).ya2yaml.gsub(RE, ' \1:')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def translate_keys(hash)
|
|
32
|
+
hash.each_pair do |key, v|
|
|
33
|
+
if v.is_a? Hash
|
|
34
|
+
if v.keys.sort == (v.keys & PKLIST).sort
|
|
35
|
+
new = {}
|
|
36
|
+
v.keys.each do |k|
|
|
37
|
+
new["#{PKORDER[k]}#{k.to_s}"] = v[k]
|
|
38
|
+
end
|
|
39
|
+
hash[key] = new
|
|
40
|
+
else
|
|
41
|
+
translate_keys v
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
hash
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def initialize(list = nil, exclude = nil, source = nil)
|
|
50
|
+
I18n.backend.send(:init_translations) unless I18n.backend.initialized?
|
|
51
|
+
@translations = I18n.backend.send :translations
|
|
52
|
+
if source
|
|
53
|
+
re = Regexp.new "#{Regexp.escape source}_[^.]+\\.(yml|rb)\\Z"
|
|
54
|
+
I18n.load_path.reject! do |path|
|
|
55
|
+
path !~ re
|
|
56
|
+
end
|
|
57
|
+
@translations.each do |key, hash|
|
|
58
|
+
hash.keys.each do |k|
|
|
59
|
+
hash.delete(k) unless k == :pluralize
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
I18n.backend.send(:init_translations)
|
|
63
|
+
end
|
|
64
|
+
@full_list = ((list || DEFAULT_LIST).split(',').map(&:to_sym) + translations.keys).uniq
|
|
65
|
+
exclude = (exclude || EXCLUDE_LIST).split(',').map(&:to_sym)
|
|
66
|
+
@list = @full_list - exclude
|
|
67
|
+
@flat = {}
|
|
68
|
+
@list.each do |lang|
|
|
69
|
+
flatten_keys(lang, translations[lang] || {}, @flat)
|
|
70
|
+
end
|
|
71
|
+
@flat.delete([:pluralize]) # we do not need this proc if it exists
|
|
72
|
+
@pluralize_keys = @list.inject({}) do |acc, lang|
|
|
73
|
+
acc[lang] = if locale_pluralize = I18n.backend.send(:lookup, lang, :pluralize) and
|
|
74
|
+
locale_pluralize.respond_to?(:call)
|
|
75
|
+
((0..100).map do |n|
|
|
76
|
+
locale_pluralize.call n
|
|
77
|
+
end << :other).uniq
|
|
78
|
+
else
|
|
79
|
+
[:one, :other]
|
|
80
|
+
end
|
|
81
|
+
acc
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def locales_with_missing
|
|
86
|
+
unless @locales_with_missing
|
|
87
|
+
size = list.size
|
|
88
|
+
@locales_with_missing = []
|
|
89
|
+
@flat.each_pair do |key, val|
|
|
90
|
+
if val.size < size
|
|
91
|
+
(@locales_with_missing += list - val.keys).uniq!
|
|
92
|
+
break if @locales_with_missing.size == size
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
@locales_with_missing
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def missing
|
|
100
|
+
unless @missing
|
|
101
|
+
@missing = {}
|
|
102
|
+
locales_with_missing.each do |lang|
|
|
103
|
+
@missing[lang] = {}
|
|
104
|
+
end
|
|
105
|
+
@flat.each_pair do |key, val|
|
|
106
|
+
(locales_with_missing - val.keys).each do |lang|
|
|
107
|
+
push_to_hash @missing[lang], lang, key, val, :missing
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
@missing.stringify_keys!
|
|
111
|
+
end
|
|
112
|
+
@missing
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def locales_with_singles
|
|
116
|
+
unless @locales_with_singles
|
|
117
|
+
size = list.size
|
|
118
|
+
@locales_with_singles = []
|
|
119
|
+
@flat.each_pair do |key, val|
|
|
120
|
+
if val.size < size
|
|
121
|
+
(@locales_with_singles += val.keys).uniq! if val.size == 1
|
|
122
|
+
break if @locales_with_singles.size == size
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
@locales_with_singles
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def singles
|
|
130
|
+
unless @singles
|
|
131
|
+
@singles = {}
|
|
132
|
+
locales_with_singles.each do |lang|
|
|
133
|
+
@singles[lang] = {}
|
|
134
|
+
end
|
|
135
|
+
@flat.each_pair do |key, val|
|
|
136
|
+
lang = val.keys.first
|
|
137
|
+
push_to_hash @singles[lang], lang, key, val, :singles if val.size == 1
|
|
138
|
+
end
|
|
139
|
+
@singles.stringify_keys!
|
|
140
|
+
end
|
|
141
|
+
@singles
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def move(key, destination)
|
|
145
|
+
key = key.split('.').map(&:to_sym)
|
|
146
|
+
key_length = key.length - 1
|
|
147
|
+
return false if key_length < 0
|
|
148
|
+
destination ||= ''
|
|
149
|
+
destination = destination.split('.').map(&:to_sym)
|
|
150
|
+
result = false
|
|
151
|
+
@flat.each_pair do |array, val|
|
|
152
|
+
if array[0, key_length + 1] == key
|
|
153
|
+
array[0, key_length] = destination
|
|
154
|
+
result = true
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
@moved = nil
|
|
158
|
+
result
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def moved
|
|
162
|
+
unless @moved
|
|
163
|
+
@moved = {}
|
|
164
|
+
@list.each do |lang|
|
|
165
|
+
@moved[lang] = {}
|
|
166
|
+
end
|
|
167
|
+
@flat.each_pair do |key, val|
|
|
168
|
+
val.keys.each do |lang|
|
|
169
|
+
push_to_hash @moved[lang], lang, key, val, :moved
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
@moved.keys.each do |key|
|
|
173
|
+
@moved.delete(key) if @moved[key].size == 0
|
|
174
|
+
end
|
|
175
|
+
@moved.stringify_keys!
|
|
176
|
+
end
|
|
177
|
+
@moved
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
private
|
|
181
|
+
|
|
182
|
+
def flatten_keys(lang, src, dest = {}, prefix = [])
|
|
183
|
+
src.each_pair do |key, value|
|
|
184
|
+
new = prefix.dup << key
|
|
185
|
+
if value.is_a? Hash
|
|
186
|
+
if value.keys.include? :other
|
|
187
|
+
insert_translation(dest, new, lang, value)
|
|
188
|
+
else
|
|
189
|
+
flatten_keys lang, value, dest, new
|
|
190
|
+
end
|
|
191
|
+
else
|
|
192
|
+
insert_translation(dest, new, lang, value)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
dest
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def insert_translation(dest, key, lang, value)
|
|
199
|
+
dest[key] ||= {}
|
|
200
|
+
dest[key][lang] = value
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def push_to_hash(hash, target, keys, val, mode)
|
|
204
|
+
key = keys.pop
|
|
205
|
+
h = hash
|
|
206
|
+
keys.each do |k|
|
|
207
|
+
h[k.to_s] = {} unless h[k.to_s]
|
|
208
|
+
h = h[k.to_s]
|
|
209
|
+
end
|
|
210
|
+
case mode
|
|
211
|
+
when :missing
|
|
212
|
+
lang = @full_list.detect do |lang|
|
|
213
|
+
not val[lang].nil?
|
|
214
|
+
end
|
|
215
|
+
if val[lang].is_a? Hash
|
|
216
|
+
h[key.to_s] = {}
|
|
217
|
+
@pluralize_keys[target].each do |pkey|
|
|
218
|
+
h[key.to_s][pkey.to_s] =
|
|
219
|
+
(val[lang][pkey] || val[lang][:many] || val[lang][:other]) + TAIL
|
|
220
|
+
end
|
|
221
|
+
elsif val[lang].is_a? Array
|
|
222
|
+
h[key.to_s] = val[lang].map do |text|
|
|
223
|
+
text.is_a?(String) ? (text + TAIL) : text
|
|
224
|
+
end
|
|
225
|
+
else
|
|
226
|
+
begin
|
|
227
|
+
h[key.to_s] = val[lang].to_s + TAIL
|
|
228
|
+
rescue
|
|
229
|
+
puts %Q(Can not assign to the key "#{key}")
|
|
230
|
+
raise
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
when :singles
|
|
234
|
+
value = val.values.first
|
|
235
|
+
value.stringify_keys! if value.is_a? Hash
|
|
236
|
+
h[key.to_s] = value
|
|
237
|
+
when :moved
|
|
238
|
+
value = val[target] or raise 'The translations are not synchronized'
|
|
239
|
+
value.stringify_keys! if value.is_a? Hash
|
|
240
|
+
h[key.to_s] = value
|
|
241
|
+
end
|
|
242
|
+
keys.push key
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: translations_sync
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 23
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 2
|
|
9
|
+
- 0
|
|
10
|
+
version: 0.2.0
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Dmitri Koulikoff
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2011-03-16 00:00:00 +03:00
|
|
19
|
+
default_executable: translations_sync
|
|
20
|
+
dependencies:
|
|
21
|
+
- !ruby/object:Gem::Dependency
|
|
22
|
+
name: ya2yaml
|
|
23
|
+
prerelease: false
|
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
hash: 3
|
|
30
|
+
segments:
|
|
31
|
+
- 0
|
|
32
|
+
version: "0"
|
|
33
|
+
type: :runtime
|
|
34
|
+
version_requirements: *id001
|
|
35
|
+
description: Synchronizes the different locales represeinted in yaml, in particular, for I18n
|
|
36
|
+
email: koulikoff@gmail.com
|
|
37
|
+
executables:
|
|
38
|
+
- translations_sync
|
|
39
|
+
extensions: []
|
|
40
|
+
|
|
41
|
+
extra_rdoc_files:
|
|
42
|
+
- README
|
|
43
|
+
- MIT-LICENSE
|
|
44
|
+
files:
|
|
45
|
+
- MIT-LICENSE
|
|
46
|
+
- README
|
|
47
|
+
- Rakefile
|
|
48
|
+
- init.rb
|
|
49
|
+
- bin/translations_sync
|
|
50
|
+
- lib/tasks/translations_sync.rake
|
|
51
|
+
- lib/translations_sync.rb
|
|
52
|
+
- spec/spec_helper.rb
|
|
53
|
+
has_rdoc: true
|
|
54
|
+
homepage: http://github.com/dima4p/translations_sync/
|
|
55
|
+
licenses: []
|
|
56
|
+
|
|
57
|
+
post_install_message:
|
|
58
|
+
rdoc_options: []
|
|
59
|
+
|
|
60
|
+
require_paths:
|
|
61
|
+
- lib
|
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
|
+
none: false
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
hash: 3
|
|
68
|
+
segments:
|
|
69
|
+
- 0
|
|
70
|
+
version: "0"
|
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
|
+
none: false
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
hash: 3
|
|
77
|
+
segments:
|
|
78
|
+
- 0
|
|
79
|
+
version: "0"
|
|
80
|
+
requirements: []
|
|
81
|
+
|
|
82
|
+
rubyforge_project:
|
|
83
|
+
rubygems_version: 1.6.2
|
|
84
|
+
signing_key:
|
|
85
|
+
specification_version: 3
|
|
86
|
+
summary: Synchronizes the different locales represeinted in yaml, in particular, for I18n
|
|
87
|
+
test_files: []
|
|
88
|
+
|