aigu 0.4.5 → 0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 84521cb2e0c9827217bada8bda9ec4a7c5a0cfe4
4
- data.tar.gz: 8142e1fc307e0568a3115ffe10d8a6be31160836
3
+ metadata.gz: 2541e277f5d4bb08688838d37d097f32567a2682
4
+ data.tar.gz: af50d9f37a958dfd01306b5206434334d3feb46a
5
5
  SHA512:
6
- metadata.gz: 372b73941b8fa6c84f8e5914ba438f612e3e221445048510273bb399482d9cff2917de2f976cd6d4b700ab5f58cee1b5970e9bda866ed4d867624c5415365ab7
7
- data.tar.gz: 39a2099251184eb6ab56a384f23fa7fb4a4585cc216e439859c9a7fc84877567fb743aba2ae7a815d81789bba651bde7022e78da1ebc27f4b8e0dce0e75c5106
6
+ metadata.gz: 2bd8d227116755e4eeecacfd2cd91558cfa7c13881804acfa261cd0ec66454902e71d1fd1bf4ac093749be64c4a50e27888323802d2ea18100e39c758c6aaa45
7
+ data.tar.gz: 3ecec7944c56ef8c42180db1033ed45489840610b5a27589fbe17d5a5cd77f6fc2b19129bcb50c62e998873cfcdd2c206cd856cfef0d1cdd902407031c09186e
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.2
5
+
6
+ sudo: false
7
+
8
+ script:
9
+ - 'echo "Checking code style" && ./bin/phare'
10
+ - 'echo "Running specs" && bundle exec rake spec'
data/README.md CHANGED
@@ -4,8 +4,8 @@ Aigu is a set of utility to process localization files to genarate JSON files
4
4
  to push to Accent service. Pulling from Accent to update localization files
5
5
  is also supported.
6
6
 
7
- The following localization file formats are supported: Rails YAML, Android
8
- XML, Java Enum Core, iOS strings and stringsdict.
7
+ The following localization file formats are supported: Rails YAML, Android XML,
8
+ Java Enum Core, iOS strings and stringsdict and Ember JavaScript.
9
9
 
10
10
  Merge and unmerge commands allows to merge different source files into a
11
11
  single JSON file to send as a single Accent project.
@@ -28,36 +28,37 @@ Aigu provides an executable named `aigu`.
28
28
 
29
29
  ### Exporting the JSON file for Accent
30
30
 
31
- The `export` command looks for YAML localization files and generates a JSON
32
- file. This file will then be compatible with Accent.
31
+ The `export` command looks for localization files and generates a JSON file.
32
+ This file will then be compatible with Accent.
33
33
 
34
34
  ```bash
35
- $ aigu export --locale=fr --input-directory=config/locales --output-file=my-project.json
35
+ $ aigu <export-command> --locale=fr --input-directory=config/locales --output-file=my-project.json
36
36
  ```
37
37
 
38
38
  #### Options
39
39
 
40
- | Option | Description |
41
- |-------------------|---------------------------------------------------------------------------------------------------------------------------|
42
- | `locale` | The locale used to find localization files. Files that match `*.<locale>.yml` in the input directory will be processed. |
43
- | `input-directory` | The directory used to find localization files |
44
- | `output-file` | The path to the JSON file that will be written by `aigu` |
45
- | `ignore` | The patterns `aigu` will use to skip ignored files (eg. `routes.yml`)
40
+ | Option | Description |
41
+ |-------------------|------------------------------------------------------------------------|
42
+ | `locale` | The locale used to find localization files. |
43
+ | `input-directory` | The directory used to find localization files |
44
+ | `output-file` | The path to the JSON file that will be written by `aigu` |
45
+ | `ignore` | The patterns `aigu` will use to skip ignored files (eg. `routes.yml`) |
46
46
 
47
- | Command | File format |
47
+ | Command | File format |
48
48
  |-------------------|-------------------------------------------------------|
49
- | `export` | Rails YAML |
50
- | `andoird_export` | Android XML |
51
- | `core_export` | Java Enum Core |
52
- | `ios_export` | iOS strings & stringsdict |
49
+ | `rails-export` | Rails YAML |
50
+ | `android-export` | Android XML |
51
+ | `core-export` | Java Enum Core |
52
+ | `ios-export` | iOS strings & stringsdict |
53
+ | `ember-export` | Ember.js JavaScript (`node` and `babel` are required) |
53
54
 
54
55
  ### Importing the JSON file from Accent
55
56
 
56
57
  The `import` command takes a generated JSON file from Accent and generates
57
- the original YAML file structure.
58
+ localization files in the output directory.
58
59
 
59
60
  ```bash
60
- $ aigu import --locale=fr --input-file=file-from-accent.json --output-directory=config/locales
61
+ $ aigu <import-command> --locale=fr --input-file=file-from-accent.json --output-directory=config/locales
61
62
  ```
62
63
 
63
64
  #### Options
@@ -68,12 +69,12 @@ $ aigu import --locale=fr --input-file=file-from-accent.json --output-directory=
68
69
  | `input-file` | The path to the Accent-generated JSON file |
