babelyoda 2.0.7 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ notification :gntp, :sticky => true, :host => '127.0.0.1', :password => ENV['GNTP_PASS']
2
+
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| ["spec/lib/#{m[1]}_spec.rb"] }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/babelyoda.gemspec CHANGED
@@ -17,7 +17,10 @@ Gem::Specification.new do |s|
17
17
  s.require_paths = ["lib"]
18
18
 
19
19
  # specify any dependencies here; for example:
20
- s.add_development_dependency "rspec", '~> 2.8', '>= 2.8.0'
20
+ s.add_development_dependency "rspec"
21
+ s.add_development_dependency "guard"
22
+ s.add_development_dependency "guard-rspec"
23
+ s.add_development_dependency "ruby_gntp"
21
24
  s.add_runtime_dependency "awesome_print", '~> 1.0', '>= 1.0.2'
22
25
  s.add_runtime_dependency "rake", '~> 0.9', '>= 0.9.2.2'
23
26
  s.add_runtime_dependency "active_support", '~> 3.0', '>= 3.0.0'
@@ -59,9 +59,7 @@ module Babelyoda
59
59
 
60
60
  def ensure_languages!(languages = [])
61
61
  @keys.each_value do |key|
62
- languages.each do |language|
63
- key.values[language] ||= Babelyoda::LocalizationValue.new(language, '')
64
- end
62
+ key.ensure_languages!(languages)
65
63
  end
66
64
  end
67
65
 
@@ -1,3 +1,5 @@
1
+ require_relative 'regexp'
2
+
1
3
  module Babelyoda
2
4
  class LocalizationKey
3
5
  attr_reader :id
@@ -8,14 +10,31 @@ module Babelyoda
8
10
  @id = id
9
11
  @context = context
10
12
  @values = {}
13
+ @plural = plural_id?(id)
14
+ @plural_key = plural? ? extract_plural_key(id) : nil
15
+ @id = depluralize_key(@id) if plural?
11
16
  end
12
17
 
13
18
  def to_s
14
19
  "\"#{@id}\" [#{@values.keys.map{|k| ":#{k.to_s}"}.join(', ')}] // #{@context}"
15
20
  end
16
21
 
22
+ def plural? ; @plural ; end
23
+
17
24
  def <<(localization_value)
18
- @values[localization_value.language.to_sym] = localization_value.dup
25
+ raise "Can't merge a plural value into a non-plural key" if !plural? && localization_value.plural?
26
+ lang = localization_value.language.to_sym
27
+ value = localization_value.dup
28
+ if plural?
29
+ value.pluralize!(@plural_key)
30
+ if @values[lang]
31
+ @values[lang].merge!(value, { :preserve => true })
32
+ else
33
+ @values[lang] = value
34
+ end
35
+ else
36
+ @values[lang] = value
37
+ end
19
38
  self
20
39
  end
21
40
 
@@ -23,7 +42,8 @@ module Babelyoda
23
42
  updated = false
24
43
 
25
44
  context_changed = false
26
- if @context != localization_key.context
45
+ new_context = localization_key.context
46
+ if @context != new_context && new_context != nil && new_context.length > 0
27
47
  @context = localization_key.context
28
48
  updated = context_changed = true
29
49
  end
@@ -56,5 +76,16 @@ module Babelyoda
56
76
  def empty?
57
77
  @values.empty?
58
78
  end
79
+
80
+ def ensure_languages!(languages = [])
81
+ languages.each do |language|
82
+ unless self.values[language]
83
+ self << Babelyoda::LocalizationValue.new(language, '')
84
+ end
85
+ end
86
+ end
87
+
88
+ private
89
+ include Babelyoda::Regexp
59
90
  end
60
91
  end
@@ -1,3 +1,5 @@
1
+ require_relative 'regexp'
2
+
1
3
  module Babelyoda
2
4
  class LocalizationValue
3
5
  attr_accessor :language
@@ -6,21 +8,62 @@ module Babelyoda
6
8
 
7
9
  def initialize(language, text, status = :requires_translation)
8
10
  @language, @text, @status = language.to_sym, text, status.to_sym
11
+ pluralize! if plural_id?(@text)
9
12
  end
10
13
 
14
+ def pluralize!(plural_key = :one)
15
+ return if plural?
16
+ new_text = { :one => nil, :some => nil, :many => nil, :none => nil }
17
+
18
+ if plural_id?(text)
19
+ m = plural_match(text)
20
+ new_text[m[2].to_sym] = depluralize_value(@text)
21
+ else
22
+ new_text[plural_key] = text
23
+ end
24
+
25
+ @text = new_text
26
+ end
27
+
28
+ def plural? ; text.kind_of? Hash ; end
29
+
11
30
  def merge!(other_value, options = {})
12
31
  updated = false
13
32
  options = { preserve: false }.merge!(options)
33
+
14
34
  unless @language.to_sym == other_value.language.to_sym
15
- raise RuntimeError.new("Can't merge values in different languages: #{@language.to_sym} and #{other_value.language.to_sym}")
35
+ raise "Can't merge values in different languages: #{@language.to_sym} and #{other_value.language.to_sym}"
16
36
  end
