langulator 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -4,6 +4,16 @@ Manage your i18n.
4
4
 
5
5
  Or rather: compile it into a single managable file and give it to the translator, so you don't have to deal with it.
6
6
 
7
+ For example, given that you've written the original translations in English and also need French and Norwegian versions, and that you have multiple paths that contain i18n yml files named per the convention `<iso-language-code>.yml` (don't get me started on the Norwegian iso language code), then this will give you a single output file where each key is listed with the translations immediately below it.
8
+
9
+ If you have partial translations in the target languages, these will be included.
10
+
11
+ Any extraneous translations (i.e. keys that may have been in use previously but are no longer referenced in the original language) will be discarded.
12
+
13
+ Any missing translations will be given keys with an empty spot, ready for translation.
14
+
15
+ It handles arbitrarily deep nestings.
16
+
7
17
  ## Caveats
8
18
 
9
19
  If you need something other than US-ASCII, you may want to consider using ruby 1.9.3.
@@ -30,65 +40,126 @@ Or install it yourself as:
30
40
 
31
41
  $ gem install langulator
32
42
 
43
+
33
44
  ## Usage
34
45
 
35
- Given that you've written the original translations in English and also need French and German versions, and that you have multiple paths that contain i18n yml files named per the convention `<iso-language-code>.yml`, then this will give you a single output file where each key is listed with the translations immediately below it.
46
+ ### Compile
36
47
 
37
- If you have partial translations in the target languages, these will be included.
48
+ * load individual translations
49
+ * combine into aggregated translations
50
+ * write to an aggregate file
38
51
 
39
- Any extraneous translations (i.e. keys that may have been in use previously but are no longer referenced in the original language) will be discarded.
52
+ Langulator.compile(:source_language => :en, :target_languages => [:fr, :no], :base_path => '**/i18n/', :to => '/tmp/translations.yml')
40
53
 
41
- Any missing translations will be given keys with an empty spot, ready for translation.
54
+ Input:
42
55
 
43
- It handles arbitrarily deep nestings.
56
+ # config/i18n/en.yml
57
+ ---
58
+ food:
59
+ breakfast: Eggs
60
+ lunch: Sandwich
61
+ dinner:
62
+ main_course: Steak
63
+ desert: Chocolate mousse
64
+
65
+ # config/i18n/fr.yml
66
+ ---
67
+ food:
68
+ breakfast: Des oeufs
69
+ thank_you: Merci
44
70
 
45
- This first version doesn't handle yml files that are namespaced by the language, but I anticipate needing it very soon.
71
+ # missing no.yml file
46
72
 
47
- Also, this first version doesn't actually decompile the finished product. Come back tomorrow for that one.
73
+ Outputs:
48
74
 
49
- e.g.
75
+ # tmp/translations.yml
76
+ config/i18n/:
77
+ food:
78
+ breakfast:
79
+ en: Eggs
80
+ fr: Des oeufs
81
+ no:
82
+ lunch:
83
+ en: Sandwich
84
+ fr:
85
+ no:
86
+ dinner:
87
+ main_course:
88
+ en: Steak
89
+ fr:
90
+ no:
91
+ desert:
92
+ en: Chocolate pudding
93
+ fr:
94
+ no:
95
+
96
+ ### Decompile
97
+
98
+ * load an aggregate file
99
+ * separate into individual translations
100
+ * write to individual translation files
101
+
102
+ Langulator.decompile(:from => './tmp/translations.yml', :languages => [:en, :fr, :no])
50
103
 
51
104
  Input:
52
105
 
53
- # en.yml
106
+ config/i18n/:
107
+ food:
108
+ breakfast:
109
+ en: Eggs
110
+ fr: Des oeufs
111
+ no: Egg
112
+ lunch:
113
+ en: Sandwich
114
+ fr: Sandwich
115
+ no: Ostesmørbrød
116
+ dinner:
117
+ main_course:
118
+ en: Steak
119
+ fr: Biffteak
120
+ no: Steak
121
+ desert:
122
+ en: Chocolate mousse
123
+ fr: Mousse au chocolat
124
+ no: Sjokolademousse
125
+
126
+ Output:
127
+
128
+ # config/i18n/en.yml
54
129
  ---
