langulator 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Langulator
2
2
 
3
- TODO: Write a gem description
3
+ Manage your i18n.
4
+
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
+
7
+ ## Caveats
8
+
9
+ If you need something other than US-ASCII, you may want to consider using ruby 1.9.3.
10
+
11
+ In 1.9.2 (patch 290):
12
+
13
+ S\xC3\xB8knadstekst
14
+
15
+ In 1.9.3:
16
+
17
+ Søknadstekst
4
18
 
5
19
  ## Installation
6
20
 
@@ -18,7 +32,63 @@ Or install it yourself as:
18
32
 
19
33
  ## Usage
20
34
 
21
- TODO: Write usage instructions here
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.
36
+
37
+ If you have partial translations in the target languages, these will be included.
38
+
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.
40
+
41
+ Any missing translations will be given keys with an empty spot, ready for translation.
42
+
43
+ It handles arbitrarily deep nestings.
44
+
45
+ This first version doesn't handle yml files that are namespaced by the language, but I anticipate needing it very soon.
46
+
47
+ Also, this first version doesn't actually decompile the finished product. Come back tomorrow for that one.
48
+
49
+ e.g.
50
+
51
+ Input:
52
+
53
+ # en.yml
54
+ ---
55
+ food:
56
+ breakfast: Eggs
57
+ lunch: Sandwich
58
+ dinner:
59
+ main_course: Steak
60
+ desert: Chocolate pudding
61
+
62
+ # fr.yml
63
+ ---
64
+ food:
65
+ 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:
73
+
74
+ food:
75
+ breakfast:
76
+ en: Eggs
77
+ fr: Des oeufs
78
+ de:
79
+ lunch:
80
+ en: Sandwich
81
+ fr:
82
+ de:
83
+ dinner:
84
+ main_course:
85
+ en: Steak
86
+ fr:
87
+ de:
88
+ desert:
89
+ en: Chocolate pudding
90
+ fr:
91
+ de:
22
92
 
23
93
  ## Contributing
24
94
 
@@ -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.1"
15
+ gem.version = "0.0.2"
16
16
 
17
17
  gem.add_development_dependency "rspec"
18
18
  end
@@ -1,18 +1,44 @@
1
+ # encoding: utf-8
2
+ require 'yaml'
1
3
  require 'langulator/loader'
2
4
  require 'langulator/munger'
5
+ require 'langulator/untangler'
3
6
 
4
7
  module Langulator
5
- def self.compile(options = {})
6
- loader = Loader.new(options)
7
- munger = Munger.new(:language => loader.origin, :translations => loader.source_translations, :alternates => loader.destination_translations)
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)
8
12
 
9
- munger.munge
10
- end
13
+ munger.munge
14
+ end
15
+
16
+ def compile(options)
17
+ filename = options[:to]
18
+ translations = compile(options)
19
+ write filename, translations
20
+ end
21
+
22
+ def untangle(aggregate, options)
23
+ Untangler.new(aggregate, options).untangle
24
+ end
25
+
26
+ def decompile(aggregate, options)
27
+ translations = untangle(aggregate, options)
28
+
29
+ translations.each do |language, data|
30
+ data.each do |path, translation|
31
+ filename = "#{path}#{language}.yml"
32
+ write filename, translation
33
+ end
34
+ end
35
+ end
11
36
 
12
- def self.write(options)
13
- translations = compile(options)
14
- File.open(options[:to], 'w') do |file|
15
- file.write translations.to_yaml
37
+ private
38
+ def write(filename, content)
39
+ File.open(filename, 'w:utf-8') do |file|
40
+ file.write content.to_yaml
41
+ end
16
42
  end
17
43
  end
18
44
  end
@@ -0,0 +1,34 @@
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
@@ -2,4 +2,4 @@
2
2
  volume:
3
3
  sound: loud
4
4
  liquid: sloshing
5
- hair: "because I'm worth it"
5
+ hair: because I'm worth it
@@ -4,7 +4,7 @@ require 'langulator'
4
4
  describe Langulator do
5
5
  let(:options) { {:base_path => 'spec/fixtures/**/', :origin => 'english', :alternates => ['norsk', 'francais']} }
6
6
 
7
- let(:combined) do
7
+ let(:aggregate_incomplete) do
8
8
  {
9
9
  "spec/fixtures/" => {
10
10
  "food" => {
@@ -28,6 +28,60 @@ describe Langulator do
28
28
  end
29
29
 
30
30
  it "loads and munges" do
31
- Langulator.compile(options).should eq(combined)
31
+ Langulator.munge(options).should eq(aggregate_incomplete)
32
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
+
33
87
  end
@@ -0,0 +1,75 @@
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
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.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70137034740080 !ruby/object:Gem::Requirement
16
+ requirement: &70102603779800 !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: *70137034740080
24
+ version_requirements: *70102603779800
25
25
  description: Manage, maintain, and munge your i18n files.
26
26
  email:
27
27
  - katrina.owen@gmail.com
@@ -40,12 +40,14 @@ files:
40
40
  - lib/langulator.rb
41
41
  - lib/langulator/loader.rb
42
42
  - lib/langulator/munger.rb
43
+ - lib/langulator/untangler.rb
43
44
  - spec/fixtures/english.yml
44
45
  - spec/fixtures/lang/english.yml
45
46
  - spec/fixtures/norsk.yml
46
47
  - spec/langulator_spec.rb
47
48
  - spec/loader_spec.rb
48
49
  - spec/munger_spec.rb
50
+ - spec/untangler_spec.rb
49
51
  homepage: http://github.com/kytrinyx/langulator
50
52
  licenses: []
51
53
  post_install_message:
@@ -77,3 +79,4 @@ test_files:
77
79
  - spec/langulator_spec.rb
78
80
  - spec/loader_spec.rb
79
81
  - spec/munger_spec.rb
82
+ - spec/untangler_spec.rb