aigu 0.1 → 0.1.1
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.
- 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
|