i18n 1.1.1 → 1.2.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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/lib/i18n/backend.rb +1 -0
  4. data/lib/i18n/backend/base.rb +12 -1
  5. data/lib/i18n/backend/cache_file.rb +36 -0
  6. data/lib/i18n/backend/chain.rb +22 -0
  7. data/lib/i18n/backend/key_value.rb +24 -0
  8. data/lib/i18n/backend/simple.rb +1 -1
  9. data/lib/i18n/config.rb +16 -0
  10. data/lib/i18n/core_ext/hash.rb +8 -0
  11. data/lib/i18n/interpolate/ruby.rb +5 -3
  12. data/lib/i18n/version.rb +1 -1
  13. metadata +16 -52
  14. data/gemfiles/Gemfile.rails-3.2.x +0 -10
  15. data/gemfiles/Gemfile.rails-4.0.x +0 -10
  16. data/gemfiles/Gemfile.rails-4.1.x +0 -10
  17. data/gemfiles/Gemfile.rails-4.2.x +0 -10
  18. data/gemfiles/Gemfile.rails-5.0.x +0 -10
  19. data/gemfiles/Gemfile.rails-5.1.x +0 -10
  20. data/gemfiles/Gemfile.rails-master +0 -10
  21. data/test/api/all_features_test.rb +0 -58
  22. data/test/api/cascade_test.rb +0 -28
  23. data/test/api/chain_test.rb +0 -24
  24. data/test/api/fallbacks_test.rb +0 -30
  25. data/test/api/key_value_test.rb +0 -24
  26. data/test/api/memoize_test.rb +0 -56
  27. data/test/api/override_test.rb +0 -42
  28. data/test/api/pluralization_test.rb +0 -30
  29. data/test/api/simple_test.rb +0 -28
  30. data/test/backend/cache_test.rb +0 -109
  31. data/test/backend/cascade_test.rb +0 -86
  32. data/test/backend/chain_test.rb +0 -122
  33. data/test/backend/exceptions_test.rb +0 -36
  34. data/test/backend/fallbacks_test.rb +0 -211
  35. data/test/backend/interpolation_compiler_test.rb +0 -118
  36. data/test/backend/key_value_test.rb +0 -85
  37. data/test/backend/memoize_test.rb +0 -79
  38. data/test/backend/metadata_test.rb +0 -48
  39. data/test/backend/pluralization_test.rb +0 -45
  40. data/test/backend/simple_test.rb +0 -111
  41. data/test/backend/transliterator_test.rb +0 -84
  42. data/test/core_ext/hash_test.rb +0 -36
  43. data/test/gettext/api_test.rb +0 -214
  44. data/test/gettext/backend_test.rb +0 -92
  45. data/test/i18n/exceptions_test.rb +0 -117
  46. data/test/i18n/gettext_plural_keys_test.rb +0 -20
  47. data/test/i18n/interpolate_test.rb +0 -91
  48. data/test/i18n/load_path_test.rb +0 -34
  49. data/test/i18n/middleware_test.rb +0 -24
  50. data/test/i18n_test.rb +0 -462
  51. data/test/locale/fallbacks_test.rb +0 -133
  52. data/test/locale/tag/rfc4646_test.rb +0 -143
  53. data/test/locale/tag/simple_test.rb +0 -32
  54. data/test/run_all.rb +0 -20
  55. data/test/test_data/locales/de.po +0 -82
  56. data/test/test_data/locales/en.rb +0 -3
  57. data/test/test_data/locales/en.yaml +0 -3
  58. data/test/test_data/locales/en.yml +0 -3
  59. data/test/test_data/locales/invalid/empty.yml +0 -0
  60. data/test/test_data/locales/invalid/syntax.yml +0 -4
  61. data/test/test_data/locales/plurals.rb +0 -113
  62. data/test/test_helper.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e56b50c83ab6291a1321b462814b80ad73d74d01cb77c25ab6a1d948c8737afc
4
- data.tar.gz: 23d1ac1b19a36a2543e063f612170f45be6d404d2ff258c611c75be159dde98c
3
+ metadata.gz: 8f090f4664c260c453c6287eda93ccabd1681c8ca2cef077794fcc8ec32dab4f
4
+ data.tar.gz: 639643c1611bd9800407a84b1fc4c0dcf57e85e9cab85c9a4a82e56418a15a48
5
5
  SHA512:
6
- metadata.gz: b555490dcb1c101f72f04f6ce9f257070da32021906355f7ccf96ee8ef62d33fda682e75bfb634d91c13afc72fa2d6f74135721a0df40c473edb083cf0a04360
7
- data.tar.gz: 810d9280d42cf03d60d4251371bad79f602799b786660413e00b8f4d351a81c70b0ad7f4223ac276d0600721139e367b2b39a656f6d60335993bcc46d30abafb
6
+ metadata.gz: 8b9747cc4ba7e203400ed38c21a2c6e5c35b45c4283bd56e4cb608b72c3904e6117d80b11a91b97753344ac0185fae0f340e3687b26eb40a95669d0039fad6ee
7
+ data.tar.gz: 48aa51116fe7450ce06036dbd537e7711d66d755a4001bc148936573c08b74744428cf5877f757fe53fb6326d8b99f891639a31844396d9c24e1ff2477cebd1d
data/README.md CHANGED
@@ -104,6 +104,10 @@ the API definition test methods in test/api/tests.
104
104
  All other test cases (e.g. as defined in test/backend, test/core_ext) etc.
105
105
  follow the usual test setup and should be easy to grok.
106
106
 
107
+ ## More Documentation
108
+
109
+ Additional documentation can be found here: https://github.com/svenfuchs/i18n/wiki
110
+
107
111
  ## Authors
108
112
 