69
70
  | `output-directory` | The directory where the localization YAML files will be generated |
70
71
 
71
- | Command | File format |
72
- |-------------------|-------------------------------------------------------|
73
- | `import` | Rails YAML |
74
- | `andoird_import` | Android XML |
75
- | `core_import` | Java Enum Core |
76
- | `ios_import` | iOS strings & stringsdict |
72
+ | Command | File format |
73
+ |-------------------|----------------------------|
74
+ | `rails-import` | Rails YAML |
75
+ | `android-import` | Android XML |
76
+ | `core-import` | Java Enum Core |
77
+ | `ios-import` | iOS strings & stringsdict |
77
78
 
78
79
  ### Merge
79
80
 
@@ -107,11 +108,11 @@ The `push` command takes a JSON file exported by Aigu and send it to Accent
107
108
 
108
109
  #### Options
109
110
 
110
- | Option | Description |
111
- |--------------------|---------------------------------------------------------------------------------------------------|
112
- | `input-file` | The path to the Aigu-generated JSON file |
113
- | `accent-api-key` | The API key of the Accent project. (See project config in Accent) |
114
- | `accent-url` | The URL to the instance of Accent to use (Prod: http://accent.mirego.com, QA: https://mirego-accent-qa.herokuapp.com ) |
111
+ | Option | Description |
112
+ |--------------------|-------------------------------------------------------------------|
113
+ | `input-file` | The path to the Aigu-generated JSON file |
114
+ | `accent-api-key` | The API key of the Accent project. (See project config in Accent) |
115
+ | `accent-url` | The URL to the instance of Accent to use |
115
116
 
116
117
  ### Pulling from Accent
117
118
 
@@ -119,11 +120,11 @@ The `pull` command GET the Accent generated JSON file
119
120
 
120
121
  #### Options
121
122
 
122
- | Option | Description |
123
- |--------------------|---------------------------------------------------------------------------------------------------|
124
- | `output-file` | The path to write the Accent JSON file to |
125
- | `accent-api-key` | The API key of the Accent project. (See project config in Accent) |
126
- | `accent-url` | The URL to the instance of Accent to use (Prod: http://accent.mirego.com, QA: https://mirego-accent-qa.herokuapp.com ) |
123
+ | Option | Description |
124
+ |--------------------|-------------------------------------------------------------------|
125
+ | `output-file` | The path to write the Accent JSON file to |
126
+ | `accent-api-key` | The API key of the Accent project. (See project config in Accent) |
127
+ | `accent-url` | The URL to the instance of Accent to use |
127
128
 
128
129
  ### Using `.aigu.yml`
129
130
 
@@ -153,7 +154,7 @@ the commit if there are errors.
153
154
 
154
155
  ## License
155
156
 
156
- `Aigu` is © 2014 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/aigu/blob/master/LICENSE.md) file.
157
+ `Aigu` is © 2014-2015 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/aigu/blob/master/LICENSE.md) file.
157
158
 
158
159
  ## About Mirego
159
160
 
@@ -11,16 +11,22 @@ require 'openssl'
11
11
 
12
12
  require 'aigu/extensions/hash'
13
13
  require 'aigu/cli'
14
+
14
15
  require 'aigu/importer'
15
16
  require 'aigu/exporter'
17
+ require 'aigu/rails_importer'
18
+ require 'aigu/rails_exporter'
16
19
  require 'aigu/android_exporter'
17
20
  require 'aigu/android_importer'
18
21
  require 'aigu/core_exporter'
19
22
  require 'aigu/core_importer'
20
23
  require 'aigu/ios_exporter'
21
24
  require 'aigu/ios_importer'
22
- require 'aigu/unmergeer'
23
- require 'aigu/mergeer'
25
+ require 'aigu/ember_exporter'
26
+ require 'aigu/ember_importer'
27
+
28
+ require 'aigu/unmerger'
29
+ require 'aigu/merger'
24
30
  require 'aigu/puller'
25
31
  require 'aigu/pusher'
26
32
 
@@ -1,29 +1,5 @@
1
1
  module Aigu
2
- class AndroidExporter
3
- def initialize(opts = {})
4
- @output_file = opts[:'output-file']
5
- @input_directory = opts[:'input-directory']
6
- @locale = opts[:locale]
7
- @ignore = opts[:ignore]
8
- end
9
-
10
- def process!
11
- puts "Generating Accent JSON file `#{@output_file}` based on Android resources files in `#{@input_directory}` directory"
12
-
13
- if @ignore
14
- print 'Ignoring '
15
- puts @ignore.join(', ')
16
- end
17
-
18
- puts '---'
19
-
20
- build_output
21
- write_json_file
22
-
23
- puts '---'
24
- puts 'Done'
25
- end
26
-
2
+ class AndroidExporter < Exporter
27
3
  protected
28
4
 
29
5
  def build_output
@@ -1,14 +1,8 @@
1
1
  module Aigu
2
- class AndroidImporter
2
+ class AndroidImporter < Importer
3
3
  ARRAY_REGEX = /__ARRAY_ITEM__#(?<index>\d+)$/
4
4
  TYPE_REGEX = /__@TYPE_(?<type_key>.+)$/