55
130
  food:
56
131
  breakfast: Eggs
57
132
  lunch: Sandwich
58
133
  dinner:
59
134
  main_course: Steak
60
- desert: Chocolate pudding
135
+ desert: Chocolate mousse
61
136
 
62
- # fr.yml
137
+ # config/i18n/fr.yml
63
138
  ---
64
139
  food:
65
140
  breakfast: Des oeufs
66
- thank_you: Merci
67
-
68
- # no de.yml file
69
-
70
- Langulator.write(:language => 'en', :alternates => ['fr', 'de'], :base_path => '**/i18n/', :to => '/tmp/translations.yml')
71
-
72
- Outputs:
141
+ lunch: Sandwich
142
+ dinner:
143
+ main_course: Biffteak
144
+ desert: Mousse au chocolat
73
145
 
146
+ # config/i18n/no.yml
147
+ ---
74
148
  food:
75
- breakfast:
76
- en: Eggs
77
- fr: Des oeufs
78
- de:
79
- lunch:
80
- en: Sandwich
81
- fr:
82
- de:
149
+ breakfast: Egg
150
+ lunch: Sandwich
83
151
  dinner:
84
- main_course:
85
- en: Steak
86
- fr:
87
- de:
88
- desert:
89
- en: Chocolate pudding
90
- fr:
91
- de:
152
+ main_course: Steak
153
+ desert: Sjokolademousse
154
+
155
+ ## TODO
156
+
157
+ * handle yml files that are namespaced by the language, e.g.
158
+ ```
159
+ ---
160
+ en:
161
+ stuff: "whatever"
162
+ ```
92
163
 
93
164
  ## Contributing
94
165
 
data/langulator.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
12
12
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
13
  gem.name = "langulator"
14
14
  gem.require_paths = ["lib"]
15
- gem.version = "0.0.3"
15
+ gem.version = "0.0.4"
16
16
 
17
17
  gem.add_development_dependency "rspec"
18
18
  end
@@ -0,0 +1,124 @@
1
+ require 'langulator/loader'
2
+
3
+ module Langulator
4
+ class Aggregate
5
+
6
+ class << self
7
+ def from_file(options)
8
+ translations = YAML.load(File.read(options[:from]))
9
+ new options.merge(:aggregate_translations => translations)
10
+ end
11
+
12
+ def from_files(options)
13
+ loader = Loader.new(options)
14
+ new options.merge(:individual_translations => loader.translations)
15
+ end
16
+ end
17
+
18
+ attr_reader :languages, :source_language, :target_languages, :aggregate_file_path
19
+ def initialize(options = {})
20
+ @aggregate_file_path = options[:to]
21
+ @aggregate = options[:aggregate_translations]
22
+ @individual_translations = options[:individual_translations]
23
+ @source_language = options[:source_language]
24
+ @target_languages = Array(options[:target_languages])
25
+ @languages = options[:languages] || [source_language] + target_languages
26
+ end
27
+
28
+ def individual_translations
29
+ @individual_translations ||= separate
30
+ end
31
+
32
+ def aggregate
33
+ @aggregate ||= combine
34
+ end
35
+
36
+ def extract(language, tangled)
37
+ separated = {}
38
+ tangled.keys.each do |key|
39
+ values = tangled[key]
40
+ if translations?(values)
41
+ separated[key] = values[language]
42
+ else
43
+ separated[key] = extract(language, values)
44
+ end
45
+ end
46
+ separated
47
+ end
48
+
49
+ def compile
50
+ write(aggregate_file_path, aggregate)
51
+ end
52
+
53
+ def decompile
54
+ individual_translations.each do |language, translations|
55
+ translations.each do |path, translation|
56
+ filename = "#{path}#{language}.yml"
57
+ write filename, translation
58
+ end
59
+ end
60
+ end
61
+
62
+ # TODO: find a good name for this
63
+ def to_aggregate(language, translations)
64
+ dictionary = {}
65
+ translations.each do |key, value|
66
+ dictionary[key] ||= {}
67
+ if value.is_a?(Hash)
68
+ dictionary[key] = to_aggregate(language, value)
69
+ else
70
+ dictionary[key][language] = value
71
+ end
72
+ end
73
+ dictionary
74
+ end
75
+
76
+ def insert(language, translations, dictionary)
77
+ dictionary.dup.each do |key, value|
78
+ if value.is_a?(Hash)
79
+ insert(language, (translations || {})[key], value)
80
+ else
81
+ dictionary[language] = translations
82
+ end
83
+ end
84
+ dictionary
85
+ end
86
+
87
+ private
88
+
89
+ def translations?(values)
90
+ !values.keys.select {|key| languages.include?(key) }.empty?
91
+ end
92
+
93
+ def write(filename, content)
94
+ File.open(filename, 'w:utf-8') do |file|
95
+ file.write content.to_yaml
96
+ end
97
+ end
98
+
99
+ def separate
100
+ separated = {}
101
+ languages.each do |language|
102
+ separated[language] = extract(language, aggregate)
103
+ end
104
+ separated
105
+ end
106
+
107
+ def combine
108
+ source_translations = individual_translations[source_language]
109
+
110
+ target_translations = {}
111
+ target_languages.each do |language|
112
+ target_translations[language] = individual_translations[language]
113
+ end
114
+
115
+ dictionary = to_aggregate(source_language, source_translations)
116
+ target_translations.each do |language, translations|
117
+ dictionary = insert(language, translations, dictionary)
118
+ end
119
+
120
+ dictionary
121
+ end
122
+
123
+ end
124
+ end
@@ -1,24 +1,23 @@
1
1
  module Langulator