109
113
  * [Sven Fuchs](http://www.artweb-design.de)
@@ -5,6 +5,7 @@ module I18n
5
5
  autoload :Base, 'i18n/backend/base'
6
6
  autoload :InterpolationCompiler, 'i18n/backend/interpolation_compiler'
7
7
  autoload :Cache, 'i18n/backend/cache'
8
+ autoload :CacheFile, 'i18n/backend/cache_file'
8
9
  autoload :Cascade, 'i18n/backend/cascade'
9
10
  autoload :Chain, 'i18n/backend/chain'
10
11
  autoload :Fallbacks, 'i18n/backend/fallbacks'
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'yaml'
4
+ require 'json'
4
5
  require 'i18n/core_ext/hash'
5
6
 
6
7
  module I18n
@@ -9,7 +10,7 @@ module I18n
9
10
  include I18n::Backend::Transliterator
10
11
 
11
12
  # Accepts a list of paths to translation files. Loads translations from
12
- # plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml
13
+ # plain Ruby (*.rb), YAML files (*.yml), or JSON files (*.json). See #load_rb, #load_yml, and #load_json
13
14
  # for details.
14
15
  def load_translations(*filenames)
15
16
  filenames = I18n.load_path if filenames.empty?
@@ -235,6 +236,16 @@ module I18n
235
236
  end
236
237
  alias_method :load_yaml, :load_yml
237
238
 
239
+ # Loads a JSON translations file. The data must have locales as
240
+ # toplevel keys.
241
+ def load_json(filename)
242
+ begin
243
+ ::JSON.parse(File.read(filename))
244
+ rescue TypeError, StandardError => e
245
+ raise InvalidLocaleData.new(filename, e.inspect)
246
+ end
247
+ end
248
+
238
249
  def translate_localization_format(locale, object, format, options)
239
250
  format.to_s.gsub(/%[aAbBpP]/) do |match|
240
251
  case match
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest/sha2'
4
+
5
+ module I18n
6
+ module Backend
7
+ # Overwrites the Base load_file method to cache loaded file contents.
8
+ module CacheFile
9
+ # Optionally provide path_roots array to normalize filename paths,
10
+ # to make the cached i18n data portable across environments.
11
+ attr_accessor :path_roots
12
+
13
+ protected
14
+
15
+ # Track loaded translation files in the `i18n.load_file` scope,
16
+ # and skip loading the file if its contents are still up-to-date.
17
+ def load_file(filename)
18
+ initialized = !respond_to?(:initialized?) || initialized?
19
+ key = I18n::Backend::Flatten.escape_default_separator(normalized_path(filename))
20
+ old_mtime, old_digest = initialized && lookup(:i18n, key, :load_file)
21
+ return if (mtime = File.mtime(filename).to_i) == old_mtime ||
22
+ (digest = Digest::SHA2.file(filename).hexdigest) == old_digest
23
+ super
24
+ store_translations(:i18n, load_file: { key => [mtime, digest] })
25
+ end
26
+
27
+ # Translate absolute filename to relative path for i18n key.
28
+ def normalized_path(file)
29
+ return file unless path_roots
30
+ path = path_roots.find(&file.method(:start_with?)) ||
31
+ raise(InvalidLocaleData.new(file, 'outside expected path roots'))
32
+ file.sub(path, path_roots.index(path).to_s)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -26,6 +26,15 @@ module I18n
26
26
  self.backends = backends
27
27
  end
28
28
 
29
+ def initialized?
30
+ backends.all? do |backend|
31
+ backend.instance_eval do
32
+ return false unless initialized?
33
+ end
34
+ end
35
+ true
36
+ end
37
+
29
38
  def reload!
30
39
  backends.each { |backend| backend.reload! }
31
40
  end
@@ -74,6 +83,19 @@ module I18n
74
83
  end
75
84
 
76
85
  protected
86
+ def init_translations
87
+ backends.each do |backend|
88
+ backend.send(:init_translations)
89
+ end
90
+ end
91
+
92
+ def translations
93
+ backends.first.instance_eval do
94
+ init_translations unless initialized?
95
+ translations
96
+ end
97
+ end
98
+
77
99
  def namespace_lookup?(result, options)
78
100
  result.is_a?(Hash) && !options.has_key?(:count)
79
101
  end
@@ -76,6 +76,10 @@ module I18n
76
76
  @store, @subtrees = store, subtrees
77
77
  end
78
78
 
79
+ def initialized?
80
+ !@store.nil?
81
+ end
82
+
79
83
  def store_translations(locale, data, options = EMPTY_HASH)
80
84
  escape = options.fetch(:escape, true)
81
85
  flatten_translations(locale, data, escape, @subtrees).each do |key, value|
@@ -105,6 +109,26 @@ module I18n
105
109
 
106
110
  protected
107
111
 
112
+ # Queries the translations from the key-value store and converts
113
+ # them into a hash such as the one returned from loading the
114
+ # haml files
115
+ def translations
116
+ @translations = @store.keys.clone.map do |main_key|
117
+ main_value = JSON.decode(@store[main_key])
118
+ main_key.to_s.split(".").reverse.inject(main_value) do |value, key|
119
+ {key.to_sym => value}
120
+ end
121
+ end.inject{|hash, elem| hash.deep_merge!(elem)}.deep_symbolize_keys
122
+ end
123
+
124
+ def init_translations
125
+ # NO OP
126
+ # This call made also inside Simple Backend and accessed by
127
+ # other plugins like I18n-js and babilu and
128
+ # to use it along with the Chain backend we need to
129
+ # provide a uniform API even for protected methods :S
130
+ end
131
+
108
132
  def subtrees?
109
133
  @subtrees
110
134
  end
@@ -39,7 +39,7 @@ module I18n
39
39
  end
40
40
  locale = locale.to_sym
41
41
  translations[locale] ||= {}
42
- data = data.deep_symbolize_keys
42
+ data = data.deep_stringify_keys.deep_symbolize_keys
43
43
  translations[locale].deep_merge!(data)
44
44
  end
45
45
 
@@ -145,5 +145,21 @@ module I18n
145
145
  def enforce_available_locales=(enforce_available_locales)
146
146
  @@enforce_available_locales = enforce_available_locales
147
147
  end
148
+
149
+ # Returns the current interpolation patterns. Defaults to
150
+ # I18n::DEFAULT_INTERPOLATION_PATTERNS.
151
+ def interpolation_patterns
152
+ @@interpolation_patterns ||= I18n::DEFAULT_INTERPOLATION_PATTERNS.dup
153
+ end
154
+
155
+ # Sets the current interpolation patterns. Used to set a interpolation
156
+ # patterns.
157
+ #
158
+ # E.g. using {{}} as a placeholder like "{{hello}}, world!":
159
+ #
160
+ # I18n.config.interpolation_patterns << /\{\{(\w+)\}\}/
161
+ def interpolation_patterns=(interpolation_patterns)
162
+ @@interpolation_patterns = interpolation_patterns
163
+ end
148
164
  end
149
165
  end
@@ -17,6 +17,14 @@ class Hash
17
17
  }
