get_pomo 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|