simple_ar_localizer 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +13 -0
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.textile +85 -0
- data/doc/custom_data.textile +80 -0
- data/doc/localisation_data.textile +103 -0
- data/lib/simple_ar_localizer.rb +14 -0
- data/lib/simple_ar_localizer/localizer.rb +171 -0
- data/lib/simple_ar_localizer/map.rb +21 -0
- data/lib/simple_ar_localizer/version.rb +5 -0
- data/simple_ar_localizer.gemspec +21 -0
- metadata +70 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 152ed9286c2d6f90a46dc350377dffca6cfc6bb1
|
4
|
+
data.tar.gz: 05e5020751b6edbfbe80b19a01c2feffb8c7053b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ffa8da686b8fbfe11da12add82f2453209ec1f8812ae19ab85ae140477d3b28997372a27ecbe92cde7ab602bd0e234b6bccc83eb6fa0343bc4f16b4807b7effc
|
7
|
+
data.tar.gz: e80d40c0c4fe167375f942691e79c77cd2d72966e165b1dde6de0404df171a7b8782bdac629ada89dc9054f1974fea55c2c077345412f91c72844c741d4e4afc
|
data/.editorconfig
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# EditorConfig is awesome: http://EditorConfig.org
|
2
|
+
|
3
|
+
# top-most EditorConfig file
|
4
|
+
root = true
|
5
|
+
|
6
|
+
# Defaults for all files
|
7
|
+
[*]
|
8
|
+
end_of_line = lf
|
9
|
+
insert_final_newline = true
|
10
|
+
charset = utf-8
|
11
|
+
indent_style = space
|
12
|
+
indent_size = 2
|
13
|
+
trim_trailing_whitespace = true
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Jon Pearse
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
h1. Simple AR Localizer
|
2
|
+
|
3
|
+
SimpleARLocalizer is a gem that—hopefully—provides a slightly easier way of writing localisations for ActiveRecord models when splitting things out into per-model files.
|
4
|
+
Out of the box, it provides hooks for a model’s human name, human attribute names, and both per-model and per-attribute error messaging.
|
5
|
+
|
6
|
+
This means that instead of having:
|
7
|
+
|
8
|
+
<pre># config/locales/foo/en.yml
|
9
|
+
en:
|
10
|
+
activerecord:
|
11
|
+
models:
|
12
|
+
foo: model name
|
13
|
+
|
14
|
+
attributes:
|
15
|
+
foo:
|
16
|
+
attr_one: attribute name
|
17
|
+
|
18
|
+
errors:
|
19
|
+
models:
|
20
|
+
foo:
|
21
|
+
attributes:
|
22
|
+
attr_one:
|
23
|
+
blank: You need to fill this in
|
24
|
+
</pre>
|
25
|
+
|
26
|
+
You can instead use:
|
27
|
+
|
28
|
+
<pre><code># config/locales/foo/en.rb
|
29
|
+
SimpleARLocalizer::transform( Foo, :en, {
|
30
|
+
name: 'model name',
|
31
|
+
attributes: {
|
32
|
+
attr_one: {
|
33
|
+
name: 'attribute name',
|
34
|
+
errors: {
|
35
|
+
blank: 'You need to fill this in'
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
})</code></pre>
|
40
|
+
|
41
|
+
It’s still not exactly _pretty_, but it’s a little more descriptive and you’re less likely to put things in the wrong place/get your indents wrong.
|
42
|
+
|
43
|
+
h2. Installation and using
|
44
|
+
|
45
|
+
Add the following to your @Gemfile@ and run `bundle install`.
|
46
|
+
|
47
|
+
<pre>gem 'simple_ar_localizer', '~> 1.0'</pre>
|
48
|
+
|
49
|
+
Then, add the following in your @config/application.rb@:
|
50
|
+
|
51
|
+
<pre># Also allow nested locale files
|
52
|
+
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]</pre>
|
53
|
+
|
54
|
+
You should now be able to start using SimpleARLocalizer to generate your localisations, however it is important to note that this can only be used in Ruby files, rather than the YAML files to which you may be used.
|
55
|
+
|
56
|
+
h3. Usage
|
57
|
+
|
58
|
+
The main entry point is @SimpleARLocalizer::transform( model, language, l10n_data )@, which takes three arguments:
|
59
|
+
|
60
|
+
- model _(String or Constant)_ := the model you’re localising, either as a string (eg: @'Foo'@) or as a constant
|
61
|
+
- language _(Symbol)_ := ISO-639 language code of the language you’re providing a localisation for (eg: @:hu@)
|
62
|
+
- l10n_data _(Hash)_ := the localisation data itself.
|
63
|
+
|
64
|
+
The format of the localisation data is described "in its own file":doc/localisation_data.textile
|
65
|
+
|
66
|
+
h3. Custom data formatting
|
67
|
+
|
68
|
+
By design, this gem should cover ~90% of your localisation needs, but it also supports "custom data":doc/custom_data.textile if you need a little extra control.
|
69
|
+
|
70
|
+
h2. A quick note about dialect/spelling
|
71
|
+
|
72
|
+
Keen observers will note that I use US English (-ize) in the code, and British English (-ise) throughout comments and documentation: this is intentional.
|
73
|
+
|
74
|
+
For better or worse, the world seems to have settled on US English as the de-facto standard for writing software and I have honoured (honored?) that in this gem. That said, however, it feels ‘wrong’ for me to use it when writing continuous prose, thus reverting to British English elsewhere. Sorry!
|
75
|
+
|
76
|
+
h2. Version History
|
77
|
+
|
78
|
+
*1.0.0 _(May 23rd, 2018)_*
|
79
|
+
|
80
|
+
Extraction from the project whence it came and turning into a standalone gem.
|
81
|
+
|
82
|
+
h2. @#include 'sales_pitch.h'@
|
83
|
+
|
84
|
+
When I’m not hacking at random gems, I’m a freelance web developer specialising in all things front-end, based in the beautiful city of Cardiff, UK.
|
85
|
+
I’m usually kept fairly busy with project work, but I’m always on the lookout for new people to do cool stuff with. "Drop me a line":mailto:hello@jonpearse.net – I’d love to hear from you!
|
@@ -0,0 +1,80 @@
|
|
1
|
+
h1. Custom localisation mapping
|
2
|
+
|
3
|
+
Whilst the "defaults":./localisation_data.textile for SimpleARLocalizer are probably enough to cover the majority of things you’ll want to do with it, it also provides the ability to provide custom mappings from the localisation data hash to Rails I18n framework should you wish to extend its abilities.
|
4
|
+
This includes overriding default rules, should they be a little limited.
|
5
|
+
|
6
|
+
_(side note: this is how this gem came about—I needed a way of simply and easily localising a CMS which made heavy use of Rails’ inbuilt ‘human’ naming functionality, as well as labelling and messaging that could be localised on a per-model basis)_
|
7
|
+
|
8
|
+
h2. Configuring custom rules
|
9
|
+
|
10
|
+
In a Rails app, custom rules are added through the Rails configuration system:
|
11
|
+
|
12
|
+
<pre><code>Rails.application.config.ar_localization_rules = {
|
13
|
+
…
|
14
|
+
}</code></pre>
|
15
|
+
|
16
|
+
This consists of a hash, where the keys are the pseudo-path within the localisation data hash (more on that in a moment), and the value is the Rails I18n key to which it should be mapped.
|
17
|
+
|
18
|
+
Thus, the default @:name@ rule would be specified as:
|
19
|
+
|
20
|
+
<pre><code>Rails.application.config.ar_localization_rules = {
|
21
|
+
'name': 'activerecord.models.%{model}'
|
22
|
+
}</code></pre>
|
23
|
+
|
24
|
+
h2. Specifying keys
|
25
|
+
|
26
|
+
The mapping key is the nested keys from the incoming localisation data, separated by the forward slash (à lá XPath), thus given the localisation data:
|
27
|
+
|
28
|
+
<pre>{
|
29
|
+
foo: {
|
30
|
+
bar: {
|
31
|
+
baz: 'value'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}</pre>
|
35
|
+
|
36
|
+
The key would be: @foo/bar/baz@
|
37
|
+
|
38
|
+
h3. Interpolations
|
39
|
+
|
40
|
+
The mapping parser understands interpolations, which work in a similar way to parameters in routes, for example the default rule for attribute names is specified as:
|
41
|
+
|
42
|
+
<pre><code> …
|
43
|
+
'attributes/:attr': 'activerecord.attributes.%{model}.%{attr}'
|
44
|
+
…</code></pre>
|
45
|
+
|
46
|
+
The values of the interpolations (and indeed, the name of the model) can be used in the mapping, as shown above.
|
47
|
+
|
48
|
+
h3. More complex mapping
|
49
|
+
|
50
|
+
Sometimes you might want to do something more complex than simply taking a string from the localisation data and dropping it into a particular I18n key.
|
51
|
+
SimpleARLocalizer allows multiple behaviours beyond a simple input–output mapping:
|
52
|
+
|
53
|
+
A mapping value can be specified as an @Array@, which allows the mapping of a single item of localisation data to multiple I18n keys.
|
54
|
+
|
55
|
+
<pre><code> …
|
56
|
+
'foo/bar': [
|
57
|
+
'foo.bar.baz',
|
58
|
+
'qux.quux.quuz'
|
59
|
+
]
|
60
|
+
…</code></pre>
|
61
|
+
|
62
|
+
A mapping value can also be specified as a @Hash@, with members @key@ and @proc@:
|
63
|
+
|
64
|
+
<pre><code> …
|
65
|
+
'foo/bar': { key: 'foo.bar.baz', proc: ->(v){ v.uppercase }}
|
66
|
+
…</code></pre>
|
67
|
+
|
68
|
+
This takes whatever is specified by @l10n_data[:foo][:bar]@, converts it to uppercase, and stores it in the I18n key @foo.bar.baz@.
|
69
|
+
|
70
|
+
These can also be combined, for example, as a workaround for @Model.model_name.human@ not pluralising anything unless you explicitly tell it how to do so (which is irritating).
|
71
|
+
|
72
|
+
<pre><code> …
|
73
|
+
'name': [
|
74
|
+
'activerecord.models.%{model}.one',
|
75
|
+
{ key: 'activerecord.models.%{model}.other', proc: ->(s){ s.pluralize }}
|
76
|
+
]
|
77
|
+
…
|
78
|
+
</code></pre>
|
79
|
+
|
80
|
+
Will take the inbound name and stores it in the I18n key @activerecord.models.%{model}.one@, but also stores its plural form in @activerecord.models.%{model}.other@, and saves you having to do this manually.
|
@@ -0,0 +1,103 @@
|
|
1
|
+
h1. Localisation data
|
2
|
+
|
3
|
+
Localisation data is passed to SimpleARLocalizer as a nested hash, thus:
|
4
|
+
|
5
|
+
<pre><code>SimpleARLocalizer::transform( Foo, :en, {
|
6
|
+
name: 'model name',
|
7
|
+
attributes: {
|
8
|
+
attr_one: {
|
9
|
+
name: 'attribute name',
|
10
|
+
errors: {
|
11
|
+
blank: 'You need to fill this in'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
})</code></pre>
|
16
|
+
|
17
|
+
This file quickly documents how this works, and the options that are configured by default.
|
18
|
+
|
19
|
+
Note that, by default, none of the hash members are required. Additionally, unconfigured members are simply ignored.
|
20
|
+
|
21
|
+
h2. Model name: @name@
|
22
|
+
|
23
|
+
_Mapped to @activerecord.models.%{model}@_
|
24
|
+
|
25
|
+
This is used to specify the ‘human’ name for the model being localised (accessed via @Model.model_name.human@ ), and can be specified either as a string or a hash.
|
26
|
+
Using a hash ties into "Rails’ default behaviour":http://guides.rubyonrails.org/i18n.html#translations-for-active-record-models with regard pluralisation, thus:
|
27
|
+
|
28
|
+
<pre><code>SimpleARLocalizer::transform( Foo, :en, {
|
29
|
+
name: {
|
30
|
+
one: 'foo',
|
31
|
+
two: 'foos'
|
32
|
+
}
|
33
|
+
})
|
34
|
+
|
35
|
+
Foo.model_name.human( count: 1 ) # ‘foo’
|
36
|
+
Foo.model_name.human( count: 2 ) # 'foos'
|
37
|
+
</code></pre>
|
38
|
+
|
39
|
+
SimpleARLocalizer also provides two aliases at this level: @:singular@ and @:plural@ which are mapped to @:one@ and @:other@ respectively. This is simply to make things a little clearer when defining localisations, especially who might not be quite as familiar with Rails’ I18n framework.
|
40
|
+
|
41
|
+
As such, the two statements below are equal.
|
42
|
+
|
43
|
+
<pre><code>SimpleARLocalizer::transform( Foo, :en, {
|
44
|
+
name: {
|
45
|
+
one: 'foo',
|
46
|
+
other: 'foos'
|
47
|
+
}
|
48
|
+
})
|
49
|
+
|
50
|
+
SimpleARLocalizer::transform( Foo, :en, {
|
51
|
+
name: {
|
52
|
+
singular: 'foo',
|
53
|
+
plural: 'foos'
|
54
|
+
}
|
55
|
+
})</code></pre>
|
56
|
+
|
57
|
+
h3. Side note on pluralisation
|
58
|
+
|
59
|
+
If you intend to use @Model.model_name.human( count: x )@ in your code, Rails requires that you specify at least @:one@ and @:other@ for it to work properly. That is, if you just specify a single value, it’ll not pluralise it for you.
|
60
|
+
There is a simple workaround for this in the "custom data"./custom_data.textile documentation.
|
61
|
+
|
62
|
+
h2. Generic error messages: @errors@
|
63
|
+
|
64
|
+
_Mapped to @activerecord.errors.models.%{model}@_
|
65
|
+
|
66
|
+
This takes a @hash@, and is used to specify "validation error messages":http://guides.rubyonrails.org/active_record_validations.html on a per-model basis. A list of possible keys is available in "the appropriate Rails guide":http://guides.rubyonrails.org/i18n.html#error-message-interpolation
|
67
|
+
|
68
|
+
<pre><code>SimpleARLocalizer::transform( Foo, :en, {
|
69
|
+
errors: {
|
70
|
+
blank: 'This is required',
|
71
|
+
invalid: 'That doesn’t look right to me…',
|
72
|
+
less_than: 'Must be less than %{count}'
|
73
|
+
}
|
74
|
+
})
|
75
|
+
</code></pre>
|
76
|
+
|
77
|
+
h2. Model attributes: @attributes@
|
78
|
+
|
79
|
+
*_Mapped to @activerecord.attributes.%{model}@ … kinda_*
|
80
|
+
|
81
|
+
This is a hash, where each member relates to a particular attribute of your model. In its simplest form, each value is a simple string:
|
82
|
+
|
83
|
+
<pre><code>SimpleARLocalizer::transform( Foo, :en, {
|
84
|
+
attributes: {
|
85
|
+
title: 'Title',
|
86
|
+
body: 'Body'
|
87
|
+
}
|
88
|
+
})</code></pre>
|
89
|
+
|
90
|
+
This provides localisation for the ‘human’ attribute name, accessed via @Model.human_attribute_name( attr )@
|
91
|
+
|
92
|
+
However, SimpleARLocalizer also supports per-attribute error messages, in which case the value of each hash member should itself be a Hash.
|
93
|
+
|
94
|
+
<pre><code>SimpleARLocalizer::transform( Foo, :en, {
|
95
|
+
attributes: {
|
96
|
+
title: {
|
97
|
+
name: 'Title',
|
98
|
+
errors: {
|
99
|
+
blank: 'You really need a title…'
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
})</code></pre>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'simple_ar_localizer/version'
|
2
|
+
require 'simple_ar_localizer/map'
|
3
|
+
require 'simple_ar_localizer/localizer'
|
4
|
+
|
5
|
+
module SimpleARLocalizer
|
6
|
+
|
7
|
+
# Convenience accessort to SimpleARLocalizer::Localizer::transform()
|
8
|
+
def self.transform( model_name, language, l10n_data )
|
9
|
+
|
10
|
+
Localizer.transform( model_name, language, l10n_data )
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module SimpleARLocalizer
|
4
|
+
|
5
|
+
# Localizer provides a slightly easier way of hooking into the depths of Rails’ Internationalization functionality.
|
6
|
+
#
|
7
|
+
# By default, it allows you to specify the human name (with plurality), human attribute names, and any custom error messages
|
8
|
+
# on both a per-model and per-attribute level via a simple hash… rather than having to worry about exactly where things
|
9
|
+
# get nested in .YAML files.
|
10
|
+
#
|
11
|
+
# It takes a bit of explaining to start with, but should be way nicer in the long-run =)
|
12
|
+
class Localizer
|
13
|
+
include Singleton
|
14
|
+
|
15
|
+
# Constructor logic. This should not be called directly.
|
16
|
+
def initialize
|
17
|
+
|
18
|
+
@custom_rules = {}
|
19
|
+
|
20
|
+
# if we have a custom startup hook
|
21
|
+
if defined?( Rails ) and Rails.application.config.respond_to?( :ar_localization_rules )
|
22
|
+
|
23
|
+
@custom_rules = Rails.application.config.ar_localization_rules
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
# Does the actual translation from the nicely-formatted hash, to a more Rails i18n-friendly one.
|
30
|
+
#
|
31
|
+
# === Parameters
|
32
|
+
#
|
33
|
+
# [model_name] the model we’re specifying localisations for
|
34
|
+
# [language] the ISO-639 language code of the language we’re providing a localisation for
|
35
|
+
# [L10n_data] a hash containing localisation data for the model/language combination
|
36
|
+
def self.transform( model_name, language, l10n_data )
|
37
|
+
|
38
|
+
self.instance.send( :perform_translation, model_name, language, l10n_data )
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
# Callback from self.transform that actually does the work.
|
45
|
+
#
|
46
|
+
# === Parameters
|
47
|
+
#
|
48
|
+
# [model_name] the model we’re specifying localisations for
|
49
|
+
# [language] the ISO-639 language code of the language we’re providing a localisation for
|
50
|
+
# [L10n_data] a hash containing localisation data for the model/language combination
|
51
|
+
def perform_translation( model_name, language, l10n_data )
|
52
|
+
|
53
|
+
# normalise the model name
|
54
|
+
model_name = model_name.name.underscore.to_sym if model_name.is_a?( Class )
|
55
|
+
|
56
|
+
# normalise the language, while we’re at it
|
57
|
+
language = language.to_sym unless language.is_a?( Symbol )
|
58
|
+
|
59
|
+
# compile our rules into a tree for easier matching
|
60
|
+
@rules = SimpleARLocalizer::DEFAULT_MAP.merge( @custom_rules ).deep_stringify_keys
|
61
|
+
|
62
|
+
# parse everything
|
63
|
+
parsed = deep_parse( l10n_data.deep_stringify_keys, { model: model_name })
|
64
|
+
|
65
|
+
# squish it out to a hash
|
66
|
+
hsh = {}
|
67
|
+
parsed.each{ |k,v| deep_assign( hsh, k, v ) }
|
68
|
+
|
69
|
+
# drop in the language and return
|
70
|
+
retval = {}
|
71
|
+
retval[language] = hsh
|
72
|
+
retval
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# Performs the grunt work of recursing through the inbound array and turning it into a hash where keys are the
|
77
|
+
# dotted internationalization keys, and the values are the translated value for that key.
|
78
|
+
#
|
79
|
+
# === Parameters
|
80
|
+
#
|
81
|
+
# [data_in] the current level of the hash to parse
|
82
|
+
# [replacements] a hash containing values of tokens that should be replaced when generating internationalization keys
|
83
|
+
# [curr_path] the current path within the hash for use when looking up mapping values
|
84
|
+
def deep_parse( data_in, replacements, curr_path = '' )
|
85
|
+
|
86
|
+
# start a return value
|
87
|
+
retval = {}
|
88
|
+
|
89
|
+
# find some rules that match at this level
|
90
|
+
local_paths = @rules.keys
|
91
|
+
local_paths.select!{ |p| p.starts_with?( curr_path ) } unless curr_path.blank?
|
92
|
+
|
93
|
+
# finally, strip off any trailing stuff so we only have the current stub, then sort them so wildcards go at the end
|
94
|
+
local_paths = local_paths.map{ |p| p.gsub(curr_path, '').gsub(/\/(.*)/, '') }.uniq.sort.reverse
|
95
|
+
|
96
|
+
# now, stash some replacements somewhere
|
97
|
+
local_replacements = replacements.dup
|
98
|
+
|
99
|
+
# start iterating through keys at this level
|
100
|
+
data_in.each do |key, value|
|
101
|
+
|
102
|
+
# search for candidates
|
103
|
+
candidates = local_paths.select{ |p| ((p === key) or p.starts_with?( ':' )) }
|
104
|
+
next if candidates.empty?
|
105
|
+
matched_path = candidates.first
|
106
|
+
|
107
|
+
# if we’ve matched a symbol
|
108
|
+
local_replacements[matched_path[1..-1].to_sym] = key if matched_path.starts_with?( ':' )
|
109
|
+
|
110
|
+
# if it’s a hash, recurse
|
111
|
+
if value.is_a?( Hash )
|
112
|
+
|
113
|
+
retval.merge!( deep_parse( value, local_replacements, "#{curr_path}#{matched_path}/" ))
|
114
|
+
|
115
|
+
else
|
116
|
+
|
117
|
+
# do some substitution + cast to an array (so we can do multiple at once)
|
118
|
+
full_rule = @rules["#{curr_path}#{matched_path}"]
|
119
|
+
full_rule = [ full_rule ] unless full_rule.is_a?( Array )
|
120
|
+
|
121
|
+
# and then…
|
122
|
+
full_rule.each do |r|
|
123
|
+
|
124
|
+
# allow passing in more complex rules as hashes
|
125
|
+
if r.is_a?( Hash )
|
126
|
+
|
127
|
+
value = r['proc'].call( value )
|
128
|
+
r = r['key']
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
# write it to the array
|
133
|
+
retval[ r.gsub( /%\{(\w+)\}/ ){ |m| local_replacements[ $1.to_sym ] }] = value
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
# return the result
|
142
|
+
retval
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
def deep_assign( hsh, key, data )
|
147
|
+
|
148
|
+
# prepare for some recursion fun
|
149
|
+
target = hsh
|
150
|
+
path = key.to_s.split( '.' ).map( &:to_sym )
|
151
|
+
final = path.pop
|
152
|
+
|
153
|
+
# unravel stuff a bit
|
154
|
+
path.each do |k|
|
155
|
+
|
156
|
+
target[k] = {} unless target.key?( k )
|
157
|
+
target = target[k]
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
# push the final data…
|
162
|
+
target[final] = data
|
163
|
+
|
164
|
+
# … + return
|
165
|
+
hsh
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SimpleARLocalizer
|
2
|
+
|
3
|
+
# Default mapping from inbound localisation data to I18n keys. These can be supplemented/overridden via the
|
4
|
+
# <tt>Rails.application.config.ar_localization_rules</tt> configuration variable.
|
5
|
+
DEFAULT_MAP = {
|
6
|
+
|
7
|
+
# per-model stuff
|
8
|
+
'name': 'activerecord.models.%{model}',
|
9
|
+
'name/singular': 'activerecord.models.%{model}.one',
|
10
|
+
'name/plural': 'activerecord.models.%{model}.other',
|
11
|
+
'name/:key': 'activerecord.models.%{model}.%{key}',
|
12
|
+
'errors/:error': 'activerecord.errors.models.%{model}.%{error}',
|
13
|
+
|
14
|
+
# per-attribute stuff
|
15
|
+
'attributes/:attr': 'activerecord.attributes.%{model}.%{attr}', # only specifying a name
|
16
|
+
'attributes/:attr/name': 'activerecord.attributes.%{model}.%{attr}', # verbose specification
|
17
|
+
'attributes/:attr/errors/:error': 'activerecord.errors.models.%{model}.attributes.%{attr}.%{error}'
|
18
|
+
|
19
|
+
}
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require File.expand_path('../lib/simple_ar_localizer/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
|
6
|
+
gem.name = 'simple_ar_localizer'
|
7
|
+
gem.summary = 'Easier localisation for ActiveRecord models.'
|
8
|
+
gem.description = 'Provides a (hopefully) simpler way of localising the human name, attribute names, and error message for ActiveRecord models.'
|
9
|
+
gem.version = SimpleARLocalizer::VERSION
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.require_paths = [ 'lib' ]
|
13
|
+
|
14
|
+
gem.authors = 'Jon Pearse'
|
15
|
+
gem.email = 'hello@jonpearse.net'
|
16
|
+
gem.license = 'MIT'
|
17
|
+
gem.homepage = 'https://github.com/jonpearse/simple_ar_localizer'
|
18
|
+
|
19
|
+
gem.add_dependency( 'activerecord', '~> 5.1' )
|
20
|
+
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_ar_localizer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Pearse
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-05-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.1'
|
27
|
+
description: Provides a (hopefully) simpler way of localising the human name, attribute
|
28
|
+
names, and error message for ActiveRecord models.
|
29
|
+
email: hello@jonpearse.net
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".editorconfig"
|
35
|
+
- ".gitignore"
|
36
|
+
- Gemfile
|
37
|
+
- LICENSE
|
38
|
+
- README.textile
|
39
|
+
- doc/custom_data.textile
|
40
|
+
- doc/localisation_data.textile
|
41
|
+
- lib/simple_ar_localizer.rb
|
42
|
+
- lib/simple_ar_localizer/localizer.rb
|
43
|
+
- lib/simple_ar_localizer/map.rb
|
44
|
+
- lib/simple_ar_localizer/version.rb
|
45
|
+
- simple_ar_localizer.gemspec
|
46
|
+
homepage: https://github.com/jonpearse/simple_ar_localizer
|
47
|
+
licenses:
|
48
|
+
- MIT
|
49
|
+
metadata: {}
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 2.6.14
|
67
|
+
signing_key:
|
68
|
+
specification_version: 4
|
69
|
+
summary: Easier localisation for ActiveRecord models.
|
70
|
+
test_files: []
|