locca 2.1.0 → 2.2.6

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
- SHA1:
3
- metadata.gz: ff2073ab9c95c9468cba788b05d37cac96ff2a6d
4
- data.tar.gz: 0ae04421b2a1f2e8f6ffc3d33a4bb3f2d9f4be75
2
+ SHA256:
3
+ metadata.gz: cc26bb2f03287b0e7453e9ce7039157d1f002a406c4b056a2bed3679fb0cb39c
4
+ data.tar.gz: b256544ee1dbb061ae8264fb680efe3f5ed483c4b6654fbc1414a464b5d13a31
5
5
  SHA512:
6
- metadata.gz: bfc71e2ecf42f5d8d904bdb83cf1e67fdb8437bdf51bc04761bdc85789955e9d70b097761b18b3a9b6fbd755a6a5e60d5b0c5dda8f403cb72379ca8f213dabff
7
- data.tar.gz: 057d6f0106c0673f1c431cc95510839babdf56f37179650e5609dcc6fa738878a422e3da5fb7aaa33f716480d8c7cebb90952a467ba8db9314355715896fcfd4
6
+ metadata.gz: 5a0bf3b7887825323608e8236fec10951f7115f442648566f2e967942c159c8430be69bef88c6c40483f5324ef0d08cff60af284cacf4b886715fe304d35ae50
7
+ data.tar.gz: 336975865b60608b482bf1b391b18c57ef6ca3249b624534883ce529c34228bbc805b501417701d6b310209b2e065eec93758791db19aa4c5ad84cdc4421381b
data/bin/locca CHANGED
@@ -109,6 +109,24 @@ command :translate do |c|
109
109
  end
110
110
  end
111
111
 
112
+ desc 'Audit translation (find missing / extra / untranslated keys)'
113
+ command :audit do |c|
114
+ c.action do |global_options, options, args|
115
+ work_dir = global_options['work-dir'.to_sym]
116
+ if not work_dir
117
+ work_dir = Dir.getwd
118
+ end
119
+
120
+ success = true
121
+ projects_in_dir(work_dir).each { |project|
122
+ if !$locca.audit(project)
123
+ success = false
124
+ end
125
+ }
126
+ exit!(success)
127
+ end
128
+ end
129
+
112
130
  pre do |global, command, options, args|
113
131
  $locca = Locca::Locca.new()
114
132
  true
@@ -33,6 +33,7 @@ require 'locca/projects/android_project'
33
33
  require 'locca/config_reader'
34
34
  require 'locca/config_validator'
35
35
 
36
+ require 'locca/actions/audit_action'
36
37
  require 'locca/actions/build_action'
37
38
  require 'locca/actions/merge_action'
38
39
  require 'locca/actions/onesky_sync_action'
@@ -58,6 +59,42 @@ require 'babelyoda/strings_parser'
58
59
 
59
60
  module Locca
60
61
  class Locca
62
+ def audit(project)
63
+ if not project
64
+ raise 'Can\'t initialize Locca with nil project'
65
+ end
66
+
67
+ action = AuditAction.new(project, project.collection_builder(), project.collections_generator())
68
+ failed_audit_results = action.execute()
69
+
70
+ failed_audit_results.each do |audit_result|
71
+ puts()
72
+ puts(">>> #{project.name}/#{audit_result.lang}/#{audit_result.collection_name}")
73
+ unless audit_result.missing_keys.empty?
74
+ puts("Missing Keys:")
75
+ audit_result.missing_keys.each do |key|
76
+ puts("- #{key}")
77
+ end
78
+ end
79
+
80
+ unless audit_result.extra_keys.empty?
81
+ puts("Extra Keys:")
82
+ audit_result.extra_keys.each do |key|
83
+ puts("- #{key}")
84
+ end
85
+ end
86
+
87
+ unless audit_result.untranslated_keys.empty?
88
+ puts("Untranslated:")
89
+ audit_result.untranslated_keys.each do |key|
90
+ puts("- #{key}")
91
+ end
92
+ end
93
+ end
94
+
95
+ return failed_audit_results.empty?
96
+ end
97
+
61
98
  def build(project)