5
5
 
6
- def initialize(opts = {})
7
- @input_file = opts[:'input-file']
8
- @output_directory = opts[:'output-directory']
9
- @locale = opts[:locale]
10
- end
11
-
12
6
  def process!
13
7
  puts "Generating Android XML files in `#{@output_directory}` based on Accent-generated `#{@input_file}` file"
14
8
  puts '---'
@@ -1,8 +1,24 @@
1
1
  module Aigu
2
2
  class CLI
3
+ COMMANDS = {
4
+ 'rails-import' => 'RailsImporter',
5
+ 'rails-export' => 'RailsExporter',
6
+ 'android-import' => 'AndroidImporter',
7
+ 'android-export' => 'AndroidExporter',
8
+ 'core-import' => 'CoreImporter',
9
+ 'core-export' => 'CoreExporter',
10
+ 'ios-import' => 'IOSImporter',
11
+ 'ios-export' => 'IOSExporter',
12
+ 'ember-import' => 'EmberImporter',
13
+ 'ember-export' => 'EmberExporter',
14
+ 'merge' => 'Merger',
15
+ 'unmerge' => 'Unmerger'
16
+ }
17
+
3
18
  def initialize(env, argv)
4
19
  @env = env
5
20
  @command = argv.first =~ /^[^-]/ ? argv.shift : nil
21
+ @command = @command.gsub('_', '-') if @command
6
22
  @argv = argv
7
23
  @options = {}
8
24
  @options = parse_options_from_yaml(@options)
@@ -10,12 +26,10 @@ module Aigu
10
26
  end
11
27
 
12
28
  def run
13
- service_name = "#{@command}er".split('_').map(&:capitalize).join
14
-
15
- begin
16
- service_class = Aigu.const_get(service_name)
17
- rescue NameError
18
- puts "The Aigu::#{service_name} service doesn’t exist. Nice try."
29
+ if COMMANDS[@command]
30
+ service_class = Aigu.const_get(COMMANDS[@command])
31
+ else
32
+ puts "The #{@command} command doesn’t exist. Nice try."
19
33
  exit 0
20
34
  end
21
35
 
@@ -42,7 +56,14 @@ module Aigu
42
56
  # rubocop:disable Metrics/MethodLength
43
57
  def parse_options_from_arguments(options)
44
58
  OptionParser.new do |opts|
45
- opts.banner = 'Usage: aigu [options]'
59
+ opts.banner = <<DOC
60
+ "Usage: aigu <command> [options]"
61
+
62
+ Commands:
63
+ #{COMMANDS.keys.map { |command| " #{command}" }.join("\n")}
64
+
65
+ Options:
66
+ DOC
46
67
 
47
68
  opts.on('--input-directory=', 'The directory in which the Rails YAML localization files are stored.') do |directory|
48
69
  options[:'input-directory'] = directory
@@ -1,31 +1,7 @@
1
1
  module Aigu
2
- class CoreExporter
2
+ class CoreExporter < Exporter
3
3
  ENUM_LINE_REGEX = /^\s*(?<key>\w+)\s?\("(?<value_en>.*)",\s?"(?<value_fr>.*)"\)[,;]?\s$/
4
4
 
5
- def initialize(opts = {})
6
- @output_file = opts[:'output-file']
7
- @input_directory = opts[:'input-directory']
8
- @locale = opts[:locale]
9
- @ignore = opts[:ignore]
10
- end
11
-
12
- def process!
13
- puts "Generating Accent JSON file `#{@output_file}` based on Core Java Enum files in `#{@input_directory}` directory"
14
-
15
- if @ignore
16
- print 'Ignoring '
17
- puts @ignore.join(', ')
18
- end
19
-
20
- puts '---'
21
-
22
- build_output
23
- write_json_file
24
-
25
- puts '---'
26
- puts 'Done'
27
- end
28
-
29
5
  protected
30
6
 
31
7
  def build_output
@@ -1,13 +1,7 @@
1
1
  module Aigu
2
- class CoreImporter
2
+ class CoreImporter < Importer
3
3
  ENUM_LINE_REGEX = /^\s*(?<key>\w+)\s?\("(?<value_en>.*)",\s?"(?<value_fr>.*)"\)(?<comma>[,;]?)\s$/
4
4
 
5
- def initialize(opts = {})
6
- @input_file = opts[:'input-file']
7
- @output_directory = opts[:'output-directory']
8
- @locale = opts[:locale]
9
- end
10
-
11
5
  def process!
12
6
  puts "Updating Core Java Enum files in `#{@output_directory}` based on Accent-generated `#{@input_file}` file"
13
7
  puts '---'
