vocab 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/README.md +58 -0
- data/Rakefile +13 -0
- data/bin/vocab +11 -0
- data/lib/vocab/application.rb +58 -0
- data/lib/vocab/extractor/android.rb +56 -0
- data/lib/vocab/extractor/base.rb +92 -0
- data/lib/vocab/extractor/rails.rb +81 -0
- data/lib/vocab/extractor.rb +7 -0
- data/lib/vocab/merger/android.rb +59 -0
- data/lib/vocab/merger/base.rb +21 -0
- data/lib/vocab/merger/rails.rb +105 -0
- data/lib/vocab/merger.rb +7 -0
- data/lib/vocab/settings.rb +35 -0
- data/lib/vocab/translator/android.rb +43 -0
- data/lib/vocab/translator/base.rb +12 -0
- data/lib/vocab/translator/rails.rb +67 -0
- data/lib/vocab/translator.rb +7 -0
- data/lib/vocab/ui.rb +19 -0
- data/lib/vocab/validator/android.rb +23 -0
- data/lib/vocab/validator/base.rb +40 -0
- data/lib/vocab/validator/rails.rb +31 -0
- data/lib/vocab/validator.rb +7 -0
- data/lib/vocab/version.rb +3 -0
- data/lib/vocab.rb +36 -0
- data/spec/application_spec.rb +20 -0
- data/spec/data/android/current.xml +8 -0
- data/spec/data/android/locales/values/strings.xml +10 -0
- data/spec/data/android/locales/values-es/strings.xml +6 -0
- data/spec/data/android/locales/values-large-hdpi/dimens.xml +1 -0
- data/spec/data/android/locales/values-large-hdpi/styles.xml +1 -0
- data/spec/data/android/previous.xml +6 -0
- data/spec/data/android/translations/values-es/es-string-file.xml +7 -0
- data/spec/data/android/write.xml +6 -0
- data/spec/data/rails/locales/en.yml +10 -0
- data/spec/data/rails/locales/es.yml +6 -0
- data/spec/data/rails/locales/models/product/en.yml +13 -0
- data/spec/data/rails/locales/models/product/es.yml +13 -0
- data/spec/data/rails/translations/cn.yml +21 -0
- data/spec/data/rails/translations/es.yml +12 -0
- data/spec/extractor/android_spec.rb +95 -0
- data/spec/extractor/base_spec.rb +134 -0
- data/spec/extractor/rails_spec.rb +116 -0
- data/spec/merger/android_spec.rb +138 -0
- data/spec/merger/base_spec.rb +24 -0
- data/spec/merger/rails_spec.rb +183 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/support/matchers.rb +13 -0
- data/spec/support/shared.rb +6 -0
- data/spec/tmp/.gitkeep +0 -0
- data/spec/translator/android_spec.rb +24 -0
- data/spec/translator/rails_spec.rb +155 -0
- data/spec/ui_spec.rb +15 -0
- data/spec/validator/android_spec.rb +54 -0
- data/spec/validator/base_spec.rb +5 -0
- data/spec/validator/rails_spec.rb +83 -0
- data/spec/vocab_spec.rb +13 -0
- data/vocab.gemspec +25 -0
- metadata +171 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
# Warning: this object has some sharp edges because it is an unusual use of the i18n gem
|
2
|
+
# For example:
|
3
|
+
# - we are calling private methods
|
4
|
+
# - instances share the I18n.load_path, which could lead to unexpected behavior
|
5
|
+
|
6
|
+
module Vocab
|
7
|
+
module Translator
|
8
|
+
class Rails < Base
|
9
|
+
|
10
|
+
attr_accessor :locale
|
11
|
+
|
12
|
+
def initialize( locale = :en )
|
13
|
+
@backend = I18n::Backend::Simple.new
|
14
|
+
@locale = locale
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_dir( dir )
|
18
|
+
I18n.load_path = Dir.glob( "#{dir}/**/*.{yml,rb}" )
|
19
|
+
load_translations
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_file( file )
|
23
|
+
@locale = File.basename( file ).gsub( /\..*$/, '' ).to_sym
|
24
|
+
I18n.load_path = [ file ]
|
25
|
+
load_translations
|
26
|
+
end
|
27
|
+
|
28
|
+
def write_file( file )
|
29
|
+
yaml = { @locale => self.translations }.to_yaml
|
30
|
+
File.open( file, 'w+' ) { |f| f.write( yaml ) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def translations( options = {} )
|
34
|
+
t = @backend.send(:translations)
|
35
|
+
trans = t[ @locale ]
|
36
|
+
return options[ :prefix ] == true ? { @locale => trans } : trans
|
37
|
+
end
|
38
|
+
|
39
|
+
def flattened_translations( options = {} )
|
40
|
+
return @backend.flatten_translations( @locale, translations( options ), true, false )
|
41
|
+
end
|
42
|
+
|
43
|
+
def store( key, value )
|
44
|
+
keys = I18n.normalize_keys( @locale, key, [], nil)
|
45
|
+
keys.shift # remove locale
|
46
|
+
data = keys.reverse.inject( value ) { |result, _key| { _key => result } }
|
47
|
+
@backend.store_translations( @locale, data )
|
48
|
+
end
|
49
|
+
|
50
|
+
def fetch( key )
|
51
|
+
return flattened_translations[ key.to_sym ]
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.en_equivalent_path( path )
|
55
|
+
return "#{File.dirname( path )}/en.yml"
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def load_translations
|
61
|
+
@backend.reload!
|
62
|
+
@backend.send( :init_translations )
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/vocab/ui.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Vocab
|
2
|
+
module Validator
|
3
|
+
class Android < Base
|
4
|
+
|
5
|
+
def initialize( locales_dir = nil )
|
6
|
+
@locales_dir = locales_dir || 'res'
|
7
|
+
end
|
8
|
+
|
9
|
+
def other_keys( path )
|
10
|
+
return Vocab::Translator::Android.hash_from_xml( path ).keys
|
11
|
+
end
|
12
|
+
|
13
|
+
def english_keys( path = nil )
|
14
|
+
return Vocab::Translator::Android.english_keys( @locales_dir )
|
15
|
+
end
|
16
|
+
|
17
|
+
def files_to_validate
|
18
|
+
return Dir.glob( "#{@locales_dir}/values-*/strings.xml" )
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Vocab
|
2
|
+
module Validator
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def validate
|
6
|
+
files = files_to_validate
|
7
|
+
Vocab.ui.say( "#{files.size} file(s) to validate in #{@locales_dir}" )
|
8
|
+
files.each do |path|
|
9
|
+
validation = validate_file( path )
|
10
|
+
print( path, validation )
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def print( path, validation )
|
15
|
+
Vocab.ui.say( "Validating: #{path}" )
|
16
|
+
|
17
|
+
unless validation[ :missing ].empty?
|
18
|
+
Vocab.ui.say( " Missing keys:" )
|
19
|
+
validation[ :missing ].each { |missing| Vocab.ui.say( " - #{missing}" ) }
|
20
|
+
end
|
21
|
+
|
22
|
+
unless validation[ :extra ].empty?
|
23
|
+
Vocab.ui.say( " Extra keys:" )
|
24
|
+
validation[ :extra ].each { |extra| Vocab.ui.say( " + #{extra}" ) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate_file( path )
|
29
|
+
other = other_keys( path )
|
30
|
+
english = english_keys( path )
|
31
|
+
|
32
|
+
result = {}
|
33
|
+
result[ :missing ] = ( english - other ).sort
|
34
|
+
result[ :extra ] = ( other - english ).sort
|
35
|
+
return result
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Vocab
|
2
|
+
module Validator
|
3
|
+
class Rails < Base
|
4
|
+
|
5
|
+
def initialize( locales_dir = nil )
|
6
|
+
@locales_dir = locales_dir || 'config/locales'
|
7
|
+
end
|
8
|
+
|
9
|
+
def other_keys( path )
|
10
|
+
return flattened_keys( path )
|
11
|
+
end
|
12
|
+
|
13
|
+
def english_keys( path )
|
14
|
+
return flattened_keys( Vocab::Translator::Rails.en_equivalent_path( path ) )
|
15
|
+
end
|
16
|
+
|
17
|
+
def files_to_validate
|
18
|
+
return Dir.glob( "#{@locales_dir}/**/*.yml" ).reject { |path| File.basename( path ) == 'en.yml' }
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def flattened_keys( path )
|
24
|
+
translator = Vocab::Translator::Rails.new
|
25
|
+
translator.load_file( path )
|
26
|
+
return translator.flattened_translations.keys.collect { |key| key.to_s }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/vocab.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'i18n'
|
3
|
+
require 'pathname'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
require 'vocab/application'
|
7
|
+
require 'vocab/extractor'
|
8
|
+
require 'vocab/translator'
|
9
|
+
require 'vocab/merger'
|
10
|
+
require 'vocab/settings'
|
11
|
+
require 'vocab/ui'
|
12
|
+
require 'vocab/validator'
|
13
|
+
require 'vocab/version'
|
14
|
+
|
15
|
+
I18n::Backend::Simple.send( :include, I18n::Backend::Flatten )
|
16
|
+
|
17
|
+
module Vocab
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def settings
|
21
|
+
@settings ||= Settings.new( root )
|
22
|
+
end
|
23
|
+
|
24
|
+
def ui
|
25
|
+
@ui ||= UI.new
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns root directory where .vocab is located
|
29
|
+
# TODO: make this work in subdirectory under .vocab
|
30
|
+
def root
|
31
|
+
return File.expand_path( Dir.pwd )
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "init" do
|
4
|
+
|
5
|
+
before( :each ) do
|
6
|
+
@tmpdir = File.join( vocab_root, "spec", "tmp" )
|
7
|
+
FileUtils.rm_rf( Dir.glob( "#{@tmpdir}/*" ) )
|
8
|
+
Dir.chdir( @tmpdir )
|
9
|
+
end
|
10
|
+
|
11
|
+
it "creates a .vocab file if one doesn't exist" do
|
12
|
+
Vocab.ui.should_receive( :say ).with( "Writing new .vocab file. Check this file into your project repo" )
|
13
|
+
Vocab::Settings.create
|
14
|
+
path = "#{@tmpdir}/.vocab"
|
15
|
+
File.exists?( path ).should be_true
|
16
|
+
YAML.load_file( path ).should == { "last_translation" => `git rev-parse HEAD`.strip }
|
17
|
+
`git rm -f #{path}`
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<resources>
|
3
|
+
<string name="app_name">Kid Mode</string>
|
4
|
+
<string name="pd_app_name">Parent Dashboard</string>
|
5
|
+
<string name="app_current">current</string>
|
6
|
+
<string name="cancel">Cancel</string>
|
7
|
+
<string name="delete">Delete</string>
|
8
|
+
</resources>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<resources>
|
3
|
+
<string name="app_name">Kid Mode</string>
|
4
|
+
<string name="pd_app_name">Parent Dashboard</string>
|
5
|
+
<!-- This is a comment -->
|
6
|
+
<string name="app_current">current</string>
|
7
|
+
<string name="cancel">Cancel</string>
|
8
|
+
<string name="delete">Delete</string>
|
9
|
+
<string name="not_in_es">This key not in spanish</string>
|
10
|
+
</resources>
|
@@ -0,0 +1 @@
|
|
1
|
+
This is just a decoy
|
@@ -0,0 +1 @@
|
|
1
|
+
This is just a decoy
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<resources>
|
3
|
+
<string name="cancel">Cancelar</string>
|
4
|
+
<string name="delete">La función Child Lock</string>
|
5
|
+
<string name="pd_app_name">el Panel para padres bien</string>
|
6
|
+
<string name="translator_cruft">Malo</string>
|
7
|
+
</resources>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
---
|
2
|
+
en:
|
3
|
+
models:
|
4
|
+
product:
|
5
|
+
id_125:
|
6
|
+
description: Green with megawatts
|
7
|
+
name: Lazer
|
8
|
+
id_36:
|
9
|
+
description: Polarized and lazer resistant
|
10
|
+
name: This nested value has changed
|
11
|
+
id_55:
|
12
|
+
description: A new nested description
|
13
|
+
name: a new nested name
|
@@ -0,0 +1,21 @@
|
|
1
|
+
cn:
|
2
|
+
marketing:
|
3
|
+
banner: 這改變了營銷信息
|
4
|
+
dashboard:
|
5
|
+
chart: 此值已更改
|
6
|
+
details: 此鍵 /值已添加
|
7
|
+
menu:
|
8
|
+
first: 第一個菜單項
|
9
|
+
second: 第二個菜單項
|
10
|
+
models:
|
11
|
+
product:
|
12
|
+
id_125:
|
13
|
+
description: 綠色與兆瓦
|
14
|
+
name: 休閒
|
15
|
+
id_36:
|
16
|
+
description: 極化和激光耐
|
17
|
+
name: 此嵌套值已更改
|
18
|
+
id_55:
|
19
|
+
description: 一個新的嵌套描述
|
20
|
+
name: 一個新的嵌套的名稱
|
21
|
+
translator_cruft: 這是不小心添加了一個翻譯
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Vocab::Extractor::Android" do
|
4
|
+
|
5
|
+
before( :each ) do
|
6
|
+
@locale = "#{vocab_root}/spec/data/android/locales/values/strings.xml"
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'extract_current' do
|
10
|
+
|
11
|
+
it "extracts hash of current string translations" do
|
12
|
+
actual = Vocab::Extractor::Android.extract_current( @locale )
|
13
|
+
actual.should eql( { "app_name" =>"Kid Mode",
|
14
|
+
"delete" =>"Delete",
|
15
|
+
"cancel" =>"Cancel",
|
16
|
+
"app_current"=>"current",
|
17
|
+
"pd_app_name"=>"Parent Dashboard",
|
18
|
+
"not_in_es" =>"This key not in spanish",} )
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'extract_previous' do
|
24
|
+
|
25
|
+
before( :each ) do
|
26
|
+
Dir.chdir( vocab_root )
|
27
|
+
end
|
28
|
+
|
29
|
+
before( :each ) do
|
30
|
+
@sha = '2302e5acb50a9b56d113c46805de5ae0c12d28c0'
|
31
|
+
Vocab.settings.stub!( :last_translation ).and_return( @sha )
|
32
|
+
end
|
33
|
+
|
34
|
+
it "extracts hash of previous string translations" do
|
35
|
+
actual = Vocab::Extractor::Android.extract_previous( @locale )
|
36
|
+
actual.should eql( { 'app_name' => 'Kid Mode',
|
37
|
+
'pd_app_name' => 'Parent Dashboard',
|
38
|
+
'app_current' => 'current' } )
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'write_full' do
|
44
|
+
|
45
|
+
it 'writes the full translation to the correct xml file' do
|
46
|
+
hash = { 'foo' => 'bar' }
|
47
|
+
Vocab::Translator::Android.should_receive( :write ).
|
48
|
+
with( hash, "#{vocab_root}/strings.full.xml" )
|
49
|
+
Vocab::Extractor::Android.write_full( hash )
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'write_diff' do
|
55
|
+
|
56
|
+
it 'writes the diff translation to the correct xml file' do
|
57
|
+
hash = { 'foo' => 'bar' }
|
58
|
+
Vocab::Translator::Android.should_receive( :write ).
|
59
|
+
with( hash, "#{vocab_root}/strings.diff.xml" )
|
60
|
+
Vocab::Extractor::Android.write_diff( hash )
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'write' do
|
66
|
+
|
67
|
+
it 'writes the translation to a xml file' do
|
68
|
+
translation = { 'app_name' => 'Kid Mode',
|
69
|
+
'pd_app_name' => 'Parent Dashboard',
|
70
|
+
'delete' => "La función Child Lock" }
|
71
|
+
path = "#{vocab_root}/spec/tmp/strings.xml"
|
72
|
+
Vocab::Translator::Android.write( translation, path )
|
73
|
+
should_eql_file( File.open( path ) { |f| f.read },
|
74
|
+
"spec/data/android/write.xml" )
|
75
|
+
File.delete( path )
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'examples' do
|
81
|
+
|
82
|
+
it 'returns file names for completed translations' do
|
83
|
+
dir = "#{vocab_root}/spec/data/android/locales"
|
84
|
+
actual = Vocab::Extractor::Android.examples( dir )
|
85
|
+
actual.should =~ [ "tmp/translations/values-es" ]
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'uses the conventional android locales directory by default' do
|
89
|
+
Vocab::Translator::Android.should_receive( :locales ).with( "#{vocab_root}/res/values" ).and_return( [] )
|
90
|
+
Vocab::Extractor::Android.examples
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Vocab::Extractor::Base" do
|
4
|
+
|
5
|
+
describe "diff" do
|
6
|
+
|
7
|
+
it "finds the new keys in the current hash" do
|
8
|
+
@current = { 1 => 2, 3 => 4 }
|
9
|
+
@previous = { 1 => 2 }
|
10
|
+
diff = Vocab::Extractor::Base.diff( @previous, @current )
|
11
|
+
diff.should == { 3 => 4 }
|
12
|
+
end
|
13
|
+
|
14
|
+
it "finds the updated keys in the current hash" do
|
15
|
+
@current = { 1 => 10 }
|
16
|
+
@previous = { 1 => 2 }
|
17
|
+
diff = Vocab::Extractor::Base.diff( @previous, @current )
|
18
|
+
diff.should == { 1 => 10 }
|
19
|
+
end
|
20
|
+
|
21
|
+
it "ignores updated keys that begin with 'debug_'" do
|
22
|
+
@current = { 'debug_foo' => 'bar' }
|
23
|
+
@previous = {}
|
24
|
+
diff = Vocab::Extractor::Base.diff( @previous, @current )
|
25
|
+
diff.should == {}
|
26
|
+
end
|
27
|
+
|
28
|
+
it "handles the hash format of the translations" do
|
29
|
+
@current = { :"en.marketing.banner"=>"This product is so good",
|
30
|
+
:"en.models.product.id_125.name"=>"This has been updated",
|
31
|
+
:"en.models.product.id_126.name"=>"This is new"}
|
32
|
+
@previous = { :"en.marketing.banner"=>"This product is so good",
|
33
|
+
:"en.models.product.id_125.name"=>"Lazer"}
|
34
|
+
diff = Vocab::Extractor::Base.diff( @previous, @current )
|
35
|
+
diff.should == { :"en.models.product.id_125.name"=>"This has been updated",
|
36
|
+
:"en.models.product.id_126.name"=>"This is new"}
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "extract" do
|
42
|
+
|
43
|
+
before( :each ) do
|
44
|
+
@diff_path = "#{vocab_root}/spec/tmp/en.yml"
|
45
|
+
@full_path = "#{vocab_root}/spec/tmp/en.yml"
|
46
|
+
File.delete( @diff_path ) if File.exists?( @diff_path )
|
47
|
+
end
|
48
|
+
|
49
|
+
it "extracts the strings that need to be translated into a yml file" do
|
50
|
+
current = { 1 => 5, 3 => 4 }
|
51
|
+
previous = { 1 => 2 }
|
52
|
+
Vocab::Extractor::Base.should_receive( :extract_current ).and_return( current )
|
53
|
+
Vocab::Extractor::Base.should_receive( :extract_previous ).and_return( previous )
|
54
|
+
Vocab::Extractor::Base.should_receive( :write_diff ).with( { 1 => 5, 3 => 4 }, @diff_path )
|
55
|
+
Vocab::Extractor::Base.should_receive( :write_full ).with( current, @full_path )
|
56
|
+
Vocab::Extractor::Base.should_receive( :mkdir_examples )
|
57
|
+
Vocab::Extractor::Base.extract( @diff_path, @full_path )
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "previous_file" do
|
63
|
+
|
64
|
+
before( :each ) do
|
65
|
+
Dir.chdir( vocab_root )
|
66
|
+
@path = "spec/data/android/locales/strings.xml"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns the contents of a file from a specific git version" do
|
70
|
+
contents = Vocab::Extractor::Base.previous_file( @path, 'a19f7c5c28c1158792a966c0d2153a04490dd35e' )
|
71
|
+
should_eql_file( contents, 'spec/data/android/previous.xml' )
|
72
|
+
|
73
|
+
contents = Vocab::Extractor::Base.previous_file( @path, '0533bcd9a304cd6e74d6a56959dbcabd57b2f1b9' )
|
74
|
+
should_eql_file( contents, 'spec/data/android/current.xml' )
|
75
|
+
end
|
76
|
+
|
77
|
+
it "returns the correct contents when a full path is specified" do
|
78
|
+
contents = Vocab::Extractor::Base.previous_file( "#{vocab_root}/#{@path}", 'a19f7c5c28c1158792a966c0d2153a04490dd35e' )
|
79
|
+
should_eql_file( contents, 'spec/data/android/previous.xml' )
|
80
|
+
end
|
81
|
+
|
82
|
+
it "returns the contents of a file when in a subdir of the git directory" do
|
83
|
+
Dir.chdir( "spec" )
|
84
|
+
@path = "data/android/locales/strings.xml"
|
85
|
+
contents = Vocab::Extractor::Base.previous_file( @path, 'a19f7c5c28c1158792a966c0d2153a04490dd35e' )
|
86
|
+
should_eql_file( contents, 'spec/data/android/previous.xml' )
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'git_root' do
|
92
|
+
|
93
|
+
it 'returns empty string if already at git root' do
|
94
|
+
Dir.chdir( vocab_root )
|
95
|
+
Vocab::Extractor::Base.git_root.should eql( vocab_root )
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'returns path to git root if in subdir' do
|
99
|
+
Dir.chdir( "#{vocab_root}/spec/data" )
|
100
|
+
Vocab::Extractor::Base.git_root.should eql( vocab_root )
|
101
|
+
Dir.chdir( "#{vocab_root}" )
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
describe 'git_relative_path' do
|
107
|
+
|
108
|
+
it 'returns the path to the specified file relative to the git root dir' do
|
109
|
+
Dir.chdir( vocab_root )
|
110
|
+
path = "spec/data/android/locales/values/strings.xml"
|
111
|
+
Vocab::Extractor::Base.git_path( path ).should eql( path )
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'returns the path to the specified file relative to the git root dir while in subdir' do
|
115
|
+
Dir.chdir( "#{vocab_root}/spec/data" )
|
116
|
+
path = "android/locales/values/strings.xml"
|
117
|
+
git_path = "spec/data/android/locales/values/strings.xml"
|
118
|
+
Vocab::Extractor::Base.git_path( path ).should eql( git_path )
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'mkdir_examples' do
|
124
|
+
|
125
|
+
it 'creates example directories for completed translations' do
|
126
|
+
examples = [ 'tmp/translations/values-zh', 'tmp/translations/values-zh-rCN' ]
|
127
|
+
examples.each { |example| FileUtils.should_receive( :mkdir_p ).with( example ) }
|
128
|
+
Vocab::Extractor::Base.should_receive( :examples ).and_return( examples )
|
129
|
+
Vocab::Extractor::Base.mkdir_examples
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|