i18n_accessor 0.1.0
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 +14 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +179 -0
- data/Rakefile +2 -0
- data/i18n_accessor.gemspec +27 -0
- data/lib/i18n_accessor.rb +36 -0
- data/lib/i18n_accessor/version.rb +3 -0
- data/spec/fixtures/locales/en.yml +18 -0
- data/spec/i18n_accessor_spec.rb +64 -0
- metadata +115 -0
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Critical Juncture, LLC
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
# I18nAccessor
|
2
|
+
|
3
|
+
I18nAccessor uses a little metaprogramming to provide some syntactic sugar that
|
4
|
+
will help clean up your views when using I18n to display static properties on an
|
5
|
+
object.
|
6
|
+
|
7
|
+
I18nAccessor is especially useful in combination with ActiveHash where you now
|
8
|
+
only need an `:identifier` attribute and can remove all other string based
|
9
|
+
values from the data array.
|
10
|
+
|
11
|
+
See Usage and Examples sections below.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'i18n_accessor'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install i18n_accessor
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
Add `i18n_accessor` to your model as follows: `i18n_accessor :accessor`
|
31
|
+
|
32
|
+
This will look up the corresponding translation as follows:
|
33
|
+
```yml
|
34
|
+
# config locales/en.yml, etc
|
35
|
+
model_name:
|
36
|
+
accessor: 'your string'
|
37
|
+
```
|
38
|
+
|
39
|
+
I18nAccessor` also accepts a second `:scope` param as follows:
|
40
|
+
`i18n_accessor :accessor, scope: 'short'`
|
41
|
+
|
42
|
+
This will look up the corresponding translation as follows:
|
43
|
+
```yml
|
44
|
+
# config/locales/en.yml, etc
|
45
|
+
model_name:
|
46
|
+
accessor:
|
47
|
+
short: 'your string'
|
48
|
+
```
|
49
|
+
|
50
|
+
Often however when using `:scope` you'll have want to have more than one
|
51
|
+
accessor for the same key. In these cases you should also pass the `:key`
|
52
|
+
parameter:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
# app/models/product.rb
|
56
|
+
i18n_accessor :short_category, key: "category", scope: "short"
|
57
|
+
i18n_accessor :long_category, key: "category", scope: "long"
|
58
|
+
|
59
|
+
# config/locales/en.yml
|
60
|
+
model_name:
|
61
|
+
key:
|
62
|
+
short: 'your string'
|
63
|
+
long: 'your longer, more verbose string'
|
64
|
+
```
|
65
|
+
|
66
|
+
Scope can be any arbitrarily long string that you would use with the
|
67
|
+
I18n#translate method.
|
68
|
+
|
69
|
+
Scope is useful when you want to defined multiple accessors for the same key.
|
70
|
+
|
71
|
+
## Examples
|
72
|
+
|
73
|
+
### Simple
|
74
|
+
Simple usage is great for wrapping I18n strings in a method.
|
75
|
+
|
76
|
+
For example:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
# app/models/product.rb
|
80
|
+
class Product
|
81
|
+
i18n_accessor :name
|
82
|
+
end
|
83
|
+
|
84
|
+
# config/locales/en.yml
|
85
|
+
product:
|
86
|
+
name: 'Product'
|
87
|
+
|
88
|
+
# app/views/products/show.html.erb
|
89
|
+
# you get:
|
90
|
+
<%= @product.name %>
|
91
|
+
|
92
|
+
# rather than:
|
93
|
+
<%= I18n.t('product.name') %>
|
94
|
+
```
|
95
|
+
|
96
|
+
### ActiveHash
|
97
|
+
When used with ActiveHash it allows you to remove all strings from your
|
98
|
+
data array and making it less verbose while also giving you get the added
|
99
|
+
benefit of the I18n translation layer.
|
100
|
+
|
101
|
+
When I18nAccessor detects your model inherits from ActiveHash::Base it assumes
|
102
|
+
that you have an `:identifer` key and uses the value of this to do the i18n
|
103
|
+
lookup.
|
104
|
+
|
105
|
+
A typical entry in an ActiveHash data array might look like:
|
106
|
+
```ruby
|
107
|
+
# app/model/grade.rb
|
108
|
+
...
|
109
|
+
{id: 7, identifier: :first, long_name: 'First grade', short_name: '1st'},
|
110
|
+
...
|
111
|
+
```
|
112
|
+
|
113
|
+
With I18nAccessor:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
# app/models/grade.rb
|
117
|
+
class Grade < ActiveHash::Base
|
118
|
+
include ActiveHashI18n
|
119
|
+
i18n_accessor :short_name, scope: 'short'
|
120
|
+
i18n_accessor :long_name, scope: 'long'
|
121
|
+
|
122
|
+
self.data = [
|
123
|
+
{id: 0, identifier: :kindergarten},
|
124
|
+
{id: 1, identifier: :first},
|
125
|
+
{id: 2, identifier: :second}
|
126
|
+
#...
|
127
|
+
]
|
128
|
+
end
|
129
|
+
|
130
|
+
# config/locales/en.yml
|
131
|
+
grade:
|
132
|
+
kindergarten:
|
133
|
+
long: Kindergarten
|
134
|
+
short: Kindergarten
|
135
|
+
first:
|
136
|
+
long: First grade
|
137
|
+
short: 1st Grade
|
138
|
+
second:
|
139
|
+
long: Second grade
|
140
|
+
short: 2nd Grade
|
141
|
+
|
142
|
+
# app/views/grades/show.html.erb
|
143
|
+
<%= @grade.short_name %>
|
144
|
+
<%= @grade.long_name %>
|
145
|
+
```
|
146
|
+
|
147
|
+
Without I18nAccessor you'd end up with each element of your active_hash data
|
148
|
+
array needing a short_name and long_name key and value
|
149
|
+
(eg. `short_name: I18n.t('grade.kindergarten.short')`).
|
150
|
+
|
151
|
+
Note: when using `:scope` with ActiveHash you don't specify a `:key`
|
152
|
+
when creating multiple accessors. This is because the key is inferred from the
|
153
|
+
`:identifier` property on the data item.
|
154
|
+
|
155
|
+
When using I18nAccessor on an ActiveHash based class in order to create an
|
156
|
+
accessor that isn't based on the currently instantiated object you'll need to
|
157
|
+
pass the `:key` argument. This allows you to also make the use of simple case
|
158
|
+
outlined above.
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
# app/models/grade.rb
|
162
|
+
i18n_accessor :name, key: 'name'
|
163
|
+
|
164
|
+
# config/locales/en.yml
|
165
|
+
grade:
|
166
|
+
name: Grade
|
167
|
+
kindergarten:
|
168
|
+
long: Kindergarten
|
169
|
+
short: Kindergarten
|
170
|
+
...
|
171
|
+
```
|
172
|
+
|
173
|
+
## Contributing
|
174
|
+
|
175
|
+
1. Fork it ( https://github.com/[my-github-username]/i18n_accessor/fork )
|
176
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
177
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
178
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
179
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'i18n_accessor/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "i18n_accessor"
|
8
|
+
spec.version = I18nAccessor::VERSION
|
9
|
+
spec.authors = ["Peregrinator"]
|
10
|
+
spec.email = ["bob.burbach@gmail.com"]
|
11
|
+
spec.summary = "Makes keys in your I18N files accessible as methods."
|
12
|
+
spec.description = "see README"
|
13
|
+
spec.homepage = "http://github.com/criticaljuncture/i18n_accessor"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "activesupport", ">= 3.0.0"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec", ">= 3.3.0"
|
26
|
+
spec.add_development_dependency "active_hash", '~> 1.4.0'
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "i18n_accessor/version"
|
2
|
+
require 'active_support/core_ext/string/inflections'
|
3
|
+
|
4
|
+
module I18nAccessor
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def i18n_accessor(accessor_name, options={})
|
11
|
+
scope = options.fetch(:scope) { nil }
|
12
|
+
key = options.fetch(:key) { nil }
|
13
|
+
|
14
|
+
class_name = self.name.underscore
|
15
|
+
is_active_hash = defined?(ActiveHash::Base) && self.ancestors.include?(ActiveHash::Base)
|
16
|
+
|
17
|
+
define_method accessor_name do
|
18
|
+
unless key
|
19
|
+
key = if is_active_hash
|
20
|
+
self.identifier
|
21
|
+
else
|
22
|
+
accessor_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
i18n_path = [
|
27
|
+
class_name,
|
28
|
+
key,
|
29
|
+
scope
|
30
|
+
].compact.join('.')
|
31
|
+
|
32
|
+
I18n.t("#{i18n_path}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
en:
|
2
|
+
product:
|
3
|
+
name: Automobile
|
4
|
+
category:
|
5
|
+
short: SUV
|
6
|
+
long: Sports Utility Vehicle
|
7
|
+
|
8
|
+
grade:
|
9
|
+
name: Grade
|
10
|
+
kindergarten:
|
11
|
+
long: Kindergarten
|
12
|
+
short: K
|
13
|
+
first:
|
14
|
+
long: First grade
|
15
|
+
short: 1st
|
16
|
+
second:
|
17
|
+
long: Second grade
|
18
|
+
short: 2nd
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'active_hash'
|
2
|
+
require 'i18n_accessor'
|
3
|
+
|
4
|
+
class Grade < ActiveHash::Base
|
5
|
+
include I18nAccessor
|
6
|
+
|
7
|
+
i18n_accessor :name, key: 'name'
|
8
|
+
|
9
|
+
i18n_accessor :long_abbreviation, scope: 'long'
|
10
|
+
i18n_accessor :short_abbreviation, scope: 'short'
|
11
|
+
|
12
|
+
self.data = [
|
13
|
+
{id: 0, identifier: :kindergarten},
|
14
|
+
{id: 1, identifier: :first},
|
15
|
+
{id: 2, identifier: :second}
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
class Product
|
20
|
+
include I18nAccessor
|
21
|
+
|
22
|
+
i18n_accessor :name
|
23
|
+
i18n_accessor :short_category, key: "category", scope: "short"
|
24
|
+
i18n_accessor :long_category, key: "category", scope: "long"
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "I18nAccessor" do
|
28
|
+
before(:all) do
|
29
|
+
I18n.load_path = ["spec/fixtures/locales/en.yml"]
|
30
|
+
I18n.locale = 'en'
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#i18n_accessor" do
|
34
|
+
let(:product) { Product.new }
|
35
|
+
|
36
|
+
it "returns the proper i18n string for a simple usage" do
|
37
|
+
expect(product.name).to eql( I18n.t('product.name') )
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns the proper i18n string for complex usage" do
|
41
|
+
expect(product.short_category).to eql(
|
42
|
+
I18n.t('product.category.short')
|
43
|
+
)
|
44
|
+
|
45
|
+
expect(product.long_category).to eql(
|
46
|
+
I18n.t('product.category.long')
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#i18n_accessor with Active Hash" do
|
52
|
+
let(:grade) { Grade.first }
|
53
|
+
|
54
|
+
it "returns the proper i18n string for a simple usage" do
|
55
|
+
expect(grade.name).to eql( I18n.t('grade.name') )
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns the proper i18n string for complex usage" do
|
59
|
+
expect(grade.long_abbreviation).to eql("Kindergarten")
|
60
|
+
|
61
|
+
expect(grade.short_abbreviation).to eql("K")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: i18n_accessor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Peregrinator
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-10-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &70313951055400 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70313951055400
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bundler
|
27
|
+
requirement: &70313951054140 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.7'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70313951054140
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &70313951052640 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '10.0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70313951052640
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: &70313951051880 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.3.0
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70313951051880
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: active_hash
|
60
|
+
requirement: &70313951051160 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.4.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70313951051160
|
69
|
+
description: see README
|
70
|
+
email:
|
71
|
+
- bob.burbach@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- CHANGELOG.md
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- i18n_accessor-0.1.0.gem
|
83
|
+
- i18n_accessor.gemspec
|
84
|
+
- lib/i18n_accessor.rb
|
85
|
+
- lib/i18n_accessor/version.rb
|
86
|
+
- spec/fixtures/locales/en.yml
|
87
|
+
- spec/i18n_accessor_spec.rb
|
88
|
+
homepage: http://github.com/criticaljuncture/i18n_accessor
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.8.11
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: Makes keys in your I18N files accessible as methods.
|
113
|
+
test_files:
|
114
|
+
- spec/fixtures/locales/en.yml
|
115
|
+
- spec/i18n_accessor_spec.rb
|