i18n-active_record 0.2.1 → 0.4.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 +5 -5
- data/README.md +97 -0
- data/Rakefile +8 -3
- data/lib/generators/i18n/active_record/install_generator.rb +27 -0
- data/lib/generators/i18n/active_record/templates/advanced_initializer.rb.erb +17 -0
- data/lib/generators/i18n/active_record/templates/migration.rb.erb +13 -0
- data/lib/generators/i18n/active_record/templates/simple_initializer.rb.erb +6 -0
- data/lib/i18n/active_record/version.rb +1 -1
- data/lib/i18n/backend/active_record/translation.rb +12 -0
- data/lib/i18n/backend/active_record.rb +27 -2
- data/test/active_record_test.rb +33 -0
- data/test/missing_test.rb +2 -2
- metadata +11 -8
- data/README.textile +0 -94
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d742b8d5877fc39c8855a29b4cd864732b750f3167567ced3dcd3bf2e9ad3d25
|
4
|
+
data.tar.gz: e6f0df2b6ff56a75568c44e11c7e19e6a5e161352308247e12afeb8ffd294522
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fba006f4b5feb3d33cc9917a8c487d11b33e1bdfc64dff8e78e52f909393a0ee86b5a820b674f1b69ad28223459a336dba509fd1cf7f4a9eecbcf922ba4b86c
|
7
|
+
data.tar.gz: b8e8a9b39d0d531d0cea78034372f2ac46dedfe1a66269bd9aa72738dcc82544b307222aa603dd1037874a1609f9cb592f7349de4d879aca3c4a4f74f67736d4
|
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# I18n::Backend::ActiveRecord
|
2
|
+
|
3
|
+
This repository contains the I18n ActiveRecord backend and support code that has been extracted from the "I18n": http://github.com/svenfuchs/i18n.
|
4
|
+
It is fully compatible with Rails 3, 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
|
+
## Usage
|
81
|
+
|
82
|
+
You can now use `I18n.t('Your String')` to lookup translations in the database.
|
83
|
+
|
84
|
+
## Missing Translations -> Interpolations
|
85
|
+
|
86
|
+
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.
|
87
|
+
|
88
|
+
The `interpolations` field is otherwise unused since the "value" in `Translation#value` is actually used for interpolation during actual translations.
|
89
|
+
|
90
|
+
## Examples
|
91
|
+
|
92
|
+
* http://collectiveidea.com/blog/archives/2016/05/31/beyond-yml-files-dynamic-translations/
|
93
|
+
|
94
|
+
## Maintainers
|
95
|
+
|
96
|
+
* Sven Fuchs
|
97
|
+
* Tim Masliuchenko
|
data/Rakefile
CHANGED
@@ -8,8 +8,9 @@ def execute(command)
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def bundle_options
|
11
|
-
|
12
|
-
|
11
|
+
return '' unless ENV['BUNDLE_GEMFILE']
|
12
|
+
|
13
|
+
"--gemfile #{ENV['BUNDLE_GEMFILE']}"
|
13
14
|
end
|
14
15
|
|
15
16
|
def each_database(&block)
|
@@ -33,8 +34,12 @@ namespace :bundle do
|
|
33
34
|
execute "bundle install #{bundle_options}"
|
34
35
|
end
|
35
36
|
|
37
|
+
task update: :env do
|
38
|
+
execute "bundle update #{bundle_options}"
|
39
|
+
end
|
40
|
+
|
36
41
|
task :install_all do
|
37
|
-
[nil, '3', '4', '5', '
|
42
|
+
[nil, '3', '4', '5', '6', 'head'].each do |ar|
|
38
43
|
opt = ar && "AR=#{ar}"
|
39
44
|
execute "rake bundle:install #{opt}"
|
40
45
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module ActiveRecord
|
5
|
+
module Generators
|
6
|
+
class InstallGenerator < ::ActiveRecord::Generators::Base
|
7
|
+
desc "Installs i18n-active_record and generates the necessary migrations"
|
8
|
+
|
9
|
+
argument :name, type: :string, default: 'Translation'
|
10
|
+
|
11
|
+
class_option :simple, type: :boolean, default: false, desc: 'Perform the simple setup'
|
12
|
+
|
13
|
+
source_root File.expand_path('templates', __dir__)
|
14
|
+
|
15
|
+
def copy_initializer
|
16
|
+
tpl = "#{options[:simple] ? 'simple' : 'advanced'}_initializer.rb.erb"
|
17
|
+
|
18
|
+
template tpl, 'config/initializers/i18n_active_record.rb'
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_migrations
|
22
|
+
migration_template 'migration.rb.erb', "db/migrate/create_#{table_name}.rb"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'i18n/backend/active_record'
|
2
|
+
|
3
|
+
Translation = I18n::Backend::ActiveRecord::Translation
|
4
|
+
|
5
|
+
if Translation.table_exists?
|
6
|
+
I18n.backend = I18n::Backend::ActiveRecord.new
|
7
|
+
|
8
|
+
I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Memoize)
|
9
|
+
I18n::Backend::Simple.send(:include, I18n::Backend::Memoize)
|
10
|
+
I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
|
11
|
+
|
12
|
+
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n.backend)
|
13
|
+
end
|
14
|
+
|
15
|
+
I18n::Backend::ActiveRecord.configure do |config|
|
16
|
+
# config.cleanup_with_destroy = true # defaults to false
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
2
|
+
def change
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
t.string :locale
|
5
|
+
t.string :key
|
6
|
+
t.text :value
|
7
|
+
t.text :interpolations
|
8
|
+
t.boolean :is_proc, default: false
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -75,6 +75,18 @@ module I18n
|
|
75
75
|
def available_locales
|
76
76
|
Translation.select('DISTINCT locale').to_a.map { |t| t.locale.to_sym }
|
77
77
|
end
|
78
|
+
|
79
|
+
def to_hash
|
80
|
+
Translation.all.each.with_object({}) do |t, memo|
|
81
|
+
locale_hash = (memo[t.locale.to_sym] ||= {})
|
82
|
+
keys = t.key.split('.')
|
83
|
+
keys.each.with_index.inject(locale_hash) do |iterator, (key_part, index)|
|
84
|
+
key = key_part.to_sym
|
85
|
+
iterator[key] = keys[index + 1] ? (iterator[key] || {}) : t.value
|
86
|
+
iterator[key]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
78
90
|
end
|
79
91
|
|
80
92
|
def interpolates?(key)
|
@@ -45,11 +45,36 @@ module I18n
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
def reload!
|
49
|
+
@translations = nil
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialized?
|
54
|
+
!@translations.nil?
|
55
|
+
end
|
56
|
+
|
57
|
+
def init_translations
|
58
|
+
@translations = Translation.to_hash
|
59
|
+
end
|
60
|
+
|
61
|
+
def translations(do_init: false)
|
62
|
+
init_translations if do_init || !initialized?
|
63
|
+
@translations ||= {}
|
64
|
+
end
|
65
|
+
|
48
66
|
protected
|
49
67
|
|
50
68
|
def lookup(locale, key, scope = [], options = {})
|
51
69
|
key = normalize_flat_keys(locale, key, scope, options[:separator])
|
52
|
-
|
70
|
+
if key.first == '.'
|
71
|
+
key = key[1..-1]
|
72
|
+
end
|
73
|
+
if key.last == '.'
|
74
|
+
key = key[0..-2]
|
75
|
+
end
|
76
|
+
|
77
|
+
result = if key == ''
|
53
78
|
Translation.locale(locale).all
|
54
79
|
else
|
55
80
|
Translation.locale(locale).lookup(key)
|
@@ -69,7 +94,7 @@ module I18n
|
|
69
94
|
|
70
95
|
def build_translation_hash_by_key(lookup_key, translation)
|
71
96
|
hash = {}
|
72
|
-
if lookup_key == '
|
97
|
+
if lookup_key == ''
|
73
98
|
chop_range = 0..-1
|
74
99
|
else
|
75
100
|
chop_range = (lookup_key.size + FLATTEN_SEPARATOR.size)..-1
|
data/test/active_record_test.rb
CHANGED
@@ -94,10 +94,43 @@ class I18nBackendActiveRecordTest < I18n::TestCase
|
|
94
94
|
assert_equal expected_hash, I18n.t('.')
|
95
95
|
end
|
96
96
|
|
97
|
+
test "accessing keys with a trailing/leading period" do
|
98
|
+
expected_hash = { :bar => 'bar', :baz => 'baz' }
|
99
|
+
assert_equal expected_hash, I18n.t('foo')
|
100
|
+
assert_equal expected_hash, I18n.t('.foo')
|
101
|
+
assert_equal expected_hash, I18n.t('foo.')
|
102
|
+
assert_equal expected_hash, I18n.t('.foo.')
|
103
|
+
assert_equal expected_hash, I18n.t('.foo.')
|
104
|
+
end
|
105
|
+
|
97
106
|
test "returning all keys via . when there are no keys" do
|
98
107
|
I18n.t('.') # Fixes test flakiness by loading available locales
|
99
108
|
I18n::Backend::ActiveRecord::Translation.destroy_all
|
100
109
|
|
101
110
|
assert_equal "translation missing: en.no key", I18n.t('.')
|
102
111
|
end
|
112
|
+
|
113
|
+
test "intially unitinitialized" do
|
114
|
+
refute I18n.backend.initialized?
|
115
|
+
I18n.backend.init_translations
|
116
|
+
assert I18n.backend.initialized?
|
117
|
+
I18n.backend.reload!
|
118
|
+
refute I18n.backend.initialized?
|
119
|
+
I18n.backend.init_translations
|
120
|
+
assert I18n.backend.initialized?
|
121
|
+
end
|
122
|
+
|
123
|
+
test "translations returns all translations" do
|
124
|
+
expected_hash = { :en => { :foo => { :bar => 'bar', :baz => 'baz' } } }
|
125
|
+
I18n.backend.init_translations
|
126
|
+
assert_equal expected_hash, I18n.backend.send(:translations)
|
127
|
+
assert I18n.backend.initialized?
|
128
|
+
end
|
129
|
+
|
130
|
+
test "translations initialized with do_init argument" do
|
131
|
+
expected_hash = { :en => { :foo => { :bar => 'bar', :baz => 'baz' } } }
|
132
|
+
refute I18n.backend.initialized?
|
133
|
+
assert_equal expected_hash, I18n.backend.send(:translations, { do_init: true })
|
134
|
+
assert I18n.backend.initialized?
|
135
|
+
end
|
103
136
|
end
|
data/test/missing_test.rb
CHANGED
@@ -51,7 +51,7 @@ class I18nActiveRecordMissingTest < I18n::TestCase
|
|
51
51
|
|
52
52
|
test "creates a stub when a custom separator is used" do
|
53
53
|
I18n.t('foo|baz', :separator => '|')
|
54
|
-
I18n::Backend::ActiveRecord::Translation.locale(:en).lookup("foo.baz").first.
|
54
|
+
I18n::Backend::ActiveRecord::Translation.locale(:en).lookup("foo.baz").first.update(:value => 'baz!')
|
55
55
|
assert_equal 'baz!', I18n.t('foo|baz', :separator => '|')
|
56
56
|
end
|
57
57
|
|
@@ -64,7 +64,7 @@ class I18nActiveRecordMissingTest < I18n::TestCase
|
|
64
64
|
test "creates a stub when a custom separator is used and the key contains the flatten separator (a dot character)" do
|
65
65
|
key = 'foo|baz.zab'
|
66
66
|
I18n.t(key, :separator => '|')
|
67
|
-
I18n::Backend::ActiveRecord::Translation.locale(:en).lookup("foo.baz\001zab").first.
|
67
|
+
I18n::Backend::ActiveRecord::Translation.locale(:en).lookup("foo.baz\001zab").first.update(:value => 'baz!')
|
68
68
|
assert_equal 'baz!', I18n.t(key, :separator => '|')
|
69
69
|
end
|
70
70
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-active_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Fuchs
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -46,8 +46,12 @@ extensions: []
|
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
48
|
- MIT-LICENSE
|
49
|
-
- README.
|
49
|
+
- README.md
|
50
50
|
- Rakefile
|
51
|
+
- lib/generators/i18n/active_record/install_generator.rb
|
52
|
+
- lib/generators/i18n/active_record/templates/advanced_initializer.rb.erb
|
53
|
+
- lib/generators/i18n/active_record/templates/migration.rb.erb
|
54
|
+
- lib/generators/i18n/active_record/templates/simple_initializer.rb.erb
|
51
55
|
- lib/i18n/active_record.rb
|
52
56
|
- lib/i18n/active_record/version.rb
|
53
57
|
- lib/i18n/backend/active_record.rb
|
@@ -63,7 +67,7 @@ homepage: http://github.com/svenfuchs/i18n-active_record
|
|
63
67
|
licenses:
|
64
68
|
- MIT
|
65
69
|
metadata: {}
|
66
|
-
post_install_message:
|
70
|
+
post_install_message:
|
67
71
|
rdoc_options: []
|
68
72
|
require_paths:
|
69
73
|
- lib
|
@@ -78,9 +82,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
82
|
- !ruby/object:Gem::Version
|
79
83
|
version: '0'
|
80
84
|
requirements: []
|
81
|
-
|
82
|
-
|
83
|
-
signing_key:
|
85
|
+
rubygems_version: 3.1.4
|
86
|
+
signing_key:
|
84
87
|
specification_version: 4
|
85
88
|
summary: I18n ActiveRecord backend
|
86
89
|
test_files: []
|
data/README.textile
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
h1. I18n::Backend::ActiveRecord
|
2
|
-
|
3
|
-
!https://travis-ci.org/svenfuchs/i18n-active_record.svg?branch=master!:https://travis-ci.org/svenfuchs/i18n-active_record
|
4
|
-
|
5
|
-
This repository contains the I18n ActiveRecord backend and support code that has been extracted from the "I18n":http://github.com/svenfuchs/i18n.
|
6
|
-
It is fully compatible with Rails 3, 4 and 5
|
7
|
-
|
8
|
-
h2. Installation
|
9
|
-
|
10
|
-
For Bundler put the following in your Gemfile:
|
11
|
-
|
12
|
-
<pre>
|
13
|
-
gem 'i18n-active_record', :require => 'i18n/active_record'
|
14
|
-
</pre>
|
15
|
-
|
16
|
-
Next create a active record model named @Translation@ with the Rails Generator.
|
17
|
-
Your migration should look like this:
|
18
|
-
|
19
|
-
<pre>
|
20
|
-
class CreateTranslations < ActiveRecord::Migration
|
21
|
-
def self.up
|
22
|
-
create_table :translations do |t|
|
23
|
-
t.string :locale
|
24
|
-
t.string :key
|
25
|
-
t.text :value
|
26
|
-
t.text :interpolations
|
27
|
-
t.boolean :is_proc, :default => false
|
28
|
-
|
29
|
-
t.timestamps
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.down
|
34
|
-
drop_table :translations
|
35
|
-
end
|
36
|
-
end
|
37
|
-
</pre>
|
38
|
-
|
39
|
-
With this translation model you will be able to manage your translation, and add new translations or languages through
|
40
|
-
it.
|
41
|
-
|
42
|
-
To load @I18n::Backend::ActiveRecord@ into your Rails application, create a new file in *config/initializers* named *locale.rb*.
|
43
|
-
|
44
|
-
A simple configuration for your locale.rb could look like this:
|
45
|
-
|
46
|
-
<pre>
|
47
|
-
require 'i18n/backend/active_record'
|
48
|
-
I18n.backend = I18n::Backend::ActiveRecord.new
|
49
|
-
</pre>
|
50
|
-
|
51
|
-
A more advanced example (Thanks Moritz), which uses YAML files and ActiveRecord for lookups:
|
52
|
-
|
53
|
-
<pre>
|
54
|
-
require 'i18n/backend/active_record'
|
55
|
-
|
56
|
-
Translation = I18n::Backend::ActiveRecord::Translation
|
57
|
-
|
58
|
-
if Translation.table_exists?
|
59
|
-
I18n.backend = I18n::Backend::ActiveRecord.new
|
60
|
-
|
61
|
-
I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Memoize)
|
62
|
-
I18n::Backend::Simple.send(:include, I18n::Backend::Memoize)
|
63
|
-
I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
|
64
|
-
|
65
|
-
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n.backend)
|
66
|
-
end
|
67
|
-
</pre>
|
68
|
-
|
69
|
-
You may also configure whether the ActiveRecord backend should use @destroy@ or @delete@ when cleaning up internally.
|
70
|
-
|
71
|
-
<pre>
|
72
|
-
I18n::Backend::ActiveRecord.configure do |config|
|
73
|
-
config.cleanup_with_destroy = true # defaults to false
|
74
|
-
end
|
75
|
-
</pre>
|
76
|
-
|
77
|
-
h2. Usage
|
78
|
-
|
79
|
-
You can now use @I18n.t('Your String')@ to lookup translations in the database.
|
80
|
-
|
81
|
-
h2. Missing Translations -> Interpolations
|
82
|
-
|
83
|
-
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.
|
84
|
-
|
85
|
-
The interpolations field is otherwise unused since the "value" in Translation.value is actually used for interpolation during actual translations.
|
86
|
-
|
87
|
-
h2. Examples
|
88
|
-
|
89
|
-
* http://collectiveidea.com/blog/archives/2016/05/31/beyond-yml-files-dynamic-translations/
|
90
|
-
|
91
|
-
h2. Maintainers
|
92
|
-
|
93
|
-
* Sven Fuchs
|
94
|
-
* Tim Maslyuchenko
|