17
- if (!options[:preserve] || @status.to_sym == :requires_translation)
18
- unless @text == other_value.text
19
- @text = other_value.text
20
- updated = true
37
+
38
+ raise "Can't merge a plural and a non-plural value!" unless plural? == other_value.plural?
39
+
40
+ if plural?
41
+ [:one, :some, :many, :none].each do |plural_type|
42
+ key_updated = merge_plural_type!(plural_type, other_value.text[plural_type], options)
43
+ updated ||= key_updated
44
+ end
45
+ else
46
+ if (!options[:preserve] || @status.to_sym == :requires_translation)
47
+ if @text != other_value.text && !other_value.nil?
48
+ @text = other_value.text
49
+ updated = true
50
+ end
21
51
  end
22
52
  end
23
53
  return updated
24
54
  end
55
+
56
+ private
57
+ include Babelyoda::Regexp
58
+
59
+ def merge_plural_type!(type, other_value, options)
60
+ if (!options[:preserve] || @status.to_sym == :requires_translation)
61
+ if @text[type] != other_value && !other_value.nil?
62
+ @text[type] = other_value
63
+ return true
64
+ end
65
+ end
66
+ return false
67
+ end
25
68
  end
26
69
  end
@@ -0,0 +1,30 @@
1
+ module Babelyoda
2
+ module Regexp
3
+ PLURAL_ID = /([^%]|^)%\[(one|some|many|none|plural)\]([^\s])/
4
+ PLURALIZED_ID = /([^%]|^)%\[(plural)\]([^\s])/
5
+
6
+ def plural_id?(id)
7
+ plural_match(id) != nil
8
+ end
9
+
10
+ def plural_match(id)
11
+ id.match(PLURAL_ID)
12
+ end
13
+
14
+ def depluralize_value(id)
15
+ id.gsub(PLURAL_ID, '\1%\3')
16
+ end
17
+
18
+ def depluralize_key(id)
19
+ id.gsub(PLURAL_ID, '\1%[plural]\3')
20
+ end
21
+
22
+ def pluralize_key(id, plural_key)
23
+ id.gsub(PLURALIZED_ID, "\\1%[#{plural_key}]\\3")
24
+ end
25
+
26
+ def extract_plural_key(id)
27
+ id.match(PLURAL_ID)[2].to_sym
28
+ end
29
+ end
30
+ end
@@ -29,7 +29,7 @@ module Babelyoda
29
29
  def self.load
30
30
  trace_spec = @spec.nil? && ::Rake.application.options.trace
31
31
  @spec ||= load_from_file(filename = FILENAME)
32
- @spec.dump if trace_spec && @spec
32
+ @spec.dump if trace_spec && @spec
33
33
  return @spec
34
34
  end
35
35
 
@@ -17,7 +17,11 @@ module Babelyoda
17
17
  end
18
18
 
19
19
  def dump
20
- ap self, :indent => -2
20
+ unless ::Rake.application.options.trace
21
+ ap self, :indent => -2
22
+ else
23
+ p self
24
+ end
21
25
  end
22
26
 
23
27
  module ClassMethods
@@ -6,6 +6,31 @@ require_relative 'strings_lexer'
6
6
  require_relative 'strings_parser'
7
7
 
8
8
  module Babelyoda
9
+ class Keyset
10
+ def to_strings(io, language)
11
+ keys.each_value do |key|
12
+ key.to_strings(io, language)
13
+ end
14
+ end
15
+ end
16
+
17
+ class LocalizationKey
18
+ def to_strings(io, language)
19
+ return if self.values[language].nil?
20
+ io << "/* #{self.context} */\n" if self.context
21
+ if plural?
22
+ values[language].text.keys.each do |plural_key|
23
+ if values[language].text[plural_key] != nil && values[language].text[plural_key].length > 0
24
+ io << "\"#{pluralize_key(id, plural_key)}\" = \"#{values[language].text[plural_key]}\";\n"
25
+ end
26
+ end
27
+ else
28
+ io << "\"#{id}\" = \"#{values[language].text}\";\n"
29
+ end
30
+ io << "\n"
31
+ end
32
+ end
33
+
9
34
  class Strings < Keyset
10
35
  attr_reader :filename
11
36
  attr_reader :language
@@ -36,12 +61,7 @@ module Babelyoda
36
61
  def save!
37
62
  FileUtils.mkdir_p(File.dirname(filename))
38
63
  File.open(filename, "wb") do |f|
39
- keys.each_pair do |id, key|
40
- next unless key.values[language]
41
- f << "/* #{key.context} */\n" if key.context
42
- f << "\"#{id}\" = \"#{key.values[language].text}\";\n"
43
- f << "\n"
44
- end
64
+ to_strings(f, language)
45
65
  end
46
66
  end
47
67
 
@@ -5,19 +5,15 @@ require 'stringio'
5
5
 
6
6
  require_relative 'logger'
7
7
  require_relative 'specification_loader'
8
+ require_relative 'localization_key'
9
+ require_relative 'localization_value'
8
10
 
9
11
  module Babelyoda
10
12
  class Keyset
11
13
  def to_xml(xml, language = nil)
12
14
  xml.keyset(:id => name) do
13
15
  keys.each_value do |key|
14
- xml.key(:id => key.id, :is_plural => 'False') do
15
- xml.context(key.context)
16
- key.values.each_value do |value|
17
- next if language && (value.language.to_s != language.to_s)
18
- xml.value(value.text, :language => value.language, :status => value.status)
19
- end
20
- end
16
+ key.to_xml(xml, language)
21
17
  end