18
18
  end unless Hash.method_defined?(:deep_symbolize_keys)
19
19
 
20
+ def deep_stringify_keys
21
+ inject({}) { |result, (key, value)|
22
+ value = value.deep_stringify_keys if value.is_a?(Hash)
23
+ result[key.to_s] = value
24
+ result
25
+ }
26
+ end unless Hash.method_defined?(:deep_stringify_keys)
27
+
20
28
  # deep_merge_hash! by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
21
29
  MERGER = proc do |key, v1, v2|
22
30
  Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2
@@ -2,11 +2,13 @@
2
2
  # http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
3
3
 
4
4
  module I18n
5
- INTERPOLATION_PATTERN = Regexp.union(
5
+ DEFAULT_INTERPOLATION_PATTERNS = [
6
6
  /%%/,
7
7
  /%\{(\w+)\}/, # matches placeholders like "%{foo}"
8
8
  /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%<foo>.d"
9
- )
9
+ ].freeze
10
+ INTERPOLATION_PATTERN = Regexp.union(DEFAULT_INTERPOLATION_PATTERNS)
11
+ deprecate_constant :INTERPOLATION_PATTERN if method_defined? :INTERPOLATION_PATTERN
10
12
 
11
13
  class << self
12
14
  # Return String or raises MissingInterpolationArgument exception.
@@ -18,7 +20,7 @@ module I18n
18
20
  end
19
21
 
20
22
  def interpolate_hash(string, values)
21
- string.gsub(INTERPOLATION_PATTERN) do |match|
23
+ string.gsub(Regexp.union(config.interpolation_patterns)) do |match|
22
24
  if match == '%%'
23
25
  '%'
24
26
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module I18n
4
- VERSION = "1.1.1"
4
+ VERSION = "1.2.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Fuchs
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2018-10-14 00:00:00.000000000 Z
16
+ date: 2018-12-11 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: concurrent-ruby
@@ -37,17 +37,11 @@ extra_rdoc_files: []
37
37
  files:
38
38
  - MIT-LICENSE
39
39
  - README.md
40
- - gemfiles/Gemfile.rails-3.2.x
41
- - gemfiles/Gemfile.rails-4.0.x
42
- - gemfiles/Gemfile.rails-4.1.x
43
- - gemfiles/Gemfile.rails-4.2.x
44
- - gemfiles/Gemfile.rails-5.0.x
45
- - gemfiles/Gemfile.rails-5.1.x
46
- - gemfiles/Gemfile.rails-master
47
40
  - lib/i18n.rb
48
41
  - lib/i18n/backend.rb
49
42
  - lib/i18n/backend/base.rb
50
43
  - lib/i18n/backend/cache.rb
44
+ - lib/i18n/backend/cache_file.rb
51
45
  - lib/i18n/backend/cascade.rb
52
46
  - lib/i18n/backend/chain.rb
53
47
  - lib/i18n/backend/fallbacks.rb
@@ -89,48 +83,6 @@ files:
89
83
  - lib/i18n/tests/pluralization.rb
90
84
  - lib/i18n/tests/procs.rb
91
85
  - lib/i18n/version.rb
