localize 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ Copyright (c) 2010, Andrey Savchenko
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
+
6
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+ * Neither the name of the Aejis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9
+
10
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.rdoc ADDED
@@ -0,0 +1,127 @@
1
+ = Localize
2
+ Localize is a small library for internationalization.
3
+ Example:
4
+
5
+ puts t.hello # => Hola
6
+ puts t.hello.world # => Hola, mundo
7
+ puts f 380441234567 # => +380 (44) 123-45-67
8
+ puts l Time.utc(2000, "jan"), :short # => Sat 01-Jan-00
9
+ puts l 1200.05 # => 1.200,05
10
+
11
+ == Install
12
+
13
+ gem install localize
14
+ require 'localize'
15
+
16
+ == Setup
17
+
18
+ Set the store, yaml or plain for now, xml and others planned (default yaml):
19
+
20
+ Localize.store = :plain
21
+
22
+ Specify location of the translation files:
23
+
24
+ Localize.location = 'lib/translations'
25
+
26
+ if store set to plain, location must be a ruby hash:
27
+
28
+ Localize.location = {'text' => { 'hello' => {'world' => 'mundo' } }
29
+
30
+ Set locale:
31
+
32
+ Localize.locale = :esp
33
+
34
+ and default locale (optional, en by default):
35
+
36
+ Localize.default_locale = :ru
37
+
38
+ Now, load the translation:
39
+
40
+ t = Localize.translate
41
+ f = Localize.f
42
+ l = Localize.l
43
+
44
+ == Sinatra setup
45
+ sinatra.rb contains predefined helpers <tt>t</tt>, <tt>l</tt> and <tt>f</tt> and set locale from <tt>session['locale']</tt>
46
+
47
+ require 'localize/sinatra'
48
+ Localize.default_locale = :ru
49
+ Localize.location = 'locales' # Change to your path
50
+
51
+ == Translation files
52
+ Translation file must contain two sections: 'text' and 'formats'.
53
+
54
+ Text section contains translations and can have an unlimited nesting:
55
+
56
+ text:
57
+ hello: 'hola' # t.hello
58
+ foo:
59
+ bar: 'baz' # t.foo.bar
60
+
61
+ Formats section contains different localization rules and formats:
62
+
63
+ formats:
64
+ phone:
65
+ :full: '+### (##) ###-##-##'
66
+ :short: '###-##-##'
67
+ number:
68
+ separator: ','
69
+ dec_point: '.'
70
+
71
+ Phone subsection must have format named 'full', and may have arbitrary names which can called by second parameter in f method:
72
+
73
+ f(78977654) # Full format
74
+ f(12345678, :short)
75
+ f(32145687, :other)
76
+
77
+ Date subsection must contains translations for months and days of the week. Also set formats in strftime format:
78
+
79
+ formats:
80
+ date:
81
+ format:
82
+ :full: '%a %b %d %H:%M:%S %Z %Y'
83
+ :short: '%a %d-%B-%y'
84
+ day_names:
85
+ short:
86
+ - Sun
87
+ - Mon
88
+ - Tue
89
+ - Wed
90
+ - Thu
91
+ - Fri
92
+ - Sat
93
+ full:
94
+ - Sunday
95
+ - Monday
96
+ - Tuesday
97
+ - Wednesday
98
+ - Thursday
99
+ - Friday
100
+ - Saturday
101
+ mon_names:
102
+ short:
103
+ - Jan
104
+ - Feb
105
+ - Mar
106
+ - Apr
107
+ - May
108
+ - Jun
109
+ - Jul
110
+ - Aug
111
+ - Sep
112
+ - Oct
113
+ - Nov
114
+ - Dec
115
+ full:
116
+ - January
117
+ - February
118
+ - March
119
+ - April
120
+ - May
121
+ - June
122
+ - July
123
+ - August
124
+ - September
125
+ - October
126
+ - November
127
+ - December
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ module Localize
3
+ class YAMLadapter
4
+ require 'yaml'
5
+
6
+ def self.get_trans
7
+ tr = {}
8
+ Dir.glob(File.join(Localize::location, "#{Localize::locale.to_s}.yml")).each do |file|
9
+ f = (RUBY_VERSION < '1.9') ? ::File.open(file) : ::File.open(file, 'r:utf-8')
10
+ tr.merge! ::YAML.load(f)
11
+ end
12
+ tr
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,60 @@
1
+ module Localize
2
+ class Formats
3
+ class << self
4
+
5
+ # Based on snippet in http://snippets.dzone.com/posts/show/2472
6
+ def phone(str, format = :full)
7
+ require 'strscan'
8
+ pattern = Localize.trans[:formats]['phone'][format]
9
+ slots = pattern.count('#')
10
+ source = str.to_s
11
+
12
+ if source.length < slots
13
+ keepCount = source.length
14
+ leftmost, rightmost = 0, pattern.length - 1
15
+
16
+ leftmost = (1...keepCount).inject(pattern.rindex('#')) {
17
+ |leftmost, n| pattern.rindex('#', leftmost - 1) }
18
+
19
+ pattern = pattern[leftmost..rightmost]
20
+ end
21
+
22
+ scanner = ::StringScanner.new(pattern)
23
+ sourceIndex = 0
24
+ result = ''
25
+ fixRegexp = Regexp.new(Regexp.escape('#'))
26
+ while not scanner.eos?
27
+ if scanner.scan(fixRegexp) then
28
+ result += source[sourceIndex].chr
29
+ sourceIndex += 1
30
+ else
31
+ result += scanner.getch
32
+ end
33
+ end
34
+ result
35
+ end
36
+
37
+ def date(source, format = :full)
38
+ locale = Localize.trans[:formats]['date']
39
+ format = locale['format'][format]
40
+
41
+ format.gsub!(/%a/, locale['day_names']['short'][source.wday])
42
+ format.gsub!(/%A/, locale['day_names']['full'][source.wday])
43
+ format.gsub!(/%b/, locale['mon_names']['short'][source.mon-1])
44
+ format.gsub!(/%B/, locale['mon_names']['full'][source.mon-1])
45
+
46
+ source.strftime(format)
47
+ end
48
+
49
+ # Based on snippet on rubygarden
50
+ def number(num)
51
+ locale = Localize.trans[:formats]['number']
52
+ separator = locale['separator'] || ''
53
+ decimal_point = locale['dec_point'] || '.'
54
+ num_parts = num.to_s.split('.')
55
+ x = num_parts[0].reverse.scan(/.{1,3}/).join(separator).reverse
56
+ x << decimal_point + num_parts[1]
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,19 @@
1
+ require 'localize'
2
+
3
+ before do
4
+ Localize.locale = session['locale'] if session['locale']
5
+ end
6
+
7
+ helpers do
8
+ def t
9
+ Localize.translate
10
+ end
11
+
12
+ def l(source, format = :full)
13
+ Localize.l(source, format)
14
+ end
15
+
16
+ def f(source, format = :full)
17
+ Localize.f(source, format)
18
+ end
19
+ end
data/lib/localize.rb ADDED
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+ $KCODE = 'u' if RUBY_VERSION < '1.9'
3
+
4
+ module Localize
5
+
6
+ autoload :YAMLadapter, File.join(File.dirname(__FILE__), 'localize/adapters/yaml')
7
+ autoload :Formats, File.join(File.dirname(__FILE__), 'localize/formats')
8
+
9
+ @@default_locale = :en
10
+ @@locale = @@default_locale
11
+ @@store = :yaml
12
+ @@location = ''
13
+
14
+ class << self
15
+ def load(locale=nil, location=nil)
16
+ @@locale = locale if locale
17
+ @@location = location if location
18
+
19
+ ret = case @@store
20
+ when :yaml
21
+ YAMLadapter.get_trans
22
+ when :plain
23
+ @@location
24
+ else
25
+ raise "Adapter not avalaible: #{adapter}"
26
+ end
27
+ @@trans = {
28
+ :text => Translation.new(ret['text']),
29
+ :formats => ret['formats']
30
+ }
31
+ end
32
+
33
+ def translate
34
+ load unless @@trans
35
+ @@trans[:text]
36
+ end
37
+
38
+ def localize(source, format = :full)
39
+ load unless @@trans
40
+
41
+ if source.is_a?(Integer)
42
+ Formats.number(source)
43
+ elsif source.is_a?(Float)
44
+ Formats.number(source)
45
+ elsif source.is_a?(Time) or source.is_a?(Date)
46
+ Formats.date(source, format)
47
+ else
48
+ raise "Format not recognize"
49
+ end
50
+ end
51
+
52
+ alias :l :localize
53
+
54
+ def phone(source, format = :full)
55
+ load unless @@trans
56
+
57
+ fone = if source.is_a?(Integer)
58
+ source
59
+ elsif source.is_a?(String)
60
+ source.gsub(/[\+., -]/, '').trim.to_i
61
+ elsif source.is_a?(Float)
62
+ source.to_s.gsub('.', '').to_i
63
+ else
64
+ raise "Format not recognize"
65
+ end
66
+ Formats.phone(fone, format)
67
+ end
68
+
69
+ alias :f :phone
70
+
71
+ def reset!
72
+ @@trans = nil
73
+ end
74
+
75
+ def store=(str)
76
+ reset!
77
+ @@store = str.to_sym
78
+ end
79
+
80
+ def store
81
+ @@store
82
+ end
83
+
84
+ def locale=(loc)
85
+ reset!
86
+ @@locale = loc
87
+ end
88
+
89
+ def locale
90
+ @@locale
91
+ end
92
+
93
+ def default_locale=(loc)
94
+ reset!
95
+ @@locale = loc.to_sym
96
+ end
97
+
98
+ def default_locale
99
+ @@locale
100
+ end
101
+
102
+ def location=(locat)
103
+ reset!
104
+ @@location = locat
105
+ end
106
+
107
+ def location
108
+ @@location
109
+ end
110
+
111
+ def trans
112
+ @@trans
113
+ end
114
+ end
115
+
116
+ class Translation
117
+ def initialize(hash)
118
+ hash.each_pair do |key, value|
119
+ value = Translation.new(value) if value.is_a?(Hash)
120
+ key = key.to_s
121
+ instance_variable_set("@#{key}", value)
122
+ self.class.class_eval do
123
+ define_method("#{key}") { instance_variable_get("@#{key}") }
124
+ end
125
+ end
126
+ end
127
+
128
+ def method_missing(name, *params)
129
+ MissString.new('Translation missing: '+name.to_s)
130
+ end
131
+ end
132
+
133
+ class MissString < String
134
+ def method_missing(name, *params)
135
+ self << '.' + name.to_s
136
+ end
137
+ end
138
+ end
data/localize.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "localize"
3
+ s.version = "0.1"
4
+ s.date = "2010-05-06"
5
+
6
+ s.summary = "Lightweight localization library"
7
+ s.description = "Lightweight, ruby-way localization solution"
8
+
9
+ s.author = "Andrey Savchenko"
10
+ s.email = "andrey@aejis.eu"
11
+ s.homepage = "http://aejis.eu/tools/localize"
12
+
13
+ s.files = %w[
14
+ LICENSE
15
+ README.rdoc
16
+ lib/localize.rb
17
+ lib/localize/formats.rb
18
+ lib/localize/sinatra.rb
19
+ lib/localize/adapters/yaml.rb
20
+ localize.gemspec
21
+ test/formats_test.rb
22
+ test/translate_test.rb
23
+ test/stores/en.yml
24
+ ]
25
+ s.require_paths = %w[lib]
26
+
27
+ s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
28
+
29
+ s.has_rdoc = true
30
+ s.extra_rdoc_files = %w[README.rdoc LICENSE]
31
+
32
+ s.add_development_dependency 'rspec'
33
+ end
@@ -0,0 +1,23 @@
1
+ require File.join(File.dirname(__FILE__), '../lib/localize')
2
+
3
+ describe Localize do
4
+ before do
5
+ Localize.location = 'stores'
6
+ end
7
+
8
+ it "Format phone numbers" do
9
+ Localize.f(380446666666, :full).should == '+380 (44) 666-66-66'
10
+ end
11
+
12
+ it "Localize dates" do
13
+ Localize.l(Time.utc(2000, "jan")).should == 'Sat Jan 01 00:00:00 UTC 2000'
14
+ end
15
+
16
+ it "Format dates" do
17
+ Localize.l(Time.utc(2000, "jan"), :short).should == 'Sat 01-January-00'
18
+ end
19
+
20
+ it "Format numbers" do
21
+ Localize.l(1000.02).should == '1,000.02'
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ text:
2
+ hello: 'world'
3
+ foo:
4
+ bar: 'baz'
5
+ formats:
6
+ phone:
7
+ :full: '+### (##) ###-##-##'
8
+ :short: '###-##-##'
9
+ number:
10
+ separator: ','
11
+ dec_point: '.'
12
+ date:
13
+ format:
14
+ :full: '%a %b %d %H:%M:%S %Z %Y'
15
+ :short: '%a %d-%B-%y'
16
+ day_names:
17
+ short:
18
+ - Sun
19
+ - Mon
20
+ - Tue
21
+ - Wed
22
+ - Thu
23
+ - Fri
24
+ - Sat
25
+ full:
26
+ - Sunday
27
+ - Monday
28
+ - Tuesday
29
+ - Wednesday
30
+ - Thursday
31
+ - Friday
32
+ - Saturday
33
+ mon_names:
34
+ short:
35
+ - Jan
36
+ - Feb
37
+ - Mar
38
+ - Apr
39
+ - May
40
+ - Jun
41
+ - Jul
42
+ - Aug
43
+ - Sep
44
+ - Oct
45
+ - Nov
46
+ - Dec
47
+ full:
48
+ - January
49
+ - February
50
+ - March
51
+ - April
52
+ - May
53
+ - June
54
+ - July
55
+ - August
56
+ - September
57
+ - October
58
+ - November
59
+ - December
@@ -0,0 +1,36 @@
1
+ require File.join(File.dirname(__FILE__), '../lib/localize')
2
+
3
+ describe Localize do
4
+ it "Get translation from plain" do
5
+ Localize.store = :plain
6
+ Localize.location = {
7
+ 'text' => {
8
+ 'hello' => 'world'
9
+ }
10
+ }
11
+ t = Localize.translate
12
+ t.hello.should == 'world'
13
+ end
14
+
15
+ it "Get translation from yaml" do
16
+ Localize.store = :yaml
17
+ Localize.load(:en, 'stores')
18
+ t = Localize.translate
19
+ t.hello.should == 'world'
20
+ end
21
+
22
+ it "Accept nested translations" do
23
+ t = Localize.translate
24
+ t.foo.bar.should == 'baz'
25
+ end
26
+
27
+ it "Return right error" do
28
+ t = Localize.translate
29
+ t.fee.should == 'Translation missing: fee'
30
+ end
31
+
32
+ it "Return right error with nested translation" do
33
+ t = Localize.translate
34
+ t.fee.baz.should == 'Translation missing: fee.baz'
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: localize
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - Andrey Savchenko
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-05-06 00:00:00 +03:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rspec
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 0
28
+ version: "0"
29
+ type: :development
30
+ version_requirements: *id001
31
+ description: Lightweight, ruby-way localization solution
32
+ email: andrey@aejis.eu
33
+ executables: []
34
+
35
+ extensions: []
36
+
37
+ extra_rdoc_files:
38
+ - README.rdoc
39
+ - LICENSE
40
+ files:
41
+ - LICENSE
42
+ - README.rdoc
43
+ - lib/localize.rb
44
+ - lib/localize/formats.rb
45
+ - lib/localize/sinatra.rb
46
+ - lib/localize/adapters/yaml.rb
47
+ - localize.gemspec
48
+ - test/formats_test.rb
49
+ - test/translate_test.rb
50
+ - test/stores/en.yml
51
+ has_rdoc: true
52
+ homepage: http://aejis.eu/tools/localize
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.6
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Lightweight localization library
81
+ test_files:
82
+ - test/formats_test.rb
83
+ - test/translate_test.rb