62
99
  if not project
63
100
  raise 'Can\'t initialize Locca with nil project'
@@ -96,7 +133,7 @@ module Locca
96
133
  lang = project.base_lang
97
134
  end
98
135
 
99
- action = TranslateAction.new(project, lang, project.collection_builder, project.collection_writer, collection_merger())
136
+ action = TranslateAction.new(project, lang, project.collection_builder(), project.collection_writer(), collection_merger())
100
137
  action.execute()
101
138
  end
102
139
 
@@ -0,0 +1,80 @@
1
+ #
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2014 Evgeny Shurakov
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ #
24
+
25
+ require 'locca/audit_result'
26
+
27
+ module Locca
28
+ class AuditAction
29
+ def initialize(project, collection_builder, collections_generator)
30
+ @project = project
31
+ @collections_generator = collections_generator
32
+ @collection_builder = collection_builder
33
+ end
34
+
35
+ def execute()
36
+ generated_collections = @collections_generator.generate()
37
+
38
+ audit_ignore = @project.config_value_for_key('audit_ignore')
39
+ failed_audit_results = []
40
+
41
+ @project.collection_names().each do |collection_name|
42
+ keys_to_ignore = []
43
+ if audit_ignore != nil && audit_ignore.key?(collection_name)
44
+ keys_to_ignore = audit_ignore[collection_name]
45
+ end
46
+
47
+ @project.langs().each do |lang|
48
+ collection_path = @project.path_for_collection(collection_name, lang)
49
+ collection = @collection_builder.collection_at_path(collection_path)
50
+
51
+ audit_result = AuditResult.new(collection_name, lang)
52
+
53
+ generated_collections.each do |generated_collection|
54
+ if generated_collection.name == collection.name
55
+ generated_collection_keys = generated_collection.all_keys().to_set
56
+ collection_keys = collection.all_keys().to_set
57
+
58
+ audit_result.missing_keys = (generated_collection_keys - collection_keys).to_a
59
+ audit_result.extra_keys = (collection_keys - generated_collection_keys).to_a
60
+ end
61
+ end
62
+
63
+ collection.sorted_each do |item|
64
+ if item.translated? || keys_to_ignore.include?(item.key) || audit_result.extra_keys.include?(item.key)
65
+ next
66
+ end
67
+
68
+ audit_result.add_untranslated_key(item.key)
69
+ end
70
+
71
+ unless audit_result.passed?
72
+ failed_audit_results.push(audit_result)
73
+ end
74
+ end
75
+ end
76
+
77
+ return failed_audit_results
78
+ end
79
+ end
80
+ end
@@ -65,8 +65,22 @@ module Locca
65
65
  # 1
66
66
  @generated_collections.each do |generated_collection|
67
67
  @langs.each do |lang|
68
- print "[*] #{@project.name}: fetch: #{lang}/#{generated_collection.name}\n"
69
- data = @onesky.fetch_translations(lang, @project.full_collection_name(generated_collection.name))
68
+ max_attempts = 3
69
+ for attempt in 1..max_attempts do
70
+ print "[*] #{@project.name}: fetch: #{lang}/#{generated_collection.name}\n"
71
+ begin
72
+ data = @onesky.fetch_translations(lang, @project.full_collection_name(generated_collection.name))
73
+ rescue Exception => ex
74
+ if attempt == max_attempts
75
+ raise ex
76
+ end
77
+ puts "[!] #{ex}"
78
+ sleep 2
79
+ else
80
+ break
81
+ end
82
+ end
83
+
70
84
  fetched_collection = @collection_builder.collection_from_datastring(data)
71
85
 