2
2
  class Loader
3
3
 
4
- attr_reader :base_path, :origin, :alternates
4
+ attr_reader :base_path, :languages
5
5
  def initialize(options = {})
6
6
  @base_path = options[:base_path]
7
- @origin = options[:origin]
8
- @alternates = options[:alternates]
7
+ @languages = [options[:source_language]] + options[:target_languages]
9
8
  end
10
9
 
11
10
  def paths
12
- @paths ||= Dir.glob("#{base_path}#{origin}.yml").map {|file| file.gsub("#{origin}.yml", '') }.sort
13
- end
14
-
15
- def source_translations
16
- translations = load_translations(origin)
11
+ unless @paths
12
+ filename = "#{languages.first}.yml"
13
+ @paths = Dir.glob("#{base_path}#{filename}").map {|file| file.gsub(filename, '') }.sort
14
+ end
15
+ @paths
17
16
  end
18
17
 
19
- def destination_translations
18
+ def translations
20
19
  translations = {}
21
- alternates.each do |language|
20
+ languages.each do |language|
22
21
  translations[language] = load_translations(language)
23
22
  end
24
23
  translations
data/lib/langulator.rb CHANGED
@@ -1,46 +1,17 @@
1
1
  # encoding: utf-8
2
2
  require 'yaml'
3
- require 'langulator/loader'
4
- require 'langulator/munger'
5
- require 'langulator/untangler'
3
+ require 'langulator/aggregate'
6
4
 
7
5
  module Langulator
8
- class << self
9
- def munge(options = {})
10
- loader = Loader.new(options)
11
- munger = Munger.new(:language => loader.origin, :translations => loader.source_translations, :alternates => loader.destination_translations)
12
-
13
- munger.munge
14
- end
15
6
 
7
+ class << self
16
8
  def compile(options)
17
- filename = options[:to]
18
- translations = munge(options)
19
- write filename, translations
20
- end
21
-
22
- def untangle(aggregate, options)
23
- Untangler.new(aggregate, options).untangle
9
+ Aggregate.from_files(options).compile
24
10
  end
25
11
 
26
12
  def decompile(options)
27
- puts options[:file].inspect
28
- aggregate = YAML.load(File.read(options[:file]))
29
- translations = untangle(aggregate, options)
30
-
31
- translations.each do |language, data|
32
- data.each do |path, translation|
33
- filename = "#{path}#{language}.yml"
34
- write filename, translation
35
- end
36
- end
37
- end
38
-
39
- private
40
- def write(filename, content)
41
- File.open(filename, 'w:utf-8') do |file|
42
- file.write content.to_yaml
43
- end
13
+ Aggregate.from_file(options).decompile
44
14
  end