22
18
  end
23
19
  end
@@ -42,14 +38,67 @@ module Babelyoda
42
38
  end
43
39
  result
44
40
  end
41
+
42
+ def to_xml(xml, language = nil)
43
+ xml.key(:id => self.id, :is_plural => (plural? ? 'True' : 'False')) do |key|
44
+ xml << "<context>#{self.context}</context>"
45
+ self.values.each_value do |value|
46
+ next if language && (value.language.to_s != language.to_s)
47
+ value.to_xml(xml)
48
+ end
49
+ end
50
+ end
45
51
  end
46
52
 
47
53
  class LocalizationValue
48
54
  def self.parse_xml(node)
49
- if node.text.length > 0
55
+ if node.css('plural').first
56
+ plural = node.css('plural').first
57
+
58
+ plural_key = plural.css('one').first
59
+ value_one = self.new(node[:language], plural_key.text, node[:status])
60
+ value_one.pluralize!(:one)
61
+
62
+ plural_key = plural.css('some').first
63
+ value_some = self.new(node[:language], plural_key.text, node[:status])
64
+ value_some.pluralize!(:some)
65
+
66
+ plural_key = plural.css('many').first
67
+ value_many = self.new(node[:language], plural_key.text, node[:status])
68
+ value_many.pluralize!(:many)
69
+
70
+ plural_key = plural.css('none').first
71
+ value_none = self.new(node[:language], plural_key.text, node[:status])
72
+ value_none.pluralize!(:none)
73
+
74
+ value_one.merge!(value_some)
75
+ value_one.merge!(value_many)
76
+ value_one.merge!(value_none)
77
+
78
+ value_one.text.keys.each do |k|
79
+ value_one.text[k] = nil if value_one.text[k] == ''
80
+ end
81
+
82
+ value_one
83
+ elsif node.text.length > 0
50
84
  self.new(node[:language], node.text, node[:status])
51
85
  end
52
86
  end
87
+
88
+ def to_xml(xml)
89
+ unless plural?
90
+ xml.value(self.text, :language => self.language, :status => self.status)
91
+ else
92
+ xml.value(:language => self.language, :status => self.status) do |value|
93
+ value.plural do |plural|
94
+ plural.one text[:one] || ''
95
+ plural.some text[:some] || ''
96
+ plural.many text[:many] || ''
97
+ plural.none text[:none] || ''
98
+ end
99
+ end
100
+ end
101
+ end
53
102
  end
54
103
 
55
104
  class Tanker
@@ -124,13 +173,14 @@ module Babelyoda
124
173
  end
125
174
 
126
175
  def project_xml(&block)
127
- xml = Builder::XmlMarkup.new
128
- xml.instruct!(:xml, :encoding => "UTF-8")
129
- xml.tanker do
130
- xml.project(:id => project_id) do
131
- yield xml
176
+ xml = Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
177
+ xml.tanker do
178
+ xml.project(:id => project_id) do
179
+ yield xml
180
+ end
132
181
  end
133
182
  end
183
+ xml.to_xml(:indent => 2)
134
184
  end
135
185
 
136
186
  def multipart_data(payload = {}, boundary = MULTIPART_BOUNDARY)
@@ -1,3 +1,3 @@
1
1
  module Babelyoda
