aigu 0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/aigu.gemspec +1 -0
- data/lib/aigu.rb +2 -73
- data/lib/aigu/cli.rb +12 -2
- data/lib/aigu/exporter.rb +85 -0
- data/lib/aigu/importer.rb +91 -0
- data/lib/aigu/version.rb +1 -1
- data/spec/aigu/exporter_spec.rb +38 -0
- data/spec/aigu/importer_spec.rb +38 -0
- data/spec/spec_helper.rb +7 -0
- metadata +25 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2399c45ee60052b0923ec680f270da427d9fbf13
|
4
|
+
data.tar.gz: 25faad74c5700510c038818e99001a9f2106bdf1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 675100dddff32390a6806e3036ff778f6566a8ac5d36c6fb2e82ed4ded2c6ef6b17994769bb5c4cdae58af9a3757224b7404b4cd33fbc9422a2451729785780d
|
7
|
+
data.tar.gz: e61bd39dca2aa76a4c5c479c083f7bd997351555563f8f92823d7054e930e6b9fa7d5f4cf212ca7bc2a3f798cbadd9d8be2de5cc4818cdb389f40096f8407361
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/aigu.gemspec
CHANGED
data/lib/aigu.rb
CHANGED
@@ -7,79 +7,8 @@ require 'yaml'
|
|
7
7
|
|
8
8
|
require 'aigu/extensions/hash'
|
9
9
|
require 'aigu/cli'
|
10
|
+
require 'aigu/importer'
|
11
|
+
require 'aigu/exporter'
|
10
12
|
|
11
13
|
module Aigu
|
12
|
-
PUBLIC_COMMANDS = %w(import export)
|
13
|
-
|
14
|
-
def self.import(input_file: nil, output_directory: nil)
|
15
|
-
puts "Generating YAML files in `#{output_directory}` based on Accent-generated `#{input_file}` file"
|
16
|
-
puts '---'
|
17
|
-
json = File.read(input_file)
|
18
|
-
object = JSON.parse(json)
|
19
|
-
blob = Hash.recursive
|
20
|
-
|
21
|
-
object.each_pair do |key, value|
|
22
|
-
filename, flat_key = key.split('|')
|
23
|
-
|
24
|
-
parts = flat_key.split('.')
|
25
|
-
hash = blob[filename]
|
26
|
-
|
27
|
-
parts.each_with_index do |part, index|
|
28
|
-
if index + 1 < parts.length
|
29
|
-
hash = hash[part]
|
30
|
-
else
|
31
|
-
hash[part] = value
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
blob.each_pair do |file_name, hash|
|
37
|
-
file_path = File.join(output_directory, "#{file_name}.yml")
|
38
|
-
puts "Generating #{file_path}"
|
39
|
-
FileUtils.mkdir_p(File.dirname(file_path))
|
40
|
-
|
41
|
-
File.open(file_path, 'w+') do |file|
|
42
|
-
file << hash.to_yaml(line_width: 100_000_000)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
puts '---'
|
47
|
-
puts 'Done'
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.export(output_file: nil, input_directory: nil)
|
51
|
-
puts "Generating Accent JSON file `#{output_file}` based on YAML localization files in `#{input_directory}` directory"
|
52
|
-
puts '---'
|
53
|
-
|
54
|
-
output = {}
|
55
|
-
|
56
|
-
Dir[File.join(input_directory, '**', '*.yml')].each do |file|
|
57
|
-
content = YAML.load_file(file)
|
58
|
-
base_key = file.gsub(input_directory, '').gsub(/^\/*/, '').gsub(/\.yml$/, '|')
|
59
|
-
|
60
|
-
output.merge! flattenize_hash(content, base_key)
|
61
|
-
end
|
62
|
-
|
63
|
-
file_path = output_file
|
64
|
-
puts "Generating #{file_path}"
|
65
|
-
FileUtils.mkdir_p(File.dirname(file_path))
|
66
|
-
|
67
|
-
File.open(file_path, 'w+') do |file|
|
68
|
-
file << output.to_json
|
69
|
-
end
|
70
|
-
|
71
|
-
puts '---'
|
72
|
-
puts 'Done'
|
73
|
-
end
|
74
|
-
|
75
|
-
def self.flattenize_hash(hash, base_key = '')
|
76
|
-
if hash.is_a?(Hash)
|
77
|
-
hash.reduce({}) do |memo, (key, value)|
|
78
|
-
new_base_key = [base_key, key].join('.').sub('|.', '|')
|
79
|
-
memo.merge! flattenize_hash(value, new_base_key)
|
80
|
-
end
|
81
|
-
else
|
82
|
-
{ base_key => hash }
|
83
|
-
end
|
84
|
-
end
|
85
14
|
end
|
data/lib/aigu/cli.rb
CHANGED
@@ -2,13 +2,23 @@ module Aigu
|
|
2
2
|
class CLI
|
3
3
|
def initialize(env, argv)
|
4
4
|
@env = env
|
5
|
-
@command =
|
5
|
+
@command = argv.first =~ /[^-]/ ? argv.shift : nil
|
6
6
|
@argv = argv
|
7
7
|
parse_options
|
8
8
|
end
|
9
9
|
|
10
10
|
def run
|
11
|
-
|
11
|
+
service_name = "#{@command}er".capitalize
|
12
|
+
|
13
|
+
begin
|
14
|
+
service_class = Aigu.const_get(service_name)
|
15
|
+
rescue NameError
|
16
|
+
puts "The Aigu::#{service_name} service doesn’t exist. Nice try."
|
17
|
+
exit 0
|
18
|
+
end
|
19
|
+
|
20
|
+
service_object = service_class.new(@options)
|
21
|
+
service_object.process!
|
12
22
|
end
|
13
23
|
|
14
24
|
def parse_options
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Aigu
|
2
|
+
class Exporter
|
3
|
+
def initialize(output_file: nil, input_directory: nil)
|
4
|
+
@output_file = output_file
|
5
|
+
@input_directory = input_directory
|
6
|
+
end
|
7
|
+
|
8
|
+
def process!
|
9
|
+
puts "Generating Accent JSON file `#{@output_file}` based on YAML localization files in `#{@input_directory}` directory"
|
10
|
+
puts '---'
|
11
|
+
|
12
|
+
build_output
|
13
|
+
write_json_file
|
14
|
+
|
15
|
+
puts '---'
|
16
|
+
puts 'Done'
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def build_output
|
22
|
+
@output = {}
|
23
|
+
|
24
|
+
Dir[File.join(@input_directory, '**', '*.yml')].each do |file|
|
25
|
+
content = YAML.load_file(file)
|
26
|
+
base_key = file.gsub(@input_directory, '').gsub(/^\/*/, '').gsub(/\.yml$/, '|')
|
27
|
+
|
28
|
+
content = flattenize_hash(content)
|
29
|
+
content = flattenize_content_values(content)
|
30
|
+
@output.merge! flattenize_hash(content, base_key)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_json_file
|
35
|
+
file_path = @output_file
|
36
|
+
puts "Generating #{file_path}"
|
37
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
38
|
+
|
39
|
+
File.open(file_path, 'w+') do |file|
|
40
|
+
file << @output.to_json
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def flattenize_content_values(hash)
|
45
|
+
result = {}
|
46
|
+
|
47
|
+
hash.reduce({}) do |memo, (key, value)|
|
48
|
+
if value.is_a?(Array)
|
49
|
+
value.each_with_index do |array_value, index|
|
50
|
+
tainted_key = "#{key}___KEY___#{index}"
|
51
|
+
memo[tainted_key] = sanitize_value_to_string(array_value)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
memo[key] = sanitize_value_to_string(value)
|
55
|
+
end
|
56
|
+
|
57
|
+
memo
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def sanitize_value_to_string(value)
|
62
|
+
case value
|
63
|
+
when true
|
64
|
+
'___TRUE___'
|
65
|
+
when false
|
66
|
+
'___FALSE___'
|
67
|
+
when nil
|
68
|
+
'___NULL___'
|
69
|
+
else
|
70
|
+
value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def flattenize_hash(hash, base_key = '')
|
75
|
+
if hash.is_a?(Hash)
|
76
|
+
hash.reduce({}) do |memo, (key, value)|
|
77
|
+
new_base_key = [base_key, key].join('.').gsub(/\|\.+/, '|')
|
78
|
+
memo.merge! flattenize_hash(value, new_base_key)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
{ base_key => hash }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Aigu
|
2
|
+
class Importer
|
3
|
+
ARRAY_REGEX = /___KEY___(?<index>\d+)$/
|
4
|
+
|
5
|
+
def initialize(input_file: nil, output_directory: nil)
|
6
|
+
@input_file = input_file
|
7
|
+
@output_directory = output_directory
|
8
|
+
end
|
9
|
+
|
10
|
+
def process!
|
11
|
+
puts "Generating YAML files in `#{@output_directory}` based on Accent-generated `#{@input_file}` file"
|
12
|
+
puts '---'
|
13
|
+
|
14
|
+
parse_json
|
15
|
+
build_blob
|
16
|
+
write_yaml_files
|
17
|
+
|
18
|
+
puts '---'
|
19
|
+
puts 'Done'
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def parse_json
|
25
|
+
json = File.read(@input_file)
|
26
|
+
@object = JSON.parse(json)
|
27
|
+
@object = expand_content_values(@object)
|
28
|
+
end
|
29
|
+
|
30
|
+
def write_yaml_files
|
31
|
+
@blob.each_pair do |file_name, hash|
|
32
|
+
file_path = File.join(@output_directory, "#{file_name}.yml")
|
33
|
+
puts "Generating #{file_path}"
|
34
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
35
|
+
|
36
|
+
File.open(file_path, 'w+') do |file|
|
37
|
+
file << hash.to_yaml(line_width: 100_000_000)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_blob
|
43
|
+
@blob = Hash.recursive
|
44
|
+
|
45
|
+
@object.each_pair do |key, value|
|
46
|
+
filename, flat_key = key.split('|')
|
47
|
+
|
48
|
+
parts = flat_key.split('.')
|
49
|
+
hash = @blob[filename]
|
50
|
+
|
51
|
+
parts.each_with_index do |part, index|
|
52
|
+
if index + 1 < parts.length
|
53
|
+
hash = hash[part]
|
54
|
+
else
|
55
|
+
hash[part] = value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def expand_content_values(content)
|
62
|
+
content.reduce({}) do |memo, (key, value)|
|
63
|
+
match_data = key.match(ARRAY_REGEX)
|
64
|
+
|
65
|
+
if match_data
|
66
|
+
canonical_key = key.gsub(ARRAY_REGEX, '')
|
67
|
+
value_index = match_data[:index].to_i
|
68
|
+
memo[canonical_key] ||= []
|
69
|
+
memo[canonical_key][value_index] = sanitize_string_to_value(value)
|
70
|
+
else
|
71
|
+
memo[key] = sanitize_string_to_value(value)
|
72
|
+
end
|
73
|
+
|
74
|
+
memo
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def sanitize_string_to_value(string)
|
79
|
+
case string
|
80
|
+
when '___TRUE___'
|
81
|
+
true
|
82
|
+
when '___FALSE___'
|
83
|
+
false
|
84
|
+
when '___NULL___'
|
85
|
+
nil
|
86
|
+
else
|
87
|
+
string
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/aigu/version.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Aigu::Exporter do
|
4
|
+
describe :flattenize_content_values do
|
5
|
+
let(:exporter) { described_class.new }
|
6
|
+
let(:flattenized_content) { exporter.send(:flattenize_content_values, content) }
|
7
|
+
|
8
|
+
let(:content) do
|
9
|
+
{
|
10
|
+
'users.fr|fr.users.index.title' => 'Foo',
|
11
|
+
'users.fr|fr.users.index.actions' => [
|
12
|
+
'Bar',
|
13
|
+
true,
|
14
|
+
'LOL'
|
15
|
+
],
|
16
|
+
'users.fr|fr.users.index.footer' => 'Bla',
|
17
|
+
'users.fr|fr.users.index.shown' => false,
|
18
|
+
'users.fr|fr.users.index.hidden' => true,
|
19
|
+
'users.fr|fr.users.index.what' => nil
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:expected_content) do
|
24
|
+
{
|
25
|
+
'users.fr|fr.users.index.title' => 'Foo',
|
26
|
+
'users.fr|fr.users.index.actions___KEY___0' => 'Bar',
|
27
|
+
'users.fr|fr.users.index.actions___KEY___1' => '___TRUE___',
|
28
|
+
'users.fr|fr.users.index.actions___KEY___2' => 'LOL',
|
29
|
+
'users.fr|fr.users.index.footer' => 'Bla',
|
30
|
+
'users.fr|fr.users.index.shown' => '___FALSE___',
|
31
|
+
'users.fr|fr.users.index.hidden' => '___TRUE___',
|
32
|
+
'users.fr|fr.users.index.what' => '___NULL___'
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
it { expect(flattenized_content).to eql expected_content }
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Aigu::Importer do
|
4
|
+
describe :build_blob do
|
5
|
+
let(:importer) { described_class.new }
|
6
|
+
let(:expanded_content) { importer.send(:expand_content_values, content) }
|
7
|
+
|
8
|
+
let(:content) do
|
9
|
+
{
|
10
|
+
'users.fr|fr.users.index.title' => 'Foo',
|
11
|
+
'users.fr|fr.users.index.actions___KEY___0' => 'Bar',
|
12
|
+
'users.fr|fr.users.index.actions___KEY___2' => '___TRUE___',
|
13
|
+
'users.fr|fr.users.index.actions___KEY___1' => 'Baz',
|
14
|
+
'users.fr|fr.users.index.footer' => 'Bla',
|
15
|
+
'users.fr|fr.users.index.shown' => '___FALSE___',
|
16
|
+
'users.fr|fr.users.index.hidden' => '___TRUE___',
|
17
|
+
'users.fr|fr.users.index.what' => '___NULL___'
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:expected_content) do
|
22
|
+
{
|
23
|
+
'users.fr|fr.users.index.title' => 'Foo',
|
24
|
+
'users.fr|fr.users.index.actions' => [
|
25
|
+
'Bar',
|
26
|
+
'Baz',
|
27
|
+
true
|
28
|
+
],
|
29
|
+
'users.fr|fr.users.index.footer' => 'Bla',
|
30
|
+
'users.fr|fr.users.index.shown' => false,
|
31
|
+
'users.fr|fr.users.index.hidden' => true,
|
32
|
+
'users.fr|fr.users.index.what' => nil
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
it { expect(expanded_content).to eql expected_content }
|
37
|
+
end
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aigu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rémi Prévost
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0.beta2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0.beta2
|
41
55
|
description: Aigu converts a directory of Rails localization files into a single JSON
|
42
56
|
file to import in Accent.
|
43
57
|
email:
|
@@ -48,6 +62,7 @@ extensions: []
|
|
48
62
|
extra_rdoc_files: []
|
49
63
|
files:
|
50
64
|
- .gitignore
|
65
|
+
- .rspec
|
51
66
|
- Gemfile
|
52
67
|
- LICENSE.md
|
53
68
|
- README.md
|
@@ -57,8 +72,13 @@ files:
|
|
57
72
|
- bin/aigu
|
58
73
|
- lib/aigu.rb
|
59
74
|
- lib/aigu/cli.rb
|
75
|
+
- lib/aigu/exporter.rb
|
60
76
|
- lib/aigu/extensions/hash.rb
|
77
|
+
- lib/aigu/importer.rb
|
61
78
|
- lib/aigu/version.rb
|
79
|
+
- spec/aigu/exporter_spec.rb
|
80
|
+
- spec/aigu/importer_spec.rb
|
81
|
+
- spec/spec_helper.rb
|
62
82
|
homepage: https://github.com/mirego/aigu
|
63
83
|
licenses:
|
64
84
|
- BSD 3-Clause
|
@@ -84,4 +104,7 @@ signing_key:
|
|
84
104
|
specification_version: 4
|
85
105
|
summary: Aigu converts a directory of Rails localization files into a single JSON
|
86
106
|
file to import in Accent.
|
87
|
-
test_files:
|
107
|
+
test_files:
|
108
|
+
- spec/aigu/exporter_spec.rb
|
109
|
+
- spec/aigu/importer_spec.rb
|
110
|
+
- spec/spec_helper.rb
|