92
- - test/api/all_features_test.rb
93
- - test/api/cascade_test.rb
94
- - test/api/chain_test.rb
95
- - test/api/fallbacks_test.rb
96
- - test/api/key_value_test.rb
97
- - test/api/memoize_test.rb
98
- - test/api/override_test.rb
99
- - test/api/pluralization_test.rb
100
- - test/api/simple_test.rb
101
- - test/backend/cache_test.rb
102
- - test/backend/cascade_test.rb
103
- - test/backend/chain_test.rb
104
- - test/backend/exceptions_test.rb
105
- - test/backend/fallbacks_test.rb
106
- - test/backend/interpolation_compiler_test.rb
107
- - test/backend/key_value_test.rb
108
- - test/backend/memoize_test.rb
109
- - test/backend/metadata_test.rb
110
- - test/backend/pluralization_test.rb
111
- - test/backend/simple_test.rb
112
- - test/backend/transliterator_test.rb
113
- - test/core_ext/hash_test.rb
114
- - test/gettext/api_test.rb
115
- - test/gettext/backend_test.rb
116
- - test/i18n/exceptions_test.rb
117
- - test/i18n/gettext_plural_keys_test.rb
118
- - test/i18n/interpolate_test.rb
119
- - test/i18n/load_path_test.rb
120
- - test/i18n/middleware_test.rb
121
- - test/i18n_test.rb
122
- - test/locale/fallbacks_test.rb
123
- - test/locale/tag/rfc4646_test.rb
124
- - test/locale/tag/simple_test.rb
125
- - test/run_all.rb
126
- - test/test_data/locales/de.po
127
- - test/test_data/locales/en.rb
128
- - test/test_data/locales/en.yaml
129
- - test/test_data/locales/en.yml
130
- - test/test_data/locales/invalid/empty.yml
131
- - test/test_data/locales/invalid/syntax.yml
132
- - test/test_data/locales/plurals.rb
133
- - test/test_helper.rb
134
86
  homepage: http://github.com/svenfuchs/i18n
135
87
  licenses:
136
88
  - MIT
@@ -139,7 +91,19 @@ metadata:
139
91
  changelog_uri: https://github.com/svenfuchs/i18n/releases
140
92
  documentation_uri: https://guides.rubyonrails.org/i18n.html
141
93
  source_code_uri: https://github.com/svenfuchs/i18n
142
- post_install_message:
94
+ post_install_message: |2+
95
+
96
+ HEADS UP! i18n 1.1 changed fallbacks to exclude default locale.
97
+ But that may break your application.
98
+
99
+ Please check your Rails app for 'config.i18n.fallbacks = true'.
100
+ If you're using I18n 1.1.x and Rails (< 6.0), this should be
101
+ 'config.i18n.fallbacks = [I18n.default_locale]'.
102
+ If not, fallbacks will be broken in your app by I18n 1.1.x.
103
+
104
+ For more info see:
105
+ https://github.com/svenfuchs/i18n/releases/tag/v1.1.0
106
+
143
107
  rdoc_options: []
144
108
  require_paths:
145
109
  - lib
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '..'
4
-
5
- gem 'activesupport', '~> 3.2.0'
6
- gem 'mocha'
7
- gem 'test_declarative'
8
- gem 'rake'
9
- gem 'minitest'
10
- gem 'oj'
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '..'
4
-
5
- gem 'activesupport', '~> 4.0.0'
6
- gem 'mocha'
7
- gem 'test_declarative'
8
- gem 'rake'
9
- gem 'minitest'
10
- gem 'oj'
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '..'
4
-
5
- gem 'activesupport', '~> 4.1.0'
6
- gem 'mocha'
7
- gem 'test_declarative'
8
- gem 'rake'
9
- gem 'minitest'
10
- gem 'oj'
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '..'
4
-
5
- gem 'activesupport', '~> 4.2.0'
6
- gem 'mocha'
7
- gem 'test_declarative'
8
- gem 'rake'
9
- gem 'minitest'
10
- gem 'oj'
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '..'
4
-
5
- gem 'activesupport', '~> 5.0.0'
6
- gem 'mocha'
7
- gem 'test_declarative'
8
- gem 'rake'
9
- gem 'minitest'
10
- gem 'oj'
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '..'
4
-
5
- gem 'activesupport', '~> 5.1.0'
6
- gem 'mocha'
7
- gem 'test_declarative'
8
- gem 'rake'
9
- gem 'minitest'
10
- gem 'oj'
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '..'
4
-
5
- gem 'activesupport', github: 'rails/rails', branch: 'master'
6
- gem 'mocha'
7
- gem 'test_declarative'
8
- gem 'rake'
9
- gem 'minitest'
10
- gem 'oj'