i18n-active_record 0.2.1 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 82f11d7fde969b3ef11eee86da2995a54d9f5c2c
4
- data.tar.gz: fb23e1d54a386e6b856323cd1f222d9e0766b39d
2
+ SHA256:
3
+ metadata.gz: d742b8d5877fc39c8855a29b4cd864732b750f3167567ced3dcd3bf2e9ad3d25
4
+ data.tar.gz: e6f0df2b6ff56a75568c44e11c7e19e6a5e161352308247e12afeb8ffd294522
5
5
  SHA512:
6
- metadata.gz: b135f6d2c44c8e36c4856b60c287788d63b753dfe0991765062d4b416dfb587ef2b9e3e6ebae0b89fe9640017e4c57ecf78e6b566b4a871dbc5d14c1caea56fc
7
- data.tar.gz: 49a3c2fc3b68f94298355a22ffe4547e3b8693ee2cf3f91faa2707e87bbfcc6e3ef259c25aab9363a8dfad0beec81627ebf06cfc543ea0f02fd7d78c63c33604
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
- opt = ''
12
- opt += "--gemfile #{ENV['BUNDLE_GEMFILE']}" if ENV['BUNDLE_GEMFILE']
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', 'master'].each do |ar|
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
@@ -0,0 +1,6 @@
1
+ require 'i18n/backend/active_record'
2
+ I18n.backend = I18n::Backend::ActiveRecord.new
3
+
4
+ I18n::Backend::ActiveRecord.configure do |config|
5
+ # config.cleanup_with_destroy = true # defaults to false
6
+ end
@@ -1,5 +1,5 @@
1
1
  module I18n
2
2
  module ActiveRecord
3
- VERSION = '0.2.1'
3
+ VERSION = '0.4.1'
4
4
  end
5
5
  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
- result = if key == '.'
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
@@ -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.update_attributes(:value => 'baz!')
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.update_attributes(:value => 'baz!')
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.2.1
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: 2017-11-17 00:00:00.000000000 Z
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.textile
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
- rubyforge_project: "[none]"
82
- rubygems_version: 2.5.2
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