@@ -0,0 +1,66 @@
1
+ module Aigu
2
+ class EmberExporter < Exporter
3
+ protected
4
+
5
+ def build_output
6
+ @output = {}
7
+
8
+ pattern = File.join(@input_directory, "#{@locale}/translations.js")
9
+ Dir[pattern].each do |file|
10
+ filepath = file.gsub(/\A#{@input_directory}\//, '')
11
+
12
+ if ignored_filepath?(filepath)
13
+ puts "Ignoring #{filepath}"
14
+ else
15
+ puts "Processing #{filepath}"
16
+
17
+ content = JSON.parse(run_javascript_script(file))
18
+
19
+ content = flattenize_hash(content)
20
+ @output.merge! content
21
+ end
22
+ end
23
+ end
24
+
25
+ def run_javascript_script(file)
26
+ script = "require('babel/register')({stage: 0}); console.log(JSON.stringify(require('#{file}')))"
27
+ command = "node -e \"#{script}\" 2>/dev/null"
28
+ puts "Executing `#{command}`"
29
+ content = `#{command}`
30
+
31
+ if content.empty?
32
+ puts 'There was an error when executing the command. Please make sure `node` and `babel` are installed.'
33
+ exit 0
34
+ end
35
+
36
+ content
37
+ end
38
+
39
+ def write_json_file
40
+ file_path = @output_file
41
+ puts "Generating #{file_path}"
42
+ FileUtils.mkdir_p(File.dirname(file_path))
43
+
44
+ File.open(file_path, 'w+') do |file|
45
+ file << @output.to_json
46
+ end
47
+ end
48
+
49
+ def flattenize_hash(hash, base_key = '')
50
+ if hash.is_a?(Hash)
51
+ hash.reduce({}) do |memo, (key, value)|
52
+ new_base_key = [base_key, key].join('.').gsub(/\|\.+/, '|')
53
+ memo.merge! flattenize_hash(value, new_base_key)
54
+ end
55
+ else
56
+ { base_key.gsub(/^\./, '') => hash }
57
+ end
58
+ end
59
+
60
+ def ignored_filepath?(filepath)
61
+ @ignore && @ignore.any? do |pattern|
62
+ File.fnmatch(pattern, filepath, File::FNM_PATHNAME | File::FNM_DOTMATCH)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,54 @@
1
+ module Aigu
2
+ class EmberImporter < Importer
3
+ def process!
4
+ puts "Generating JavaScript file in `#{@output_directory}` based on Accent-generated `#{@input_file}` file"
5
+ puts '---'
6
+
7
+ parse_json
8
+ build_blob
9
+ write_javascript_file
10
+
11
+ puts '---'
12
+ puts 'Done'
13
+ end
14
+
15
+ protected
16
+
17
+ def parse_json
18
+ json = File.read(@input_file)
19
+ @object = JSON.parse(json)
20
+ end
21
+
22
+ def write_javascript_file
23
+ file_path = File.join(@output_directory, "#{@locale}/translations.js")
24
+ puts "Generating #{file_path}"
25
+ FileUtils.mkdir_p(File.dirname(file_path))
26
+
27
+ javascript_object = JSON.pretty_generate(@blob)
28
+ content = "export default #{javascript_object};\n"
29
+
30
+ File.open(file_path, 'w+') do |file|
31
+ file << content
32
+ end
33
+ end
34
+
35
+ def build_blob
36
+ @blob = Hash.recursive
37
+
38
+ @object.each_pair do |key, value|
39
+ parts = key.split('.')
40
+ hash = @blob[parts.first]
41
+
42
+ parts.each_with_index do |part, index|
43
+ next if index.zero?
44
+
45
+ if index + 1 < parts.length
46
+ hash = hash[part]
47
+ else
48
+ hash[part] = value
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -8,7 +8,7 @@ module Aigu
8
8
  end
9
9
 
10
10
  def process!
11
- puts "Generating Accent JSON file `#{@output_file}` based on YAML localization files in `#{@input_directory}` directory"
11
+ puts "Generating Accent JSON file `#{@output_file}` based on localization files in `#{@input_directory}` directory"
12
12
 
13
13
  if @ignore
14
14
  print 'Ignoring '
@@ -23,89 +23,5 @@ module Aigu
23
23
  puts '---'
24
24
  puts 'Done'
25
25
  end
26
-
27
- protected
28
-
29
- def build_output
30
- @output = {}
31
-
32
- pattern = File.join(@input_directory, '**', "*.#{@locale}.yml")
33
- Dir[pattern].each do |file|
34
- filepath = file.gsub(/\A#{@input_directory}\//, '')
35
-
36
- if ignored_filepath?(filepath)
37
- puts "Ignoring #{filepath}"
38
- else
39
- puts "Processing #{filepath}"
40
- content = YAML.load_file(file)
41
- base_key = file.gsub(@input_directory, '').gsub(/^\/*/, '').gsub(/\.yml$/, '|')
42
-
43
- content = flattenize_hash(content, base_key)
44
- content = flattenize_content_values(content)
45
- content = globalize_content_keys(content)
46
- @output.merge! content
47
- end
48
- end
49
- end
50
-
51
- def write_json_file
52
- file_path = @output_file
53
- puts "Generating #{file_path}"
54
- FileUtils.mkdir_p(File.dirname(file_path))
55
-
56
- File.open(file_path, 'w+') do |file|
57
- file << @output.to_json
58
- end
59
- end
60
-
61
- def globalize_content_keys(content)
62
- content.reduce({}) do |memo, (key, value)|
63
- globalized_key = key.gsub(/\.#{@locale}\|#{@locale}\./, '|')
64
- memo.merge globalized_key => value
65
- end
66
- end
67
-
68
- def flattenize_content_values(hash)
69
- hash.each_with_object({}) do |(key, value), memo|
70
- if value.is_a?(Array)
71
- value.each_with_index do |array_value, index|
72
- tainted_key = "#{key}___KEY___#{index}"
73
- memo[tainted_key] = sanitize_value_to_string(array_value)
74
- end
75
- else
76
- memo[key] = sanitize_value_to_string(value)
77
- end
78
- end
79
- end
80
-
81
- def sanitize_value_to_string(value)
82
- case value
83
- when true
84
- '___TRUE___'
85
- when false
86
- '___FALSE___'
87
- when nil
88
- '___NULL___'
89
- else
90
- value
91
- end
92
- end
93
-
94
- def flattenize_hash(hash, base_key = '')
95
- if hash.is_a?(Hash)
96
- hash.reduce({}) do |memo, (key, value)|
97
- new_base_key = [base_key, key].join('.').gsub(/\|\.+/, '|')
98
- memo.merge! flattenize_hash(value, new_base_key)
99
- end
100
- else
101
- { base_key => hash }
102
- end
103
- end
104
-
105
- def ignored_filepath?(filepath)
106
- @ignore && @ignore.any? do |pattern|
107
- File.fnmatch(pattern, filepath, File::FNM_PATHNAME | File::FNM_DOTMATCH)
108
- end
109
- end
110
26
  end
111
27
  end
@@ -1,98 +1,7 @@
1
- module Aigu
2
- class Importer
3
- ARRAY_REGEX = /___KEY___(?<index>\d+)$/
4
-
5
- def initialize(opts = {})
6
- @input_file = opts[:'input-file']
7
- @output_directory = opts[:'output-directory']
8
- @locale = opts[:locale]
9
- end
10
-
11
- def process!
12
- puts "Generating YAML files in `#{@output_directory}` based on Accent-generated `#{@input_file}` file"
13
- puts '---'
14
-
15
- parse_json
16
- build_blob
17
- write_yaml_files
18
-
19
- puts '---'
20
- puts 'Done'
21
- end
22
-
23
- protected
24
-
25
- def parse_json
26
- json = File.read(@input_file)
27
- @object = JSON.parse(json)
28
- @object = expand_content_values(@object)
29
- @object = localize_content_keys(@object)
30
- end
31
-
32
- def write_yaml_files
33
- @blob.each_pair do |file_name, hash|
34
- file_path = File.join(@output_directory, "#{file_name}.yml")
35
- puts "Generating #{file_path}"
36
- FileUtils.mkdir_p(File.dirname(file_path))
37
-
38
- File.open(file_path, 'w+') do |file|
39
- file << hash.to_yaml(line_width: 100_000_000)
40
- end
41
- end
42
- end
43
-
44
- def build_blob
45
- @blob = Hash.recursive
46
-
47
- @object.each_pair do |key, value|
48
- filename, flat_key = key.split('|')
49
-
50
- parts = flat_key.split('.')
51
- hash = @blob[filename]
52
-
53
- parts.each_with_index do |part, index|
54
- if index + 1 < parts.length
55
- hash = hash[part]
56
- else
57
- hash[part] = value
58
- end
59
- end
60
- end
61
- end
62
-
63
- def localize_content_keys(content)
64
- content.reduce({}) do |memo, (key, value)|
65
- localized_key = key.gsub(/^([^|]+)\|/, "\\1.#{@locale}|#{@locale}.")
66
- memo.merge localized_key => value
67
- end
68
- end
69
-
70
- def expand_content_values(content)
71
- content.each_with_object({}) do |(key, value), memo|
72
- match_data = key.match(ARRAY_REGEX)
73
-
74
- if match_data
75
- canonical_key = key.gsub(ARRAY_REGEX, '')
76
- value_index = match_data[:index].to_i
77
- memo[canonical_key] ||= []
78
- memo[canonical_key][value_index] = sanitize_string_to_value(value)
79
- else
80
- memo[key] = sanitize_string_to_value(value)
81
- end
82
- end
83
- end
84
-
85
- def sanitize_string_to_value(string)
86
- case string
87
- when '___TRUE___'
88
- true
89
- when '___FALSE___'
90
- false
91
- when '___NULL___'
92
- nil
93
- else
94
- string
95
- end
96
- end
1
+ class Importer
2
+ def initialize(opts = {})
3
+ @input_file = opts[:'input-file']
4
+ @output_directory = opts[:'output-directory']
5
+ @locale = opts[:locale]
97
6
  end
98
7
  end
@@ -1,5 +1,5 @@
1
1
  module Aigu
2
- class IosExporter
2
+ class IOSExporter < Exporter
3
3
  PROP_LINE_REGEX = /^\s*"(?<key>.+)"\s?=\s?"(?<value>.*)";\s$/
4
4
 
5
5
  DICT_DICT_OPEN_REGEX = /^\s*<dict>\s*$/
@@ -7,30 +7,6 @@ module Aigu
7
7
  DICT_KEY_REGEX = /^\s*<key>(?<text>.*)<\/key>\s*$/
8
8
  DICT_STRING_REGEX = /^\s*<string>(?<text>.*)<\/string>\s*$/
9
9
 
10
- def initialize(opts = {})
11
- @output_file = opts[:'output-file']
12
- @input_directory = opts[:'input-directory']
13
- @locale = opts[:locale]
14
- @ignore = opts[:ignore]
15
- end
16
-
17
- def process!
18
- puts "Generating Accent JSON file `#{@output_file}` based on IOS strings files in `#{@input_directory}` directory"
19
-
20
- if @ignore
21
- print 'Ignoring '
22
- puts @ignore.join(', ')
23
- end
24
-
25
- puts '---'
26
-
27
- build_output
28
- write_json_file
29
-
30
- puts '---'
31
- puts 'Done'
32
- end
33
-
34
10
  protected
35
11
 
36
12
  def build_output
@@ -1,16 +1,10 @@
1
1
  module Aigu
2
- class IosImporter
2
+ class IOSImporter < Importer
3
3
  DICT_DICT_OPEN_REGEX = /^\s*<dict>\s*$/
4
4
  DICT_DICT_CLOSE_REGEX = /^\s*<\/dict>\s*$/
5
5
  DICT_KEY_REGEX = /^\s*<key>(?<text>.*)<\/key>\s*$/
6
6
  DICT_STRING_REGEX = /^(?<left>\s*<string>)(?<text>.*)(?<right><\/string>\s*)$/
7
7
 
8
- def initialize(opts = {})
9
- @input_file = opts[:'input-file']
10
- @output_directory = opts[:'output-directory']
11
- @locale = opts[:locale]
12
- end
13
-
14
8
  def process!
15
9
  puts "Generating IOS strings files in `#{@output_directory}` based on Accent-generated `#{@input_file}` file"
16
10
  puts '---'
@@ -1,5 +1,5 @@
1
1
  module Aigu
2
- class Mergeer
2
+ class Merger
3
3
  def initialize(opts = {})
4
4
  @output_file = opts[:'output-file']
5
5
  @input_directory = opts[:'input-directory']
@@ -2,6 +2,10 @@ module Aigu
2
2
  class Pusher
3
3
  PUSH_PATH = '/public_api/revisions'
4
4
 
5
+ HTTP_ALREADY_UP_TO_DATE = '200'.freeze
6
+ HTTP_UPDATED = '201'.freeze
7
+ HTTP_SUCCESS_CODES = [HTTP_ALREADY_UP_TO_DATE, HTTP_UPDATED].freeze
8
+
5
9
  def initialize(opts = {})
6
10
  @input_file = opts[:'input-file']
7
11
  @accent_api_key = opts[:'accent-api-key']
@@ -40,7 +44,7 @@ module Aigu
40
44
 
41
45
  puts 'Response: ' + response.code
42
46
 
43
- if response.code != '201'
47
+ unless HTTP_SUCCESS_CODES.include? response.code
44
48
  puts 'Error pushing string update to Accent'
45
49
  exit 1
46
50
  end
@@ -0,0 +1,87 @@
1
+ module Aigu
2
+ class RailsExporter < Exporter
3
+ protected
4
+
5
+ def build_output
6
+ @output = {}
7
+
8
+ pattern = File.join(@input_directory, '**', "*.#{@locale}.yml")
9
+ Dir[pattern].each do |file|
10
+ filepath = file.gsub(/\A#{@input_directory}\//, '')
11
+
12
+ if ignored_filepath?(filepath)
13
+ puts "Ignoring #{filepath}"
14
+ else
15
+ puts "Processing #{filepath}"
16
+ content = YAML.load_file(file)
17
+ base_key = file.gsub(@input_directory, '').gsub(/^\/*/, '').gsub(/\.yml$/, '|')
18
+
19
+ content = flattenize_hash(content, base_key)
20
+ content = flattenize_content_values(content)
21
+ content = globalize_content_keys(content)
22
+ @output.merge! content
23
+ end
24
+ end
25
+ end
26
+
27
+ def write_json_file
28
+ file_path = @output_file
29
+ puts "Generating #{file_path}"
30
+ FileUtils.mkdir_p(File.dirname(file_path))
31
+
32
+ File.open(file_path, 'w+') do |file|
33
+ file << @output.to_json
34
+ end
35
+ end
36
+
37
+ def globalize_content_keys(content)
38
+ content.reduce({}) do |memo, (key, value)|
39
+ globalized_key = key.gsub(/\.#{@locale}\|#{@locale}\./, '|')
40
+ memo.merge globalized_key => value
41
+ end
42
+ end
43
+
44
+ def flattenize_content_values(hash)
45
+ hash.each_with_object({}) do |(key, value), memo|
46
+ if value.is_a?(Array)
47
+ value.each_with_index do |array_value, index|
48
+ tainted_key = "#{key}___KEY___#{index}"
49
+ memo[tainted_key] = sanitize_value_to_string(array_value)
50
+ end
51
+ else
52
+ memo[key] = sanitize_value_to_string(value)
53
+ end
54
+ end
55
+ end
56
+
57
+ def sanitize_value_to_string(value)
58
+ case value
59
+ when true
60
+ '___TRUE___'
61
+ when false
62
+ '___FALSE___'
63
+ when nil
64
+ '___NULL___'
65
+ else
66
+ value
67
+ end
68
+ end
69
+
70
+ def flattenize_hash(hash, base_key = '')
71
+ if hash.is_a?(Hash)
72
+ hash.reduce({}) do |memo, (key, value)|
73
+ new_base_key = [base_key, key].join('.').gsub(/\|\.+/, '|')
74
+ memo.merge! flattenize_hash(value, new_base_key)
75
+ end
76
+ else
77
+ { base_key => hash }
78
+ end
79
+ end
80
+
81
+ def ignored_filepath?(filepath)
82
+ @ignore && @ignore.any? do |pattern|
83
+ File.fnmatch(pattern, filepath, File::FNM_PATHNAME | File::FNM_DOTMATCH)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,92 @@
1
+ module Aigu
2
+ class RailsImporter < Importer
3
+ ARRAY_REGEX = /___KEY___(?<index>\d+)$/
4
+
5
+ def process!
6
+ puts "Generating YAML files in `#{@output_directory}` based on Accent-generated `#{@input_file}` file"
7
+ puts '---'
8
+
9
+ parse_json
10
+ build_blob
11
+ write_yaml_files
12
+
13
+ puts '---'
14
+ puts 'Done'
15
+ end
16
+
17
+ protected
18
+
19
+ def parse_json
20
+ json = File.read(@input_file)
21
+ @object = JSON.parse(json)
22
+ @object = expand_content_values(@object)
23
+ @object = localize_content_keys(@object)
24
+ end
25
+
26
+ def write_yaml_files
27
+ @blob.each_pair do |file_name, hash|
28
+ file_path = File.join(@output_directory, "#{file_name}.yml")
29
+ puts "Generating #{file_path}"
30
+ FileUtils.mkdir_p(File.dirname(file_path))
31
+
32
+ File.open(file_path, 'w+') do |file|
33
+ file << hash.to_yaml(line_width: 100_000_000)
34
+ end
35
+ end
36
+ end
37
+
38
+ def build_blob
39
+ @blob = Hash.recursive
40
+
41
+ @object.each_pair do |key, value|
42
+ filename, flat_key = key.split('|')
43
+
44
+ parts = flat_key.split('.')
45
+ hash = @blob[filename]
46
+
47
+ parts.each_with_index do |part, index|
48
+ if index + 1 < parts.length
49
+ hash = hash[part]
50
+ else
51
+ hash[part] = value
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def localize_content_keys(content)
58
+ content.reduce({}) do |memo, (key, value)|
59
+ localized_key = key.gsub(/^([^|]+)\|/, "\\1.#{@locale}|#{@locale}.")
60
+ memo.merge localized_key => value
61
+ end
62
+ end
63
+
64
+ def expand_content_values(content)
65
+ content.each_with_object({}) do |(key, value), memo|
66
+ match_data = key.match(ARRAY_REGEX)
67
+
68
+ if match_data
69
+ canonical_key = key.gsub(ARRAY_REGEX, '')
70
+ value_index = match_data[:index].to_i
71
+ memo[canonical_key] ||= []
72
+ memo[canonical_key][value_index] = sanitize_string_to_value(value)
73
+ else
74
+ memo[key] = sanitize_string_to_value(value)
75
+ end
76
+ end
77
+ end
78
+
79
+ def sanitize_string_to_value(string)
80
+ case string
81
+ when '___TRUE___'
82
+ true
83
+ when '___FALSE___'
84
+ false
85
+ when '___NULL___'
86
+ nil
87
+ else
88
+ string
89
+ end
90
+ end
91
+ end
92
+ end
@@ -1,5 +1,5 @@
1
1
  module Aigu
2
- class Unmergeer
2
+ class Unmerger
3
3
  UNMERGE_REGEX = /^@(?<file_name>\w+)@__(?<key>.+)$/
4
4
 
5
5
  def initialize(opts = {})
@@ -1,3 +1,3 @@
1
1
  module Aigu
2
- VERSION = '0.4.5'
2
+ VERSION = '0.5'
3
3
  end
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Aigu::IosExporter do
3
+ describe Aigu::IOSExporter do
4
4
  describe :parse_strings_file do
5
- let(:exporter) { Aigu::IosExporter.new }
5
+ let(:exporter) { Aigu::IOSExporter.new }
6
6
  let(:parse_strings_file) { exporter.send(:parse_strings_file, content) }
7
7
 
8
8
  let(:content) do
@@ -33,7 +33,7 @@ describe Aigu::IosExporter do
33
33
  end
34
34
 
35
35
  describe :parse_stringsdict_file do
36
- let(:exporter) { Aigu::IosExporter.new }
36
+ let(:exporter) { Aigu::IOSExporter.new }
37
37
  let(:parse_stringsdict_file) { exporter.send(:parse_stringsdict_file, content) }
38
38
 
39
39
  let(:content) do
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Aigu::IosImporter do
3
+ describe Aigu::IOSImporter do
4
4
  describe :format_strings_file do
5
- let(:importer) { Aigu::IosImporter.new }
5
+ let(:importer) { Aigu::IOSImporter.new }
6
6
  let(:format_strings_file) { importer.send(:format_strings_file, content) }
7
7
 
8
8
  let(:content) do
@@ -33,7 +33,7 @@ describe Aigu::IosImporter do
33
33
  end
34
34
 
35
35
  describe :update_stringsdict_content do
36
- let(:exporter) { Aigu::IosImporter.new }
36
+ let(:exporter) { Aigu::IOSImporter.new }
37
37
  let(:update_stringsdict_content) { exporter.send(:update_stringsdict_content, file_content, new_hash) }
38
38
 
39
39
  let(:file_content) do
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Aigu::Exporter do
3
+ describe Aigu::RailsExporter do
4
4
  describe :flattenize_content_values do
5
- let(:exporter) { Aigu::Exporter.new }
5
+ let(:exporter) { Aigu::RailsExporter.new }
6
6
  let(:flattenized_content) { exporter.send(:flattenize_content_values, content) }
7
7
 
8
8
  let(:content) do
@@ -37,7 +37,7 @@ describe Aigu::Exporter do
37
37
  end
38
38
 
39
39
  describe :globalize_content_keys do
40
- let(:exporter) { Aigu::Exporter.new }
40
+ let(:exporter) { Aigu::RailsExporter.new }
41
41
  let(:globalized_keys) { exporter.send(:globalize_content_keys, content).keys }
42
42
  before { exporter.instance_variable_set(:@locale, 'fr') }
43
43
 
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Aigu::Importer do
3
+ describe Aigu::RailsImporter do
4
4
  describe :build_blob do
5
- let(:importer) { Aigu::Importer.new }
5
+ let(:importer) { Aigu::RailsImporter.new }
6
6
  let(:expanded_content) { importer.send(:expand_content_values, content) }
7
7
 
8
8
  let(:content) do
@@ -37,7 +37,7 @@ describe Aigu::Importer do
37
37
  end
38
38
 
39
39
  describe :localize_content_keys do
40
- let(:exporter) { Aigu::Importer.new }
40
+ let(:exporter) { Aigu::RailsImporter.new }
41
41
  let(:localized_keys) { exporter.send(:localize_content_keys, content).keys }
42
42
  before { exporter.instance_variable_set(:@locale, 'fr') }
43
43
 
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: 0.4.5
4
+ version: '0.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémi Prévost
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-09-22 00:00:00.000000000 Z
12
+ date: 2015-10-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -108,6 +108,7 @@ files:
108
108
  - ".gitignore"
109
109
  - ".rspec"
110
110
  - ".rubocop.yml"
111
+ - ".travis.yml"
111
112
  - Gemfile
112
113
  - LICENSE.md
113
114
  - README.md
@@ -122,24 +123,28 @@ files:
122
123
  - lib/aigu/cli.rb
123
124
  - lib/aigu/core_exporter.rb
124
125
  - lib/aigu/core_importer.rb
126
+ - lib/aigu/ember_exporter.rb
127
+ - lib/aigu/ember_importer.rb
125
128
  - lib/aigu/exporter.rb
126
129
  - lib/aigu/extensions/hash.rb
127
130
  - lib/aigu/importer.rb
128
131
  - lib/aigu/ios_exporter.rb
129
132
  - lib/aigu/ios_importer.rb
130
- - lib/aigu/mergeer.rb
133
+ - lib/aigu/merger.rb
131
134
  - lib/aigu/puller.rb
132
135
  - lib/aigu/pusher.rb
133
- - lib/aigu/unmergeer.rb
136
+ - lib/aigu/rails_exporter.rb
137
+ - lib/aigu/rails_importer.rb
138
+ - lib/aigu/unmerger.rb
134
139
  - lib/aigu/version.rb
135
140
  - spec/aigu/android_exporter_spec.rb
136
141
  - spec/aigu/android_importer_spec.rb
137
142
  - spec/aigu/core_exporter_spec.rb
138
143
  - spec/aigu/core_importer_spec.rb
139
- - spec/aigu/exporter_spec.rb
140
- - spec/aigu/importer_spec.rb
141
144
  - spec/aigu/ios_exporter_spec.rb
142
145
  - spec/aigu/ios_importer_spec.rb
146
+ - spec/aigu/rails_exporter_spec.rb
147
+ - spec/aigu/rails_importer_spec.rb
143
148
  - spec/spec_helper.rb
144
149
  homepage: https://github.com/mirego/aigu
145
150
  licenses:
@@ -171,8 +176,8 @@ test_files:
171
176
  - spec/aigu/android_importer_spec.rb
172
177
  - spec/aigu/core_exporter_spec.rb
173
178
  - spec/aigu/core_importer_spec.rb
174
- - spec/aigu/exporter_spec.rb
175
- - spec/aigu/importer_spec.rb
176
179
  - spec/aigu/ios_exporter_spec.rb
177
180
  - spec/aigu/ios_importer_spec.rb
181
+ - spec/aigu/rails_exporter_spec.rb
182
+ - spec/aigu/rails_importer_spec.rb
178
183
  - spec/spec_helper.rb