multilang 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +93 -0
- data/Rakefile +26 -0
- data/lib/multilang.rb +53 -0
- data/lib/multilang/language_names.rb +41 -0
- data/lib/multilang/language_names.yaml +1155 -0
- data/lib/multilang/slot.rb +71 -0
- data/lib/multilang/version.rb +3 -0
- data/multilang.gemspec +22 -0
- data/spec/for_test.rb +1 -0
- data/spec/for_test2.rb +1 -0
- data/spec/multilang/language_names_spec.rb +20 -0
- data/spec/multilang/slot_spec.rb +71 -0
- data/spec/multilang_spec.rb +106 -0
- data/spec/spec_helper.rb +29 -0
- metadata +101 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'multilang/language_names'
|
2
|
+
|
3
|
+
module Multilang
|
4
|
+
class Slot
|
5
|
+
def initialize
|
6
|
+
@items = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
# Register the object to the slot.
|
10
|
+
#
|
11
|
+
# @param [String, Symbol] language_spec the language specifier
|
12
|
+
# @param [Object] object object to register
|
13
|
+
# @yield called once at getting the object first
|
14
|
+
#
|
15
|
+
# @see Multilang::Slot#[]
|
16
|
+
def register(language_spec, object, &first)
|
17
|
+
item = {:object => object}
|
18
|
+
item[:first] = first if first
|
19
|
+
@items[LanguageNames[language_spec]] = item
|
20
|
+
end
|
21
|
+
|
22
|
+
# Determine if registered with the language specifier in the slot.
|
23
|
+
#
|
24
|
+
# @param [String, Symbol] language_spec the language specifier
|
25
|
+
# @return whether registered with the language specifier in the slot
|
26
|
+
def exists?(language_spec)
|
27
|
+
!!@items[LanguageNames[language_spec]]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Get the object by the language specifier. And call once the block that was
|
31
|
+
# given at registration the object.
|
32
|
+
#
|
33
|
+
# @param [String, Symbol] language_spec the language specifier
|
34
|
+
# @return [Object] registered object in the slot
|
35
|
+
#
|
36
|
+
# @see Multilang::Slot#register
|
37
|
+
def [](language_spec)
|
38
|
+
language_name = LanguageNames[language_spec]
|
39
|
+
raise ArgumentError, "#{language_spec.inspect} does not register" unless @items.key?(language_name)
|
40
|
+
item = @items[language_name]
|
41
|
+
|
42
|
+
if item[:first]
|
43
|
+
item[:first].call
|
44
|
+
item.delete(:first)
|
45
|
+
end
|
46
|
+
|
47
|
+
item[:object]
|
48
|
+
end
|
49
|
+
|
50
|
+
module Access
|
51
|
+
|
52
|
+
# @attribute [r] slot
|
53
|
+
# @return [Multilang::Slot] slot that is bound to class or module
|
54
|
+
def slot
|
55
|
+
instance_variable_get(Multilang::SLOT_KEY)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Get registered object in the slot.
|
59
|
+
#
|
60
|
+
# @param [String, Symbol] language_spec
|
61
|
+
# @return [Object] registered object to the slot
|
62
|
+
#
|
63
|
+
# @see Multilang::Slot::Access#slot
|
64
|
+
# @see Multilang::Slot#[]
|
65
|
+
def [](language_spec)
|
66
|
+
slot[language_spec]
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/multilang.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'multilang/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = 'multilang'
|
8
|
+
gem.version = Multilang::VERSION
|
9
|
+
gem.authors = ['Takahiro Kondo']
|
10
|
+
gem.email = ['heartery@gmail.com']
|
11
|
+
gem.description = %q{Support multilingualization}
|
12
|
+
gem.summary = %q{Foundation for multilingualization}
|
13
|
+
gem.homepage = ''
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
|
20
|
+
gem.add_development_dependency('rspec')
|
21
|
+
gem.add_development_dependency('nokogiri')
|
22
|
+
end
|
data/spec/for_test.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
module ForTest end
|
data/spec/for_test2.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
module ForTest2 end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'multilang/language_names'
|
2
|
+
|
3
|
+
describe Multilang::LanguageNames, '.#[]' do
|
4
|
+
it 'returns normalized language name if the language specifier is string' do
|
5
|
+
described_class['english'].should == 'English'
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'returns language name if the language specifier is symbol' do
|
9
|
+
described_class[:en ].should == 'English'
|
10
|
+
described_class[:eng].should == 'English'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'raises TypeError if the language specifier is not string and symbol' do
|
14
|
+
lambda { described_class[1] }.should raise_error(TypeError, "can't convert Fixnum into String or Symbol")
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'raises ArgumentError if the language specifier does not exist' do
|
18
|
+
lambda { described_class['unknown'] }.should raise_error(ArgumentError, '"unknown" language specifier does not defined')
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'multilang/slot'
|
3
|
+
|
4
|
+
describe Multilang::Slot, '#register' do
|
5
|
+
before do
|
6
|
+
@slot = described_class.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'registers the object to the slot' do
|
10
|
+
object = Object.new
|
11
|
+
@slot.register(:en, object)
|
12
|
+
@slot.should be_exists('English')
|
13
|
+
@slot['English'].should == object
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Multilang::Slot, '#[]' do
|
18
|
+
before do
|
19
|
+
@slot = described_class.new
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns registered object' do
|
23
|
+
object = Object.new
|
24
|
+
@slot.register(:en, object)
|
25
|
+
@slot['English'].should == object
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'calls the block once if gives a block at construction' do
|
29
|
+
count = 0
|
30
|
+
@slot.register(:en, Object.new) { count += 1 }
|
31
|
+
@slot['English']
|
32
|
+
count.should == 1
|
33
|
+
@slot['English']
|
34
|
+
count.should == 1
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'raises ArgumentError if the language specifier does not register to the slot' do
|
38
|
+
lambda { @slot[:en] }.should raise_error(ArgumentError, ':en does not register')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe Multilang::Slot::Access, '#slot' do
|
43
|
+
before do
|
44
|
+
@slot = slot_stub
|
45
|
+
@class = Class.new
|
46
|
+
@class.extend(described_class)
|
47
|
+
@class.instance_variable_set(Multilang::SLOT_KEY, @slot)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns the value of instance variable named with Multilang::SLOT_KEY' do
|
51
|
+
@class.slot.should == @slot
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe Multilang::Slot::Access, '#[]' do
|
56
|
+
before do
|
57
|
+
@slot = slot_stub
|
58
|
+
@class = Class.new
|
59
|
+
@class.extend(described_class)
|
60
|
+
@class.instance_variable_set(Multilang::SLOT_KEY, @slot)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'calls #[] of the slot with the language specifier' do
|
64
|
+
@class.slot.should_receive(:[]).with('English')
|
65
|
+
@class['English']
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns the return value from #[] of the slot' do
|
69
|
+
@class['English'].should == 'item for English'
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'multilang'
|
3
|
+
|
4
|
+
describe Multilang, '.#register' do
|
5
|
+
before do
|
6
|
+
define_const Class, 'SampleClass::English'
|
7
|
+
define_const Module, 'SampleModule::English'
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
remove_const 'SampleClass::English'
|
12
|
+
remove_const 'SampleModule::English'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'extends parent class (parent class of Foo::Bar::Baz is Foo::Bar)' do
|
16
|
+
described_class.register SampleClass::English
|
17
|
+
SampleClass.should be_respond_to(:slot)
|
18
|
+
SampleClass.should be_respond_to(:[])
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'extends parent module' do
|
22
|
+
described_class.register SampleModule::English
|
23
|
+
SampleModule.should be_respond_to(:slot)
|
24
|
+
SampleModule.should be_respond_to(:[])
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'registers to the slot' do
|
28
|
+
described_class.register SampleClass::English
|
29
|
+
SampleClass.slot.should be_exists('English')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'raises TypeError if gives non-module' do
|
33
|
+
lambda { described_class.register 1 }.should raise_error(TypeError, "can't convert Fixnum into Module")
|
34
|
+
lambda { described_class.register 'English' }.should raise_error(TypeError, "can't convert String into Module")
|
35
|
+
lambda { described_class.register SampleClass::English }.should_not raise_error(TypeError)
|
36
|
+
lambda { described_class.register SampleModule::English }.should_not raise_error(TypeError)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'raises ArgumentError if gives anonymous class' do
|
40
|
+
lambda { described_class.register Class.new }.should raise_error(ArgumentError, "anonymous class can't register")
|
41
|
+
lambda { described_class.register SampleClass::English }.should_not raise_error(ArgumentError)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'raises ArgumentError if gives anonymous module' do
|
45
|
+
lambda { described_class.register Module.new }.should raise_error(ArgumentError, "anonymous module can't register")
|
46
|
+
lambda { described_class.register SampleModule::English }.should_not raise_error(ArgumentError)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'raises ArgumentError if gives top-level class' do
|
50
|
+
lambda { described_class.register SampleClass }.should raise_error(ArgumentError, "can't permit top-level class")
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'raises ArgumentError if gives top-level module' do
|
54
|
+
lambda { described_class.register SampleModule }.should raise_error(ArgumentError, "can't permit top-level module")
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with :as option' do
|
58
|
+
before { define_const Class, 'SampleClass::E' }
|
59
|
+
after { remove_const 'SampleClass::E' }
|
60
|
+
|
61
|
+
it 'registers to the slot with the value of :as option' do
|
62
|
+
described_class.register SampleClass::E, :as => 'English'
|
63
|
+
SampleClass.slot.should be_exists('English')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with :with option' do
|
68
|
+
it 'calls Kernel#.require with the value of :with option at initialization' do
|
69
|
+
Object.should_not be_const_defined(:ForTest)
|
70
|
+
described_class.register SampleClass::English, :with => 'for_test'
|
71
|
+
SampleClass['English']
|
72
|
+
Object.should be_const_defined(:ForTest)
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'with a block' do
|
76
|
+
it 'considers both the value of :with option and the block' do
|
77
|
+
Object.should_not be_const_defined(:ForTest2)
|
78
|
+
passed = false
|
79
|
+
|
80
|
+
described_class.register SampleClass::English, :with => 'for_test2' do
|
81
|
+
passed = true
|
82
|
+
end
|
83
|
+
|
84
|
+
SampleClass['English']
|
85
|
+
Object.should be_const_defined(:ForTest2)
|
86
|
+
passed.should be_true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe Multilang, ' including' do
|
93
|
+
before do
|
94
|
+
define_const Class, 'SampleClass::English'
|
95
|
+
end
|
96
|
+
|
97
|
+
after do
|
98
|
+
remove_const 'SampleClass::English'
|
99
|
+
end
|
100
|
+
|
101
|
+
it "calls #{described_class}.#register" do
|
102
|
+
described_class.should_receive(:register).with(SampleClass::English)
|
103
|
+
mod = described_class
|
104
|
+
SampleClass::English.class_eval { include mod }
|
105
|
+
end
|
106
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
def define_const(type, name)
|
2
|
+
klass = name.split('::').inject(Object) do |parent, name|
|
3
|
+
if parent.const_defined?(name)
|
4
|
+
parent.const_get(name)
|
5
|
+
else
|
6
|
+
parent.const_set(name, type.new)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove_const(name)
|
12
|
+
names = name.split('::')
|
13
|
+
|
14
|
+
parents = names[0..-2].inject([Object]) do |parents, name|
|
15
|
+
parents << parents.last.const_get(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
names.reverse.each do |name|
|
19
|
+
parent = parents.pop
|
20
|
+
parent.class_eval { remove_const name }
|
21
|
+
break unless parent.constants.empty?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def slot_stub
|
26
|
+
stub.tap do |s|
|
27
|
+
s.stub!(:[]).and_return { |language_spec| "item for #{language_spec}" }
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multilang
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Takahiro Kondo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: nokogiri
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Support multilingualization
|
47
|
+
email:
|
48
|
+
- heartery@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- LICENSE.txt
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- lib/multilang.rb
|
59
|
+
- lib/multilang/language_names.rb
|
60
|
+
- lib/multilang/language_names.yaml
|
61
|
+
- lib/multilang/slot.rb
|
62
|
+
- lib/multilang/version.rb
|
63
|
+
- multilang.gemspec
|
64
|
+
- spec/for_test.rb
|
65
|
+
- spec/for_test2.rb
|
66
|
+
- spec/multilang/language_names_spec.rb
|
67
|
+
- spec/multilang/slot_spec.rb
|
68
|
+
- spec/multilang_spec.rb
|
69
|
+
- spec/spec_helper.rb
|
70
|
+
homepage: ''
|
71
|
+
licenses: []
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 1.8.24
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: Foundation for multilingualization
|
94
|
+
test_files:
|
95
|
+
- spec/for_test.rb
|
96
|
+
- spec/for_test2.rb
|
97
|
+
- spec/multilang/language_names_spec.rb
|
98
|
+
- spec/multilang/slot_spec.rb
|
99
|
+
- spec/multilang_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
101
|
+
has_rdoc:
|