72
86
  local_collection_path = @project.path_for_collection(generated_collection.name, lang)
@@ -113,9 +127,24 @@ module Locca
113
127
 
114
128
  # 4
115
129
  @generated_collections.each do |generated_collection|
116
- print "[*] #{@project.name}: upload: #{@project.base_lang}/#{generated_collection.name}\n"
117
130
  collection_path = @project.path_for_collection(generated_collection.name, @project.base_lang())
118
- @onesky.upload_file(collection_path, @project.one_sky_file_format, prune_missing_strings)
131
+
132
+ max_attempts = 3
133
+ for attempt in 1..max_attempts do
134
+ print "[*] #{@project.name}: upload: #{@project.base_lang}/#{generated_collection.name}\n"
135
+ begin
136
+ @onesky.upload_file(collection_path, @project.one_sky_file_format, prune_missing_strings)
137
+ rescue Exception => ex
138
+ if attempt == max_attempts
139
+ raise ex
140
+ end
141
+ puts "[!] #{ex}"
142
+ sleep 2
143
+ else
144
+ break
145
+ end
146
+ end
147
+
119
148
  end
120
149
  end
121
150
  end
@@ -57,7 +57,7 @@ module Locca
57
57
  item.value.each do |key, value|
58
58
  nodeItem = Nokogiri::XML::Node.new('item', document)
59
59
  nodeItem["quantity"] = key
60
- nodeItem.content = value
60
+ nodeItem.content = prepare_content(value)
61
61
  node.add_child(nodeItem)
62
62
  end
63
63
 
@@ -65,7 +65,7 @@ module Locca
65
65
  else
66
66
  node = Nokogiri::XML::Node.new('string', document)
67
67
  node["name"] = item.key
68
- node.content = item.value
68
+ node.content = prepare_content(item.value)
69
69
  resources.add_child(node)
70
70
  end
71
71
  end
@@ -76,6 +76,10 @@ module Locca
76
76
  io << document.to_xml
77
77
  end
78
78
  end
79
+
80
+ def prepare_content(content)
81
+ return content.gsub(/\n/, "\\n")
82
+ end
79
83
  end
80
84
 
81
85
  end
@@ -0,0 +1,49 @@
1
+ #
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2014 Evgeny Shurakov
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ #
24
+
25
+ module Locca
26
+ class AuditResult
27
+ attr_reader :collection_name
28
+ attr_reader :lang
29
+ attr_reader :untranslated_keys
30
+ attr_accessor :missing_keys
31
+ attr_accessor :extra_keys
32
+
33
+ def initialize(collection_name, lang)
34
+ @collection_name = collection_name
35
+ @lang = lang
36
+ @untranslated_keys = []
37
+ @missing_keys = []
38
+ @extra_keys = []
39
+ end
40
+
41
+ def add_untranslated_key(value)
42
+ @untranslated_keys.push(value)
43
+ end
44
+
45
+ def passed?
46
+ return @untranslated_keys.empty? && @missing_keys.empty? && @extra_keys.empty?
47
+ end
48
+ end
49
+ end
@@ -91,8 +91,10 @@ module Locca
91
91
 
92
92
  def collections_generator()
93
93
  source_files = Array.new()