2
- VERSION = "2.0.7"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -0,0 +1,43 @@
1
+ require 'babelyoda/strings_lexer'
2
+ require 'babelyoda/strings_parser'
3
+ require 'babelyoda/keyset'
4
+
5
+ describe "keyset" do
6
+ it "can be created" do
7
+ keyset = Babelyoda::Keyset.new('Combined')
8
+ keyset.name.should == 'Combined'
9
+ keyset.keys.size.should == 0
10
+ end
11
+
12
+ it "should correctly merge plural keys" do
13
+ lexer = Babelyoda::StringsLexer.new
14
+ parser = Babelyoda::StringsParser.new(lexer, :en)
15
+ str = <<-EOF
16
+ /* Some comment */
17
+ "Some plural %[one]u key" = "Some translation for one %u";
18
+ /* Some comment */
19
+ "Some plural %[some]u key" = "Some translation for some %u";
20
+ /* Some comment */
21
+ "Some plural %[many]u key" = "Some translation for many %u";
22
+ /* Some comment */
23
+ "Some plural %[none]u key" = "Some translation for none %u";
24
+ EOF
25
+ keyset = Babelyoda::Keyset.new('Combined')
26
+ parser.parse(str) do |record|
27
+ keyset.merge_key!(record)
28
+ end
29
+ keyset.keys.size.should == 1
30
+ key = keyset.keys['Some plural %[plural]u key']
31
+ key.should_not == nil
32
+ key.id.should == 'Some plural %[plural]u key'
33
+ key.values.size.should == 1
34
+ value = key.values[:en]
35
+ value.should_not == nil
36
+ value.plural?.should == true
37
+ text = value.text
38
+ text[:one].should == 'Some translation for one %u'
39
+ text[:some].should == 'Some translation for some %u'
40
+ text[:many].should == 'Some translation for many %u'
41
+ text[:none].should == 'Some translation for none %u'
42
+ end
43
+ end
@@ -0,0 +1,152 @@
1
+ require 'babelyoda/localization_key'
2
+ require 'babelyoda/localization_value'
3
+
4
+ describe "basic localization key" do
5
+ it "can be created" do
6
+ key = Babelyoda::LocalizationKey.new("Hello world!", "Some translator comment")
7
+ key.values.size.should == 0
8
+ end
9
+
10
+ it "should not be marked as plural" do
11
+ key = Babelyoda::LocalizationKey.new("Hello world!", "Some translator comment")
12
+ key.plural?.should == false
13
+ end
14
+
15
+ it "ensures the set of languages is present" do
16
+ key = Babelyoda::LocalizationKey.new("Hello world!", "Some translator comment")
17
+ key.ensure_languages!([:en, :ru])
18
+ [:en, :ru].each do |lang|
19
+ value = key.values[lang]
20
+ value.should_not == nil
21
+ value.plural?.should == false
22
+ end
23
+ [:tr, :uk].each do |lang|
24
+ value = key.values[lang]
25
+ value.should == nil
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ describe "plural localization key" do
32
+ it "can be created with a plural id of [one]" do
33
+ key = Babelyoda::LocalizationKey.new("%[one]d organization nearby", "The number of organizations")
34
+ key.plural?.should == true
35
+ key.id.should == "%[plural]d organization nearby"
36
+ end
37
+
38
+ it "can be created with a plural id of [some]" do
39
+ key = Babelyoda::LocalizationKey.new("%[some]d organization nearby", "The number of organizations")
40
+ key.plural?.should == true
41
+ key.id.should == "%[plural]d organization nearby"
42
+ end
43
+
44
+ it "can be created with a plural id of [many]" do
45
+ key = Babelyoda::LocalizationKey.new("%[many]d organization nearby", "The number of organizations")
46
+ key.plural?.should == true
47
+ key.id.should == "%[plural]d organization nearby"
48
+ end
49
+
50
+ it "can be created with a plural id of [none]" do
51
+ key = Babelyoda::LocalizationKey.new("%[none]d organization nearby", "The number of organizations")
52
+ key.plural?.should == true
53
+ key.id.should == "%[plural]d organization nearby"
54
+ end
55
+
56
+ it "%% should be ignored and the key be singular" do
57
+ key = Babelyoda::LocalizationKey.new("%%[none]d organization nearby", "The number of organizations")
58
+ key.plural?.should == false
59
+ key.id.should == "%%[none]d organization nearby"
60
+ end
61
+
62
+ context "after a pluralized key has been created" do
63
+
64
+ before(:each) do
65
+ @key = Babelyoda::LocalizationKey.new("%[one]d organization nearby", "The number of organizations")
66
+ end
67
+
68
+ it "should pluralize given values" do
69
+ value = Babelyoda::LocalizationValue.new(:en, "%[one]d organization nearby")
70
+ @key << value
71
+ @key.values.size.should == 1
72
+ value = @key.values[:en]
73
+ value.plural?.should == true
74
+ value.text.kind_of?(Hash).should == true
75
+ end
76
+
77
+ it "should merge plural values for different plurals of the same key" do
78
+ value1 = Babelyoda::LocalizationValue.new(:en, "%[one]d organization nearby")
79
+ value2 = Babelyoda::LocalizationValue.new(:en, "%[some]d organization nearby")
80
+ @key << value1
81
+ @key << value2
82
+ @key.values.size.should == 1
83
+ value = @key.values[:en]
84
+ value.plural?.should == true
85
+ value.text[:one].should == '%d organization nearby'
86
+ value.text[:some].should == '%d organization nearby'
87
+ value.text[:many].should == nil
88
+ value.text[:none].should == nil
89
+ end
90
+
91
+ end
92
+
93
+ it "should correctly merge non-plural value into the correct plural key :one" do
94
+ key = Babelyoda::LocalizationKey.new("%[one]d organization nearby", "The number of organizations")
95
+ value = Babelyoda::LocalizationValue.new(:en, "%d organization nearby")
96
+ key << value
97
+ value = key.values[:en]
98
+ value.text[:one].should == '%d organization nearby'
99
+ end
100
+
101
+ it "should correctly merge non-plural value into the correct plural key :some" do
102
+ key = Babelyoda::LocalizationKey.new("%[some]d organization nearby", "The number of organizations")
103
+ value = Babelyoda::LocalizationValue.new(:en, "%d organization nearby")
104
+ key << value
105
+ value = key.values[:en]
106
+ value.text[:some].should == '%d organization nearby'
107
+ end
108
+
109
+ it "should correctly depluralize the key with the plural key in the middle of the key" do
110
+ key = Babelyoda::LocalizationKey.new("Some plural %[none]u key", "The number of organizations")
111
+ key.id.should == 'Some plural %[plural]u key'
112
+ key.plural?.should == true
113
+ end
114
+
115
+ it "should correctly depluralize the key with the plural key at the beginning of the key" do
116
+ key = Babelyoda::LocalizationKey.new("%[none]u key", "The number of organizations")
117
+ key.id.should == '%[plural]u key'
118
+ key.plural?.should == true
119
+ end
120
+
121
+ it "should correctly depluralize the key with the plural key at the end of the key" do
122
+ key = Babelyoda::LocalizationKey.new("the key is %[none]u", "The number of organizations")
123
+ key.id.should == 'the key is %[plural]u'
124
+ key.plural?.should == true
125
+ end
126
+
127
+ it "should not override a non-empty context with an empty context on merge" do
128
+ key1 = Babelyoda::LocalizationKey.new("the key is %[none]u", "Non empty context")
129
+ key2 = Babelyoda::LocalizationKey.new("the key is %[none]u", "")
130
+ key1.merge!(key2)
131
+ key1.context.should == "Non empty context"
132
+ end
133
+
134
+ it "ensures the set of languages is present" do
135
+ key = Babelyoda::LocalizationKey.new("the key is %[none]u", "Non empty context")
136
+ key.ensure_languages!([:en, :ru])
137
+ [:en, :ru].each do |lang|
138
+ value = key.values[lang]
139
+ value.should_not == nil
140
+ value.plural?.should == true
141
+ [:one, :some, :many].each do |plural_key|
142
+ value.text[plural_key].should == nil
143
+ end
144
+ value.text[:none].should == ''
145
+ end
146
+ [:tr, :uk].each do |lang|
147
+ value = key.values[lang]
148
+ value.should == nil
149
+ end
150
+ end
151
+
152
+ end
@@ -0,0 +1,17 @@
1
+ require 'babelyoda/localization_value'
2
+
3
+ describe "localization value" do
4
+ it "can be created" do
5
+ value = Babelyoda::LocalizationValue.new(:en, "Value 1")
6
+ value.language.should == :en
7
+ value.text.should == "Value 1"
8
+ end
9
+
10
+ it "should merge non-plural values" do
11
+ value1 = Babelyoda::LocalizationValue.new(:en, "Value 1")
12
+ value2 = Babelyoda::LocalizationValue.new(:en, "Value 2")
13
+ value1.merge!(value2)
14
+ value1.language.should == :en
15
+ value1.text.should == "Value 2"
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ require "babelyoda/strings_lexer"
2
+
3
+ describe "strings lexer" do
4
+ it "can be created" do
5
+ lexer = Babelyoda::StringsLexer.new
6
+ end
7
+
8
+ context "basic strings lexer" do
9
+
10
+ before(:each) do
11
+ @lexer = Babelyoda::StringsLexer.new
12
+ end
13
+
14
+ it "can parse tokens" do
15
+ str = <<-EOF
16
+ /* Some comment */
17
+ "Some key" = "Some translation";
18
+ EOF
19
+ result = []
20
+ @lexer.lex(str) do |token, value|
21
+ result << { :token => token, :value => value }
22
+ end
23
+ result.size.should == 5
24
+ result[0][:token].should == :multiline_comment
25
+ result[0][:value].should == "/* Some comment */"
26
+ result[1][:token].should == :string
27
+ result[1][:value].should == "\"Some key\""
28
+ result[2][:token].should == :equal_sign
29
+ result[2][:value].should == "="
30
+ result[3][:token].should == :string
31
+ result[3][:value].should == "\"Some translation\""
32
+ result[4][:token].should == :semicolon
33
+ result[4][:value].should == ";"
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,57 @@
1
+ require 'babelyoda/strings_lexer'
2
+ require 'babelyoda/strings_parser'
3
+
4
+ describe "strings parser" do
5
+ before(:each) do
6
+ @lexer = Babelyoda::StringsLexer.new
7
+ end
8
+
9
+ it "can be created" do
10
+ parser = Babelyoda::StringsParser.new(@lexer, :en)
11
+ end
12
+
13
+ context "parsing" do
14
+ before(:each) do
15
+ @parser = Babelyoda::StringsParser.new(@lexer, :en)
16
+ end
17
+
18
+ it "should parse simple keys" do
19
+ str = <<-EOF
20
+ /* Some comment */
21
+ "Some key" = "Some translation";
22
+ EOF
23
+ result = []
24
+ @parser.parse(str) do |record|
25
+ result << record
26
+ end
27
+ result.size.should == 1
28
+ result[0].context.should == "Some comment"
29
+ result[0].id.should == "Some key"
30
+ result[0].values.size.should == 1
31
+ result[0].plural?.should == false
32
+ result[0].values[:en].language.should == :en
33
+ result[0].values[:en].status.should == :requires_translation
34
+ result[0].values[:en].text.should == "Some translation"
35
+ end
36
+
37
+ it "should parse plural keys" do
38
+ str = <<-EOF
39
+ // Some comment
40
+ "%[one]d organizations" = "%[one]d organizations";
41
+ EOF
42
+ result = []
43
+ @parser.parse(str) do |record|
44
+ result << record
45
+ end
46
+ result.size.should == 1
47
+ result[0].context.should == "Some comment"
48
+ result[0].id.should == "%[plural]d organizations"
49
+ result[0].values.size.should == 1
50
+ result[0].plural?.should == true
51
+ result[0].values[:en].language.should == :en
52
+ result[0].values[:en].status.should == :requires_translation
53
+ result[0].values[:en].text[:one].should == "%d organizations"
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,71 @@
1
+ require 'babelyoda/strings'
2
+
3
+ describe "strings-based keyset" do
4
+ it "can be created with a filename and language" do
5
+ strings = Babelyoda::Strings.new('Combined.strings', :en)
6
+ end
7
+
8
+ context "when empty" do
9
+ it "serializes to an IO object" do
10
+ strings = Babelyoda::Strings.new('Combined.strings', :en)
11
+ io = StringIO.new
12
+ strings.to_strings(io, :en)
13
+ io.read.should == ''
14
+ end
15
+ end
16
+
17
+ context "when has only non-plural keys" do
18
+ it "merges keys in" do
19
+ strings = Babelyoda::Strings.new('Combined.strings', :en)
20
+ value = Babelyoda::LocalizationValue.new(:en, 'Some translation')
21
+ key = Babelyoda::LocalizationKey.new('Some key', 'Some comment')
22
+ key << value
23
+ strings.merge_key!(key)
24
+ strings.keys.size.should == 1
25
+ end
26
+
27
+ it "serializes to an IO object" do
28
+ strings = Babelyoda::Strings.new('Combined.strings', :en)
29
+
30
+ value = Babelyoda::LocalizationValue.new(:en, 'Some translation')
31
+ key = Babelyoda::LocalizationKey.new('Some key', 'Some comment')
32
+ key << value
33
+ strings.merge_key!(key)
34
+
35
+ io = StringIO.new
36
+ strings.to_strings(io, :en)
37
+ io.rewind
38
+ io.read.should ==
39
+ <<-EOF
40
+ /* Some comment */
41
+ "Some key" = "Some translation";
42
+
43
+ EOF
44
+ end
45
+ end
46
+
47
+ context "with plural keys" do
48
+ it "serializes to an IO object" do
49
+ strings = Babelyoda::Strings.new('Combined.strings', :en)
50
+
51
+ value_one = Babelyoda::LocalizationValue.new(:en, 'Some translation for %d one')
52
+ value_some = Babelyoda::LocalizationValue.new(:en, 'Some translation for %d some')
53
+ value_some.pluralize!(:some)
54
+ key = Babelyoda::LocalizationKey.new('Some %[one]d plural key', 'Some comment')
55
+ key << value_one
56
+ key << value_some
57
+ strings.merge_key!(key)
58
+
59
+ io = StringIO.new
60
+ strings.to_strings(io, :en)
61
+ io.rewind
62
+ io.read.should ==
63
+ <<-EOF
64
+ /* Some comment */
65
+ "Some %[one]d plural key" = "Some translation for %d one";
66
+ "Some %[some]d plural key" = "Some translation for %d some";
67
+
68
+ EOF
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,164 @@
1
+ require 'babelyoda/tanker'
2
+
3
+ describe "tanker XML serialization" do
4
+ it "should serialize non-plural values" do
5
+ value = Babelyoda::LocalizationValue.new(:en, "Some translation")
6
+
7
+ builder = Nokogiri::XML::Builder.new do |xml|
8
+ value.to_xml(xml)
9
+ end
10
+
11
+ builder.to_xml.should == "<?xml version=\"1.0\"?>\n<value language=\"en\" status=\"requires_translation\">Some translation</value>\n"
12
+ end
13
+
14
+ it "should serialize plural values" do
15
+ value = Babelyoda::LocalizationValue.new(:en, "some plural %u translation")
16
+ value.pluralize!
17
+
18
+ builder = Nokogiri::XML::Builder.new do |xml|
19
+ value.to_xml(xml)
20
+ end
21
+
22
+ builder.to_xml.should == '<?xml version="1.0"?>' + "\n" +
23
+ '<value language="en" status="requires_translation">' + "\n" +
24
+ ' <plural>' + "\n" +
25
+ ' <one>some plural %u translation</one>' + "\n" +
26
+ ' <some></some>' + "\n" +
27
+ ' <many></many>' + "\n" +
28
+ ' <none></none>' + "\n" +
29
+ ' </plural>' + "\n" +
30
+ '</value>' + "\n"
31
+ end
32
+
33
+ it "should serialize non-plural keys" do
34
+ key = Babelyoda::LocalizationKey.new("Some key", "Some context")
35
+ value = Babelyoda::LocalizationValue.new(:en, "Some translation")
36
+ key << value
37
+
38
+ builder = Nokogiri::XML::Builder.new do |xml|
39
+ key.to_xml(xml)
40
+ end
41
+
42
+ builder.to_xml.should == "<?xml version=\"1.0\"?>\n" +
43
+ "<key id=\"Some key\" is_plural=\"False\">\n" +
44
+ " <context>Some context</context>\n" +
45
+ " <value language=\"en\" status=\"requires_translation\">Some translation</value>\n" +
46
+ "</key>\n"
47
+ end
48
+
49
+ it "should serialize plural keys" do
50
+ key = Babelyoda::LocalizationKey.new("Some %[one]d plural key", "Some context")
51
+
52
+ value = Babelyoda::LocalizationValue.new(:en, "Some translation for one")
53
+ value.pluralize!(:one)
54
+ key << value
55
+
56
+ value = Babelyoda::LocalizationValue.new(:en, "Some translation for some")
57
+ value.pluralize!(:some)
58
+ key << value
59
+
60
+ builder = Nokogiri::XML::Builder.new do |xml|
61
+ key.to_xml(xml)
62
+ end
63
+
64
+ builder.to_xml.should ==
65
+ <<-EOF
66
+ <?xml version="1.0"?>
67
+ <key id="Some %[plural]d plural key" is_plural="True">
68
+ <context>Some context</context>
69
+ <value language="en" status="requires_translation">
70
+ <plural>
71
+ <one>Some translation for one</one>
72
+ <some>Some translation for some</some>
73
+ <many></many>
74
+ <none></none>
75
+ </plural>
76
+ </value>
77
+ </key>
78
+ EOF
79
+ end
80
+
81
+ it "should parse non-plural value" do
82
+ doc = Nokogiri::XML.parse(
83
+ <<-EOF
84
+ <?xml version="1.0"?>
85
+ <value language="en" status="requires_translation">Some translation</value>
86
+ EOF
87
+ )
88
+ value = Babelyoda::LocalizationValue.parse_xml(doc.root)
89
+ value.language.should == :en
90
+ value.status.should == :requires_translation
91
+ value.text.should == 'Some translation'
92
+ value.plural?.should == false
93
+ end
94
+
95
+ it "should parse plural value" do
96
+ doc = Nokogiri::XML.parse(
97
+ <<-EOF
98
+ <?xml version="1.0"?>
99
+ <value language="en" status="requires_translation">
100
+ <plural>
101
+ <one>Some translation for one</one>
102
+ <some>Some translation for some</some>
103
+ <many></many>
104
+ <none></none>
105
+ </plural>
106
+ </value>
107
+ EOF
108
+ )
109
+ value = Babelyoda::LocalizationValue.parse_xml(doc.root)
110
+ value.language.should == :en
111
+ value.status.should == :requires_translation
112
+ value.plural?.should == true
113
+ value.text[:one].should == 'Some translation for one'
114
+ value.text[:some].should == 'Some translation for some'
115
+ value.text[:many].should == nil
116
+ value.text[:noen].should == nil
117
+ end
118
+
119
+ it "should parse non-plural key" do
120
+ doc = Nokogiri::XML.parse(
121
+ <<-EOF
122
+ <?xml version="1.0"?>
123
+ <key id="Some key" is_plural="False">
124
+ <value language="en" status="requires_translation">Some translation</value>
125
+ </key>
126
+ EOF
127
+ )
128
+ key = Babelyoda::LocalizationKey.parse_xml(doc.root)
129
+ key.id.should == "Some key"
130
+ key.plural?.should == false
131
+ key.values.size.should == 1
132
+ value = key.values[:en]
133
+ value.should_not == nil
134
+ value.text.should == "Some translation"
135
+ end
136
+
137
+ it "should parse plural key" do
138
+ doc = Nokogiri::XML.parse(
139
+ <<-EOF
140
+ <?xml version="1.0"?>
141
+ <key id="Some %[plural]d key" is_plural="True">
142
+ <value language="en" status="requires_translation">
143
+ <plural>
144
+ <one>Some translation for %d one</one>
145
+ <some>Some translation for %d some</some>
146
+ <many></many>
147
+ <none></none>
148
+ </plural>
149
+ </value>
150
+ </key>
151
+ EOF
152
+ )
153
+ key = Babelyoda::LocalizationKey.parse_xml(doc.root)
154
+ key.id.should == "Some %[plural]d key"
155
+ key.plural?.should == true
156
+ key.values.size.should == 1
157
+ value = key.values[:en]
158
+ value.should_not == nil
159
+ value.text[:one].should == 'Some translation for %d one'
160
+ value.text[:some].should == 'Some translation for %d some'
161
+ value.text[:many].should == nil
162
+ value.text[:none].should == nil
163
+ end
164
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: babelyoda
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.7
4
+ version: 2.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,25 +9,55 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-23 00:00:00.000000000Z
12
+ date: 2012-01-27 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70346691069900 !ruby/object:Gem::Requirement
16
+ requirement: &70220783285460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: '2.8'
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70220783285460
25
+ - !ruby/object:Gem::Dependency
26
+ name: guard
27
+ requirement: &70220783285040 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70220783285040
36
+ - !ruby/object:Gem::Dependency
37
+ name: guard-rspec
38
+ requirement: &70220783284600 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70220783284600
47
+ - !ruby/object:Gem::Dependency
48
+ name: ruby_gntp
49
+ requirement: &70220783284180 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
22
52
  - - ! '>='
