i18n-active_record 0.3.0 → 1.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.
- checksums.yaml +4 -4
- data/README.md +140 -0
- data/Rakefile +3 -52
- data/lib/generators/i18n/active_record/install_generator.rb +4 -2
- data/lib/generators/i18n/active_record/templates/advanced_initializer.rb.erb +1 -0
- data/lib/generators/i18n/active_record/templates/migration.rb.erb +6 -10
- data/lib/generators/i18n/active_record/templates/simple_initializer.rb.erb +1 -0
- data/lib/i18n/active_record/version.rb +3 -1
- data/lib/i18n/active_record.rb +2 -0
- data/lib/i18n/backend/active_record/configuration.rb +4 -1
- data/lib/i18n/backend/active_record/missing.rb +11 -8
- data/lib/i18n/backend/active_record/store_procs.rb +6 -5
- data/lib/i18n/backend/active_record/translation.rb +27 -7
- data/lib/i18n/backend/active_record.rb +89 -60
- data/test/active_record_test.rb +142 -79
- data/test/api_test.rb +4 -1
- data/test/missing_test.rb +85 -48
- data/test/test_helper.rb +51 -39
- metadata +91 -7
- data/README.textile +0 -109
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 402118f9fb5b5b88dec6745249ded8e131b509c3bb4b8b35e5857182c85e6ca8
|
4
|
+
data.tar.gz: f120411a8ffc00c065ef50eda91d32515e23f51d6e4125184513c5a34496edb5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f36d522e0792d4c5460fe9d7b3af69d2fa27817f2f2ecd58eb18ecdcea13012e542bfe4022d2e27c18f454107e63c1406450c3d709830caeb1c33f1a0b2997b3
|
7
|
+
data.tar.gz: 7ee1bec18a25efbad1fbec55e89b061b050cfdf2fc51c2453f6dee559ad71bf60ab8c5d8397900c4d87be82dff59f830e494c427c42214d60469c047d06c08fc
|
data/README.md
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
# I18n::Backend::ActiveRecord [](https://github.com/rubocop/rubocop) [](https://github.com/svenfuchs/i18n-active_record/actions) [](https://github.com/svenfuchs/i18n-active_record/actions)
|
2
|
+
|
3
|
+
This repository contains the I18n ActiveRecord backend and support code that has been extracted from the `I18n` gem: http://github.com/svenfuchs/i18n.
|
4
|
+
It is fully compatible with Rails 4, 5 and 6.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
For Bundler put the following in your Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'i18n-active_record', require: 'i18n/active_record'
|
12
|
+
```
|
13
|
+
|
14
|
+
After updating your bundle, run the installer
|
15
|
+
|
16
|
+
$ rails g i18n:active_record:install
|
17
|
+
|
18
|
+
It creates a migration:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
class CreateTranslations < ActiveRecord::Migration
|
22
|
+
def change
|
23
|
+
create_table :translations do |t|
|
24
|
+
t.string :locale
|
25
|
+
t.string :key
|
26
|
+
t.text :value
|
27
|
+
t.text :interpolations
|
28
|
+
t.boolean :is_proc, default: false
|
29
|
+
|
30
|
+
t.timestamps
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
To specify table name use:
|
37
|
+
|
38
|
+
$ rails g i18n:active_record:install MyTranslation
|
39
|
+
|
40
|
+
With the translation model you will be able to manage your translation, and add new translations or languages through
|
41
|
+
it.
|
42
|
+
|
43
|
+
By default the installer creates a new file in `config/initializers` named `i18n_active_record.rb` with the following content.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
require 'i18n/backend/active_record'
|
47
|
+
|
48
|
+
Translation = I18n::Backend::ActiveRecord::Translation
|
49
|
+
|
50
|
+
if Translation.table_exists?
|
51
|
+
I18n.backend = I18n::Backend::ActiveRecord.new
|
52
|
+
|
53
|
+
I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Memoize)
|
54
|
+
I18n::Backend::Simple.send(:include, I18n::Backend::Memoize)
|
55
|
+
I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
|
56
|
+
|
57
|
+
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n.backend)
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
To perform a simpler installation use:
|
62
|
+
|
63
|
+
$ rails g i18n:active_record:install --simple
|
64
|
+
|
65
|
+
It generates:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
require 'i18n/backend/active_record'
|
69
|
+
I18n.backend = I18n::Backend::ActiveRecord.new
|
70
|
+
```
|
71
|
+
|
72
|
+
You may also configure whether the ActiveRecord backend should use `destroy` or `delete` when cleaning up internally.
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
I18n::Backend::ActiveRecord.configure do |config|
|
76
|
+
config.cleanup_with_destroy = true # defaults to false
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
To configure the ActiveRecord backend to cache translations(might be useful in production) use:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
I18n::Backend::ActiveRecord.configure do |config|
|
84
|
+
config.cache_translations = true # defaults to false
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
## Usage
|
89
|
+
|
90
|
+
You can now use `I18n.t('Your String')` to lookup translations in the database.
|
91
|
+
|
92
|
+
## Missing Translations
|
93
|
+
|
94
|
+
### Usage
|
95
|
+
|
96
|
+
In order to make the `I18n::Backend::ActiveRecord::Missing` module working correctly pluralization rules should be configured properly.
|
97
|
+
The `i18n.plural.keys` translation key should be present in any of the backends.
|
98
|
+
See https://github.com/svenfuchs/i18n-active_record/blob/master/lib/i18n/backend/active_record/missing.rb for more information.
|
99
|
+
|
100
|
+
```yaml
|
101
|
+
en:
|
102
|
+
i18n:
|
103
|
+
plural:
|
104
|
+
keys:
|
105
|
+
- :zero
|
106
|
+
- :one
|
107
|
+
- :other
|
108
|
+
```
|
109
|
+
|
110
|
+
### Interpolations
|
111
|
+
|
112
|
+
The `interpolations` field in the `translations` table is used by `I18n::Backend::ActiveRecord::Missing` to store the interpolations seen the first time this Translation was requested. This will help translators understand what interpolations to expect, and thus to include when providing the translations.
|
113
|
+
|
114
|
+
The `interpolations` field is otherwise unused since the "value" in `Translation#value` is actually used for interpolation during actual translations.
|
115
|
+
|
116
|
+
## Examples
|
117
|
+
|
118
|
+
* http://collectiveidea.com/blog/archives/2016/05/31/beyond-yml-files-dynamic-translations/
|
119
|
+
|
120
|
+
## Contributing
|
121
|
+
|
122
|
+
### Test suite
|
123
|
+
|
124
|
+
The test suite can be run with:
|
125
|
+
|
126
|
+
bundle exec rake
|
127
|
+
|
128
|
+
By default it runs the tests for SQLite database, to specify a database the `DB` env variable can be used:
|
129
|
+
|
130
|
+
DB=postgres bundle exec rake
|
131
|
+
DB=mysql bundle exec rake
|
132
|
+
|
133
|
+
To run tests for a specific rails version see [Appraisal](https://github.com/thoughtbot/appraisal):
|
134
|
+
|
135
|
+
bundle exec appraisal rails-4 rake test
|
136
|
+
|
137
|
+
## Maintainers
|
138
|
+
|
139
|
+
* Sven Fuchs
|
140
|
+
* Tim Masliuchenko
|
data/Rakefile
CHANGED
@@ -1,61 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'rake/testtask'
|
3
4
|
require 'bundler/gem_tasks'
|
4
5
|
|
5
|
-
|
6
|
-
puts command
|
7
|
-
system command
|
8
|
-
end
|
9
|
-
|
10
|
-
def bundle_options
|
11
|
-
opt = ''
|
12
|
-
opt += "--gemfile #{ENV['BUNDLE_GEMFILE']}" if ENV['BUNDLE_GEMFILE']
|
13
|
-
end
|
14
|
-
|
15
|
-
def each_database(&block)
|
16
|
-
['sqlite', 'postgres', 'mysql'].each &block
|
17
|
-
end
|
18
|
-
|
19
|
-
namespace :bundle do
|
20
|
-
task :env do
|
21
|
-
ar = ENV['AR'].to_s
|
22
|
-
|
23
|
-
next if ar.empty?
|
24
|
-
|
25
|
-
gemfile = "gemfiles/Gemfile.rails_#{ar}"
|
26
|
-
raise "Cannot find gemfile at #{gemfile}" unless File.exist?(gemfile)
|
27
|
-
|
28
|
-
ENV['BUNDLE_GEMFILE'] = gemfile
|
29
|
-
puts "Using gemfile: #{gemfile}"
|
30
|
-
end
|
31
|
-
|
32
|
-
task install: :env do
|
33
|
-
execute "bundle install #{bundle_options}"
|
34
|
-
end
|
35
|
-
|
36
|
-
task :install_all do
|
37
|
-
[nil, '3', '4', '5', 'master'].each do |ar|
|
38
|
-
opt = ar && "AR=#{ar}"
|
39
|
-
execute "rake bundle:install #{opt}"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
task :test do
|
45
|
-
each_database { |db| execute "rake #{db}:test" }
|
46
|
-
end
|
47
|
-
|
48
|
-
Rake::TestTask.new :_test do |t|
|
6
|
+
Rake::TestTask.new :test do |t|
|
49
7
|
t.libs << 'test'
|
50
8
|
t.pattern = 'test/**/*_test.rb'
|
51
9
|
t.verbose = false
|
52
10
|
end
|
53
11
|
|
54
|
-
each_database do |db|
|
55
|
-
namespace db do
|
56
|
-
task(:env) { ENV['DB'] = db }
|
57
|
-
task test: ['env', 'bundle:env', '_test']
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
12
|
task default: :test
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails/generators/active_record'
|
2
4
|
|
3
5
|
module I18n
|
4
6
|
module ActiveRecord
|
5
7
|
module Generators
|
6
8
|
class InstallGenerator < ::ActiveRecord::Generators::Base
|
7
|
-
desc
|
9
|
+
desc 'Installs i18n-active_record and generates the necessary migrations'
|
8
10
|
|
9
11
|
argument :name, type: :string, default: 'Translation'
|
10
12
|
|
@@ -19,7 +21,7 @@ module I18n
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def create_migrations
|
22
|
-
migration_template 'migration.rb.erb',
|
24
|
+
migration_template 'migration.rb.erb', "db/migrate/create_#{table_name}.rb"
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -1,17 +1,13 @@
|
|
1
|
-
class
|
2
|
-
def
|
3
|
-
create_table :<%=
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
2
|
+
def change
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
4
|
t.string :locale
|
5
5
|
t.string :key
|
6
|
-
t.text
|
7
|
-
t.text
|
8
|
-
t.boolean :is_proc, :
|
6
|
+
t.text :value
|
7
|
+
t.text :interpolations
|
8
|
+
t.boolean :is_proc, default: false
|
9
9
|
|
10
10
|
t.timestamps
|
11
11
|
end
|
12
12
|
end
|
13
|
-
|
14
|
-
def self.down
|
15
|
-
drop_table :<%= name.tableize %>
|
16
|
-
end
|
17
13
|
end
|
data/lib/i18n/active_record.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module I18n
|
2
4
|
module Backend
|
3
5
|
class ActiveRecord
|
4
6
|
class Configuration
|
5
|
-
attr_accessor :cleanup_with_destroy
|
7
|
+
attr_accessor :cleanup_with_destroy, :cache_translations
|
6
8
|
|
7
9
|
def initialize
|
8
10
|
@cleanup_with_destroy = false
|
11
|
+
@cache_translations = false
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This extension stores translation stub records for missing translations to
|
2
4
|
# the database.
|
3
5
|
#
|
@@ -36,27 +38,28 @@ module I18n
|
|
36
38
|
include Flatten
|
37
39
|
|
38
40
|
def store_default_translations(locale, key, options = {})
|
39
|
-
count, scope,
|
41
|
+
count, scope, _, separator = options.values_at(:count, :scope, :default, :separator)
|
40
42
|
separator ||= I18n.default_separator
|
41
43
|
key = normalize_flat_keys(locale, key, scope, separator)
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
return if ActiveRecord::Translation.locale(locale).lookup(key).exists?
|
46
|
+
|
47
|
+
interpolations = options.keys - I18n::RESERVED_KEYS
|
48
|
+
keys = count ? I18n.t('i18n.plural.keys', locale: locale).map { |k| [key, k].join(FLATTEN_SEPARATOR) } : [key]
|
49
|
+
keys.each { |k| store_default_translation(locale, k, interpolations) }
|
48
50
|
end
|
49
51
|
|
50
52
|
def store_default_translation(locale, key, interpolations)
|
51
|
-
translation = ActiveRecord::Translation.new :
|
53
|
+
translation = ActiveRecord::Translation.new locale: locale.to_s, key: key
|
52
54
|
translation.interpolations = interpolations
|
53
55
|
translation.save
|
54
56
|
end
|
55
57
|
|
56
58
|
def translate(locale, key, options = {})
|
57
59
|
result = catch(:exception) { super }
|
60
|
+
|
58
61
|
if result.is_a?(I18n::MissingTranslation)
|
59
|
-
|
62
|
+
store_default_translations(locale, key, options)
|
60
63
|
throw(:exception, result)
|
61
64
|
else
|
62
65
|
result
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This module is intended to be mixed into the ActiveRecord backend to allow
|
2
4
|
# storing Ruby Procs as translation values in the database.
|
3
5
|
#
|
@@ -21,13 +23,13 @@ module I18n
|
|
21
23
|
module Backend
|
22
24
|
class ActiveRecord
|
23
25
|
module StoreProcs
|
24
|
-
def value=(
|
25
|
-
case
|
26
|
+
def value=(val)
|
27
|
+
case val
|
26
28
|
when Proc
|
27
|
-
write_attribute(:value,
|
29
|
+
write_attribute(:value, val.to_ruby)
|
28
30
|
write_attribute(:is_proc, true)
|
29
31
|
else
|
30
|
-
write_attribute(:value,
|
32
|
+
write_attribute(:value, val)
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
@@ -36,4 +38,3 @@ module I18n
|
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
39
|
-
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
|
3
5
|
module I18n
|
@@ -53,19 +55,20 @@ module I18n
|
|
53
55
|
|
54
56
|
serialize :value
|
55
57
|
serialize :interpolations, Array
|
58
|
+
after_commit :invalidate_translations_cache
|
56
59
|
|
57
60
|
class << self
|
58
61
|
def locale(locale)
|
59
|
-
where(:
|
62
|
+
where(locale: locale.to_s)
|
60
63
|
end
|
61
64
|
|
62
65
|
def lookup(keys, *separator)
|
63
66
|
column_name = connection.quote_column_name('key')
|
64
|
-
keys = Array(keys).map!
|
67
|
+
keys = Array(keys).map!(&:to_s)
|
65
68
|
|
66
69
|
unless separator.empty?
|
67
|
-
warn
|
68
|
-
|
70
|
+
warn '[DEPRECATION] Giving a separator to Translation.lookup is deprecated. ' \
|
71
|
+
'You can change the internal separator by overwriting FLATTEN_SEPARATOR.'
|
69
72
|
end
|
70
73
|
|
71
74
|
namespace = "#{keys.last}#{I18n::Backend::Flatten::FLATTEN_SEPARATOR}%"
|
@@ -75,10 +78,22 @@ module I18n
|
|
75
78
|
def available_locales
|
76
79
|
Translation.select('DISTINCT locale').to_a.map { |t| t.locale.to_sym }
|
77
80
|
end
|
81
|
+
|
82
|
+
def to_hash
|
83
|
+
Translation.all.each.with_object({}) do |t, memo|
|
84
|
+
locale_hash = (memo[t.locale.to_sym] ||= {})
|
85
|
+
keys = t.key.split('.')
|
86
|
+
keys.each.with_index.inject(locale_hash) do |iterator, (key_part, index)|
|
87
|
+
key = key_part.to_sym
|
88
|
+
iterator[key] = keys[index + 1] ? (iterator[key] || {}) : t.value
|
89
|
+
iterator[key] # rubocop:disable Lint/UnmodifiedReduceAccumulator
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
78
93
|
end
|
79
94
|
|
80
95
|
def interpolates?(key)
|
81
|
-
|
96
|
+
interpolations&.include?(key)
|
82
97
|
end
|
83
98
|
|
84
99
|
def value
|
@@ -95,14 +110,19 @@ module I18n
|
|
95
110
|
end
|
96
111
|
|
97
112
|
def value=(value)
|
98
|
-
|
113
|
+
case value
|
114
|
+
when false
|
99
115
|
value = FALSY_CHAR
|
100
|
-
|
116
|
+
when true
|
101
117
|
value = TRUTHY_CHAR
|
102
118
|
end
|
103
119
|
|
104
120
|
write_attribute(:value, value)
|
105
121
|
end
|
122
|
+
|
123
|
+
def invalidate_translations_cache
|
124
|
+
I18n.backend.reload! if I18n::Backend::ActiveRecord.config.cache_translations
|
125
|
+
end
|
106
126
|
end
|
107
127
|
end
|
108
128
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'i18n/backend/base'
|
2
4
|
require 'i18n/backend/active_record/translation'
|
3
5
|
|
@@ -9,6 +11,9 @@ module I18n
|
|
9
11
|
autoload :Translation, 'i18n/backend/active_record/translation'
|
10
12
|
autoload :Configuration, 'i18n/backend/active_record/configuration'
|
11
13
|
|
14
|
+
include Base
|
15
|
+
include Flatten
|
16
|
+
|
12
17
|
class << self
|
13
18
|
def configure
|
14
19
|
yield(config) if block_given?
|
@@ -19,85 +24,109 @@ module I18n
|
|
19
24
|
end
|
20
25
|
end
|
21
26
|
|
22
|
-
|
23
|
-
|
27
|
+
def initialize(*args)
|
28
|
+
super
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
Translation.available_locales
|
28
|
-
rescue ::ActiveRecord::StatementInvalid
|
29
|
-
[]
|
30
|
-
end
|
31
|
-
end
|
30
|
+
reload!
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
def available_locales
|
34
|
+
Translation.available_locales
|
35
|
+
rescue ::ActiveRecord::StatementInvalid
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
|
39
|
+
def store_translations(locale, data, options = {})
|
40
|
+
escape = options.fetch(:escape, true)
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
else
|
41
|
-
translation.delete_all
|
42
|
-
end
|
42
|
+
flatten_translations(locale, data, escape, false).each do |key, value|
|
43
|
+
translation = Translation.locale(locale).lookup(expand_keys(key))
|
43
44
|
|
44
|
-
|
45
|
+
if self.class.config.cleanup_with_destroy
|
46
|
+
translation.destroy_all
|
47
|
+
else
|
48
|
+
translation.delete_all
|
45
49
|
end
|
50
|
+
|
51
|
+
Translation.create(locale: locale.to_s, key: key.to_s, value: value)
|
46
52
|
end
|
47
53
|
|
54
|
+
reload! if self.class.config.cache_translations
|
55
|
+
end
|
56
|
+
|
57
|
+
def reload!
|
58
|
+
@translations = nil
|
59
|
+
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialized?
|
64
|
+
!@translations.nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
def init_translations
|
68
|
+
@translations = Translation.to_hash
|
69
|
+
end
|
70
|
+
|
71
|
+
def translations(do_init: false)
|
72
|
+
init_translations if do_init || !initialized?
|
73
|
+
@translations ||= {}
|
74
|
+
end
|
75
|
+
|
48
76
|
protected
|
49
77
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
if key.last == '.'
|
56
|
-
key = key[0..-2]
|
57
|
-
end
|
78
|
+
def lookup(locale, key, scope = [], options = {})
|
79
|
+
key = normalize_flat_keys(locale, key, scope, options[:separator])
|
80
|
+
key = key[1..-1] if key.first == '.'
|
81
|
+
key = key[0..-2] if key.last == '.'
|
58
82
|
|
59
|
-
|
60
|
-
|
61
|
-
else
|
62
|
-
Translation.locale(locale).lookup(key)
|
63
|
-
end
|
83
|
+
if self.class.config.cache_translations
|
84
|
+
keys = ([locale] + key.split(I18n::Backend::Flatten::FLATTEN_SEPARATOR)).map(&:to_sym)
|
64
85
|
|
65
|
-
|
66
|
-
nil
|
67
|
-
elsif result.first.key == key
|
68
|
-
result.first.value
|
69
|
-
else
|
70
|
-
result = result.inject({}) do |hash, translation|
|
71
|
-
hash.deep_merge build_translation_hash_by_key(key, translation)
|
72
|
-
end
|
73
|
-
result.deep_symbolize_keys
|
74
|
-
end
|
86
|
+
return translations.dig(*keys)
|
75
87
|
end
|
76
88
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
else
|
82
|
-
chop_range = (lookup_key.size + FLATTEN_SEPARATOR.size)..-1
|
83
|
-
end
|
84
|
-
translation_nested_keys = translation.key.slice(chop_range).split(FLATTEN_SEPARATOR)
|
85
|
-
translation_nested_keys.each.with_index.inject(hash) do |iterator, (key, index)|
|
86
|
-
iterator[key] = translation_nested_keys[index + 1] ? {} : translation.value
|
87
|
-
iterator[key]
|
88
|
-
end
|
89
|
-
hash
|
89
|
+
result = if key == ''
|
90
|
+
Translation.locale(locale).all
|
91
|
+
else
|
92
|
+
Translation.locale(locale).lookup(key)
|
90
93
|
end
|
91
94
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
95
|
+
if result.empty?
|
96
|
+
nil
|
97
|
+
elsif result.first.key == key
|
98
|
+
result.first.value
|
99
|
+
else
|
100
|
+
result = result.inject({}) do |hash, translation|
|
101
|
+
hash.deep_merge build_translation_hash_by_key(key, translation)
|
96
102
|
end
|
103
|
+
result.deep_symbolize_keys
|
97
104
|
end
|
98
105
|
end
|
99
106
|
|
100
|
-
|
107
|
+
def build_translation_hash_by_key(lookup_key, translation)
|
108
|
+
hash = {}
|
109
|
+
|
110
|
+
chop_range = if lookup_key == ''
|
111
|
+
0..-1
|
112
|
+
else
|
113
|
+
(lookup_key.size + FLATTEN_SEPARATOR.size)..-1
|
114
|
+
end
|
115
|
+
translation_nested_keys = translation.key.slice(chop_range).split(FLATTEN_SEPARATOR)
|
116
|
+
translation_nested_keys.each.with_index.inject(hash) do |iterator, (key, index)|
|
117
|
+
iterator[key] = translation_nested_keys[index + 1] ? {} : translation.value
|
118
|
+
iterator[key]
|
119
|
+
end
|
120
|
+
|
121
|
+
hash
|
122
|
+
end
|
123
|
+
|
124
|
+
# For a key :'foo.bar.baz' return ['foo', 'foo.bar', 'foo.bar.baz']
|
125
|
+
def expand_keys(key)
|
126
|
+
key.to_s.split(FLATTEN_SEPARATOR).inject([]) do |keys, k|
|
127
|
+
keys << [keys.last, k].compact.join(FLATTEN_SEPARATOR)
|
128
|
+
end
|
129
|
+
end
|
101
130
|
end
|
102
131
|
end
|
103
132
|
end
|