94
- @xcode_target.source_build_phase.files_references.each { |file|
95
- source_files.push(file.real_path.to_s)
94
+ @xcode_target.source_build_phase.files_references.each { |file|
95
+ if !file.path.nil?
96
+ source_files.push(file.real_path.to_s)
97
+ end
96
98
  }
97
99
  return CollectionsGenerator.new(source_files, Genstrings.new(), collection_builder())
98
100
  end
@@ -22,5 +22,5 @@
22
22
  # SOFTWARE.
23
23
  #
24
24
  module Locca
25
- VERSION = '2.1.0'
25
+ VERSION = '2.2.6'
26
26
  end
metadata CHANGED
@@ -1,141 +1,195 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locca
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shurakov Evgeny
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-12 00:00:00.000000000 Z
11
+ date: 2020-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '5.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
20
23
  type: :development
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - '>='
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '5.0'
30
+ - - ">="
25
31
  - !ruby/object:Gem::Version
26
- version: '0'
32
+ version: '5.0'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: mocha
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
- - - '>='
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.5'
40
+ - - ">="
32
41
  - !ruby/object:Gem::Version
33
- version: '0'
42
+ version: '1.5'
34
43
  type: :development
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
- - - '>='
47
+ - - "~>"
39
48
  - !ruby/object:Gem::Version
40
- version: '0'
49
+ version: '1.5'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '1.5'
41
53
  - !ruby/object:Gem::Dependency
42
54
  name: rake
43
55
  requirement: !ruby/object:Gem::Requirement
44
56
  requirements:
45
- - - '>='
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '12.0'
60
+ - - ">="
46
61
  - !ruby/object:Gem::Version
47
- version: '0'
62
+ version: '12.0'
48
63
  type: :development
49
64
  prerelease: false
50
65
  version_requirements: !ruby/object:Gem::Requirement
51
66
  requirements:
52
- - - '>='
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '12.0'
70
+ - - ">="
53
71
  - !ruby/object:Gem::Version
54
- version: '0'
72
+ version: '12.0'
55
73
  - !ruby/object:Gem::Dependency
56
74
  name: rdoc
57
75
  requirement: !ruby/object:Gem::Requirement
58
76
  requirements:
59
- - - '>='
77
+ - - "~>"
60
78
  - !ruby/object:Gem::Version
61
- version: '0'
79
+ version: '6.0'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '6.0'
62
83
  type: :development
63
84
  prerelease: false
64
85
  version_requirements: !ruby/object:Gem::Requirement
65
86
  requirements:
66
- - - '>='
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '6.0'
90
+ - - ">="
67
91
  - !ruby/object:Gem::Version
68
- version: '0'
92
+ version: '6.0'
69
93
  - !ruby/object:Gem::Dependency
70
94
  name: gli
71
95
  requirement: !ruby/object:Gem::Requirement
72
96
  requirements:
73
- - - '>='
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '2.0'
100
+ - - ">="
74
101
  - !ruby/object:Gem::Version
75
- version: '0'
102
+ version: '2.0'
76
103
  type: :runtime
77
104
  prerelease: false
78
105
  version_requirements: !ruby/object:Gem::Requirement
79
106
  requirements:
80
- - - '>='
107
+ - - "~>"
81
108
  - !ruby/object:Gem::Version
82
- version: '0'
109
+ version: '2.0'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '2.0'
83
113
  - !ruby/object:Gem::Dependency
84
114
  name: rest-client
85
115
  requirement: !ruby/object:Gem::Requirement
86
116
  requirements:
87
- - - '>='
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '2.0'
120
+ - - ">="
88
121
  - !ruby/object:Gem::Version
89
- version: '0'
122
+ version: '2.0'
90
123
  type: :runtime
91
124
  prerelease: false
92
125
  version_requirements: !ruby/object:Gem::Requirement
93
126
  requirements:
94
- - - '>='
127
+ - - "~>"
95
128
  - !ruby/object:Gem::Version
96
- version: '0'
129
+ version: '2.0'
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '2.0'
97
133
  - !ruby/object:Gem::Dependency
98
134
  name: nokogiri
99
135
  requirement: !ruby/object:Gem::Requirement
100
136
  requirements:
101
- - - '>='
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '1.8'
140
+ - - ">="
102
141
  - !ruby/object:Gem::Version
103
- version: '0'
142
+ version: '1.8'
104
143
  type: :runtime
105
144
  prerelease: false
106
145
  version_requirements: !ruby/object:Gem::Requirement
107
146
  requirements:
108
- - - '>='
147
+ - - "~>"
148
+ - !ruby/object:Gem::Version
149
+ version: '1.8'
150
+ - - ">="
109
151
  - !ruby/object:Gem::Version
110
- version: '0'
152
+ version: '1.8'
111
153
  - !ruby/object:Gem::Dependency
112
154
  name: xcodeproj
113
155
  requirement: !ruby/object:Gem::Requirement
114
156
  requirements:
115
- - - '>='
157
+ - - "~>"
116
158
  - !ruby/object:Gem::Version
117
- version: '0'
159
+ version: '1.5'
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '1.5'
118
163
  type: :runtime
119
164
  prerelease: false
120
165
  version_requirements: !ruby/object:Gem::Requirement
121
166
  requirements:
122
- - - '>='
167
+ - - "~>"
168
+ - !ruby/object:Gem::Version
169
+ version: '1.5'
170
+ - - ">="
123
171
  - !ruby/object:Gem::Version
124
- version: '0'
172
+ version: '1.5'
125
173
  - !ruby/object:Gem::Dependency
126
174
  name: json
127
175
  requirement: !ruby/object:Gem::Requirement
128
176
  requirements:
129
- - - '>='
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '2.1'
180
+ - - ">="
130
181
  - !ruby/object:Gem::Version
131
- version: '0'
182
+ version: '2.1'
132
183
  type: :runtime
133
184
  prerelease: false
134
185
  version_requirements: !ruby/object:Gem::Requirement
135
186
  requirements:
136
- - - '>='
187
+ - - "~>"
137
188
  - !ruby/object:Gem::Version
138
- version: '0'
189
+ version: '2.1'
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '2.1'
139
193
  description:
140
194
  email: inbox@shurakov.name
141
195
  executables:
@@ -144,9 +198,12 @@ extensions: []
144
198
  extra_rdoc_files:
145
199
  - README.rdoc
146
200
  files:
201
+ - README.rdoc
147
202
  - bin/locca
148
203
  - lib/babelyoda/strings_lexer.rb
149
204
  - lib/babelyoda/strings_parser.rb
205
+ - lib/locca.rb
206
+ - lib/locca/actions/audit_action.rb
150
207
  - lib/locca/actions/build_action.rb
151
208
  - lib/locca/actions/merge_action.rb
152
209
  - lib/locca/actions/onesky_sync_action.rb
@@ -154,6 +211,7 @@ files:
154
211
  - lib/locca/android_collection_writer.rb
155
212
  - lib/locca/android_collections_generator.rb
156
213
  - lib/locca/android_strings_parser.rb
214
+ - lib/locca/audit_result.rb
157
215
  - lib/locca/collection.rb
158
216
  - lib/locca/collection_builder.rb
159
217
  - lib/locca/collection_item.rb
@@ -172,8 +230,6 @@ files:
172
230
  - lib/locca/projects/xcode_project.rb
173
231
  - lib/locca/sync/onesky.rb
174
232
  - lib/locca/version.rb
175
- - lib/locca.rb
176
- - README.rdoc
177
233
  homepage: https://github.com/eshurakov/locca
178
234
  licenses:
179
235
  - MIT
@@ -185,17 +241,16 @@ require_paths:
185
241
  - lib
186
242
  required_ruby_version: !ruby/object:Gem::Requirement
187
243
  requirements:
188
- - - '>='
244
+ - - ">="
189
245
  - !ruby/object:Gem::Version
190
246
  version: '0'
191
247
  required_rubygems_version: !ruby/object:Gem::Requirement
192
248
  requirements:
193
- - - '>='
249
+ - - ">="
194
250
  - !ruby/object:Gem::Version
195
251
  version: '0'
196
252
  requirements: []
197
- rubyforge_project:
198
- rubygems_version: 2.0.14
253
+ rubygems_version: 3.1.2
199
254
  signing_key:
200
255
  specification_version: 4
201
256
  summary: Application localization kit