PoParser 2.0.1 → 3.0.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 +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile +5 -2
- data/README.md +23 -1
- data/Rakefile +65 -1
- data/lib/poparser/comment.rb +33 -6
- data/lib/poparser/constants.rb +4 -2
- data/lib/poparser/entry.rb +10 -10
- data/lib/poparser/header.rb +20 -0
- data/lib/poparser/po.rb +10 -10
- data/lib/poparser/tokenizer.rb +5 -17
- data/lib/poparser/version.rb +1 -1
- data/lib/poparser.rb +9 -11
- data/poparser.gemspec +1 -1
- data/spec/poparser/comment_spec.rb +4 -2
- data/spec/poparser/entry_spec.rb +23 -6
- data/spec/poparser/po_spec.rb +6 -6
- data/spec/poparser/poparser_spec.rb +126 -0
- data/spec/spec_helper.rb +12 -3
- data/spec/utils/random_pofile_generator.rb +175 -0
- data/test/benchmark.po +683 -0
- data/test/benchmark_small.po +46 -0
- data/test/complex_entry.po +21 -0
- data/test/escape_string.txt +7 -0
- metadata +12 -12
- data/lib/poparser/parser.rb +0 -67
- data/lib/poparser/transformer.rb +0 -59
- data/spec/poparser/parser_spec.rb +0 -72
- data/spec/poparser/transformer_spec.rb +0 -24
@@ -0,0 +1,46 @@
|
|
1
|
+
# PO benchmark file header
|
2
|
+
#
|
3
|
+
#, fuzzy
|
4
|
+
msgid ""
|
5
|
+
msgstr ""
|
6
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
7
|
+
"Content-Transfer-Encoding: 8bit\n"
|
8
|
+
|
9
|
+
#: m
|
10
|
+
msgctxt "AESMM"
|
11
|
+
msgid "QtXRl"
|
12
|
+
msgid_plural "h"
|
13
|
+
msgstr[0] "spfQ9g"
|
14
|
+
msgstr[1] "spfQ9g"
|
15
|
+
|
16
|
+
# EnfA
|
17
|
+
#: EnthqvU2qf6kF
|
18
|
+
msgctxt "9ihYCwlIEg=="
|
19
|
+
msgid "AloClNt81srB2Op/gEoKap7QvzlMzWBXxMEWLyjI2bQZV3praFAT2jpYhfQmgzu4Wix2tAsOeZV6lZ1TcnRmuHXht8FLfE016Q=="
|
20
|
+
msgstr "i+9eqs/otjcsICeBK5MEcfQ5hJOmP++ROezIMcPEWVOEh+XAT1brUoxfqrQAMefK"
|
21
|
+
|
22
|
+
#: jg4iou6yRTCJ7XNHeEqikz
|
23
|
+
msgctxt "9dPrCW63vhWJwoO"
|
24
|
+
msgid ""
|
25
|
+
"ZPcE\n"
|
26
|
+
"llqi4\n"
|
27
|
+
msgstr ""
|
28
|
+
"sKNQc\n"
|
29
|
+
"BwQ\n"
|
30
|
+
|
31
|
+
#: Ld
|
32
|
+
#, fuzzy
|
33
|
+
#| msgctxt "M6J"
|
34
|
+
#| msgid "P4"
|
35
|
+
msgctxt "MA9k"
|
36
|
+
msgid "P4Zc"
|
37
|
+
msgstr "4ZcKx"
|
38
|
+
|
39
|
+
#: g3K
|
40
|
+
#~ msgctxt "CVdDY"
|
41
|
+
#~ msgid ""
|
42
|
+
#~ "8Jw\n"
|
43
|
+
#~ "dwtm\n"
|
44
|
+
#~ msgstr ""
|
45
|
+
#~ "KNV2\n"
|
46
|
+
#~ "lEWV\n"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# translator-comment
|
2
|
+
#
|
3
|
+
#. extract
|
4
|
+
#: reference1
|
5
|
+
#: reference2
|
6
|
+
#, flag
|
7
|
+
#| msgctxt "previous context"
|
8
|
+
#| msgid ""
|
9
|
+
#| "multiline\n"
|
10
|
+
#|"previous messageid"
|
11
|
+
#| msgid_plural "previous msgid_plural"
|
12
|
+
msgctxt "Context"
|
13
|
+
msgid "msgid"
|
14
|
+
msgid_plural ""
|
15
|
+
"multiline msgid_plural\n"
|
16
|
+
""
|
17
|
+
msgstr[0] "msgstr 0"
|
18
|
+
msgstr[1] ""
|
19
|
+
"msgstr 1 multiline 1\n"
|
20
|
+
"msgstr 1 line 2\n"
|
21
|
+
msgstr[2] "msgstr 2"
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: PoParser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arash Mousavi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: simple_po_parser
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,10 +75,8 @@ files:
|
|
75
75
|
- lib/poparser/entry.rb
|
76
76
|
- lib/poparser/header.rb
|
77
77
|
- lib/poparser/message.rb
|
78
|
-
- lib/poparser/parser.rb
|
79
78
|
- lib/poparser/po.rb
|
80
79
|
- lib/poparser/tokenizer.rb
|
81
|
-
- lib/poparser/transformer.rb
|
82
80
|
- lib/poparser/version.rb
|
83
81
|
- poparser.gemspec
|
84
82
|
- spec/poparser/comment_spec.rb
|
@@ -92,12 +90,15 @@ files:
|
|
92
90
|
- spec/poparser/fixtures/tokenizer_empty_line.po
|
93
91
|
- spec/poparser/header_spec.rb
|
94
92
|
- spec/poparser/message_spec.rb
|
95
|
-
- spec/poparser/parser_spec.rb
|
96
93
|
- spec/poparser/po_spec.rb
|
97
94
|
- spec/poparser/poparser_spec.rb
|
98
95
|
- spec/poparser/tokenizer_spec.rb
|
99
|
-
- spec/poparser/transformer_spec.rb
|
100
96
|
- spec/spec_helper.rb
|
97
|
+
- spec/utils/random_pofile_generator.rb
|
98
|
+
- test/benchmark.po
|
99
|
+
- test/benchmark_small.po
|
100
|
+
- test/complex_entry.po
|
101
|
+
- test/escape_string.txt
|
101
102
|
homepage: http://github.com/arashm/poparser
|
102
103
|
licenses:
|
103
104
|
- MIT
|
@@ -118,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
119
|
version: '0'
|
119
120
|
requirements: []
|
120
121
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.6.
|
122
|
+
rubygems_version: 2.6.12
|
122
123
|
signing_key:
|
123
124
|
specification_version: 4
|
124
125
|
summary: A PO file parser, editor and generator.
|
@@ -134,9 +135,8 @@ test_files:
|
|
134
135
|
- spec/poparser/fixtures/tokenizer_empty_line.po
|
135
136
|
- spec/poparser/header_spec.rb
|
136
137
|
- spec/poparser/message_spec.rb
|
137
|
-
- spec/poparser/parser_spec.rb
|
138
138
|
- spec/poparser/po_spec.rb
|
139
139
|
- spec/poparser/poparser_spec.rb
|
140
140
|
- spec/poparser/tokenizer_spec.rb
|
141
|
-
- spec/poparser/transformer_spec.rb
|
142
141
|
- spec/spec_helper.rb
|
142
|
+
- spec/utils/random_pofile_generator.rb
|
data/lib/poparser/parser.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
module PoParser
|
2
|
-
class Parser < Parslet::Parser
|
3
|
-
root(:document)
|
4
|
-
|
5
|
-
rule(:document) { lines.repeat }
|
6
|
-
rule(:lines) { comments | entries }
|
7
|
-
|
8
|
-
# Comments
|
9
|
-
rule(:comments) do
|
10
|
-
reference |
|
11
|
-
extracted_comment | flag |
|
12
|
-
previous_untraslated_string |
|
13
|
-
cached |
|
14
|
-
translator_comment
|
15
|
-
end
|
16
|
-
|
17
|
-
rule(:translator_comment) { spaced('#') >> comment_text_line.as(:translator_comment) }
|
18
|
-
rule(:extracted_comment) { spaced('#.') >> comment_text_line.as(:extracted_comment) }
|
19
|
-
rule(:reference) { spaced('#:') >> comment_text_line.as(:reference) }
|
20
|
-
rule(:flag) { spaced('#,') >> comment_text_line.as(:flag) }
|
21
|
-
rule(:previous_untraslated_string){ spaced('#|') >> comment_text_line.as(:previous_untraslated_string) }
|
22
|
-
rule(:cached) { spaced('#~') >> comment_text_line.as(:cached) }
|
23
|
-
|
24
|
-
# Entries
|
25
|
-
rule(:entries) do
|
26
|
-
msgid.as(:msgid) |
|
27
|
-
msgid_plural.as(:msgid_plural) |
|
28
|
-
msgstr.as(:msgstr) |
|
29
|
-
msgstr_plural.as(:msgstr_plural) |
|
30
|
-
msgctxt.as(:msgctxt)
|
31
|
-
end
|
32
|
-
|
33
|
-
rule(:multiline) { str('"').present? >> msg_text_line.repeat.maybe }
|
34
|
-
rule(:msgid) { spaced('msgid') >> msg_text_line >> multiline.repeat }
|
35
|
-
rule(:msgid_plural) { spaced('msgid_plural') >> msg_text_line >> multiline.repeat }
|
36
|
-
|
37
|
-
rule(:msgstr) { spaced('msgstr') >> msg_text_line >> multiline.repeat }
|
38
|
-
rule(:msgstr_plural){ str('msgstr') >> bracketed(match["[0-9]"].as(:plural_id)) >> space? >> msg_text_line >> multiline.repeat }
|
39
|
-
rule(:msgctxt) { spaced('msgctxt') >> msg_text_line >> multiline.repeat }
|
40
|
-
|
41
|
-
# Helpers
|
42
|
-
rule(:space) { match['\p{Blank}'].repeat } #match only whitespace and not newline
|
43
|
-
rule(:space?) { space.maybe }
|
44
|
-
rule(:newline) { match["\n"] }
|
45
|
-
rule(:eol) { newline | any.absent? }
|
46
|
-
rule(:character) { escaped | text }
|
47
|
-
rule(:text) { any }
|
48
|
-
rule(:escaped) { str('\\') >> any }
|
49
|
-
rule(:msg_line_end){ str('"') >> space? >> eol }
|
50
|
-
|
51
|
-
rule(:comment_text_line) do
|
52
|
-
(eol.absent? >> character).repeat.maybe.as(:text) >> eol
|
53
|
-
end
|
54
|
-
|
55
|
-
rule(:msg_text_line) do
|
56
|
-
str('"') >> (msg_line_end.absent? >> character).repeat.maybe.as(:text) >> msg_line_end
|
57
|
-
end
|
58
|
-
|
59
|
-
def bracketed(atom)
|
60
|
-
str('[') >> atom >> str(']')
|
61
|
-
end
|
62
|
-
|
63
|
-
def spaced(character)
|
64
|
-
str(character) >> space?
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
data/lib/poparser/transformer.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
module PoParser
|
2
|
-
# Converts the array returned from {Parser} to a usable hash
|
3
|
-
class Transformer
|
4
|
-
def initialize
|
5
|
-
@hash = {}
|
6
|
-
super
|
7
|
-
end
|
8
|
-
|
9
|
-
def transform(obj)
|
10
|
-
apply_transforms(obj).each do |hash|
|
11
|
-
merge(hash)
|
12
|
-
end
|
13
|
-
@hash
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
# @Note: There was a problem applying all rules together. I don't know
|
18
|
-
# in what order Parslet run rules, but it's not in order. I ended up
|
19
|
-
# making two separate transform and feed one output to the other.
|
20
|
-
def first_transform
|
21
|
-
Parslet::Transform.new do
|
22
|
-
rule(:msgstr_plural => subtree(:plural)) do
|
23
|
-
if plural.is_a? Array
|
24
|
-
{ "msgstr\[#{plural[0][:plural_id]}\]".to_sym => plural }
|
25
|
-
else
|
26
|
-
{ "msgstr\[#{plural[:plural_id]}\]".to_sym => plural }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
rule(:text => simple(:txt)) { txt.to_s.chomp }
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def second_transform
|
35
|
-
Parslet::Transform.new do
|
36
|
-
rule(:plural_id => simple(:id), :text => simple(:txt)) { txt }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def apply_transforms(hash)
|
41
|
-
first = first_transform.apply(hash)
|
42
|
-
second_transform.apply(first)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Merges two hashed together. If both hashes have common keys it
|
46
|
-
# will create an array of them
|
47
|
-
#
|
48
|
-
# @return [Hash]
|
49
|
-
def merge(newh)
|
50
|
-
@hash.merge!(newh) do |key, oldval, newval|
|
51
|
-
if oldval.is_a? Array
|
52
|
-
oldval << newval
|
53
|
-
else
|
54
|
-
Array.new [oldval, newval]
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe PoParser::Parser do
|
5
|
-
let(:po) { PoParser::Parser.new }
|
6
|
-
|
7
|
-
context(:comments) do
|
8
|
-
let(:tc) { po.translator_comment }
|
9
|
-
let(:rc) { po.reference }
|
10
|
-
let(:ec) { po.extracted_comment }
|
11
|
-
let(:fc) { po.flag }
|
12
|
-
let(:pusc){ po.previous_untraslated_string }
|
13
|
-
|
14
|
-
it 'parses the translator comment' do
|
15
|
-
expect(tc).to parse("# Persian translation for damned-lies 123123\n")
|
16
|
-
expect(tc).to parse("# Copyright (C) 2012 damned-lies's COPYRIGHT HOLDER\n")
|
17
|
-
expect(tc).to parse("# Arash Mousavi <mousavi.arash@gmail.com>, 2014.\n")
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'parses refrence comment' do
|
21
|
-
expect(rc).to parse("#: database-content.py:1 database-content.py:129 settings.py:52\n")
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'parses extracted_comment' do
|
25
|
-
expect(ec).to parse("#. database-content.py:1 database-content.py:129 settings.py:52\n")
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'parses flag_comment' do
|
29
|
-
expect(fc).to parse("#, python-format\n")
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'parses previous_untraslated_string' do
|
33
|
-
expect(pusc).to parse("#| msgid \"\"\n")
|
34
|
-
expect(pusc).to parse("#| \"Hello,\\n\"\n")
|
35
|
-
expect(pusc).to parse("#| \"The new state of %(module)s - %(branch)s - %(domain)s (%(language)s) is \"\n")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context 'Entries' do
|
40
|
-
let(:msgid) { po.msgid }
|
41
|
-
let(:msgstr){ po.msgstr }
|
42
|
-
let(:pofile){ Pathname.new('spec/poparser/fixtures/multiline.po').realpath }
|
43
|
-
|
44
|
-
it 'parses msgid' do
|
45
|
-
expect(msgid).to parse "msgid \"The new state of %(module)s - %(branch)s - %(domain)s (%(language)s) is now \"\n"
|
46
|
-
expect(msgid).to parse "msgid \"The new \"state\" of %(module)s - %(branch)s - %(domain)s (%(language)s) is now \"\n"
|
47
|
-
expect(msgid).to parse "msgid \"The new \"state\" of %(module)s - %(branch)s - %(domain)s (%(language)s) is now \"\n"
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'parses msgstr' do
|
51
|
-
expect(msgstr).to parse "msgstr \"The new state of %(module)s - %(branch)s - %(domain)s (%(language)s) is now \"\n"
|
52
|
-
expect(msgstr).to parse "msgstr \"فعالیت نامعتبر. شاید یک نفر دیگر دقیقا قبل از شما یک فعالیت دیگر ارسال کرده ۱۲۳۱۲۳۱safda \"\n"
|
53
|
-
expect(msgstr).to parse "msgstr \"The new state of %(module)s - %(branch)s - %(domain)s (%(language)s) is now \"\n"
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'parses multiline entries' do
|
57
|
-
data = pofile.read
|
58
|
-
result = [{:msgid=>[{:text=>""}, {:text=>"first"}, {:text=>"second"}]}, {:msgstr=>[{:text=>""}, {:text=>"aval"}, {:text=>"dovom"}]}]
|
59
|
-
expect(po.parse data).to eq(result)
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'parses plural msgstr entries' do
|
63
|
-
str1 = "msgstr[0] \"\""
|
64
|
-
str2 = "msgstr[0] \"\""
|
65
|
-
str3 = "msgstr[0]\"\""
|
66
|
-
result = [{:msgstr_plural=>{:plural_id=>"0", :text=>""}}]
|
67
|
-
expect(po.parse(str1)).to eq(result)
|
68
|
-
expect(po.parse(str2)).to eq(result)
|
69
|
-
expect(po.parse(str3)).to eq(result)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "spec_helper"
|
3
|
-
|
4
|
-
describe PoParser::Transformer do
|
5
|
-
let(:trans){ PoParser::Transformer.new }
|
6
|
-
|
7
|
-
it 'transforms the returned array from parslet to a usable hash' do
|
8
|
-
parslet_array = [{:translator_comment=>"Persian translation\n"}, {:translator_comment=>"Copyright\n"}, {:msgid=>"\"test\"\n"}]
|
9
|
-
transformed_hash = {:translator_comment=>["Persian translation\n", "Copyright\n"], :msgid=>"\"test\"\n"}
|
10
|
-
expect(trans.transform(parslet_array)).to eq(transformed_hash)
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'transforms plural msgstr forms correctly' do
|
14
|
-
data = [{:msgstr_plural=>{:plural_id=>"0", :text=>"this is a txt"}}]
|
15
|
-
result = { :'msgstr[0]' => "this is a txt" }
|
16
|
-
expect(trans.transform(data)).to eq(result)
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'transforms multiline plural msgstr forms correctly' do
|
20
|
-
data = [{:msgstr_plural=>[{:plural_id=>"0", :text=>"this is a txt"}, {:text => 'some text'}]}]
|
21
|
-
result = { :'msgstr[0]' => ["this is a txt", "some text"] }
|
22
|
-
expect(trans.transform(data)).to eq(result)
|
23
|
-
end
|
24
|
-
end
|