45
15
  end
16
+
46
17
  end
@@ -0,0 +1,141 @@
1
+ require 'langulator/aggregate'
2
+
3
+ describe Langulator::Aggregate do
4
+
5
+ let(:aggregate) do
6
+ {
7
+ "spec/fixtures/" => {
8
+ "words" => {
9
+ "affirmative" => {
10
+ :klingon => "HISlaH",
11
+ :lolcode => "YA RLY"
12
+ },
13
+ "negative" => {
14
+ :klingon => "ghobe'",
15
+ :lolcode => "NO WAI"
16
+ },
17
+ "hello" => {
18
+ :klingon => "nuqneH",
19
+ :lolcode => "O HAI"
20
+ }
21
+ }
22
+ }
23
+ }
24
+ end
25
+
26
+ let(:klingon) { {"spec/fixtures/" => {"words" => {"affirmative" => "HISlaH", "negative" => "ghobe'", "hello" => "nuqneH"}}} }
27
+ let(:lolcode) { {"spec/fixtures/" => {"words" => {"affirmative" => "YA RLY", "negative" => "NO WAI", "hello" => "O HAI"}}} }
28
+
29
+ describe "combining individual translations" do
30
+ let(:klingon_as_aggregate) do
31
+ {
32
+ "spec/fixtures/" => {
33
+ "words" => {
34
+ "affirmative" => { :klingon => "HISlaH" },
35
+ "negative" => { :klingon => "ghobe'" },
36
+ "hello" => { :klingon => "nuqneH" }
37
+ }
38
+ }
39
+ }
40
+ end
41
+
42
+ let(:outfile) { 'spec/fixtures/output.yml' }
43
+
44
+ let(:compile_options) do
45
+ {
46
+ :source_language => :klingon,
47
+ :target_languages => :lolcode,
48
+ :individual_translations => {:klingon => klingon, :lolcode => lolcode},
49
+ :to => outfile
50
+ }
51
+ end
52
+
53
+ subject { Langulator::Aggregate.new(compile_options) }
54
+
55
+ its(:source_language) { should eq(:klingon) }
56
+ its(:target_languages) { should eq([:lolcode]) }
57
+ its(:languages) { should eq([:klingon, :lolcode]) }
58
+ its(:individual_translations) { should eq({:klingon => klingon, :lolcode => lolcode}) }
59
+ its(:aggregate_file_path) { should eq(outfile) }
60
+ its(:aggregate) { should eq(aggregate) }
61
+
62
+ it "remappes the source language to initialize aggregate" do
63
+ subject.to_aggregate(:klingon, subject.individual_translations[:klingon]).should eq(klingon_as_aggregate)
64
+ end
65
+
66
+ it "inserts a target language into the aggregate" do
67
+ subject.insert(:lolcode, lolcode, klingon_as_aggregate).should eq(aggregate)
68
+ end
69
+
70
+ it "loads an aggregate" do
71
+ subject = Langulator::Aggregate.from_file(:from => 'spec/fixtures/translations.yml', :languages => [:klingon, :lolcode])
72
+ subject.aggregate.should eq(aggregate)
73
+ end
74
+
75
+ context "writing an aggregate" do
76
+ before(:each) do
77
+ FileUtils.rm(outfile) if File.exists? outfile
78
+ end
79
+
80
+ after(:each) do
81
+ FileUtils.rm(outfile) if File.exists? outfile
82
+ end
83
+
84
+ it "compiles" do
85
+ subject.compile
86
+ YAML.load(File.read(outfile)).should eq(aggregate)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "de-aggregating translations" do
92
+ subject { Langulator::Aggregate.new(:languages => [:english]) }
93
+
94
+ it 'extracts English' do
95
+ input = {:rock => {:english => "rock"}, :paper => {:english => "paper"}}
96
+ expected_output = {:rock => "rock", :paper => "paper"}
97
+ subject.extract(:english, input).should eq(expected_output)
98
+ end
99
+
100
+ it "extracts complicated English" do
101
+ input = {:a => {:really => {:deeply => {:nested => {:game => {:rock => {:english => "rock"}, :paper => {:english => "paper"}}}}}}}
102
+ expected_output = {:a => {:really => {:deeply => {:nested => {:game => {:rock => "rock", :paper => "paper"}}}}}}
103
+ subject.extract(:english, input).should eq(expected_output)
104
+ end
105
+ end
106
+
107
+ context "with aggregated data" do
108
+ subject { Langulator::Aggregate.new(:aggregate_translations => aggregate, :languages => [:klingon, :lolcode]) }
109
+
110
+ it "filters out the klingon" do
111
+ subject.individual_translations[:klingon].should eq(klingon)
112
+ end
113
+
114
+ it "filters out the lolcode" do
115
+ subject.individual_translations[:lolcode].should eq(lolcode)
116
+ end
117
+ end
118
+
119
+ context "writing individual translations" do
120
+ let(:klingon_file) { "spec/fixtures/klingon.yml" }
121
+ let(:lolcode_file) { "spec/fixtures/lolcode.yml" }
122
+
123
+ subject { Langulator::Aggregate.new(:aggregate_translations => aggregate, :languages => [:klingon, :lolcode]) }
124
+
125
+ before(:each) do
126
+ FileUtils.rm(klingon_file) if File.exists? klingon_file
127
+ FileUtils.rm(lolcode_file) if File.exists? lolcode_file
128
+ end
129
+
130
+ after(:each) do
131
+ FileUtils.rm(klingon_file) if File.exists? klingon_file
132
+ FileUtils.rm(lolcode_file) if File.exists? lolcode_file
133
+ end
134
+
135
+ it "decompiles" do
136
+ subject.decompile
137
+ YAML.load(File.read(klingon_file)).should eq(klingon["spec/fixtures/"])
138
+ YAML.load(File.read(lolcode_file)).should eq(lolcode["spec/fixtures/"])
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,12 @@
1
+ ---
2
+ spec/fixtures/:
3
+ words:
4
+ affirmative:
5
+ :klingon: HISlaH
6
+ :lolcode: YA RLY
7
+ negative:
8
+ :klingon: ghobe'
9
+ :lolcode: NO WAI
10
+ hello:
11
+ :klingon: nuqneH
12
+ :lolcode: O HAI
data/spec/loader_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ require 'yaml'
2
3
  require 'langulator/loader'