23
53
  - !ruby/object:Gem::Version
24
- version: 2.8.0
54
+ version: '0'
25
55
  type: :development
26
56
  prerelease: false
27
- version_requirements: *70346691069900
57
+ version_requirements: *70220783284180
28
58
  - !ruby/object:Gem::Dependency
29
59
  name: awesome_print
30
- requirement: &70346691067000 !ruby/object:Gem::Requirement
60
+ requirement: &70220783283640 !ruby/object:Gem::Requirement
31
61
  none: false
32
62
  requirements:
33
63
  - - ~>
@@ -38,10 +68,10 @@ dependencies:
38
68
  version: 1.0.2
39
69
  type: :runtime
40
70
  prerelease: false
41
- version_requirements: *70346691067000
71
+ version_requirements: *70220783283640
42
72
  - !ruby/object:Gem::Dependency
43
73
  name: rake
44
- requirement: &70346691064320 !ruby/object:Gem::Requirement
74
+ requirement: &70220783282840 !ruby/object:Gem::Requirement
45
75
  none: false
46
76
  requirements:
47
77
  - - ~>
@@ -52,10 +82,10 @@ dependencies:
52
82
  version: 0.9.2.2
53
83
  type: :runtime
54
84
  prerelease: false
55
- version_requirements: *70346691064320
85
+ version_requirements: *70220783282840
56
86
  - !ruby/object:Gem::Dependency
