po_to_json 0.0.7 → 0.1.0

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 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.