3
4
 
4
5
  describe Langulator::Loader do
@@ -40,10 +41,6 @@ describe Langulator::Loader do
40
41
  }
41
42
  end
42
43
 
43
- subject { Langulator::Loader.new(:base_path => 'spec/fixtures/**/', :origin => 'english', :alternates => ['norsk', 'francais']) }
44
-
45
- its(:paths) { should eq(['spec/fixtures/', 'spec/fixtures/lang/']) }
46
-
47
- its(:source_translations) { should eq(english) }
48
- its(:destination_translations) { should eq({'norsk' => norwegian, 'francais' => french}) }
44
+ subject { Langulator::Loader.new(:base_path => 'spec/fixtures/**/', :source_language => 'english', :target_languages => ['norsk', 'francais']) }
45
+ its(:translations) { should eq({'english' => english, 'norsk' => norwegian, 'francais' => french}) }
49
46
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: langulator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-03 00:00:00.000000000 Z
12
+ date: 2012-05-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70303028217820 !ruby/object:Gem::Requirement
16
+ requirement: &70204764441280 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70303028217820
24
+ version_requirements: *70204764441280
25
25
  description: Manage, maintain, and munge your i18n files.
26
26
  email:
27
27
  - katrina.owen@gmail.com
@@ -38,16 +38,14 @@ files:
38
38
  - bin/langulator
39
39
  - langulator.gemspec
40
40
  - lib/langulator.rb
41
+ - lib/langulator/aggregate.rb
41
42
  - lib/langulator/loader.rb
42
- - lib/langulator/munger.rb
43
- - lib/langulator/untangler.rb
43
+ - spec/aggregate_spec.rb
44
44
  - spec/fixtures/english.yml
45
45
  - spec/fixtures/lang/english.yml