57
87
  name: active_support
58
- requirement: &70346691060660 !ruby/object:Gem::Requirement
88
+ requirement: &70220783282100 !ruby/object:Gem::Requirement
59
89
  none: false
60
90
  requirements:
61
91
  - - ~>
@@ -66,10 +96,10 @@ dependencies:
66
96
  version: 3.0.0
67
97
  type: :runtime
68
98
  prerelease: false
69
- version_requirements: *70346691060660
99
+ version_requirements: *70220783282100
70
100
  - !ruby/object:Gem::Dependency
71
101
  name: rchardet19
72
- requirement: &70346691057880 !ruby/object:Gem::Requirement
102
+ requirement: &70220783281360 !ruby/object:Gem::Requirement
73
103
  none: false
74
104
  requirements:
75
105
  - - ~>
@@ -80,10 +110,10 @@ dependencies:
80
110
  version: 1.3.5
81
111
  type: :runtime
82
112
  prerelease: false
83
- version_requirements: *70346691057880
113
+ version_requirements: *70220783281360
84
114
  - !ruby/object:Gem::Dependency
85
115
  name: builder
86
- requirement: &70346691048740 !ruby/object:Gem::Requirement
116
+ requirement: &70220783280620 !ruby/object:Gem::Requirement
87
117
  none: false
