i18n_multitenant 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eb35d5985cf6d4869028f5370b636016011059be
4
+ data.tar.gz: b47174e2024be883a1a0b25a63c6678acb7af154
5
+ SHA512:
6
+ metadata.gz: 80ccc546b9f990086bbabcf9213d0ec2d0a47afed41f7092b4a8572e44a889658a7cc31f2a6d1cdcca9e6b27e6119f1cc63053b2547b3b8e6e5dcacf684054e3
7
+ data.tar.gz: 849ea28b7d3fb78006cddbff7e4f6f53aeb1da8f5d551dc1f2c925d7f03c4f7598fc930011132c1473897b79170a62a68a7506221641313531668f09ca23d9b8
@@ -0,0 +1,3 @@
1
+ ## I18nMultitenant 1.0.0 (2017-01-11) ##
2
+
3
+ * Initial Version.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2017 Máximo Mussini
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,99 @@
1
+ # I18nMultitenant
2
+
3
+ This gem extend the standard i18n backend (I18n::Backend::Simple) to introduce {Conventions over configuration}[http://en.wikipedia.org/wiki/Convention_over_configuration] about 2 new types of locale files.
4
+
5
+ WARNING: Have to rethink parts of the implementation which seem to reimplement I18n::Backend::Fallbacks without this nice to have convention over configuration "algorithm".
6
+
7
+ So you can also write this with a little help of i18n's basic fallback module (at bootstrap process):
8
+
9
+ ```ruby
10
+ I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
11
+
12
+ I18n.fallbacks[:es] = [:es]
13
+ I18n.fallbacks[:tenant_name_es] = [:tenant_name_es, :es]
14
+ ```
15
+
16
+ This gem will just save you these lines through a convenient convention over configuration "algorithm".
17
+
18
+ ## Conventions
19
+
20
+ ### *_formal.yml
21
+
22
+ Given you want to offer your users the option to be addressed formally or informally through a {session locale switch}[https://github.com/Applicat/i18n_multitenant#backend-locale-switch]:
23
+
24
+ Then this is a {DRY}[http://en.wikipedia.org/wiki/Don%27t_repeat_yourself] solution for the workaround about having duplication of de locales in the de_formal namespace even though informal & formal translation are the same.
25
+
26
+ This locale file will own all translations from its base *.yml and lets you override them through the same translation keys (except of the deviant locale namespaces de and de_formal at the beginning).
27
+
28
+ ### #{locales_path}/tenants/your_tenant_name/**/your_tenant_name.yml
29
+
30
+ Given you want to have tenant specific locales through a {session locale switch}[https://github.com/Applicat/i18n_multitenant#backend-locale-switch]:
31
+
32
+ <b>Precondition:</b> Assure that you recursively add locale files to i18n's locale path e.g. through your Rails 3 application.rb:
33
+
34
+ config.i18n.load_path +# Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
35
+
36
+ You may like to enable multi tenancy for your rails application by deploying the repository branch on multiple servers each with a different tenant-specific application constants file to load by a config system like {rails_config}[https://github.com/railsjedi/rails_config] at initialization.
37
+
38
+ This locale file owns all translations from its base *.yml and optional *_formal.yml under #{locales_path}/tenants/your-tenant-name/ (recurively) and lets you override them through the same translation keys (except of the deviant locale namespaces de and de_formal at the beginning).
39
+
40
+ ## Installation
41
+
42
+ Add this to your Gemfile and run the +bundle+ command.
43
+
44
+ gem "i18n_multitenant"
45
+
46
+ The gem (# engine) will automatically set the backend for your Rails application.
47
+
48
+ OPTIONAL: you have to manually set the i18n backend for your non-rails Ruby application:
49
+
50
+ I18n.backend # I18nMultitenant::Backend.new
51
+
52
+ ## Backend Locale Switch
53
+
54
+ Available since version 0.0.3.
55
+
56
+ <b>Initializer</b>
57
+
58
+ To initialize the global default locale based on current configuration.
59
+
60
+ Put this file for instance under config/initializer/multi_tenancy.rb
61
+
62
+ I18n.locale # I18n.backend.available_locale(
63
+ formal: Settings.address_formally, tenant: Settings.tenant.name
64
+ )
65
+
66
+ Settings is a constant for your settings brought by most popular rack app config system: https://github.com/railsjedi/rails_config
67
+
68
+ I18n.locale # I18n.backend.available_locale(formal: Settings.formal, tenant: Settings.tenant.name)
69
+
70
+ <b>Controller</b>
71
+
72
+ Dependency: https://github.com/iain/http_accept_language
73
+
74
+ class ApplicationController
75
+ AVAILABLE_LOCALES # %w{de en}
76
+
77
+ before_filter :set_locale
78
+
79
+ private
80
+
81
+ def set_locale
82
+ if user_signed_in?
83
+ # use of devise helper methods: user_signed_in?, current_user
84
+ I18n.locale # current_user.language # you have to add a language string column to your schema
85
+ else
86
+ locale # request.preferred_language_from AVAILABLE_LOCALES
87
+ locale ||# request.compatible_language_from AVAILABLE_LOCALES
88
+ locale ||# I18n.default_locale
89
+
90
+ unless Settings.tenant.name ## 'global'
91
+ locale # ("#{Settings.tenant.name.downcase.strip.tr(' ', '_')}_#{locale}").to_sym
92
+ end
93
+ end
94
+
95
+ I18n.locale # I18n.backend.available_locale(
96
+ base_locale: locale, formal: Settings.formal_address, tenant: Settings.tenant.name
97
+ )
98
+ end
99
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env rake
2
+ require 'rspec/core/rake_task'
3
+
4
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
5
+ require 'i18n_multitenant/version'
6
+
7
+ name = 'i18n_multitenant'
8
+ version = I18nMultitenant::VERSION
9
+
10
+ task :gem => :build
11
+ task :build do
12
+ system "gem build #{name}.gemspec"
13
+ end
14
+
15
+ task :install => :build do
16
+ system "sudo gem install #{name}-#{version}.gem"
17
+ end
18
+
19
+ task :release => :build do
20
+ system "git tag -a v#{version} -m 'Tagging #{version}'"
21
+ system 'git push --tags'
22
+ system "gem push #{name}-#{version}.gem"
23
+ system "rm #{name}-#{version}.gem"
24
+ end
25
+
26
+ RSpec::Core::RakeTask.new(:spec)
27
+ task :default => :spec
@@ -0,0 +1,3 @@
1
+ require 'i18n_multitenant/version'
2
+ require 'i18n_multitenant/backend'
3
+ require 'i18n_multitenant/railtie' if defined?(Rails::Railtie)
@@ -0,0 +1,134 @@
1
+ require 'i18n'
2
+
3
+ class I18nMultitenant::Backend < I18n::Backend::Simple
4
+ FORMAL_FILENAME_PATTERN = /_formal\.[a-zA-Z]+$/
5
+ FORMAL_LOCALE_PATTERN = /_formal$/
6
+
7
+ TENANT_FILENAME_PATTERN = /tenants/
8
+ TENANT_LOCALE_PATTERN = /tenants$/
9
+
10
+ attr_accessor :filenames
11
+
12
+ # Accepts a list of paths to translation files. Loads translations from
13
+ # plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml
14
+ # for details.
15
+ def load_translations(*filenames)
16
+ filenames = I18n.load_path if filenames.empty?
17
+
18
+ @filenames = filenames.flatten
19
+
20
+ @filenames.each { |filename| load_file(filename) }
21
+ end
22
+
23
+ def available_locale(options = {})
24
+ options.assert_valid_keys(:base_locale, :formal, :tenant) if options.respond_to? :assert_valid_keys
25
+
26
+ base_locale = options[:base_locale] || I18n.default_locale
27
+ formal = options[:formal] || false
28
+ tenant = (options[:tenant] || '').downcase.strip.tr(' ', '_')
29
+
30
+ deepest_available_locale = nil
31
+
32
+ # take last / deepest available locale of possible combinations
33
+ variant_index = -1
34
+
35
+ [
36
+ [
37
+ (formal && tenant),
38
+ [tenant, base_locale, 'formal']
39
+ ],
40
+ [
41
+ formal && tenant && available_locales.include?([tenant, base_locale].join('_').to_sym) &&
42
+ available_locales.include?([base_locale, 'formal'].join('_').to_sym),
43
+ [tenant, base_locale, 'formal']
44
+ ],
45
+ [tenant, [tenant, base_locale]],
46
+ [formal, [base_locale, 'formal']],
47
+ [true, [base_locale]],
48
+ ].each do |variant|
49
+ variant_index += 1
50
+
51
+ next unless variant[0]
52
+
53
+ if available_locales.include?(variant[1].join('_').to_sym) || (variant_index == 1 && [tenant, base_locale, 'formal'] == variant[1])
54
+ deepest_available_locale = variant[1].join('_').to_sym
55
+ end
56
+
57
+ break if deepest_available_locale
58
+ end
59
+
60
+ deepest_available_locale || I18n.default_locale
61
+ end
62
+
63
+ protected
64
+
65
+ # Looks up a translation from the translations hash. Returns nil if
66
+ # eiher key is nil, or locale, scope or key do not exist as a key in the
67
+ # nested translations hash. Splits keys or scopes containing dots
68
+ # into multiple keys, i.e. <tt>currency.format</tt> is regarded the same as
69
+ # <tt>%w(currency format)</tt>.
70
+ def lookup(locale, key, scope = [], options = {})
71
+ init_translations unless initialized?
72
+
73
+ # only formal address: [:de, :de_formal]
74
+ # only multi tenancy: [:de, :tenant_name_de]
75
+ # formal address & multi tenancy: [:de, :tenant_name_de, :de_formal, :tenant_name_de_formal]
76
+
77
+ locales = []
78
+
79
+ base_locale = locale.to_s.gsub(FORMAL_LOCALE_PATTERN, '')
80
+
81
+ tenant = tenant_from_locale?(locale)
82
+ base_locale.gsub!(/^#{tenant}_/, '') if tenant
83
+
84
+ locales << base_locale.to_sym
85
+
86
+ if locale.to_s.match(FORMAL_LOCALE_PATTERN) && tenant && locale.to_s.match(/^#{tenant}_/)
87
+ locales << locale.to_s.gsub(FORMAL_LOCALE_PATTERN, '').to_sym
88
+ locales << locale.to_s.gsub(/^#{tenant}_/, '').to_sym
89
+ end
90
+
91
+ locales << locale unless locales.include?(locale)
92
+
93
+ entry, last_entry = nil, nil
94
+
95
+ locales.each do |locale|
96
+ keys = I18n.normalize_keys(locale, key, scope, options[:separator])
97
+
98
+ entry = keys.inject(translations) do |result, _key|
99
+ _key = _key.to_sym
100
+
101
+ unless result.is_a?(Hash) && result.has_key?(_key)
102
+ nil
103
+ else
104
+ result = result[_key]
105
+ result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
106
+ result
107
+ end
108
+ end
109
+
110
+ if entry.nil?
111
+ entry = last_entry
112
+ else
113
+ last_entry = entry
114
+ end
115
+ end
116
+
117
+ entry
118
+ end
119
+
120
+ private
121
+
122
+ def tenant_from_locale?(locale)
123
+ tenant = locale.to_s.gsub(FORMAL_LOCALE_PATTERN, '').split('_')
124
+
125
+ if tenant.length > 2
126
+ tenant.pop # pop languages like de
127
+ tenant = tenant.join('_')
128
+ else
129
+ tenant = nil
130
+ end
131
+
132
+ tenant && @filenames.select{|f| f.match("/tenants/#{tenant}/")}.any? ? tenant : nil
133
+ end
134
+ end
@@ -0,0 +1,6 @@
1
+ class I18nMultitenant::Railtie < ::Rails::Railtie
2
+ config.before_initialize do |app|
3
+ I18n.config.enforce_available_locales = false
4
+ I18n.backend = I18nMultitenant::Backend.new
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module I18nMultitenant
2
+ VERSION = '0.0.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ de:
2
+ formal_available: 'Du'
3
+ formal_unavailable: 'Du'
4
+ de_formal_formal_available: 'Du'
@@ -0,0 +1,3 @@
1
+ de_formal:
2
+ formal_available: 'Sie'
3
+ de_formal_formal_available: 'Sie'
@@ -0,0 +1,4 @@
1
+ de:
2
+ devise:
3
+ example: 'Dein Beispiel'
4
+ informal_example: 'Dein anderes Beispiel'
@@ -0,0 +1,4 @@
1
+ de_formal:
2
+ devise:
3
+ example: Ihr Beispiel
4
+ examples: Ihre Beispiele
@@ -0,0 +1,2 @@
1
+ en:
2
+ example: 'Dummy'
@@ -0,0 +1,2 @@
1
+ another_tenant_name_fr_formal:
2
+ formal_available: 'jamais vous'
@@ -0,0 +1,3 @@
1
+ your_tenant_name_de_formal:
2
+ devise:
3
+ example: Ihr formelles Beispiel
@@ -0,0 +1,3 @@
1
+ your_tenant_name_de:
2
+ formal_available: 'Du auch'
3
+ formal_unavailable_again: 'Du auch wieder'
@@ -0,0 +1,2 @@
1
+ your_tenant_name_de_formal:
2
+ formal_available: 'Sie auch'
@@ -0,0 +1,2 @@
1
+ your_tenant_name_en:
2
+ example: 'Dummy change'
@@ -0,0 +1,204 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe I18nMultitenant::Backend do
4
+ before :all do
5
+ I18n.config.enforce_available_locales = false
6
+ I18n.default_locale = :de
7
+ I18n.locale = I18n.default_locale
8
+ end
9
+
10
+ describe '#lookup' do
11
+ include_context :all_locale_file_constellations
12
+
13
+ before :all do
14
+ I18n.backend = I18nMultitenant::Backend.new
15
+ end
16
+
17
+ context 'default' do
18
+ context 'formal translation available' do
19
+ context 'returns the translation' do
20
+ Given { I18n.locale = :de }
21
+ Then { I18n.t('formal_available') == 'Du' }
22
+ Then { I18n.t('de_formal_formal_available') == 'Du' }
23
+ end
24
+
25
+ context 'returns the formal translation' do
26
+ Given { I18n.locale = :de_formal }
27
+ Then { I18n.t('formal_available') == 'Sie' }
28
+ Then { I18n.t('de_formal_formal_available') == 'Sie' }
29
+ end
30
+ end
31
+
32
+ context 'formal translation unavailable' do
33
+ context 'inerits the informal locales from :de' do
34
+ Given { I18n.locale = :de_formal }
35
+ Then { I18n.t('formal_unavailable') == 'Du' }
36
+ end
37
+ end
38
+ end
39
+
40
+ context 'tenant-specific' do
41
+ context 'formal translation available' do
42
+ context 'returns the translation' do
43
+ Given { I18n.locale = :your_tenant_name_de }
44
+ Then { I18n.t('formal_available') == 'Du auch' }
45
+ Then { I18n.t('de_formal_formal_available') == 'Du' }
46
+ end
47
+
48
+ context 'returns the formal translation' do
49
+ Given { I18n.locale = :your_tenant_name_de_formal }
50
+ Then { I18n.t('formal_available') == 'Sie auch' }
51
+ Then { I18n.t('de_formal_formal_available') == 'Sie' }
52
+ end
53
+ end
54
+
55
+ context 'formal translation unavailable' do
56
+ context 'inerits the informal locales from :de and :your_tenant_name_de' do
57
+ Given { I18n.locale = :your_tenant_name_de_formal }
58
+ Then { I18n.t('formal_unavailable') == 'Du' }
59
+ Then { I18n.t('formal_unavailable_again') == 'Du auch wieder' }
60
+ end
61
+ end
62
+
63
+ context 'formal translation available for locale without base locale' do
64
+ context 'inits the locale without inheritation of unavailable base locale' do
65
+ Given { I18n.locale = :another_tenant_name_fr_formal }
66
+ Then { I18n.t('formal_available') == 'jamais vous' }
67
+ end
68
+ end
69
+ end
70
+
71
+ context 'locale files with more than 1 dot' do
72
+ context 'principally works' do
73
+ Given { I18n.locale = :de }
74
+ Then { I18n.t('devise.example') == 'Dein Beispiel' }
75
+ end
76
+
77
+ context 'principally works' do
78
+ Given { I18n.locale = :de_formal }
79
+ Then { I18n.t('devise.example') == 'Ihr Beispiel' }
80
+ end
81
+
82
+ context 'principally works tenant' do
83
+ Given { I18n.locale = :your_tenant_name_de_formal }
84
+ Then { I18n.t('devise.informal_example') == 'Dein anderes Beispiel' } # devise.de.yml
85
+ Then { I18n.t('devise.examples') == 'Ihre Beispiele' } # devise.de_formal.yml
86
+ Then { I18n.t('devise.example') == 'Ihr formelles Beispiel' } # tenants/your_tenant_name/devise.your_tenant_name_de_formal.yml
87
+ end
88
+ end
89
+ end
90
+
91
+ describe '.available_locale' do
92
+ context 'any locale' do
93
+ before :all do
94
+ I18n.load_path = [
95
+ File.expand_path('../../../fixtures/de.yml', __FILE__),
96
+ File.expand_path('../../../fixtures/en.yml', __FILE__)
97
+ ]
98
+ end
99
+
100
+ # .available_locale any locale principally works
101
+ it 'principally works' do
102
+ I18n.backend = I18nMultitenant::Backend.new
103
+
104
+ [
105
+ [{}, :de],
106
+ [{base_locale: :en}, :en],
107
+ [{base_locale: :unavailable}, :de],
108
+ [{tenant: 'Your Tenant Name'}, :de],
109
+ [{formal: true, tenant: 'Your Tenant Name'}, :de],
110
+ [{formal: true, tenant: 'Unavailable Tenant Name'}, :de]
111
+ ].each do |variant|
112
+ actual = I18n.backend.available_locale(variant.first)
113
+ expect(actual).to(
114
+ be(variant.last),
115
+ "input #{variant.first.inspect} should result in the output: #{variant.last.inspect} but got #{actual.inspect}"
116
+ )
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'any formal locale' do
122
+ before :all do
123
+ I18n.load_path = [
124
+ File.expand_path('../../../fixtures/de.yml', __FILE__),
125
+ File.expand_path('../../../fixtures/de_formal.yml', __FILE__)
126
+ ]
127
+ end
128
+
129
+ it 'principally works' do
130
+ I18n.backend = I18nMultitenant::Backend.new
131
+
132
+ [
133
+ [{formal: true}, :de_formal],
134
+ [{formal: true, tenant: 'Your Tenant Name'}, :de_formal]
135
+ ].each do |variant|
136
+ actual = I18n.backend.available_locale(variant.first)
137
+ expect(actual).to(
138
+ be(variant.last),
139
+ "input #{variant.first.inspect} should result in the output: #{variant.last.inspect} but got #{actual.inspect}"
140
+ )
141
+ end
142
+ end
143
+ end
144
+
145
+ context 'any formal locale plus tenant specific locale' do
146
+ before :all do
147
+ I18n.load_path = [
148
+ File.expand_path('../../../fixtures/de.yml', __FILE__),
149
+ File.expand_path('../../../fixtures/de_formal.yml', __FILE__),
150
+ File.expand_path('../../../fixtures/tenants/your_tenant_name/your_tenant_name_de.yml', __FILE__),
151
+ File.expand_path('../../../fixtures/tenants/your_tenant_name/your_tenant_name_en.yml', __FILE__)
152
+ ]
153
+ end
154
+
155
+ it 'principally works' do
156
+ I18n.backend = I18nMultitenant::Backend.new
157
+
158
+ [
159
+ [{formal: true}, :de_formal],
160
+ # should be :your_tenant_name_de_formal even though there is no :your_tenant_name_de_formal file
161
+ # but the base file :de_formal to inherit from
162
+ [{formal: true, tenant: 'Your Tenant Name'}, :your_tenant_name_de_formal],
163
+ [{base_locale: :en, formal: true, tenant: 'Your Tenant Name'}, :your_tenant_name_en]
164
+ ].each do |variant|
165
+ actual = I18n.backend.available_locale(variant.first)
166
+ expect(actual).to(
167
+ be(variant.last),
168
+ "input #{variant.first.inspect} should result in the output: #{variant.last.inspect} but got #{actual.inspect}"
169
+ )
170
+ end
171
+ end
172
+ end
173
+
174
+ context 'any formal tenant-specific locale' do
175
+ include_context :all_locale_file_constellations
176
+
177
+ it 'principally works' do
178
+ I18n.backend = I18nMultitenant::Backend.new
179
+ end
180
+ end
181
+
182
+ context 'tenant has special locale without an equivalent base locale' do
183
+ before :all do
184
+ I18n.load_path = [
185
+ File.expand_path('../../../fixtures/tenants/your_tenant_name/your_tenant_name_de_formal.yml', __FILE__)
186
+ ]
187
+ end
188
+
189
+ it 'principally works' do
190
+ I18n.backend = I18nMultitenant::Backend.new
191
+
192
+ [
193
+ [{base_locale: :de, formal: true, tenant: 'Your Tenant Name'}, :your_tenant_name_de_formal]
194
+ ].each do |variant|
195
+ actual = I18n.backend.available_locale(variant.first)
196
+ expect(actual).to(
197
+ be(variant.last),
198
+ "input #{variant.first.inspect} should result in the output: #{variant.last.inspect} but got #{actual.inspect}"
199
+ )
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ if ENV['CODECLIMATE_REPO_TOKEN']
3
+ require 'codeclimate-test-reporter'
4
+ CodeClimate::TestReporter.start
5
+ end
6
+
7
+ require 'rspec/given'
8
+ require 'pry'
9
+ require 'i18n_multitenant'
10
+
11
+ RSpec.configure do |config|
12
+ config.raise_errors_for_deprecations!
13
+ config.expose_dsl_globally = false
14
+ end
15
+
16
+ # Load Support files
17
+ Dir['./spec/support/**/*.rb'].each do |f|
18
+ require f
19
+ end
@@ -0,0 +1,14 @@
1
+ RSpec.shared_context :all_locale_file_constellations do
2
+ before :all do
3
+ I18n.load_path = [
4
+ File.expand_path('../../../fixtures/de.yml', __FILE__),
5
+ File.expand_path('../../../fixtures/de_formal.yml', __FILE__),
6
+ File.expand_path('../../../fixtures/tenants/your_tenant_name/your_tenant_name_de.yml', __FILE__),
7
+ File.expand_path('../../../fixtures/tenants/your_tenant_name/your_tenant_name_de_formal.yml', __FILE__),
8
+ File.expand_path('../../../fixtures/tenants/another_tenant_name/another_tenant_name_fr_formal.yml', __FILE__),
9
+ File.expand_path('../../../fixtures/devise.de.yml', __FILE__),
10
+ File.expand_path('../../../fixtures/devise.de_formal.yml', __FILE__),
11
+ File.expand_path('../../../fixtures/tenants/your_tenant_name/devise.your_tenant_name_de_formal.yml', __FILE__),
12
+ ]
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: i18n_multitenant
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Máximo Mussini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: i18n
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: I18nMultitenant allows you to specify translations that are tenant-specific,
28
+ falling back to the base locale.
29
+ email:
30
+ - maximomussini@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CHANGELOG.md
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - lib/i18n_multitenant.rb
40
+ - lib/i18n_multitenant/backend.rb
41
+ - lib/i18n_multitenant/railtie.rb
42
+ - lib/i18n_multitenant/version.rb
43
+ - spec/fixtures/de.yml
44
+ - spec/fixtures/de_formal.yml
45
+ - spec/fixtures/devise.de.yml
46
+ - spec/fixtures/devise.de_formal.yml
47
+ - spec/fixtures/en.yml
48
+ - spec/fixtures/tenants/another_tenant_name/another_tenant_name_fr_formal.yml
49
+ - spec/fixtures/tenants/your_tenant_name/devise.your_tenant_name_de_formal.yml
50
+ - spec/fixtures/tenants/your_tenant_name/your_tenant_name_de.yml
51
+ - spec/fixtures/tenants/your_tenant_name/your_tenant_name_de_formal.yml
52
+ - spec/fixtures/tenants/your_tenant_name/your_tenant_name_en.yml
53
+ - spec/lib/i18n_multitenant/backend_spec.rb
54
+ - spec/spec_helper.rb
55
+ - spec/support/shared_contexts/all_locale_file_constellations.rb
56
+ homepage: https://github.com/ElMassimo/i18n_multitenant
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options:
62
+ - "--charset=UTF-8"
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 2.0.0
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.5.1
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Translation for multi-tenant applications.
81
+ test_files:
82
+ - spec/fixtures/de.yml
83
+ - spec/fixtures/de_formal.yml
84
+ - spec/fixtures/devise.de.yml
85
+ - spec/fixtures/devise.de_formal.yml
86
+ - spec/fixtures/en.yml
87
+ - spec/fixtures/tenants/another_tenant_name/another_tenant_name_fr_formal.yml
88
+ - spec/fixtures/tenants/your_tenant_name/devise.your_tenant_name_de_formal.yml
89
+ - spec/fixtures/tenants/your_tenant_name/your_tenant_name_de.yml
90
+ - spec/fixtures/tenants/your_tenant_name/your_tenant_name_de_formal.yml
91
+ - spec/fixtures/tenants/your_tenant_name/your_tenant_name_en.yml
92
+ - spec/lib/i18n_multitenant/backend_spec.rb
93
+ - spec/spec_helper.rb
94
+ - spec/support/shared_contexts/all_locale_file_constellations.rb