46
46
  - spec/fixtures/norsk.yml
47
- - spec/langulator_spec.rb
47
+ - spec/fixtures/translations.yml
48
48
  - spec/loader_spec.rb
49
- - spec/munger_spec.rb
50
- - spec/untangler_spec.rb
51
49
  homepage: http://github.com/kytrinyx/langulator
52
50
  licenses: []
53
51
  post_install_message:
@@ -73,10 +71,9 @@ signing_key:
73
71
  specification_version: 3
74
72
  summary: Tasks to keep your i18n files managable.
75
73
  test_files:
74
+ - spec/aggregate_spec.rb
76
75
  - spec/fixtures/english.yml
77
76
  - spec/fixtures/lang/english.yml
78
77
  - spec/fixtures/norsk.yml
79
- - spec/langulator_spec.rb
78
+ - spec/fixtures/translations.yml
80
79
  - spec/loader_spec.rb
81
- - spec/munger_spec.rb
82
- - spec/untangler_spec.rb
@@ -1,44 +0,0 @@
1
- module Langulator
2
- class Munger
3
-
4
- attr_reader :source_language, :source_translations, :alternate_translations
5
- def initialize(options = {})
6
- @source_language = options[:language]
7
- @source_translations = options[:translations]
8
- @alternate_translations = options[:alternates]
9
- end
10
-
11
- def munge
12
- dictionary = transform(source_language, source_translations)
13
- alternate_translations.each do |language, translations|
14
- dictionary = insert(language, translations, dictionary)
15
- end
16
- dictionary
17
- end
18
-
19
- def transform(language, translations)
20
- dictionary = {}
21
- translations.each do |key, value|
22
- dictionary[key] ||= {}
23
- if value.is_a?(Hash)
24
- dictionary[key] = transform(language, value)
25
- else
26
- dictionary[key][language] = value
27
- end
28
- end
29
- dictionary
30
- end
31
-
32
- def insert(language, translations, dictionary)
33
- dictionary.dup.each do |key, value|
34
- if value.is_a?(Hash)
35
- insert(language, (translations || {})[key], value)
36
- else
37
- dictionary[language] = translations
38
- end
39
- end
40
- dictionary
41
- end
42
-
43
- end
44
- end
@@ -1,34 +0,0 @@
1
- module Langulator
2
- class Untangler
3
- attr_reader :aggregate, :languages
4
- def initialize(aggregate, options = {})
5
- @aggregate = aggregate
6
- @languages = options[:languages]
7
- end
8
-
9
- def untangle
10
- untangled = {}
11
- languages.each do |language|
12
- untangled[language] = extract(language, aggregate)
13
- end
14
- untangled
15
- end
16
-
17
- def extract(language, tangled)
18
- untangled = {}
19
- tangled.keys.each do |key|
20
- values = tangled[key]
21
- if translations?(values)
22
- untangled[key] = values[language]
23
- else
24
- untangled[key] = extract(language, values)
25
- end
26
- end
27
- untangled
28
- end
29
-
30
- def translations?(values)
31
- !values.keys.select {|key| languages.include?(key) }.empty?
32
- end
33
- end
34
- end
@@ -1,87 +0,0 @@
1
- # encoding: utf-8
2
- require 'langulator'
3
-
4
- describe Langulator do
5
- let(:options) { {:base_path => 'spec/fixtures/**/', :origin => 'english', :alternates => ['norsk', 'francais']} }
6
-
7
- let(:aggregate_incomplete) do
8
- {
9
- "spec/fixtures/" => {
10
- "food" => {
11
- "breakfast" => {"english" => "yoghurt", "norsk" => nil, "francais" => nil},
12
- "lunch" => {"english" => "sandwich", "norsk" => "smørbrød", "francais" => nil},
13
- "dinner" => {
14
- "main_course" => {"english" => "steak", "norsk" => nil, "francais" => nil},
15
- "side" => {"english" => "baked potato", "norsk" => nil, "francais" => nil},
16
- "desert" => {"english" => "chocolate mousse", "norsk" => nil, "francais" => nil}
17
- }
18
- }
19
- },
20
- "spec/fixtures/lang/" => {
21
- "volume" => {
22
- "sound" => {"english" => "loud", "norsk" => nil, "francais" => nil},
23
- "liquid" => {"english" => "sloshing", "norsk" => nil, "francais" => nil},
24
- "hair" => {"english" => "because I'm worth it", "norsk" => nil, "francais" => nil}
25
- }
26
- }
27
- }
28
- end
29
-
30
- it "loads and munges" do
31
- Langulator.compile(options.merge(:to => './tmp/translations.yml')) #.should eq(aggregate_incomplete)
32
- end
33
-
34
- let(:aggregate_complete) do
35
- {
36
- "spec/fixtures/" => {
37
- "food" => {
38
- "breakfast" => {"english" => "yoghurt", "norsk" => "joggurt", "francais" => "yaourt"},
39
- "lunch" => {"english" => "sandwich", "norsk" => "smørbrød", "francais" => "sandwich"},
40
- "dinner" => {
41
- "main_course" => {"english" => "steak", "norsk" => "steak", "francais" => "biffteak"},
42
- "side" => {"english" => "baked potato", "norsk" => "bakt potet", "francais" => "pomme de terre au four"},
43
- "desert" => {"english" => "chocolate mousse", "norsk" => "sjokolademousse", "francais" => "mousse au chocolat"}
44
- }
45
- }
46
- },
47
- "spec/fixtures/lang/" => {
48
- "volume" => {
49
- "sound" => {"english" => "loud", "norsk" => "høyt", "francais" => "fort"},
50
- "liquid" => {"english" => "sloshing", "norsk" => "skvulper", "francais" => "agité"},
51
- "hair" => {"english" => "because I'm worth it", "norsk" => "for det er jeg verdt", "francais" => "parce que je le vaux bien"}
52
- }
53
- }
54
- }
55
- end
56
-
57
- it "untangles" do
58
- expected = {
59
- "english" => {
60
- "spec/fixtures/" => {
61
- "food" => {"breakfast" => "yoghurt", "lunch" => "sandwich", "dinner" => {"main_course" => "steak", "side" => "baked potato", "desert" => "chocolate mousse"}}
62
- },
63
- "spec/fixtures/lang/" => {
64
- "volume" => {"sound" => "loud", "liquid" => "sloshing", "hair" => "because I'm worth it"}
65
- }
66
- },
67
- "norsk" => {
68
- "spec/fixtures/" => {
69
- "food" => {"breakfast" => "joggurt", "lunch" => "smørbrød", "dinner" => {"main_course" => "steak", "side" => "bakt potet", "desert" => "sjokolademousse"}}
70
- },
71
- "spec/fixtures/lang/" => {
72
- "volume" => {"sound" => "høyt", "liquid" => "skvulper", "hair" => "for det er jeg verdt"}
73
- }
74
- },
75
- "francais" => {
76
- "spec/fixtures/" => {
77
- "food" => {"breakfast" => "yaourt", "lunch" => "sandwich", "dinner" => {"main_course" => "biffteak", "side" => "pomme de terre au four", "desert" => "mousse au chocolat"}}
78
- },
79
- "spec/fixtures/lang/" => {
80
- "volume" => {"sound" => "fort", "liquid" => "agité", "hair" => "parce que je le vaux bien"}
81
- }
82
- }
83
- }
84
- Langulator.untangle(aggregate_complete, :languages => ["english", "norsk", "francais"]).should eq(expected)
85
- end
86
-
87
- end
data/spec/munger_spec.rb DELETED
@@ -1,102 +0,0 @@
1
- require 'langulator/munger'
2
-
3
- describe Langulator::Munger do
4
-
5
- let(:english) do
6
- {
7
- :game => {
8
- :rock => "rock",
9
- :paper => "paper",
10
- :scissors => "scissors",
11
- :other => {:deeply => "nested"}
12
- }
13
- }
14
- end
15
-
16
- let(:english_remapped) do
17
- {
18
- :game => {
19
- :rock => {:english => "rock"},
20
- :paper => {:english => "paper"},
21
- :scissors => {:english => "scissors"},
22
- :other => {
23
- :deeply => {:english => "nested"}
24
- }
25
- }
26
- }
27
- end
28
-
29
- let(:french) { {:game => {:paper => 'papier', :other => {:not => 'included'}}} }
30
-
31
- let(:combined) do
32
- {
33
- :game => {
34
- :rock => {
35
- :english => "rock",
36
- :french => nil
37
- },
38
- :paper => {
39
- :english => "paper",
40
- :french => "papier"
41
- },
42
- :scissors => {
43
- :english => "scissors",
44
- :french => nil
45
- },
46
- :other => {
47
- :deeply => {
48
- :english => "nested",
49
- :french => nil
50
- }
51
- }
52
- }
53
- }
54
- end
55
-
56
- let(:empty_target) do
57
- {
58
- :game => {
59
- :rock => {
60
- :english => "rock",
61
- :norwegian => nil
62
- },
63
- :paper => {
64
- :english => "paper",
65
- :norwegian => nil
66
- },
67
- :scissors => {
68
- :english => "scissors",
69
- :norwegian => nil
70
- },
71
- :other => {
72
- :deeply => {
73
- :english => "nested",
74
- :norwegian => nil
75
- }
76
- }
77
- }
78
- }
79
- end
80
-
81
- context "partial munges" do
82
- subject { Langulator::Munger.new }
83
-
84
- it "remaps a source dictionary" do
85
- subject.transform(:english, english).should eq(english_remapped)
86
- end
87
-
88
- it "inserts an alternate language" do
89
- subject.insert(:french, french, english_remapped).should eq(combined)
90
- end
91
-
92
- it "inserts an empty alternate language" do
93
- subject.insert(:norwegian, {}, english_remapped).should eq(empty_target)
94
- end
95
- end
96
-
97
- it "munges" do
98
- munger = Langulator::Munger.new(:language => :english, :translations => english, :alternates => {:french => french})
99
- munger.munge.should eq(combined)
100
- end
101
-
102
- end
@@ -1,75 +0,0 @@
1
- # encoding: utf-8
2
- require 'langulator/untangler'
3
-
4
- describe Langulator::Untangler do
5
- let(:aggregate) do
6
- {
7
- :game => {
8
- :rock => {
9
- :english => "rock",
10
- :french => "pierre",
11
- },
12
- :paper => {
13
- :english => "paper",
14
- :french => "papier"
15
- },
16
- :scissors => {
17
- :english => "scissors",
18
- :french => "ciseau"
19
- },
20
- :other => {
21
- :deeply => {
22
- :english => "nested",
23
- :french => "imbriqué"
24
- }
25
- }
26
- }
27
- }
28
- end
29
-
30
- let(:english) do
31
- {
32
- :game => {
33
- :rock => "rock",
34
- :paper => "paper",
35
- :scissors => "scissors",
36
- :other => {:deeply => "nested"}
37
- }
38
- }
39
- end
40
-
41
- let(:french) do
42
- {
43
- :game => {
44
- :rock => "pierre",
45
- :paper => "papier",
46
- :scissors => "ciseau",
47
- :other => {:deeply => "imbriqué"}
48
- }
49
- }
50
- end
51
-
52
- context "with tangled data" do
53
- subject { Langulator::Untangler.new(aggregate, :languages => [:english, :french]) }
54
-
55
- it 'extracts English' do
56
- input = {:rock => {:english => "rock"}, :paper => {:english => "paper"}}
57
- expected_output = {:rock => "rock", :paper => "paper"}
58
- subject.extract(:english, input).should eq(expected_output)
59
- end
60
-
61
- it "extracts complicated English" do
62
- input = {:a => {:really => {:deeply => {:nested => {:game => {:rock => {:english => "rock"}, :paper => {:english => "paper"}}}}}}}
63
- expected_output = {:a => {:really => {:deeply => {:nested => {:game => {:rock => "rock", :paper => "paper"}}}}}}
64
- subject.extract(:english, input).should eq(expected_output)
65
- end
66
-
67
- it "filters out the english" do
68
- subject.untangle[:english].should eq(english)
69
- end
70
-
71
- it "filters out the french" do
72
- subject.untangle[:french].should eq(french)
73
- end
74
- end
75
- end