get_pomo 0.6.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.
- data/.gitignore +1 -0
- data/README.markdown +47 -0
- data/Rakefile +19 -0
- data/VERSION +1 -0
- data/get_pomo.gemspec +66 -0
- data/lib/get_pomo/mo_file.rb +62 -0
- data/lib/get_pomo/po_file.rb +111 -0
- data/lib/get_pomo/translation.rb +44 -0
- data/lib/get_pomo.rb +12 -0
- data/prototype_treetop/po.treetop +25 -0
- data/prototype_treetop/test.rb +6 -0
- data/spec/files/complex.mo +0 -0
- data/spec/files/empty.mo +0 -0
- data/spec/files/plural.mo +0 -0
- data/spec/files/singular.mo +0 -0
- data/spec/files/singular_2.mo +0 -0
- data/spec/pomo/mo_file_spec.rb +58 -0
- data/spec/pomo/po_file_spec.rb +117 -0
- data/spec/pomo/translation_spec.rb +119 -0
- data/spec/pomo_spec.rb +7 -0
- data/spec/spec_helper.rb +10 -0
- data/vendor/README.rdoc +236 -0
- data/vendor/iconv.rb +107 -0
- data/vendor/mofile.rb +296 -0
- metadata +82 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/README.markdown
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
A simple and extendable .mo and .po file parser/generator.
|
2
|
+
|
3
|
+
Advanteges over original [mo](http://github.com/mutoh/gettext/blob/abf96713327cc4c5d35f0a772f3b75ff4819450c/lib/gettext/mofile.rb) / [po](http://github.com/mutoh/gettext/blob/abf96713327cc4c5d35f0a772f3b75ff4819450c/lib/gettext/poparser.rb)-parser:
|
4
|
+
|
5
|
+
- simple architecture + easy to extend/modify
|
6
|
+
- emtpy msgstr translations are read
|
7
|
+
- comments are included
|
8
|
+
- fuzzy can be set/unset
|
9
|
+
- multiple translations can be combined in a new po file(with comments and fuzzy and ...)
|
10
|
+
- po files can be written from any kind of input
|
11
|
+
- easy mo-file handling/merging
|
12
|
+
- po/mo file handling is identical, if you know one, you know both
|
13
|
+
|
14
|
+
Setup
|
15
|
+
=====
|
16
|
+
sudo gem install get_pomo -s http://gemcutter.org
|
17
|
+
|
18
|
+
###Static interface
|
19
|
+
#parse po files
|
20
|
+
translations = GetPomo::PoFile.parse(File.read('xxx.po')) + GetPomo::PoFile.parse(File.read('yyy.po'))
|
21
|
+
|
22
|
+
#and use the data...
|
23
|
+
msgids = translations.reject{|t|t.plural? or t.fuzzy?}.map(&:msgid)
|
24
|
+
|
25
|
+
#or write a new po file (unique by msgid)...
|
26
|
+
File.open('xxx.po','w){|f|f.print(GetPomo::PoFile.to_text(translations))}
|
27
|
+
|
28
|
+
|
29
|
+
###Instance interface
|
30
|
+
p = GetPomo::PoFile.new
|
31
|
+
p.add_translations_from_text(File.read('...'))
|
32
|
+
...
|
33
|
+
p.translations
|
34
|
+
p.to_text
|
35
|
+
|
36
|
+
`GetPomo::MoFile` behaves identical.
|
37
|
+
|
38
|
+
TODO
|
39
|
+
====
|
40
|
+
- extracting of version/pluralisation_rule/plurals/translator... (from msgid "")
|
41
|
+
- the vendor/mofile is really complex, maybe it can be refactored (also some parts are not needed)
|
42
|
+
|
43
|
+
Author
|
44
|
+
======
|
45
|
+
[Michael Grosser](http://pragmatig.wordpress.com)
|
46
|
+
grosser.michael@gmail.com
|
47
|
+
Hereby placed under public domain, do what you want, just do not hold me accountable...
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
task :default => :spec
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
Spec::Rake::SpecTask.new {|t| t.spec_opts = ['--color']}
|
4
|
+
|
5
|
+
begin
|
6
|
+
project_name = 'get_pomo'
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = project_name
|
10
|
+
gem.summary = "Ruby/Gettext: A .po and .mo file parser/generator"
|
11
|
+
gem.email = "grosser.michael@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/grosser/#{project_name}"
|
13
|
+
gem.authors = ["Michael Grosser"]
|
14
|
+
end
|
15
|
+
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.6.0
|
data/get_pomo.gemspec
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{get_pomo}
|
8
|
+
s.version = "0.6.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Michael Grosser"]
|
12
|
+
s.date = %q{2009-11-20}
|
13
|
+
s.email = %q{grosser.michael@gmail.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"README.markdown"
|
16
|
+
]
|
17
|
+
s.files = [
|
18
|
+
".gitignore",
|
19
|
+
"README.markdown",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"get_pomo.gemspec",
|
23
|
+
"lib/get_pomo.rb",
|
24
|
+
"lib/get_pomo/mo_file.rb",
|
25
|
+
"lib/get_pomo/po_file.rb",
|
26
|
+
"lib/get_pomo/translation.rb",
|
27
|
+
"prototype_treetop/po.treetop",
|
28
|
+
"prototype_treetop/test.rb",
|
29
|
+
"spec/files/complex.mo",
|
30
|
+
"spec/files/empty.mo",
|
31
|
+
"spec/files/plural.mo",
|
32
|
+
"spec/files/singular.mo",
|
33
|
+
"spec/files/singular_2.mo",
|
34
|
+
"spec/pomo/mo_file_spec.rb",
|
35
|
+
"spec/pomo/po_file_spec.rb",
|
36
|
+
"spec/pomo/translation_spec.rb",
|
37
|
+
"spec/pomo_spec.rb",
|
38
|
+
"spec/spec_helper.rb",
|
39
|
+
"vendor/README.rdoc",
|
40
|
+
"vendor/iconv.rb",
|
41
|
+
"vendor/mofile.rb"
|
42
|
+
]
|
43
|
+
s.homepage = %q{http://github.com/grosser/get_pomo}
|
44
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
45
|
+
s.require_paths = ["lib"]
|
46
|
+
s.rubygems_version = %q{1.3.5}
|
47
|
+
s.summary = %q{Ruby/Gettext: A .po and .mo file parser/generator}
|
48
|
+
s.test_files = [
|
49
|
+
"spec/spec_helper.rb",
|
50
|
+
"spec/pomo_spec.rb",
|
51
|
+
"spec/pomo/translation_spec.rb",
|
52
|
+
"spec/pomo/mo_file_spec.rb",
|
53
|
+
"spec/pomo/po_file_spec.rb"
|
54
|
+
]
|
55
|
+
|
56
|
+
if s.respond_to? :specification_version then
|
57
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
58
|
+
s.specification_version = 3
|
59
|
+
|
60
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
61
|
+
else
|
62
|
+
end
|
63
|
+
else
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'get_pomo/translation'
|
2
|
+
require File.join(File.dirname(__FILE__),'..','..','vendor','mofile')
|
3
|
+
|
4
|
+
module GetPomo
|
5
|
+
class MoFile
|
6
|
+
PLURAL_SEPERATOR = "\000"
|
7
|
+
|
8
|
+
def self.parse(text)
|
9
|
+
MoFile.new.add_translations_from_text(text)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.to_text(translations)
|
13
|
+
m = MoFile.new(:translations=>translations)
|
14
|
+
m.to_text
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :translations
|
18
|
+
|
19
|
+
def initialize(options = {})
|
20
|
+
@translations = options[:translations] || []
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_translations_from_text(text)
|
24
|
+
text = StringIO.new(text)
|
25
|
+
@translations += GetPomo::GetText::MOFile.open(text, "UTF-8").map do |msgid,msgstr|
|
26
|
+
translation = Translation.new
|
27
|
+
if plural? msgid or plural? msgstr
|
28
|
+
translation.msgid = split_plural(msgid)
|
29
|
+
translation.msgstr = split_plural(msgstr)
|
30
|
+
else
|
31
|
+
translation.msgid = msgid
|
32
|
+
translation.msgstr = msgstr
|
33
|
+
end
|
34
|
+
translation
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_text
|
39
|
+
m = GetPomo::GetText::MOFile.new
|
40
|
+
GetPomo.unique_translations(translations).each {|t| m[plural_to_string(t.msgid)] = plural_to_string(t.msgstr)}
|
41
|
+
|
42
|
+
io = StringIO.new
|
43
|
+
m.save_to_stream io
|
44
|
+
io.rewind
|
45
|
+
io.read
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def plural_to_string(plural_or_singular)
|
51
|
+
[*plural_or_singular] * PLURAL_SEPERATOR
|
52
|
+
end
|
53
|
+
|
54
|
+
def plural? string
|
55
|
+
string.include? PLURAL_SEPERATOR
|
56
|
+
end
|
57
|
+
|
58
|
+
def split_plural string
|
59
|
+
string.split PLURAL_SEPERATOR
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'get_pomo/translation'
|
2
|
+
|
3
|
+
module GetPomo
|
4
|
+
class PoFile
|
5
|
+
def self.parse(text)
|
6
|
+
PoFile.new.add_translations_from_text(text)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_text(translations)
|
10
|
+
p = PoFile.new(:translations=>translations)
|
11
|
+
p.to_text
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :translations
|
15
|
+
|
16
|
+
def initialize(options = {})
|
17
|
+
@translations = options[:translations] || []
|
18
|
+
end
|
19
|
+
|
20
|
+
#the text is split into lines and then converted into logical translations
|
21
|
+
#each translation consists of comments(that come before a translation)
|
22
|
+
#and a msgid / msgstr
|
23
|
+
def add_translations_from_text(text)
|
24
|
+
start_new_translation
|
25
|
+
text.split(/$/).each_with_index do |line,index|
|
26
|
+
@line_number = index + 1
|
27
|
+
next if line.empty?
|
28
|
+
if method_call? line
|
29
|
+
parse_method_call line
|
30
|
+
elsif comment? line
|
31
|
+
add_comment line
|
32
|
+
else
|
33
|
+
add_string line
|
34
|
+
end
|
35
|
+
end
|
36
|
+
start_new_translation #instance_variable has to be overwritten or errors can occur on next add
|
37
|
+
translations
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_text
|
41
|
+
GetPomo.unique_translations(translations).map {|translation|
|
42
|
+
comment = translation.comment.to_s.split(/\n|\r\n/).map{|line|"##{line}\n"}*''
|
43
|
+
msgid_and_msgstr = if translation.plural?
|
44
|
+
msgids =
|
45
|
+
%Q(msgid "#{translation.msgid[0]}"\n)+
|
46
|
+
%Q(msgid_plural "#{translation.msgid[1]}"\n)
|
47
|
+
|
48
|
+
msgstrs = []
|
49
|
+
translation.msgstr.each_with_index do |msgstr,index|
|
50
|
+
msgstrs << %Q(msgstr[#{index}] "#{msgstr}")
|
51
|
+
end
|
52
|
+
|
53
|
+
msgids + (msgstrs*"\n")
|
54
|
+
else
|
55
|
+
%Q(msgid "#{translation.msgid}"\n)+
|
56
|
+
%Q(msgstr "#{translation.msgstr}")
|
57
|
+
end
|
58
|
+
|
59
|
+
comment + msgid_and_msgstr
|
60
|
+
} * "\n\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
#e.g. # fuzzy
|
66
|
+
def comment?(line)
|
67
|
+
line =~ /^\s*#/
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_comment(line)
|
71
|
+
start_new_translation if translation_complete?
|
72
|
+
@current_translation.add_text(line.strip.sub('#','')+"\n",:to=>:comment)
|
73
|
+
end
|
74
|
+
|
75
|
+
#msgid "hello"
|
76
|
+
def method_call?(line)
|
77
|
+
line =~ /^\s*[a-z]/
|
78
|
+
end
|
79
|
+
|
80
|
+
#msgid "hello" -> method call msgid + add string "hello"
|
81
|
+
def parse_method_call(line)
|
82
|
+
method, string = line.match(/^\s*([a-z0-9_\[\]]+)(.*)/)[1..2]
|
83
|
+
raise "no method found" unless method
|
84
|
+
|
85
|
+
start_new_translation if method == 'msgid' and translation_complete?
|
86
|
+
@last_method = method.to_sym
|
87
|
+
add_string(string)
|
88
|
+
end
|
89
|
+
|
90
|
+
#"hello" -> hello
|
91
|
+
def add_string(string)
|
92
|
+
return if string.strip.empty?
|
93
|
+
raise "not string format: #{string.inspect} on line #{@line_number}" unless string.strip =~ /^['"](.*)['"]$/
|
94
|
+
@current_translation.add_text($1,:to=>@last_method)
|
95
|
+
end
|
96
|
+
|
97
|
+
def translation_complete?
|
98
|
+
return false unless @current_translation
|
99
|
+
@current_translation.complete?
|
100
|
+
end
|
101
|
+
|
102
|
+
def store_translation
|
103
|
+
@translations += [@current_translation] if @current_translation.complete?
|
104
|
+
end
|
105
|
+
|
106
|
+
def start_new_translation
|
107
|
+
store_translation if translation_complete?
|
108
|
+
@current_translation = Translation.new
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module GetPomo
|
2
|
+
class Translation
|
3
|
+
FUZZY_REGEX = /^\s*fuzzy\s*$/
|
4
|
+
attr_accessor :msgid, :msgstr, :comment
|
5
|
+
|
6
|
+
def add_text(text,options)
|
7
|
+
to = options[:to]
|
8
|
+
if to.to_sym == :msgid_plural
|
9
|
+
self.msgid = [msgid] unless msgid.is_a? Array
|
10
|
+
msgid[1] = msgid[1].to_s + text
|
11
|
+
elsif to.to_s =~ /^msgstr\[(\d)\]$/
|
12
|
+
self.msgstr ||= []
|
13
|
+
msgstr[$1.to_i] = msgstr[$1.to_i].to_s + text
|
14
|
+
else
|
15
|
+
#simple form
|
16
|
+
send("#{to}=",send(to).to_s+text)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_hash
|
21
|
+
{:msgid=>msgid,:msgstr=>msgstr,:comment=>comment}.reject{|k,value|value.nil?}
|
22
|
+
end
|
23
|
+
|
24
|
+
def complete?
|
25
|
+
not msgid.nil? and not msgstr.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def fuzzy?
|
29
|
+
comment =~ FUZZY_REGEX
|
30
|
+
end
|
31
|
+
|
32
|
+
def fuzzy=(value)
|
33
|
+
if value and not fuzzy?
|
34
|
+
add_text "\nfuzzy", :to=>:comment
|
35
|
+
else
|
36
|
+
self.comment = comment.to_s.split(/$/).reject{|line|line=~FUZZY_REGEX}.join("\n")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def plural?
|
41
|
+
msgid.is_a? Array or msgstr.is_a? Array
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/get_pomo.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'get_pomo/po_file'
|
2
|
+
module GetPomo
|
3
|
+
VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
|
4
|
+
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def self.unique_translations(translations)
|
8
|
+
last_seen_at_index = {}
|
9
|
+
translations.each_with_index {|translation,index|last_seen_at_index[translation.msgid]=index}
|
10
|
+
last_seen_at_index.values.sort.map{|index| translations[index]}
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
grammar Po
|
2
|
+
rule translation
|
3
|
+
msgid whitespace string
|
4
|
+
end
|
5
|
+
|
6
|
+
rule string
|
7
|
+
string whitespace string
|
8
|
+
end
|
9
|
+
|
10
|
+
rule quote
|
11
|
+
'"'
|
12
|
+
end
|
13
|
+
|
14
|
+
rule text
|
15
|
+
[^"]*
|
16
|
+
end
|
17
|
+
|
18
|
+
rule whitespace
|
19
|
+
[ \t\n\r]+
|
20
|
+
end
|
21
|
+
|
22
|
+
rule msgid
|
23
|
+
"msgid"
|
24
|
+
end
|
25
|
+
end
|
Binary file
|
data/spec/files/empty.mo
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
2
|
+
require 'get_pomo/mo_file'
|
3
|
+
|
4
|
+
include GetPomo
|
5
|
+
describe GetPomo::MoFile do
|
6
|
+
it "parses empty mo file" do
|
7
|
+
MoFile.parse(File.read('spec/files/empty.mo')).should == []
|
8
|
+
end
|
9
|
+
|
10
|
+
it "parses empty strings" do
|
11
|
+
MoFile.parse(File.read('spec/files/empty.mo')).should == []
|
12
|
+
end
|
13
|
+
|
14
|
+
it "reads singulars" do
|
15
|
+
t = MoFile.parse(File.read('spec/files/singular.mo'))[0]
|
16
|
+
t.to_hash.should == {:msgid=>'Back',:msgstr=>'Zurück'}
|
17
|
+
end
|
18
|
+
|
19
|
+
it "reads plurals" do
|
20
|
+
t = MoFile.parse(File.read('spec/files/plural.mo'))[0]
|
21
|
+
t.to_hash.should == {:msgid=>['Axis','Axis'],:msgstr=>['Achse','Achsen']}
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'instance methods' do
|
25
|
+
it "combines multiple translations" do
|
26
|
+
m = MoFile.new
|
27
|
+
m.add_translations_from_text(File.read('spec/files/plural.mo'))
|
28
|
+
m.add_translations_from_text(File.read('spec/files/singular.mo'))
|
29
|
+
m.should have(2).translations
|
30
|
+
m.translations[0].msgid.should_not == m.translations[1].msgid
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can be initialized with translations" do
|
34
|
+
m = MoFile.new(:translations=>['x'])
|
35
|
+
m.translations.should == ['x']
|
36
|
+
end
|
37
|
+
|
38
|
+
it "does not generate duplicate translations" do
|
39
|
+
second_version = File.read('spec/files/singular_2.mo')
|
40
|
+
m = MoFile.new
|
41
|
+
m.add_translations_from_text(File.read('spec/files/singular.mo'))
|
42
|
+
m.add_translations_from_text(second_version)
|
43
|
+
m.to_text.should == second_version
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "reads metadata" do
|
48
|
+
meta = MoFile.parse(File.read('spec/files/complex.mo')).detect {|t|t.msgid == ''}
|
49
|
+
meta.msgstr.should_not be_empty
|
50
|
+
end
|
51
|
+
|
52
|
+
describe :to_text do
|
53
|
+
it "writes singulars" do
|
54
|
+
text = File.read('spec/files/singular.mo')
|
55
|
+
MoFile.to_text(MoFile.parse(text)).should == text
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
include GetPomo
|
4
|
+
describe GetPomo::PoFile do
|
5
|
+
describe :parse do
|
6
|
+
it "parses nothing" do
|
7
|
+
PoFile.parse("").should be_empty
|
8
|
+
end
|
9
|
+
|
10
|
+
it "parses a simple msgid and msgstr" do
|
11
|
+
t = PoFile.parse(%Q(msgid "xxx"\nmsgstr "yyy"))
|
12
|
+
t[0].to_hash.should == {:msgid=>'xxx',:msgstr=>'yyy'}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "parses a simple msgid and msg with additional whitespace" do
|
16
|
+
t = PoFile.parse(%Q( msgid "xxx" \n msgstr "yyy" ))
|
17
|
+
t[0].to_hash.should == {:msgid=>'xxx',:msgstr=>'yyy'}
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses an empty msgid with text (gettext meta data)" do
|
21
|
+
t = PoFile.parse(%Q(msgid ""\nmsgstr "PLURAL FORMS"))
|
22
|
+
t[0].to_hash.should == {:msgid=>'',:msgstr=>'PLURAL FORMS'}
|
23
|
+
end
|
24
|
+
|
25
|
+
it "parses a multiline msgid/msgstr" do
|
26
|
+
t = PoFile.parse(%Q(msgid "xxx"\n"aaa"\n\n\nmsgstr ""\n"bbb"))
|
27
|
+
t[0].to_hash.should == {:msgid=>'xxxaaa',:msgstr=>'bbb'}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "parses simple comments" do
|
31
|
+
t = PoFile.parse(%Q(#test\nmsgid "xxx"\nmsgstr "yyy"))
|
32
|
+
t[0].to_hash.should == {:msgid=>'xxx',:msgstr=>'yyy',:comment=>"test\n"}
|
33
|
+
end
|
34
|
+
|
35
|
+
it "parses comments above msgstr" do
|
36
|
+
t = PoFile.parse(%Q(#test\nmsgid "xxx"\n#another\nmsgstr "yyy"))
|
37
|
+
t[0].to_hash.should == {:msgid=>'xxx',:msgstr=>'yyy',:comment=>"test\nanother\n"}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "instance interface" do
|
42
|
+
it "adds two different translations" do
|
43
|
+
p = PoFile.new
|
44
|
+
p.add_translations_from_text(%Q(msgid "xxx"\nmsgstr "yyy"))
|
45
|
+
p.add_translations_from_text(%Q(msgid "aaa"\nmsgstr "yyy"))
|
46
|
+
p.translations[1].to_hash.should == {:msgid=>'aaa',:msgstr=>'yyy'}
|
47
|
+
end
|
48
|
+
|
49
|
+
it "can be initialized with translations" do
|
50
|
+
p = PoFile.new(:translations=>['xxx'])
|
51
|
+
p.translations[0].should == 'xxx'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "can be converted to text" do
|
55
|
+
text = %Q(msgid "xxx"\nmsgstr "aaa")
|
56
|
+
p = PoFile.new
|
57
|
+
p.add_translations_from_text(text)
|
58
|
+
p.to_text.should == text
|
59
|
+
end
|
60
|
+
|
61
|
+
it "keeps uniqueness when converting to_text" do
|
62
|
+
text = %Q(msgid "xxx"\nmsgstr "aaa")
|
63
|
+
p = PoFile.new
|
64
|
+
p.add_translations_from_text(%Q(msgid "xxx"\nmsgstr "yyy"))
|
65
|
+
p.add_translations_from_text(text)
|
66
|
+
p.to_text.should == text
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "adds plural translations" do
|
71
|
+
t = PoFile.parse(%Q(msgid "singular"\nmsgid_plural "plural"\nmsgstr[0] "one"\nmsgstr[1] "many"))
|
72
|
+
t[0].to_hash.should == {:msgid=>['singular','plural'],:msgstr=>['one','many']}
|
73
|
+
end
|
74
|
+
|
75
|
+
it "does not fail on empty string" do
|
76
|
+
PoFile.parse(%Q(\n\n\n\n\n))
|
77
|
+
end
|
78
|
+
|
79
|
+
it "shows line number for invalid strings" do
|
80
|
+
begin
|
81
|
+
PoFile.parse(%Q(\n\n\n\n\nmsgstr "))
|
82
|
+
flunk
|
83
|
+
rescue Exception => e
|
84
|
+
e.to_s.should =~ /line 5/
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe :to_text do
|
89
|
+
it "is empty when not translations where added" do
|
90
|
+
PoFile.to_text([]).should == ""
|
91
|
+
end
|
92
|
+
|
93
|
+
it "preserves simple syntax" do
|
94
|
+
text = %Q(msgid "x"\nmsgstr "y")
|
95
|
+
PoFile.to_text(PoFile.parse(text)).should == text
|
96
|
+
end
|
97
|
+
|
98
|
+
it "adds comments" do
|
99
|
+
t = GetPomo::Translation.new
|
100
|
+
t.msgid = 'a'
|
101
|
+
t.msgstr = 'b'
|
102
|
+
t.add_text("c\n",:to=>:comment)
|
103
|
+
t.add_text("d\n",:to=>:comment)
|
104
|
+
PoFile.to_text([t]).should == %Q(#c\n#d\nmsgid "a"\nmsgstr "b")
|
105
|
+
end
|
106
|
+
|
107
|
+
it "uses plural notation" do
|
108
|
+
text = %Q(#awesome\nmsgid "one"\nmsgid_plural "many"\nmsgstr[0] "1"\nmsgstr[1] "n")
|
109
|
+
PoFile.to_text(PoFile.parse(text)).should == text
|
110
|
+
end
|
111
|
+
|
112
|
+
it "only uses the latest of identicals msgids" do
|
113
|
+
text = %Q(msgid "one"\nmsgstr "1"\nmsgid "one"\nmsgstr "001")
|
114
|
+
PoFile.to_text(PoFile.parse(text)).should == %Q(msgid "one"\nmsgstr "001")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|