po_to_json 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 517508ca59483a1470635ceb485aedabb2c88ff6
4
+ data.tar.gz: 034e2d3771b4794ca9693c6861aad99622af76a2
5
+ SHA512:
6
+ metadata.gz: c6083f8fa476373e5c157394871782fa02f9641ff20e331254ea9b41331984a2c96de6b549b1a34657c2e71becd36476c720d15041c3fd873a68953bca7587cc
7
+ data.tar.gz: 0917626f4f9c86461867d17e298d3c35986f37510de56bea0045edd243c8272fe0ba837decd3a423e9cfa71ea9497c1f2aa10e1816f4ff7e4a5da11680b68b6b
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0](https://github.com/webhippie/po_to_json/releases/tag/v0.1.0) - 2015-02-19
4
+
5
+ * Transfer from github.com/nubis/po_to_json
6
+ * Added TravisCI, Rubocop and Coveralls
7
+ * Updated structure to my opinionated gem style
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2012-2015 Dropmysite.com <https://dropmyemail.com>
4
+ Copyright (c) 2015 Webhippie <http://www.webhippie.de>
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
14
+ all 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
22
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,50 +1,95 @@
1
- ## po_to_json
1
+ # PoToJson
2
2
 
3
- Convert gettext PO files to json to use in your javascript app, based po2json.pl (by DuckDuckGo, Inc. http://duckduckgo.com/, Torsten Raudssus <torsten@raudss.us>.
3
+ [![Gem Version](http://img.shields.io/gem/v/po_to_json.svg)](https://rubygems.org/gems/po_to_json)
4
+ [![Build Status](https://secure.travis-ci.org/webhippie/po_to_json.svg)](https://travis-ci.org/webhippie/po_to_json)
5
+ [![Code Climate](https://codeclimate.com/github/webhippie/po_to_json.svg)](https://codeclimate.com/github/webhippie/po_to_json)
6
+ [![Test Coverage](https://codeclimate.com/github/webhippie/po_to_json/badges/coverage.svg)](https://codeclimate.com/github/webhippie/po_to_json)
7
+ [![Dependency Status](https://gemnasium.com/webhippie/po_to_json.svg)](https://gemnasium.com/webhippie/po_to_json)
4
8
 
5
- Ideally you'll use this on a rake task that creates json versions of your po files, which can later be used from javascript
6
- with Jed ( http://slexaxton.github.com/Jed/ )
9
+ Convert gettext PO files to JSON to use in your javascript app, based on
10
+ po2json.pl by [DuckDuckGo, Inc.](http://duckduckgo.com/). Ideally you'll use
11
+ this on a Rake task that creates JSON versions of your PO files, which can
12
+ later be used from javascript with [Jed](http://slexaxton.github.io/Jed/)
7
13
 
8
- ## Installing
9
14
 
10
- Via rubygems:
11
- ```ruby
12
- gem install po_to_json
13
- ```
15
+ ## Versions
16
+
17
+ This gem is tested on the following versions automated through TravisCI:
18
+
19
+ * Ruby
20
+ * 1.9.3
21
+ * 2.0.0
22
+ * 2.1.0
23
+ * Json
24
+ * 1.6.8
25
+ * 1.7.7
26
+ * 1.8.2
27
+
28
+
29
+ ## Installation
14
30
 
15
- In your gemfile:
16
31
  ```ruby
17
- gem 'po_to_json'
32
+ gem "po_to_json", "~> 0.1.0"
18
33
  ```
19
34
 
35
+
20
36
  ## Usage
21
37
 
22
- Most common use would be to generate a Jed ready javascript file. For example, in a Rails 3 project:
38
+ Most common use would be to generate a Jed ready javascript file. For example,
39
+ in a Rails project:
23
40
 
24
41
  ```ruby
25
- require 'po_to_json'
26
- json_string = PoToJson.new("#{Rails.root}/locale/es/app.po").generate_for_jed('es')
27
- File.open("#{Rails.root}/app/assets/javascripts/locale/es/app.js",'w').write(json_string)
42
+ require "po_to_json"
43
+
44
+ json = PoToJson.new(
45
+ Rails.root.join("locale", "de", "app.po")
46
+ ).generate_for_jed("de")
47
+
48
+ Rails.root.join("app", "assets", "javascripts", "locale", "de", "app.js").write(json)
28
49
  ```
29
50
 
30
- If you need a pretty json, add `:pretty => true` to `generate_for_jed`, like
51
+ If you need a pretty json, add `pretty: true` to `generate_for_jed`, like the
52
+ following example:
31
53
 
32
54
  ```ruby
33
- json_string = PoToJson.new("#{Rails.root}/locale/es/app.po").generate_for_jed('es', :pretty => true)
55
+ require "po_to_json"
56
+
57
+ json = PoToJson.new(
58
+ Rails.root.join("locale", "de", "app.po")
59
+ ).generate_for_jed("de", pretty: true)
60
+
61
+ Rails.root.join("app", "assets", "javascripts", "locale", "de", "app.js").write(json)
34
62
  ```
35
63
 
36
- The javascript file generated has a global 'locales' object with an attribute corresponding to the generated language:
64
+ The javascript file generated has a global "locales" object with an attribute
65
+ corresponding to the generated language:
37
66
 
38
67
  ```javascript
39
- i18n = new Jed(locales['es'])
40
- i18n.gettext('Hello World') // Should evaluate to 'Hola Mundo'
68
+ i18n = new Jed(locales["de"])
69
+ i18n.gettext("Hello World") // Should evaluate to "Hallo Welt"
41
70
  ```
42
71
 
43
- ## Maintainers
44
72
 
45
- * eromirou (https://github.com/eromirou)
46
- * Nubis (https://github.com/nubis)
73
+ ## Contributing
74
+
75
+ Fork -> Patch -> Spec -> Push -> Pull Request
76
+
77
+
78
+ ## Authors
79
+
80
+ * [Thomas Boerger](https://github.com/tboerger)
81
+ * [Nubis](https://github.com/nubis)
82
+ * [Other contributors](https://github.com/webhippie/po_to_json/graphs/contributors)
83
+
47
84
 
48
85
  ## License
49
86
 
50
- MIT License. Copyright 2012 Dropmysite.com. https://dropmyemail.com
87
+ MIT
88
+
89
+
90
+ ## Copyright
91
+
92
+ ```
93
+ Copyright (c) 2012-2015 Dropmysite.com <https://dropmyemail.com>
94
+ Copyright (c) 2015 Webhippie <http://www.webhippie.de>
95
+ ```
data/lib/po_to_json.rb CHANGED
@@ -1,172 +1,329 @@
1
- require 'json'
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright (c) 2012-2015 Dropmysite.com <https://dropmyemail.com>
4
+ # Copyright (c) 2015 Webhippie <http://www.webhippie.de>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
27
+
28
+ if File.exist? ENV["BUNDLE_GEMFILE"]
29
+ require "bundler"
30
+ Bundler.setup(:default)
31
+ else
32
+ gem "json", version: ">= 1.6.0"
33
+ end
34
+
35
+ require "json"
2
36
 
3
37
  class PoToJson
38
+ autoload :Version, File.expand_path("../po_to_json/version", __FILE__)
39
+
40
+ attr_accessor :files
41
+ attr_accessor :glue
42
+ attr_accessor :options
43
+ attr_accessor :errors
44
+ attr_accessor :values
45
+ attr_accessor :buffer
46
+ attr_accessor :lastkey
47
+ attr_accessor :trans
48
+
49
+ def initialize(files, glue = "|")
50
+ @files = files
51
+ @glue = glue
52
+ end
4
53
 
54
+ def generate_for_jed(language, overwrite = {})
55
+ @options = parse_options(overwrite.merge(language: language))
56
+ @parsed ||= inject_meta(parse_document)
5
57
 
6
- # Gettext translations may be contextualized like so User|name
7
- # The default 'GLUE' in rails gettext is '|' so we use that here too.
8
- def initialize(path_to_po, context_glue = '|')
9
- # Gettext translations may be contextualized like so User|name
10
- # The default 'GLUE' in rails gettext is '|' so we use that here too.
11
- @context_glue = context_glue
12
- @path_to_po = path_to_po
58
+ generated = build_json_for(build_jed_for(@parsed))
59
+
60
+ [
61
+ "var #{@options[:variable]} = #{@options[:variable]} || {};",
62
+ "#{@options[:variable]}['#{@options[:language]}'] = #{generated};"
63
+ ].join(" ")
13
64
  end
14
65
 
66
+ def generate_for_json(language, overwrite = {})
67
+ @options = parse_options(overwrite.merge(language: language))
68
+ @parsed ||= inject_meta(parse_document)
15
69
 
16
- # Generates a jed-compatible js file from the current PO.
17
- # This include adding some wrapping structure to the translations and
18
- # making sure the minimum headers required by Jed are provided.
19
- # Jed is a js gettext library ( http://slexaxton.github.com/Jed/ )
20
- # The generated file leaves the generated json inside a global locales
21
- # object which you can use to instatiate Jed:
22
- # >>> i18n = new Jed(locales['es'])
23
- # >>> i18n.gettext('Hello World')
24
- # => 'Hola Mundo'
25
- def generate_for_jed(language_code, opts={})
26
- @parsed ||= self.parse
70
+ generated = build_json_for(build_json_for(@parsed))
27
71
 
28
- @parsed['']['lang'] = language_code
29
- @parsed['']['domain'] = 'app'
30
- @parsed['']['plural_forms'] ||= @parsed['']['Plural-Forms']
72
+ fail "Not implemented yet, current value is #{generated}!"
73
+ end
31
74
 
32
- jed_json = {
33
- :domain => 'app',
34
- :locale_data => { :app => @parsed }
35
- }
75
+ def parse_document
76
+ reset_buffer
77
+ reset_result
36
78
 
37
- if opts[:pretty]
38
- "var locales = locales || {}; locales['#{language_code}'] = #{JSON.pretty_generate(jed_json)};"
39
- else
40
- "var locales = locales || {}; locales['#{language_code}'] = #{JSON.generate(jed_json)};"
79
+ File.foreach(files) do |line|
80
+ matches_values_for(line.chomp)
41
81
  end
82
+
83
+ flush_buffer
84
+ parse_header
85
+
86
+ values
42
87
  end
43
88
 
89
+ def flush_buffer
90
+ return unless buffer[:msgid]
44
91
 
45
- # Messages in a PO file are defined as a series of 'key value' pairs,
46
- # values may span over more than one line. Each key defines an attribute
47
- # of the message, like message id, context, pluralization options, etc.
48
- # Each message is separated by a blank line.
49
- # The parser reads attributes until it finds an empty line, at that point
50
- # it saves the attributes read so far into a message and stores it in a hash
51
- # to be later turned into a json object.
52
- def parse
53
- @parsed_values = {}
54
- @buffer = {}
55
- @last_key_type = ""
56
- @errors = []
57
- File.foreach(@path_to_po) do |line|
58
- line = line.chomp
59
- case line
60
- # Empty lines means we have parsed one full message
61
- # so far and need to flush the buffer
62
- when /^$/ then flush_buffer
92
+ build_trans
93
+ assign_trans
63
94
 
64
- # These are the po file comments
65
- # The second '#' in the following regex is in square brackets
66
- # b/c it messed up my syntax highlighter, no other reason.
67
- when /^(#[^~]|[#]$)/ then next
95
+ reset_buffer
96
+ end
68
97
 
69
- when /^(?:#~ )?msgctxt\s+(.*)/ then add_to_buffer($1, :msgctxt)
98
+ def parse_header
99
+ return if reject_header
70
100
 
71
- when /^(?:#~ )?msgid\s+(.*)/ then add_to_buffer($1, :msgid)
101
+ values[""][1].split("\\n").each do |line|
102
+ next if line.empty?
103
+ build_header_for(line)
104
+ end
72
105
 
73
- when /^(?:#~ )?msgid_plural\s+(.*)/ then add_to_buffer($1, :msgid_plural)
106
+ values[""] = headers
107
+ end
74
108
 
75
- when /^(?:#~ )?msgstr\s+(.*)/ then add_to_buffer($1, :msgstr_0)
109
+ def reject_header
110
+ if values[""].nil? || values[""][1].nil?
111
+ values[""] = {}
112
+ true
113
+ else
114
+ false
115
+ end
116
+ end
76
117
 
77
- when /^(?:#~ )?msgstr\[0\]\s+(.*)/ then add_to_buffer($1, :msgstr_0)
118
+ protected
78
119
 
79
- when /^(?:#~ )?msgstr\[(\d+)\]\s+(.*)/ then add_to_buffer($2, "msgstr_#{$1}".to_sym)
120
+ def trans
121
+ @trans ||= []
122
+ end
80
123
 
81
- when /^(?:#~ )?"/ then add_to_buffer(line)
124
+ def errors
125
+ @errors ||= []
126
+ end
82
127
 
83
- else
84
- @errors << ["Strange line #{line}"]
85
- end
86
- end
128
+ def values
129
+ @values ||= {}
130
+ end
87
131
 
88
- # In case the file did not end with a newline, we want to flush the buffer
89
- # one more time to write the last message too.
90
- flush_buffer
132
+ def buffer
133
+ @buffer ||= {}
134
+ end
91
135
 
92
- # This will turn the header values into a friendlier json structure too.
93
- parse_header_lines
136
+ def headers
137
+ @headers ||= {}
138
+ end
94
139
 
95
- return @parsed_values
140
+ def lastkey
141
+ @lastkey ||= ""
96
142
  end
97
143
 
98
- def flush_buffer
99
- return unless @buffer[:msgid]
144
+ def reset_result
145
+ @values = {}
146
+ @errors = []
147
+ end
148
+
149
+ def reset_buffer
150
+ @buffer = {}
151
+ @trans = []
152
+ @lastkey = ""
153
+ end
154
+
155
+ def detect_ctxt
156
+ msgctxt = buffer[:msgctxt]
157
+ msgid = buffer[:msgid]
100
158
 
101
- msg_ctxt_id = if @buffer[:msgctxt] && @buffer[:msgctxt].size > 0
102
- @buffer[:msgctxt] + @context_glue + @buffer[:msgid]
159
+ if msgctxt && msgctxt.size > 0
160
+ [msgctxt, glue, msgid].join("")
103
161
  else
104
- @buffer[:msgid]
162
+ msgid
105
163
  end
164
+ end
106
165
 
107
- msgid_plural = if @buffer[:msgid_plural] && @buffer[:msgid_plural].size > 0
108
- @buffer[:msgid_plural]
109
- end
166
+ def detect_plural
167
+ plural = buffer[:msgid_plural]
168
+ plural if plural && plural.size > 0
169
+ end
110
170
 
111
- # find msgstr_* translations and push them on
112
- trans = []
113
- @buffer.each do |key, string|
114
- trans[$1.to_i] = string if key.to_s =~ /^msgstr_(\d+)/
171
+ def build_trans
172
+ buffer.each do |key, string|
173
+ trans[$1.to_i] = string if key.to_s.match(/^msgstr_(\d+)/)
115
174
  end
116
- trans.unshift(msgid_plural)
117
175
 
118
- @parsed_values[msg_ctxt_id] = trans if trans.size > 1
176
+ trans.unshift(detect_plural)
177
+ end
119
178
 
120
- @buffer = {}
121
- @last_key_type = ""
179
+ def assign_trans
180
+ values[detect_ctxt] = trans if trans.size > 1
122
181
  end
123
182
 
124
- # The buffer keeps key/value pairs for all the config options
125
- # defined on an entry, including the message id and value.
126
- # For continued lines, the key_type can be empty, so the last
127
- # used key type will be used. Also, the content will be appended
128
- # to the last key rather than assigned.
129
- def add_to_buffer(value, key_type = nil)
183
+ def push_buffer(value, key = nil)
130
184
  value = $1 if value =~ /^"(.*)"/
131
- value.gsub(/\\"/, '"')
185
+ value.gsub(/\\"/, "\"")
186
+
187
+ if key.nil?
188
+ buffer[lastkey] = [
189
+ buffer[lastkey],
190
+ value
191
+ ].join("")
192
+ else
193
+ buffer[key] = value
194
+ @lastkey = key
195
+ end
196
+ end
197
+
198
+ def parse_options(options)
199
+ defaults = {
200
+ pretty: false,
201
+ domain: "app",
202
+ variable: "locales"
203
+ }
204
+
205
+ defaults.merge(options)
206
+ end
207
+
208
+ def inject_meta(hash)
209
+ hash[""]["lang"] ||= options[:language]
210
+ hash[""]["domain"] ||= options[:domain]
211
+ hash[""]["plural_forms"] ||= hash[""]["Plural-Forms"]
132
212
 
133
- if key_type.nil?
134
- @buffer[@last_key_type] += value
213
+ hash
214
+ end
215
+
216
+ def build_header_for(line)
217
+ if line =~ /(.*?):(.*)/
218
+ key, value = $1, $2
219
+
220
+ if headers.key? key
221
+ errors.push "Duplicate header: #{line}"
222
+ elsif key =~ /#-#-#-#-#/
223
+ errors.push "Marked header: #{line}"
224
+ else
225
+ headers[key] = value.strip
226
+ end
135
227
  else
136
- @buffer[key_type] = value
137
- @last_key_type = key_type
228
+ errors.push "Malformed header: #{line}"
138
229
  end
139
230
  end
140
231
 
141
- # The parsed values are expected to have an empty string key ("")
142
- # which corresponds to the po file metadata defined in it's header.
143
- # the header has information like the translator, the pluralization, etc.
144
- # Each header line is subseqently parsed into a more usable hash.
145
- def parse_header_lines
146
- if @parsed_values[""].nil? || @parsed_values[""][1].nil?
147
- @parsed_values[""] = {}
148
- return
232
+ def build_json_for(hash)
233
+ if options[:pretty]
234
+ JSON.pretty_generate(hash)
235
+ else
236
+ JSON.generate(hash)
149
237
  end
238
+ end
239
+
240
+ def build_jed_for(hash)
241
+ {
242
+ domain: options[:domain],
243
+ locale_data: {
244
+ options[:domain] => hash
245
+ }
246
+ }
247
+ end
150
248
 
151
- headers = {}
152
- # Heading lines may have escaped newlines in them
153
- @parsed_values[""][1].split(/\\n/).each do |line|
154
- next if line.size == 0
155
-
156
- if line =~ /(.*?):(.*)/
157
- key, value = $1, $2
158
- if headers[key] && headers[key].size > 0
159
- @errors << ["Duplicate header line: #{line}"]
160
- elsif key =~ /#-#-#-#-#/
161
- @errors << ["Marker in header line: #{line}"]
249
+ def matches_values_for(line)
250
+ return if generic_rejects? line
251
+ return if generic_detects? line
252
+
253
+ return if iterate_detects_for(line)
254
+
255
+ errors.push "Strange line #{line}"
256
+ end
257
+
258
+ def iterate_detects_for(line)
259
+ specific_detects.each do |detect|
260
+ match = line.match(detect[:regex])
261
+
262
+ if match
263
+ if detect[:index]
264
+ push_buffer(match[detect[:index]], detect[:key].call(match))
162
265
  else
163
- headers[key] = value
266
+ push_buffer(line)
164
267
  end
165
- else
166
- @errors << ["Malformed header #{line}"]
268
+
269
+ return true
167
270
  end
168
271
  end
169
272
 
170
- @parsed_values[""] = headers
273
+ false
274
+ end
275
+
276
+ def generic_rejects?(line)
277
+ if line.match(/^$/) || line.match(/^(#[^~]|[#]$)/)
278
+ flush_buffer && true
279
+ else
280
+ false
281
+ end
282
+ end
283
+
284
+ def generic_detects?(line)
285
+ match = line.match(/^(?:#~ )?msgctxt\s+(.*)/)
286
+
287
+ if match
288
+ push_buffer(
289
+ match[1],
290
+ :msgctxt
291
+ )
292
+
293
+ return true
294
+ end
295
+
296
+ false
297
+ end
298
+
299
+ def specific_detects
300
+ [{
301
+ regex: /^(?:#~ )?msgctxt\s+(.*)/,
302
+ index: 1,
303
+ key: proc { :msgctxt }
304
+ }, {
305
+ regex: /^(?:#~ )?msgid\s+(.*)/,
306
+ index: 1,
307
+ key: proc { :msgid }
308
+ }, {
309
+ regex: /^(?:#~ )?msgid_plural\s+(.*)/,
310
+ index: 1,
311
+ key: proc { :msgid_plural }
312
+ }, {
313
+ regex: /^(?:#~ )?msgstr\s+(.*)/,
314
+ index: 1,
315
+ key: proc { :msgstr_0 }
316
+ }, {
317
+ regex: /^(?:#~ )?msgstr\[0\]\s+(.*)/,
318
+ index: 1,
319
+ key: proc { :msgstr_0 }
320
+ }, {
321
+ regex: /^(?:#~ )?msgstr\[(\d+)\]\s+(.*)/,
322
+ index: 2,
323
+ key: proc { |m| "msgstr_#{m[1]}".to_sym }
324
+ }, {
325
+ regex: /^(?:#~ )?"/,
326
+ index: nil
327
+ }]
171
328
  end
172
329
  end
@@ -0,0 +1,40 @@
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright (c) 2012-2015 Dropmysite.com <https://dropmyemail.com>
4
+ # Copyright (c) 2015 Webhippie <http://www.webhippie.de>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ class PoToJson
27
+ class Version
28
+ MAJOR = 0
29
+ MINOR = 1
30
+ PATCH = 0
31
+
32
+ PRE = nil
33
+
34
+ class << self
35
+ def to_s
36
+ [MAJOR, MINOR, PATCH, PRE].compact.join(".")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,69 @@
1
+ # SOME DESCRIPTIVE TITLE.
2
+ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3
+ # This file is distributed under the same license as the PACKAGE package.
4
+ # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5
+ msgid ""
6
+ msgstr ""
7
+ "Project-Id-Version: version 0.0.1\n"
8
+ "POT-Creation-Date: 2009-02-26 19:50+0100\n"
9
+ "PO-Revision-Date: 2011-12-04 18:54+0900\n"
10
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
11
+ "Language-Team: LANGUAGE <LL@li.org>\n"
12
+ "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
+ "Content-Transfer-Encoding: 8bit\n"
15
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
16
+
17
+ #: app/helpers/translation_helper.rb:3
18
+ msgid "%{relative_time} ago"
19
+ msgstr "vor %{relative_time}"
20
+
21
+ #: app/views/cars/show.html.erb:5
22
+ msgid "Axis"
23
+ msgid_plural "Axis"
24
+ msgstr[0] "Achse"
25
+ msgstr[1] "Achsen"
26
+
27
+ #: app/controllers/cars_controller.rb:47
28
+ msgid "Car was successfully created."
29
+ msgstr "Auto wurde erfolgreich gespeichert"
30
+
31
+ #: app/controllers/cars_controller.rb:64
32
+ msgid "Car was successfully updated."
33
+ msgstr "Auto wurde erfolgreich aktualisiert"
34
+
35
+ #: app/views/cars/show.html.erb:1 locale/model_attributes.rb:3
36
+ msgid "Car|Model"
37
+ msgstr "Modell"
38
+
39
+ msgid "Untranslated"
40
+ msgstr ""
41
+
42
+ #: app/views/cars/show.html.erb:3 locale/model_attributes.rb:4
43
+ msgid "Car|Wheels count"
44
+ msgstr "Räderzahl"
45
+
46
+ #: app/views/cars/show.html.erb:7
47
+ msgid "Created"
48
+ msgstr "Erstellt"
49
+
50
+ #: app/views/cars/show.html.erb:9
51
+ msgid "Month"
52
+ msgstr "Monat"
53
+
54
+ #: locale/model_attributes.rb:2
55
+ msgid "car"
56
+ msgstr "Auto"
57
+
58
+ #: locale/testlog_phrases.rb:2
59
+ msgid "this is a dynamic translation which was found!"
60
+ msgstr ""
61
+ "Dies ist eine dynamische Übersetzung, die "
62
+ "gefunden wurde!"
63
+
64
+ #: locale/test_escape.rb:2
65
+ msgid "You should escape '\\' as '\\\\'."
66
+ msgstr "Du solltest '\\' als '\\\\' escapen."
67
+
68
+ msgid "Umläüte"
69
+ msgstr "Umlaute"
@@ -0,0 +1,196 @@
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright (c) 2012-2015 Dropmysite.com <https://dropmyemail.com>
4
+ # Copyright (c) 2015 Webhippie <http://www.webhippie.de>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ require "spec_helper"
27
+
28
+ describe PoToJson do
29
+ let(:po_to_json) do
30
+ @subject = PoToJson.new(
31
+ File.expand_path("../fixtures/test.po", __FILE__)
32
+ )
33
+ end
34
+
35
+ describe "parsing" do
36
+ subject do
37
+ po_to_json.parse_document
38
+ end
39
+
40
+ it "should find the last author" do
41
+ expect(subject[""]["Last-Translator"]).to(
42
+ eq("FULL NAME <EMAIL@ADDRESS>")
43
+ )
44
+ end
45
+
46
+ it "should parse embedded variables" do
47
+ expect(subject["%{relative_time} ago"]).to(
48
+ eq([nil, "vor %{relative_time}"])
49
+ )
50
+ end
51
+
52
+ it "should match pluralizations" do
53
+ expect(subject["Axis"]).to(
54
+ eq(["Axis", "Achse", "Achsen"])
55
+ )
56
+ end
57
+
58
+ it "should match glued values" do
59
+ expect(subject["Car|Model"]).to(
60
+ eq([nil, "Modell"])
61
+ )
62
+ end
63
+
64
+ it "should match embedded glue" do
65
+ expect(subject["Car|Wheels count"]).to(
66
+ eq([nil, "Räderzahl"])
67
+ )
68
+ end
69
+
70
+ it "should return empty strings as well" do
71
+ expect(subject["Untranslated"]).to(
72
+ eq([nil, ""])
73
+ )
74
+ end
75
+
76
+ it "should match german umlauts" do
77
+ expect(subject["Umläüte"]).to(
78
+ eq([nil, "Umlaute"])
79
+ )
80
+ end
81
+
82
+ it "should match escaped values" do
83
+ expect(subject["You should escape '\\\\' as '\\\\\\\\'."]).to(
84
+ eq([nil, "Du solltest '\\\\' als '\\\\\\\\' escapen."])
85
+ )
86
+ end
87
+
88
+ it "should match multiline translations" do
89
+ expect(subject["this is a dynamic translation which was found!"]).to(
90
+ eq([nil, "Dies ist eine dynamische Übersetzung, die gefunden wurde!"])
91
+ )
92
+ end
93
+
94
+ it "should match simple strings" do
95
+ expect(subject["Car was successfully created."]).to(
96
+ eq([nil, "Auto wurde erfolgreich gespeichert"])
97
+ )
98
+
99
+ expect(subject["Car was successfully updated."]).to(
100
+ eq([nil, "Auto wurde erfolgreich aktualisiert"])
101
+ )
102
+
103
+ expect(subject["Created"]).to(
104
+ eq([nil, "Erstellt"])
105
+ )
106
+
107
+ expect(subject["Month"]).to(
108
+ eq([nil, "Monat"])
109
+ )
110
+
111
+ expect(subject["car"]).to(
112
+ eq([nil, "Auto"])
113
+ )
114
+ end
115
+ end
116
+
117
+ describe "generate jed compatible" do
118
+ describe "with minified output" do
119
+ subject do
120
+ po_to_json.generate_for_jed("de")
121
+ end
122
+
123
+ it "should output the var definition" do
124
+ expect(
125
+ subject.include?("var locales = locales || {}; locales['de'] = ")
126
+ ).to be_truthy
127
+ end
128
+
129
+ it "should include domain string" do
130
+ expect(
131
+ subject.include?('"domain":"app"')
132
+ ).to be_truthy
133
+ end
134
+
135
+ it "should include lang string" do
136
+ expect(
137
+ subject.include?('"lang":"de"')
138
+ ).to be_truthy
139
+ end
140
+
141
+ it "should include pluralization" do
142
+ val = '"plural_forms":"nplurals=INTEGER; plural=EXPRESSION;"'
143
+ expect(
144
+ subject.include? val
145
+ ).to be_truthy
146
+ end
147
+
148
+ it "should include a single line break" do
149
+ expect(
150
+ subject.count("\n")
151
+ ).to be < 1
152
+ end
153
+ end
154
+
155
+ context "with pretty output" do
156
+ subject do
157
+ po_to_json.generate_for_jed("de", pretty: true)
158
+ end
159
+
160
+ it "should output the var definition" do
161
+ expect(
162
+ subject.include?("var locales = locales || {}; locales['de'] = ")
163
+ ).to be_truthy
164
+ end
165
+
166
+ it "should include domain string" do
167
+ expect(
168
+ subject.include?('"domain": "app"')
169
+ ).to be_truthy
170
+ end
171
+
172
+ it "should include lang string" do
173
+ expect(
174
+ subject.include?('"lang": "de"')
175
+ ).to be_truthy
176
+ end
177
+
178
+ it "should include pluralization" do
179
+ val = '"plural_forms": "nplurals=INTEGER; plural=EXPRESSION;"'
180
+ expect(
181
+ subject.include? val
182
+ ).to be_truthy
183
+ end
184
+
185
+ it "should include multiple line breaks" do
186
+ expect(
187
+ subject.count("\n")
188
+ ).to be > 0
189
+ end
190
+ end
191
+ end
192
+
193
+ # describe "generate simple hashes" do
194
+ # pending "have to be implemented"
195
+ # end
196
+ end
@@ -0,0 +1,54 @@
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright (c) 2012-2015 Dropmysite.com <https://dropmyemail.com>
4
+ # Copyright (c) 2015 Webhippie <http://www.webhippie.de>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ require "simplecov"
27
+
28
+ if ENV["CODECLIMATE_REPO_TOKEN"]
29
+ require "coveralls"
30
+ require "codeclimate-test-reporter"
31
+
32
+ Coveralls.wear!
33
+ CodeClimate::TestReporter.start
34
+
35
+ SimpleCov.start do
36
+ add_filter "/spec"
37
+
38
+ formatter SimpleCov::Formatter::MultiFormatter[
39
+ SimpleCov::Formatter::HTMLFormatter,
40
+ CodeClimate::TestReporter::Formatter
41
+ ]
42
+ end
43
+ else
44
+ SimpleCov.start do
45
+ add_filter "/spec"
46
+ end
47
+ end
48
+
49
+ require "po_to_json"
50
+ require "rspec"
51
+
52
+ RSpec.configure do |config|
53
+ config.mock_with :rspec
54
+ end
metadata CHANGED
@@ -1,66 +1,130 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: po_to_json
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
5
- prerelease:
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
7
+ - Thomas Boerger
8
8
  - Nubis
9
- - eromirou
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-05-02 00:00:00.000000000 Z
12
+ date: 2015-02-20 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
- name: json
15
+ name: bundler
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ! '>='
18
+ - - '>='
21
19
  - !ruby/object:Gem::Version
22
20
  version: '0'
23
- type: :runtime
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: yard
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
24
50
  prerelease: false
25
51
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
52
  requirements:
28
- - - ! '>='
53
+ - - '>='
29
54
  - !ruby/object:Gem::Version
30
55
  version: '0'
31
- description: Convert gettext PO files to json to use in your javascript app, based
32
- po2json.pl (by DuckDuckGo, Inc. http://duckduckgo.com/, Torsten Raudssus <torsten@raudss.us>.)
33
- email: nubis@woobiz.com.ar
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: json
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: 1.6.0
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: 1.6.0
84
+ description: |2
85
+ Convert gettext PO files to JSON objects so that you can use it in your
86
+ application.
87
+ email:
88
+ - thomas@webhippie.de
89
+ - nubis@woobiz.com.ar
34
90
  executables: []
35
91
  extensions: []
36
92
  extra_rdoc_files: []
37
93
  files:
38
- - lib/po_to_json.rb
94
+ - CHANGELOG.md
39
95
  - README.md
40
- - MIT-LICENSE
41
- homepage: https://github.com/nubis/po_to_json
42
- licenses: []
96
+ - LICENSE
97
+ - lib/po_to_json.rb
98
+ - lib/po_to_json/version.rb
99
+ - spec/spec_helper.rb
100
+ - spec/fixtures/test.po
101
+ - spec/po_to_json_spec.rb
102
+ homepage: https://github.com/webhippie/po_to_json
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
43
106
  post_install_message:
44
107
  rdoc_options: []
45
108
  require_paths:
46
109
  - lib
47
110
  required_ruby_version: !ruby/object:Gem::Requirement
48
- none: false
49
111
  requirements:
50
- - - ! '>='
112
+ - - '>='
51
113
  - !ruby/object:Gem::Version
52
114
  version: '0'
53
115
  required_rubygems_version: !ruby/object:Gem::Requirement
54
- none: false
55
116
  requirements:
56
- - - ! '>='
117
+ - - '>='
57
118
  - !ruby/object:Gem::Version
58
119
  version: '0'
59
120
  requirements: []
60
121
  rubyforge_project:
61
- rubygems_version: 1.8.23
122
+ rubygems_version: 2.0.3
62
123
  signing_key:
63
- specification_version: 3
64
- summary: Convert gettext PO files to json
65
- test_files: []
124
+ specification_version: 4
125
+ summary: Convert gettext PO files to JSON
126
+ test_files:
127
+ - spec/spec_helper.rb
128
+ - spec/fixtures/test.po
129
+ - spec/po_to_json_spec.rb
66
130
  has_rdoc:
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright 2012 Dropmysite.com. https://dropmyemail.com
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.