88
118
  requirements:
89
119
  - - ~>
@@ -94,10 +124,10 @@ dependencies:
94
124
  version: 3.0.0
95
125
  type: :runtime
96
126
  prerelease: false
97
- version_requirements: *70346691048740
127
+ version_requirements: *70220783280620
98
128
  - !ruby/object:Gem::Dependency
99
129
  name: nokogiri
100
- requirement: &70346691045860 !ruby/object:Gem::Requirement
130
+ requirement: &70220783279860 !ruby/object:Gem::Requirement
101
131
  none: false
102
132
  requirements:
103
133
  - - ~>
@@ -108,10 +138,10 @@ dependencies:
108
138
  version: 1.5.0
109
139
  type: :runtime
110
140
  prerelease: false
111
- version_requirements: *70346691045860
141
+ version_requirements: *70220783279860
112
142
  - !ruby/object:Gem::Dependency
113
143
  name: term-ansicolor
114
- requirement: &70346691044020 !ruby/object:Gem::Requirement
144
+ requirement: &70220783279120 !ruby/object:Gem::Requirement
115
145
  none: false
116
146
  requirements:
117
147
  - - ~>
@@ -122,10 +152,10 @@ dependencies:
122
152
  version: 1.0.7
123
153
  type: :runtime
124
154
  prerelease: false
