vagrant-unbundled 2.2.18.0 → 2.2.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/Gemfile.lock +6 -6
  4. data/contrib/zsh/generate_zsh_completion.rb +2 -2
  5. data/lib/vagrant/errors.rb +8 -0
  6. data/plugins/commands/upload/command.rb +1 -1
  7. data/plugins/guests/atomic/guest.rb +1 -1
  8. data/plugins/guests/coreos/cap/configure_networks.rb +65 -0
  9. data/plugins/guests/darwin/cap/mount_smb_shared_folder.rb +6 -3
  10. data/plugins/guests/suse/cap/halt.rb +5 -1
  11. data/plugins/guests/windows/cap/rsync.rb +5 -1
  12. data/plugins/hosts/darwin/cap/path.rb +4 -0
  13. data/plugins/hosts/darwin/cap/version.rb +23 -0
  14. data/plugins/hosts/darwin/plugin.rb +5 -0
  15. data/plugins/hosts/windows/cap/ssh.rb +1 -1
  16. data/plugins/providers/virtualbox/action/network.rb +39 -2
  17. data/plugins/provisioners/chef/cap/freebsd/chef_installed.rb +5 -3
  18. data/plugins/provisioners/chef/cap/linux/chef_installed.rb +5 -3
  19. data/plugins/provisioners/chef/cap/omnios/chef_installed.rb +7 -5
  20. data/plugins/provisioners/chef/cap/windows/chef_installed.rb +3 -2
  21. data/templates/locales/en.yml +25 -0
  22. data/vagrant.gemspec +1 -1
  23. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/CONTRIBUTING.md +23 -0
  24. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/CONTRIBUTORS.md +140 -0
  25. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/LICENSE.md +20 -0
  26. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/README.md +492 -0
  27. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/data/cacert.pem +3232 -0
  28. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/excon.gemspec +45 -0
  29. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/connection.rb +599 -0
  30. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/constants.rb +172 -0
  31. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/error.rb +229 -0
  32. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/extensions/uri.rb +34 -0
  33. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/headers.rb +85 -0
  34. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/instrumentors/logging_instrumentor.rb +48 -0
  35. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/instrumentors/standard_instrumentor.rb +21 -0
  36. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/base.rb +31 -0
  37. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/capture_cookies.rb +32 -0
  38. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/decompress.rb +44 -0
  39. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/escape_path.rb +12 -0
  40. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/expects.rb +25 -0
  41. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/idempotent.rb +57 -0
  42. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/instrumentor.rb +49 -0
  43. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/mock.rb +61 -0
  44. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/redirect_follower.rb +87 -0
  45. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/response_parser.rb +16 -0
  46. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/pretty_printer.rb +39 -0
  47. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/response.rb +234 -0
  48. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/socket.rb +297 -0
  49. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/ssl_socket.rb +194 -0
  50. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/plugin/server/exec.rb +26 -0
  51. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/plugin/server/puma.rb +23 -0
  52. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/plugin/server/unicorn.rb +40 -0
  53. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/plugin/server/webrick.rb +26 -0
  54. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/server.rb +106 -0
  55. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/unix_socket.rb +42 -0
  56. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/utils.rb +143 -0
  57. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/version.rb +4 -0
  58. data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon.rb +255 -0
  59. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/MIT-LICENSE +20 -0
  60. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/README.md +122 -0
  61. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/base.rb +289 -0
  62. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/cache.rb +113 -0
  63. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/cache_file.rb +36 -0
  64. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/cascade.rb +56 -0
  65. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/chain.rb +130 -0
  66. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/fallbacks.rb +97 -0
  67. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/flatten.rb +118 -0
  68. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/gettext.rb +85 -0
  69. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/interpolation_compiler.rb +123 -0
  70. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/key_value.rb +206 -0
  71. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/memoize.rb +54 -0
  72. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/metadata.rb +71 -0
  73. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/pluralization.rb +55 -0
  74. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/simple.rb +108 -0
  75. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/transliterator.rb +108 -0
  76. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend.rb +21 -0
  77. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/config.rb +165 -0
  78. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/core_ext/hash.rb +59 -0
  79. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/exceptions.rb +111 -0
  80. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/gettext/helpers.rb +75 -0
  81. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/gettext/po_parser.rb +329 -0
  82. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/gettext.rb +28 -0
  83. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/interpolate/ruby.rb +39 -0
  84. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/fallbacks.rb +99 -0
  85. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/tag/parents.rb +24 -0
  86. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/tag/rfc4646.rb +74 -0
  87. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/tag/simple.rb +39 -0
  88. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/tag.rb +28 -0
  89. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale.rb +8 -0
  90. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/middleware.rb +17 -0
  91. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/basics.rb +60 -0
  92. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/defaults.rb +52 -0
  93. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/interpolation.rb +163 -0
  94. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/link.rb +66 -0
  95. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization/date.rb +117 -0
  96. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization/date_time.rb +103 -0
  97. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization/procs.rb +117 -0
  98. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization/time.rb +103 -0
  99. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization.rb +19 -0
  100. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/lookup.rb +81 -0
  101. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/pluralization.rb +35 -0
  102. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/procs.rb +60 -0
  103. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests.rb +14 -0
  104. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/version.rb +5 -0
  105. data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n.rb +415 -0
  106. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Code-of-Conduct.md +73 -0
  107. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Contributing.md +132 -0
  108. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/History.md +269 -0
  109. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Licence.md +25 -0
  110. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Manifest.txt +31 -0
  111. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/README.rdoc +194 -0
  112. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Rakefile +270 -0
  113. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/type/columnar.rb +57 -0
  114. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/type.rb +634 -0
  115. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/_columnar.rb +137 -0
  116. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/cache.rb +58 -0
  117. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/columnar.rb +3 -0
  118. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/container.rb +96 -0
  119. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/deprecations.rb +36 -0
  120. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/full.rb +19 -0
  121. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/loader.rb +159 -0
  122. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/logger.rb +37 -0
  123. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/registry.rb +90 -0
  124. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types.rb +233 -0
  125. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime-types.rb +3 -0
  126. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/bad-fixtures/malformed +9 -0
  127. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/fixture/json.json +1 -0
  128. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/fixture/old-data +9 -0
  129. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/fixture/yaml.yaml +55 -0
  130. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/minitest_helper.rb +11 -0
  131. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_type.rb +621 -0
  132. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types.rb +169 -0
  133. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types_cache.rb +118 -0
  134. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types_class.rb +159 -0
  135. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types_lazy.rb +49 -0
  136. data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types_loader.rb +32 -0
  137. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Code-of-Conduct.md +75 -0
  138. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Contributing.md +241 -0
  139. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/History.md +494 -0
  140. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Licence.md +24 -0
  141. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Manifest.txt +34 -0
  142. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/README.md +73 -0
  143. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Rakefile +155 -0
  144. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/content_type_mime.db +878 -0
  145. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/ext_mime.db +1198 -0
  146. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime-types.json +1 -0
  147. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.content_type.column +2376 -0
  148. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.docs.column +2376 -0
  149. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.encoding.column +2376 -0
  150. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.flags.column +2376 -0
  151. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.friendly.column +2376 -0
  152. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.pext.column +2376 -0
  153. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.use_instead.column +2376 -0
  154. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.xrefs.column +2376 -0
  155. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/lib/mime/types/data.rb +21 -0
  156. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/lib/mime-types-data.rb +3 -0
  157. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/application.yaml +17254 -0
  158. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/audio.yaml +1716 -0
  159. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/chemical.yaml +71 -0
  160. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/conference.yaml +9 -0
  161. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/drawing.yaml +15 -0
  162. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/font.yaml +65 -0
  163. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/image.yaml +1251 -0
  164. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/message.yaml +200 -0
  165. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/model.yaml +390 -0
  166. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/multipart.yaml +179 -0
  167. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/provisional-standard-types.yaml +129 -0
  168. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/text.yaml +1166 -0
  169. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/video.yaml +1121 -0
  170. data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/world.yaml +8 -0
  171. data/vendor/bundle/ruby/3.0.0/specifications/excon-0.89.0.gemspec +58 -0
  172. data/vendor/bundle/ruby/3.0.0/specifications/i18n-1.8.11.gemspec +32 -0
  173. data/vendor/bundle/ruby/3.0.0/specifications/mime-types-3.4.1.gemspec +63 -0
  174. data/vendor/bundle/ruby/3.0.0/specifications/mime-types-data-3.2021.1115.gemspec +54 -0
  175. data/version.txt +1 -1
  176. metadata +157 -4
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ # I18n locale fallbacks are useful when you want your application to use
4
+ # translations from other locales when translations for the current locale are
5
+ # missing. E.g. you might want to use :en translations when translations in
6
+ # your applications main locale :de are missing.
7
+ #
8
+ # To enable locale fallbacks you can simply include the Fallbacks module to
9
+ # the Simple backend - or whatever other backend you are using:
10
+ #
11
+ # I18n::Backend::Simple.include(I18n::Backend::Fallbacks)
12
+ module I18n
13
+ @@fallbacks = nil
14
+
15
+ class << self
16
+ # Returns the current fallbacks implementation. Defaults to +I18n::Locale::Fallbacks+.
17
+ def fallbacks
18
+ @@fallbacks ||= I18n::Locale::Fallbacks.new
19
+ Thread.current[:i18n_fallbacks] || @@fallbacks
20
+ end
21
+
22
+ # Sets the current fallbacks implementation. Use this to set a different fallbacks implementation.
23
+ def fallbacks=(fallbacks)
24
+ @@fallbacks = fallbacks.is_a?(Array) ? I18n::Locale::Fallbacks.new(fallbacks) : fallbacks
25
+ Thread.current[:i18n_fallbacks] = @@fallbacks
26
+ end
27
+ end
28
+
29
+ module Backend
30
+ module Fallbacks
31
+ # Overwrites the Base backend translate method so that it will try each
32
+ # locale given by I18n.fallbacks for the given locale. E.g. for the
33
+ # locale :"de-DE" it might try the locales :"de-DE", :de and :en
34
+ # (depends on the fallbacks implementation) until it finds a result with
35
+ # the given options. If it does not find any result for any of the
36
+ # locales it will then throw MissingTranslation as usual.
37
+ #
38
+ # The default option takes precedence over fallback locales only when
39
+ # it's a Symbol. When the default contains a String, Proc or Hash
40
+ # it is evaluated last after all the fallback locales have been tried.
41
+ def translate(locale, key, options = EMPTY_HASH)
42
+ return super unless options.fetch(:fallback, true)
43
+ return super if options[:fallback_in_progress]
44
+ default = extract_non_symbol_default!(options) if options[:default]
45
+
46
+ fallback_options = options.merge(:fallback_in_progress => true)
47
+ I18n.fallbacks[locale].each do |fallback|
48
+ begin
49
+ catch(:exception) do
50
+ result = super(fallback, key, fallback_options)
51
+ unless result.nil?
52
+ on_fallback(locale, fallback, key, options) if locale.to_s != fallback.to_s
53
+ return result
54
+ end
55
+ end
56
+ rescue I18n::InvalidLocale
57
+ # we do nothing when the locale is invalid, as this is a fallback anyways.
58
+ end
59
+ end
60
+
61
+ return if options.key?(:default) && options[:default].nil?
62
+
63
+ return super(locale, nil, options.merge(:default => default)) if default
64
+ throw(:exception, I18n::MissingTranslation.new(locale, key, options))
65
+ end
66
+
67
+ def extract_non_symbol_default!(options)
68
+ defaults = [options[:default]].flatten
69
+ first_non_symbol_default = defaults.detect{|default| !default.is_a?(Symbol)}
70
+ if first_non_symbol_default
71
+ options[:default] = defaults[0, defaults.index(first_non_symbol_default)]
72
+ end
73
+ return first_non_symbol_default
74
+ end
75
+
76
+ def exists?(locale, key, options = EMPTY_HASH)
77
+ return super unless options.fetch(:fallback, true)
78
+ I18n.fallbacks[locale].each do |fallback|
79
+ begin
80
+ return true if super(fallback, key)
81
+ rescue I18n::InvalidLocale
82
+ # we do nothing when the locale is invalid, as this is a fallback anyways.
83
+ end
84
+ end
85
+
86
+ false
87
+ end
88
+
89
+ private
90
+
91
+ # Overwrite on_fallback to add specified logic when the fallback succeeds.
92
+ def on_fallback(_original_locale, _fallback_locale, _key, _optoins)
93
+ nil
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18n
4
+ module Backend
5
+ # This module contains several helpers to assist flattening translations.
6
+ # You may want to flatten translations for:
7
+ #
8
+ # 1) speed up lookups, as in the Memoize backend;
9
+ # 2) In case you want to store translations in a data store, as in ActiveRecord backend;
10
+ #
11
+ # You can check both backends above for some examples.
12
+ # This module also keeps all links in a hash so they can be properly resolved when flattened.
13
+ module Flatten
14
+ SEPARATOR_ESCAPE_CHAR = "\001"
15
+ FLATTEN_SEPARATOR = "."
16
+
17
+ # normalize_keys the flatten way. This method is significantly faster
18
+ # and creates way less objects than the one at I18n.normalize_keys.
19
+ # It also handles escaping the translation keys.
20
+ def self.normalize_flat_keys(locale, key, scope, separator)
21
+ keys = [scope, key]
22
+ keys.flatten!
23
+ keys.compact!
24
+
25
+ separator ||= I18n.default_separator
26
+
27
+ if separator != FLATTEN_SEPARATOR
28
+ from_str = "#{FLATTEN_SEPARATOR}#{separator}"
29
+ to_str = "#{SEPARATOR_ESCAPE_CHAR}#{FLATTEN_SEPARATOR}"
30
+
31
+ keys.map! { |k| k.to_s.tr from_str, to_str }
32
+ end
33
+
34
+ keys.join(".")
35
+ end
36
+
37
+ # Receives a string and escape the default separator.
38
+ def self.escape_default_separator(key) #:nodoc:
39
+ key.to_s.tr(FLATTEN_SEPARATOR, SEPARATOR_ESCAPE_CHAR)
40
+ end
41
+
42
+ # Shortcut to I18n::Backend::Flatten.normalize_flat_keys
43
+ # and then resolve_links.
44
+ def normalize_flat_keys(locale, key, scope, separator)
45
+ key = I18n::Backend::Flatten.normalize_flat_keys(locale, key, scope, separator)
46
+ resolve_link(locale, key)
47
+ end
48
+
49
+ # Store flattened links.
50
+ def links
51
+ @links ||= I18n.new_double_nested_cache
52
+ end
53
+
54
+ # Flatten keys for nested Hashes by chaining up keys:
55
+ #
56
+ # >> { "a" => { "b" => { "c" => "d", "e" => "f" }, "g" => "h" }, "i" => "j"}.wind
57
+ # => { "a.b.c" => "d", "a.b.e" => "f", "a.g" => "h", "i" => "j" }
58
+ #
59
+ def flatten_keys(hash, escape, prev_key=nil, &block)
60
+ hash.each_pair do |key, value|
61
+ key = escape_default_separator(key) if escape
62
+ curr_key = [prev_key, key].compact.join(FLATTEN_SEPARATOR).to_sym
63
+ yield curr_key, value
64
+ flatten_keys(value, escape, curr_key, &block) if value.is_a?(Hash)
65
+ end
66
+ end
67
+
68
+ # Receives a hash of translations (where the key is a locale and
69
+ # the value is another hash) and return a hash with all
70
+ # translations flattened.
71
+ #
72
+ # Nested hashes are included in the flattened hash just if subtree
73
+ # is true and Symbols are automatically stored as links.
74
+ def flatten_translations(locale, data, escape, subtree)
75
+ hash = {}
76
+ flatten_keys(data, escape) do |key, value|
77
+ if value.is_a?(Hash)
78
+ hash[key] = value if subtree
79
+ else
80
+ store_link(locale, key, value) if value.is_a?(Symbol)
81
+ hash[key] = value
82
+ end
83
+ end
84
+ hash
85
+ end
86
+
87
+ protected
88
+
89
+ def store_link(locale, key, link)
90
+ links[locale.to_sym][key.to_s] = link.to_s
91
+ end
92
+
93
+ def resolve_link(locale, key)
94
+ key, locale = key.to_s, locale.to_sym
95
+ links = self.links[locale]
96
+
97
+ if links.key?(key)
98
+ links[key]
99
+ elsif link = find_link(locale, key)
100
+ store_link(locale, key, key.gsub(*link))
101
+ else
102
+ key
103
+ end
104
+ end
105
+
106
+ def find_link(locale, key) #:nodoc:
107
+ links[locale].each_pair do |from, to|
108
+ return [from, to] if key[0, from.length] == from
109
+ end && nil
110
+ end
111
+
112
+ def escape_default_separator(key) #:nodoc:
113
+ I18n::Backend::Flatten.escape_default_separator(key)
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/gettext'
4
+ require 'i18n/gettext/po_parser'
5
+
6
+ module I18n
7
+ module Backend
8
+ # Experimental support for using Gettext po files to store translations.
9
+ #
10
+ # To use this you can simply include the module to the Simple backend - or
11
+ # whatever other backend you are using.
12
+ #
13
+ # I18n::Backend::Simple.include(I18n::Backend::Gettext)
14
+ #
15
+ # Now you should be able to include your Gettext translation (*.po) files to
16
+ # the +I18n.load_path+ so they're loaded to the backend and you can use them as
17
+ # usual:
18
+ #
19
+ # I18n.load_path += Dir["path/to/locales/*.po"]
20
+ #
21
+ # Following the Gettext convention this implementation expects that your
22
+ # translation files are named by their locales. E.g. the file en.po would
23
+ # contain the translations for the English locale.
24
+ #
25
+ # To translate text <b>you must use</b> one of the translate methods provided by
26
+ # I18n::Gettext::Helpers.
27
+ #
28
+ # include I18n::Gettext::Helpers
29
+ # puts _("some string")
30
+ #
31
+ # Without it strings containing periods (".") will not be translated.
32
+
33
+ module Gettext
34
+ using I18n::HashRefinements
35
+
36
+ class PoData < Hash
37
+ def set_comment(msgid_or_sym, comment)
38
+ # ignore
39
+ end
40
+ end
41
+
42
+ protected
43
+ def load_po(filename)
44
+ locale = ::File.basename(filename, '.po').to_sym
45
+ data = normalize(locale, parse(filename))
46
+ { locale => data }
47
+ end
48
+
49
+ def parse(filename)
50
+ GetText::PoParser.new.parse(::File.read(filename), PoData.new)
51
+ end
52
+
53
+ def normalize(locale, data)
54
+ data.inject({}) do |result, (key, value)|
55
+ unless key.nil? || key.empty?
56
+ key = key.gsub(I18n::Gettext::CONTEXT_SEPARATOR, '|')
57
+ key, value = normalize_pluralization(locale, key, value) if key.index("\000")
58
+
59
+ parts = key.split('|').reverse
60
+ normalized = parts.inject({}) do |_normalized, part|
61
+ { part => _normalized.empty? ? value : _normalized }
62
+ end
63
+
64
+ result.deep_merge!(normalized)
65
+ end
66
+ result
67
+ end
68
+ end
69
+
70
+ def normalize_pluralization(locale, key, value)
71
+ # FIXME po_parser includes \000 chars that can not be turned into Symbols
72
+ key = key.gsub("\000", I18n::Gettext::PLURAL_SEPARATOR).split(I18n::Gettext::PLURAL_SEPARATOR).first
73
+
74
+ keys = I18n::Gettext.plural_keys(locale)
75
+ values = value.split("\000")
76
+ raise "invalid number of plurals: #{values.size}, keys: #{keys.inspect} on #{locale} locale for msgid #{key.inspect} with values #{values.inspect}" if values.size != keys.size
77
+
78
+ result = {}
79
+ values.each_with_index { |_value, ix| result[keys[ix]] = _value }
80
+ [key, result]
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The InterpolationCompiler module contains optimizations that can tremendously
4
+ # speed up the interpolation process on the Simple backend.
5
+ #
6
+ # It works by defining a pre-compiled method on stored translation Strings that
7
+ # already bring all the knowledge about contained interpolation variables etc.
8
+ # so that the actual recurring interpolation will be very fast.
9
+ #
10
+ # To enable pre-compiled interpolations you can simply include the
11
+ # InterpolationCompiler module to the Simple backend:
12
+ #
13
+ # I18n::Backend::Simple.include(I18n::Backend::InterpolationCompiler)
14
+ #
15
+ # Note that InterpolationCompiler does not yield meaningful results and consequently
16
+ # should not be used with Ruby 1.9 (YARV) but improves performance everywhere else
17
+ # (jRuby, Rubinius).
18
+ module I18n
19
+ module Backend
20
+ module InterpolationCompiler
21
+ module Compiler
22
+ extend self
23
+
24
+ TOKENIZER = /(%%\{[^\}]+\}|%\{[^\}]+\})/
25
+ INTERPOLATION_SYNTAX_PATTERN = /(%)?(%\{([^\}]+)\})/
26
+
27
+ def compile_if_an_interpolation(string)
28
+ if interpolated_str?(string)
29
+ string.instance_eval <<-RUBY_EVAL, __FILE__, __LINE__
30
+ def i18n_interpolate(v = {})
31
+ "#{compiled_interpolation_body(string)}"
32
+ end
33
+ RUBY_EVAL
34
+ end
35
+
36
+ string
37
+ end
38
+
39
+ def interpolated_str?(str)
40
+ str.kind_of?(::String) && str =~ INTERPOLATION_SYNTAX_PATTERN
41
+ end
42
+
43
+ protected
44
+ # tokenize("foo %{bar} baz %%{buz}") # => ["foo ", "%{bar}", " baz ", "%%{buz}"]
45
+ def tokenize(str)
46
+ str.split(TOKENIZER)
47
+ end
48
+
49
+ def compiled_interpolation_body(str)
50
+ tokenize(str).map do |token|
51
+ (matchdata = token.match(INTERPOLATION_SYNTAX_PATTERN)) ? handle_interpolation_token(token, matchdata) : escape_plain_str(token)
52
+ end.join
53
+ end
54
+
55
+ def handle_interpolation_token(interpolation, matchdata)
56
+ escaped, pattern, key = matchdata.values_at(1, 2, 3)
57
+ escaped ? pattern : compile_interpolation_token(key.to_sym)
58
+ end
59
+
60
+ def compile_interpolation_token(key)
61
+ "\#{#{interpolate_or_raise_missing(key)}}"
62
+ end
63
+
64
+ def interpolate_or_raise_missing(key)
65
+ escaped_key = escape_key_sym(key)
66
+ RESERVED_KEYS.include?(key) ? reserved_key(escaped_key) : interpolate_key(escaped_key)
67
+ end
68
+
69
+ def interpolate_key(key)
70
+ [direct_key(key), nil_key(key), missing_key(key)].join('||')
71
+ end
72
+
73
+ def direct_key(key)
74
+ "((t = v[#{key}]) && t.respond_to?(:call) ? t.call : t)"
75
+ end
76
+
77
+ def nil_key(key)
78
+ "(v.has_key?(#{key}) && '')"
79
+ end
80
+
81
+ def missing_key(key)
82
+ "I18n.config.missing_interpolation_argument_handler.call(#{key}, v, self)"
83
+ end
84
+
85
+ def reserved_key(key)
86
+ "raise(ReservedInterpolationKey.new(#{key}, self))"
87
+ end
88
+
89
+ def escape_plain_str(str)
90
+ str.gsub(/"|\\|#/) {|x| "\\#{x}"}
91
+ end
92
+
93
+ def escape_key_sym(key)
94
+ # rely on Ruby to do all the hard work :)
95
+ key.to_sym.inspect
96
+ end
97
+ end
98
+
99
+ def interpolate(locale, string, values)
100
+ if string.respond_to?(:i18n_interpolate)
101
+ string.i18n_interpolate(values)
102
+ elsif values
103
+ super
104
+ else
105
+ string
106
+ end
107
+ end
108
+
109
+ def store_translations(locale, data, options = EMPTY_HASH)
110
+ compile_all_strings_in(data)
111
+ super
112
+ end
113
+
114
+ protected
115
+ def compile_all_strings_in(data)
116
+ data.each_value do |value|
117
+ Compiler.compile_if_an_interpolation(value)
118
+ compile_all_strings_in(value) if value.kind_of?(Hash)
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/backend/base'
4
+
5
+ module I18n
6
+
7
+ begin
8
+ require 'oj'
9
+ class JSON
10
+ class << self
11
+ def encode(value)
12
+ Oj::Rails.encode(value)
13
+ end
14
+ def decode(value)
15
+ Oj.load(value)
16
+ end
17
+ end
18
+ end
19
+ rescue LoadError
20
+ require 'active_support/json'
21
+ JSON = ActiveSupport::JSON
22
+ end
23
+
24
+ module Backend
25
+ # This is a basic backend for key value stores. It receives on
26
+ # initialization the store, which should respond to three methods:
27
+ #
28
+ # * store#[](key) - Used to get a value
29
+ # * store#[]=(key, value) - Used to set a value
30
+ # * store#keys - Used to get all keys
31
+ #
32
+ # Since these stores only supports string, all values are converted
33
+ # to JSON before being stored, allowing it to also store booleans,
34
+ # hashes and arrays. However, this store does not support Procs.
35
+ #
36
+ # As the ActiveRecord backend, Symbols are just supported when loading
37
+ # translations from the filesystem or through explicit store translations.
38
+ #
39
+ # Also, avoid calling I18n.available_locales since it's a somehow
40
+ # expensive operation in most stores.
41
+ #
42
+ # == Example
43
+ #
44
+ # To setup I18n to use TokyoCabinet in memory is quite straightforward:
45
+ #
46
+ # require 'rufus/tokyo/cabinet' # gem install rufus-tokyo
47
+ # I18n.backend = I18n::Backend::KeyValue.new(Rufus::Tokyo::Cabinet.new('*'))
48
+ #
49
+ # == Performance
50
+ #
51
+ # You may make this backend even faster by including the Memoize module.
52
+ # However, notice that you should properly clear the cache if you change
53
+ # values directly in the key-store.
54
+ #
55
+ # == Subtrees
56
+ #
57
+ # In most backends, you are allowed to retrieve part of a translation tree:
58
+ #
59
+ # I18n.backend.store_translations :en, :foo => { :bar => :baz }
60
+ # I18n.t "foo" #=> { :bar => :baz }
61
+ #
62
+ # This backend supports this feature by default, but it slows down the storage
63
+ # of new data considerably and makes hard to delete entries. That said, you are
64
+ # allowed to disable the storage of subtrees on initialization:
65
+ #
66
+ # I18n::Backend::KeyValue.new(@store, false)
67
+ #
68
+ # This is useful if you are using a KeyValue backend chained to a Simple backend.
69
+ class KeyValue
70
+ using I18n::HashRefinements
71
+
72
+ module Implementation
73
+ attr_accessor :store
74
+
75
+ include Base, Flatten
76
+
77
+ def initialize(store, subtrees=true)
78
+ @store, @subtrees = store, subtrees
79
+ end
80
+
81
+ def initialized?
82
+ !@store.nil?
83
+ end
84
+
85
+ def store_translations(locale, data, options = EMPTY_HASH)
86
+ escape = options.fetch(:escape, true)
87
+ flatten_translations(locale, data, escape, @subtrees).each do |key, value|
88
+ key = "#{locale}.#{key}"
89
+
90
+ case value
91
+ when Hash
92
+ if @subtrees && (old_value = @store[key])
93
+ old_value = JSON.decode(old_value)
94
+ value = old_value.deep_symbolize_keys.deep_merge!(value) if old_value.is_a?(Hash)
95
+ end
96
+ when Proc
97
+ raise "Key-value stores cannot handle procs"
98
+ end
99
+
100
+ @store[key] = JSON.encode(value) unless value.is_a?(Symbol)
101
+ end
102
+ end
103
+
104
+ def available_locales
105
+ locales = @store.keys.map { |k| k =~ /\./; $` }
106
+ locales.uniq!
107
+ locales.compact!
108
+ locales.map! { |k| k.to_sym }
109
+ locales
110
+ end
111
+
112
+ protected
113
+
114
+ # Queries the translations from the key-value store and converts
115
+ # them into a hash such as the one returned from loading the
116
+ # haml files
117
+ def translations
118
+ @translations = @store.keys.clone.map do |main_key|
119
+ main_value = JSON.decode(@store[main_key])
120
+ main_key.to_s.split(".").reverse.inject(main_value) do |value, key|
121
+ {key.to_sym => value}
122
+ end
123
+ end.inject{|hash, elem| hash.deep_merge!(elem)}.deep_symbolize_keys
124
+ end
125
+
126
+ def init_translations
127
+ # NO OP
128
+ # This call made also inside Simple Backend and accessed by
129
+ # other plugins like I18n-js and babilu and
130
+ # to use it along with the Chain backend we need to
131
+ # provide a uniform API even for protected methods :S
132
+ end
133
+
134
+ def subtrees?
135
+ @subtrees
136
+ end
137
+
138
+ def lookup(locale, key, scope = [], options = EMPTY_HASH)
139
+ key = normalize_flat_keys(locale, key, scope, options[:separator])
140
+ value = @store["#{locale}.#{key}"]
141
+ value = JSON.decode(value) if value
142
+
143
+ if value.is_a?(Hash)
144
+ value.deep_symbolize_keys
145
+ elsif !value.nil?
146
+ value
147
+ elsif !@subtrees
148
+ SubtreeProxy.new("#{locale}.#{key}", @store)
149
+ end
150
+ end
151
+
152
+ def pluralize(locale, entry, count)
153
+ if subtrees?
154
+ super
155
+ else
156
+ return entry unless entry.is_a?(Hash)
157
+ key = pluralization_key(entry, count)
158
+ entry[key]
159
+ end
160
+ end
161
+ end
162
+
163
+ class SubtreeProxy
164
+ def initialize(master_key, store)
165
+ @master_key = master_key
166
+ @store = store
167
+ @subtree = nil
168
+ end
169
+
170
+ def has_key?(key)
171
+ @subtree && @subtree.has_key?(key) || self[key]
172
+ end
173
+
174
+ def [](key)
175
+ unless @subtree && value = @subtree[key]
176
+ value = @store["#{@master_key}.#{key}"]
177
+ if value
178
+ value = JSON.decode(value)
179
+ (@subtree ||= {})[key] = value
180
+ end
181
+ end
182
+ value
183
+ end
184
+
185
+ def is_a?(klass)
186
+ Hash == klass || super
187
+ end
188
+ alias :kind_of? :is_a?
189
+
190
+ def instance_of?(klass)
191
+ Hash == klass || super
192
+ end
193
+
194
+ def nil?
195
+ @subtree.nil?
196
+ end
197
+
198
+ def inspect
199
+ @subtree.inspect
200
+ end
201
+ end
202
+
203
+ include Implementation
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Memoize module simply memoizes the values returned by lookup using
4
+ # a flat hash and can tremendously speed up the lookup process in a backend.
5
+ #
6
+ # To enable it you can simply include the Memoize module to your backend:
7
+ #
8
+ # I18n::Backend::Simple.include(I18n::Backend::Memoize)
9
+ #
10
+ # Notice that it's the responsibility of the backend to define whenever the
11
+ # cache should be cleaned.
12
+ module I18n
13
+ module Backend
14
+ module Memoize
15
+ def available_locales
16
+ @memoized_locales ||= super
17
+ end
18
+
19
+ def store_translations(locale, data, options = EMPTY_HASH)
20
+ reset_memoizations!(locale)
21
+ super
22
+ end
23
+
24
+ def reload!
25
+ reset_memoizations!
26
+ super
27
+ end
28
+
29
+ def eager_load!
30
+ memoized_lookup
31
+ available_locales
32
+ super
33
+ end
34
+
35
+ protected
36
+
37
+ def lookup(locale, key, scope = nil, options = EMPTY_HASH)
38
+ flat_key = I18n::Backend::Flatten.normalize_flat_keys(locale,
39
+ key, scope, options[:separator]).to_sym
40
+ flat_hash = memoized_lookup[locale.to_sym]
41
+ flat_hash.key?(flat_key) ? flat_hash[flat_key] : (flat_hash[flat_key] = super)
42
+ end
43
+
44
+ def memoized_lookup
45
+ @memoized_lookup ||= I18n.new_double_nested_cache
46
+ end
47
+
48
+ def reset_memoizations!(locale=nil)
49
+ @memoized_locales = nil
50
+ (locale ? memoized_lookup[locale.to_sym] : memoized_lookup).clear
51
+ end
52
+ end
53
+ end
54
+ end