125
- version_requirements: *70346691044020
155
+ version_requirements: *70220783279120
126
156
  - !ruby/object:Gem::Dependency
127
157
  name: log4r-color
128
- requirement: &70346691024920 !ruby/object:Gem::Requirement
158
+ requirement: &70220783278400 !ruby/object:Gem::Requirement
129
159
  none: false
130
160
  requirements:
131
161
  - - ~>
@@ -133,7 +163,7 @@ dependencies:
133
163
  version: '1.2'
134
164
  type: :runtime
135
165
  prerelease: false
136
- version_requirements: *70346691024920
166
+ version_requirements: *70220783278400
137
167
  description: A simple utility to push/pull l10n resources of an Xcode project to/from
138
168
  the translators
139
169
  email:
@@ -145,6 +175,7 @@ files:
145
175
  - .gitignore
146
176
  - CHANGELOG
147
177
  - Gemfile
178
+ - Guardfile
148
179
  - LICENSE
149
180
  - README.rdoc
150
181
  - Rakefile
@@ -160,6 +191,7 @@ files:
160
191
  - lib/babelyoda/localization_value.rb
161
192
  - lib/babelyoda/logger.rb
162
193
  - lib/babelyoda/rake.rb
194
+ - lib/babelyoda/regexp.rb
163
195
  - lib/babelyoda/specification.rb
164
196
  - lib/babelyoda/specification_loader.rb
165
197
  - lib/babelyoda/strings.rb
@@ -168,6 +200,13 @@ files:
168
200
  - lib/babelyoda/tanker.rb
169
201
  - lib/babelyoda/version.rb
170
202
  - lib/babelyoda/xib.rb
203
+ - spec/lib/babelyoda/keyset_spec.rb
204
+ - spec/lib/babelyoda/localization_key_spec.rb
205
+ - spec/lib/babelyoda/localization_value_spec.rb
206
+ - spec/lib/babelyoda/strings_lexer_spec.rb
207
+ - spec/lib/babelyoda/strings_parser_spec.rb
208
+ - spec/lib/babelyoda/strings_spec.rb
209
+ - spec/lib/babelyoda/tanker_spec.rb
171
210
  - templates/Babelfile.erb
172
211
  homepage: http://github.com/eploko/babelyoda
173
212
  licenses: []
@@ -183,7 +222,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
222
  version: '0'
184
223
  segments:
185
224
  - 0
186
- hash: -1238750056866448662
225
+ hash: -2015034540121504841
187
226
  required_rubygems_version: !ruby/object:Gem::Requirement
188
227
  none: false
189
228
  requirements:
@@ -192,7 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
192
231
  version: '0'
193
232
  segments:
194
233
  - 0
195
- hash: -1238750056866448662
234
+ hash: -2015034540121504841
196
235
  requirements: []
197
236
  rubyforge_project: babelyoda
198
237
  rubygems_version: 1.8.10