awesome_translations 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +30 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/javascripts/awesome_translations/application.js +13 -0
  6. data/app/assets/stylesheets/awesome_translations/application.css.scss +14 -0
  7. data/app/assets/stylesheets/awesome_translations/groups.css.scss +18 -0
  8. data/app/assets/stylesheets/awesome_translations/layout.css.scss +51 -0
  9. data/app/controllers/awesome_translations/application_controller.rb +4 -0
  10. data/app/controllers/awesome_translations/groups_controller.rb +38 -0
  11. data/app/controllers/awesome_translations/handlers_controller.rb +17 -0
  12. data/app/controllers/awesome_translations/translations_controller.rb +4 -0
  13. data/app/helpers/awesome_translations/application_helper.rb +4 -0
  14. data/app/models/awesome_translations/group.rb +43 -0
  15. data/app/models/awesome_translations/handler.rb +45 -0
  16. data/app/models/awesome_translations/translated_value.rb +47 -0
  17. data/app/models/awesome_translations/translation.rb +88 -0
  18. data/app/views/awesome_translations/groups/show.html.haml +28 -0
  19. data/app/views/awesome_translations/handlers/index.html.haml +13 -0
  20. data/app/views/awesome_translations/handlers/show.html.haml +12 -0
  21. data/app/views/layouts/awesome_translations/application.html.haml +24 -0
  22. data/config/routes.rb +7 -0
  23. data/lib/awesome_translations.rb +18 -0
  24. data/lib/awesome_translations/config.rb +7 -0
  25. data/lib/awesome_translations/engine.rb +3 -0
  26. data/lib/awesome_translations/erb_inspector.rb +45 -0
  27. data/lib/awesome_translations/erb_inspector/file_inspector.rb +88 -0
  28. data/lib/awesome_translations/erb_inspector/translation_inspector.rb +69 -0
  29. data/lib/awesome_translations/handlers.rb +25 -0
  30. data/lib/awesome_translations/handlers/base_handler.rb +2 -0
  31. data/lib/awesome_translations/handlers/erb_handler.rb +35 -0
  32. data/lib/awesome_translations/handlers/global_handler.rb +31 -0
  33. data/lib/awesome_translations/handlers/model_handler.rb +95 -0
  34. data/lib/awesome_translations/handlers/validations_handler.rb +70 -0
  35. data/lib/awesome_translations/model_inspector.rb +137 -0
  36. data/lib/awesome_translations/model_inspector/attribute.rb +12 -0
  37. data/lib/awesome_translations/object_extensions.rb +13 -0
  38. data/lib/awesome_translations/version.rb +3 -0
  39. data/lib/tasks/awesome_translations_tasks.rake +29 -0
  40. data/spec/controllers/groups_controller_spec.rb +34 -0
  41. data/spec/controllers/handlers_controller_spec.rb +16 -0
  42. data/spec/controllers/users_controller_spec.rb +18 -0
  43. data/spec/dummy/README.rdoc +28 -0
  44. data/spec/dummy/Rakefile +6 -0
  45. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  46. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  47. data/spec/dummy/app/controllers/application_controller.rb +17 -0
  48. data/spec/dummy/app/controllers/locales_controller.rb +6 -0
  49. data/spec/dummy/app/controllers/users_controller.rb +32 -0
  50. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  51. data/spec/dummy/app/models/role.rb +4 -0
  52. data/spec/dummy/app/models/user.rb +7 -0
  53. data/spec/dummy/app/views/layouts/application.html.haml +21 -0
  54. data/spec/dummy/app/views/users/_partial_test.html.haml +1 -0
  55. data/spec/dummy/app/views/users/index.html.haml +16 -0
  56. data/spec/dummy/app/views/users/show.html.erb +6 -0
  57. data/spec/dummy/bin/bundle +3 -0
  58. data/spec/dummy/bin/rails +4 -0
  59. data/spec/dummy/bin/rake +4 -0
  60. data/spec/dummy/config.ru +4 -0
  61. data/spec/dummy/config/application.rb +28 -0
  62. data/spec/dummy/config/boot.rb +5 -0
  63. data/spec/dummy/config/database.yml +25 -0
  64. data/spec/dummy/config/environment.rb +5 -0
  65. data/spec/dummy/config/environments/development.rb +32 -0
  66. data/spec/dummy/config/environments/production.rb +80 -0
  67. data/spec/dummy/config/environments/test.rb +39 -0
  68. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  69. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  70. data/spec/dummy/config/initializers/inflections.rb +16 -0
  71. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  72. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  73. data/spec/dummy/config/initializers/session_store.rb +3 -0
  74. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  75. data/spec/dummy/config/locales/awesome_translations/app/views/users/da.yml +5 -0
  76. data/spec/dummy/config/locales/awesome_translations/app/views/users/de.yml +5 -0
  77. data/spec/dummy/config/locales/awesome_translations/app/views/users/en.yml +5 -0
  78. data/spec/dummy/config/locales/awesome_translations/da.yml +4 -0
  79. data/spec/dummy/config/locales/awesome_translations/de.yml +4 -0
  80. data/spec/dummy/config/locales/awesome_translations/en.yml +4 -0
  81. data/spec/dummy/config/locales/awesome_translations/models/role/da.yml +6 -0
  82. data/spec/dummy/config/locales/awesome_translations/models/role/de.yml +6 -0
  83. data/spec/dummy/config/locales/awesome_translations/models/role/en.yml +6 -0
  84. data/spec/dummy/config/locales/awesome_translations/models/user/da.yml +12 -0
  85. data/spec/dummy/config/locales/awesome_translations/models/user/de.yml +12 -0
  86. data/spec/dummy/config/locales/awesome_translations/models/user/en.yml +12 -0
  87. data/spec/dummy/config/locales/en.yml +23 -0
  88. data/spec/dummy/config/routes.rb +7 -0
  89. data/spec/dummy/db/development.sqlite3 +0 -0
  90. data/spec/dummy/db/migrate/20141018081559_create_users.rb +9 -0
  91. data/spec/dummy/db/migrate/20141018081640_create_roles.rb +10 -0
  92. data/spec/dummy/db/schema.rb +29 -0
  93. data/spec/dummy/db/test.sqlite3 +0 -0
  94. data/spec/dummy/log/development.log +16953 -0
  95. data/spec/dummy/log/test.log +4992 -0
  96. data/spec/dummy/public/404.html +58 -0
  97. data/spec/dummy/public/422.html +58 -0
  98. data/spec/dummy/public/500.html +57 -0
  99. data/spec/dummy/public/favicon.ico +0 -0
  100. data/spec/dummy/tmp/cache/assets/development/sass/79bc6a1530be4e47bb2bf0dda4943bc0e439789f/application.css.scssc +0 -0
  101. data/spec/dummy/tmp/cache/assets/development/sass/79bc6a1530be4e47bb2bf0dda4943bc0e439789f/groups.css.scssc +0 -0
  102. data/spec/dummy/tmp/cache/assets/development/sass/79bc6a1530be4e47bb2bf0dda4943bc0e439789f/layout.css.scssc +0 -0
  103. data/spec/dummy/tmp/cache/assets/development/sprockets/0cc5658eb161251c8bd64e1cf25e2191 +0 -0
  104. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  105. data/spec/dummy/tmp/cache/assets/development/sprockets/1dfc909a73e53e47b341f67cfd8a3fc3 +0 -0
  106. data/spec/dummy/tmp/cache/assets/development/sprockets/2128d293dc8ef13115c1f5d64b5acfc9 +0 -0
  107. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  108. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  109. data/spec/dummy/tmp/cache/assets/development/sprockets/3bd5629974bb1919d009bcb1da7a7e49 +0 -0
  110. data/spec/dummy/tmp/cache/assets/development/sprockets/50b9bcf05a8718d9cb5b99276f154ea9 +0 -0
  111. data/spec/dummy/tmp/cache/assets/development/sprockets/5316fc0620afefc2ba81b690c8e2c34d +0 -0
  112. data/spec/dummy/tmp/cache/assets/development/sprockets/538966109f3bbd58bfb717ad57a37096 +0 -0
  113. data/spec/dummy/tmp/cache/assets/development/sprockets/58b9ed99ad62ba462ca6a9272b96bef3 +0 -0
  114. data/spec/dummy/tmp/cache/assets/development/sprockets/697d977cf9fc7e54534f5e29b0832836 +0 -0
  115. data/spec/dummy/tmp/cache/assets/development/sprockets/6aab60b365535cc305f37a738e75868b +0 -0
  116. data/spec/dummy/tmp/cache/assets/development/sprockets/6db8498274efddac6691248cc9afe855 +0 -0
  117. data/spec/dummy/tmp/cache/assets/development/sprockets/81ab882fef1228d654a7c697f2324309 +0 -0
  118. data/spec/dummy/tmp/cache/assets/development/sprockets/908bf508cc68079cab720d6b9c36cb95 +0 -0
  119. data/spec/dummy/tmp/cache/assets/development/sprockets/91090eda0f104056144ac17a4fcae91c +0 -0
  120. data/spec/dummy/tmp/cache/assets/development/sprockets/a3c8104e5830cd7047c6a3a1c1e2ba32 +0 -0
  121. data/spec/dummy/tmp/cache/assets/development/sprockets/b512f2b016bd3aef8c28fa661e01308c +0 -0
  122. data/spec/dummy/tmp/cache/assets/development/sprockets/bd49bb0a6f5dfd284a750fb9cab40d85 +0 -0
  123. data/spec/dummy/tmp/cache/assets/development/sprockets/c39fce5fa19b758734af29527d4185ca +0 -0
  124. data/spec/dummy/tmp/cache/assets/development/sprockets/c8ecba0dbc7774cd6db79cb7fbe1ef3e +0 -0
  125. data/spec/dummy/tmp/cache/assets/development/sprockets/cb595904fcf7acdedf2b95571442fc59 +0 -0
  126. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  127. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  128. data/spec/dummy/tmp/cache/assets/development/sprockets/eb9ed717a7ef467bf260b11dfc8451eb +0 -0
  129. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  130. data/spec/dummy/tmp/cache/assets/test/sass/79bc6a1530be4e47bb2bf0dda4943bc0e439789f/application.css.scssc +0 -0
  131. data/spec/dummy/tmp/cache/assets/test/sass/79bc6a1530be4e47bb2bf0dda4943bc0e439789f/groups.css.scssc +0 -0
  132. data/spec/dummy/tmp/cache/assets/test/sass/79bc6a1530be4e47bb2bf0dda4943bc0e439789f/layout.css.scssc +0 -0
  133. data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  134. data/spec/dummy/tmp/cache/assets/test/sprockets/2128d293dc8ef13115c1f5d64b5acfc9 +0 -0
  135. data/spec/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  136. data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  137. data/spec/dummy/tmp/cache/assets/test/sprockets/50b9bcf05a8718d9cb5b99276f154ea9 +0 -0
  138. data/spec/dummy/tmp/cache/assets/test/sprockets/5316fc0620afefc2ba81b690c8e2c34d +0 -0
  139. data/spec/dummy/tmp/cache/assets/test/sprockets/538966109f3bbd58bfb717ad57a37096 +0 -0
  140. data/spec/dummy/tmp/cache/assets/test/sprockets/58b9ed99ad62ba462ca6a9272b96bef3 +0 -0
  141. data/spec/dummy/tmp/cache/assets/test/sprockets/697d977cf9fc7e54534f5e29b0832836 +0 -0
  142. data/spec/dummy/tmp/cache/assets/test/sprockets/6aab60b365535cc305f37a738e75868b +0 -0
  143. data/spec/dummy/tmp/cache/assets/test/sprockets/6db8498274efddac6691248cc9afe855 +0 -0
  144. data/spec/dummy/tmp/cache/assets/test/sprockets/81ab882fef1228d654a7c697f2324309 +0 -0
  145. data/spec/dummy/tmp/cache/assets/test/sprockets/908bf508cc68079cab720d6b9c36cb95 +0 -0
  146. data/spec/dummy/tmp/cache/assets/test/sprockets/91090eda0f104056144ac17a4fcae91c +0 -0
  147. data/spec/dummy/tmp/cache/assets/test/sprockets/a3c8104e5830cd7047c6a3a1c1e2ba32 +0 -0
  148. data/spec/dummy/tmp/cache/assets/test/sprockets/b512f2b016bd3aef8c28fa661e01308c +0 -0
  149. data/spec/dummy/tmp/cache/assets/test/sprockets/bd49bb0a6f5dfd284a750fb9cab40d85 +0 -0
  150. data/spec/dummy/tmp/cache/assets/test/sprockets/c39fce5fa19b758734af29527d4185ca +0 -0
  151. data/spec/dummy/tmp/cache/assets/test/sprockets/cb595904fcf7acdedf2b95571442fc59 +0 -0
  152. data/spec/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  153. data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  154. data/spec/dummy/tmp/cache/assets/test/sprockets/eb9ed717a7ef467bf260b11dfc8451eb +0 -0
  155. data/spec/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  156. data/spec/factories/user.rb +7 -0
  157. data/spec/handlers/erb_handler_spec.rb +35 -0
  158. data/spec/handlers/global_handler_spec.rb +19 -0
  159. data/spec/handlers/model_handler_spec.rb +30 -0
  160. data/spec/handlers/validations_handler_spec.rb +25 -0
  161. data/spec/handlers_spec.rb +9 -0
  162. data/spec/lib/erb_inspector/file_inspector_spec.rb +21 -0
  163. data/spec/lib/erb_inspector/translation_inspector_spec.rb +23 -0
  164. data/spec/lib/erb_inspector_spec.rb +26 -0
  165. data/spec/models/awesome_translations/handler_spec.rb +8 -0
  166. data/spec/models/awesome_translations/translated_value_spec.rb +43 -0
  167. data/spec/spec_helper.rb +56 -0
  168. metadata +505 -0
@@ -0,0 +1,28 @@
1
+ %h1= "Show group: #{@group.name}"
2
+
3
+ = form_for :group, url: handler_group_path(@handler, @group), method: :put do |f|
4
+ %table
5
+ %thead
6
+ %th Key
7
+ - I18n.available_locales.each do |locale|
8
+ %th= locale
9
+ %tbody
10
+ - @translations.each do |translation|
11
+ %tr
12
+ %td= translation.key
13
+
14
+ - I18n.available_locales.each do |locale|
15
+ %td
16
+ = text_field "t", "#{translation.key}[#{locale}]", value: translation.value(locale: locale)
17
+
18
+ - if translation.file_line_content?
19
+ %tr.line-content-row
20
+ %td.line-content{colspan: 1 + I18n.available_locales.length}
21
+ %pre= translation.file_line_content
22
+ %tr
23
+ %td.line-spacer{colspan: 1 + I18n.available_locales.length}
24
+ - if @translations.empty?
25
+ %tr
26
+ %td.error{colspan: 2} No translations were found.
27
+
28
+ = f.submit "Save"
@@ -0,0 +1,13 @@
1
+ %h1 Handlers
2
+
3
+ %table
4
+ %thead
5
+ %tr
6
+ %th Handler
7
+ %tbody
8
+ - @handlers.each do |handler|
9
+ %tr
10
+ %td= link_to handler.name, handler_path(handler)
11
+ - if @handlers.empty?
12
+ %tr
13
+ %td.error{colspan: 1} No handlers were found.
@@ -0,0 +1,12 @@
1
+ %h1= "Show handler: #{@handler.name}"
2
+
3
+ %table
4
+ %thead
5
+ %th Group
6
+ %tbody
7
+ - @groups.each do |group|
8
+ %tr
9
+ %td= link_to group.name, handler_group_path(@handler, group)
10
+ - if @groups.empty?
11
+ %tr
12
+ %td.error{colspan: 2} No groups were found.
@@ -0,0 +1,24 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title AwesomeTranslations
5
+
6
+ = stylesheet_link_tag "awesome_translations/application", media: "all"
7
+ = stylesheet_link_tag "http://fonts.googleapis.com/css?family=Open+Sans:400"
8
+ = stylesheet_link_tag "http://fonts.googleapis.com/css?family=Raleway:400"
9
+
10
+ = javascript_include_tag "awesome_translations/application"
11
+
12
+ = csrf_meta_tags
13
+
14
+ %body{class: ["controller_#{controller_name}", "action_#{action_name}"]}
15
+ %table.main-table
16
+ %tbody
17
+ %tr
18
+ %td.main-logo Awesome Translations
19
+ %tr
20
+ %td.main-menu
21
+ .menu-item= link_to "Handlers", handlers_path
22
+ %tr
23
+ %td.main-content
24
+ = yield
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ AwesomeTranslations::Engine.routes.draw do
2
+ resources :handlers, only: [:index, :show] do
3
+ resources :groups, only: [:show, :update]
4
+ end
5
+
6
+ root to: "handlers#index"
7
+ end
@@ -0,0 +1,18 @@
1
+ require "awesome_translations/engine"
2
+ require "haml"
3
+ require "string-cases"
4
+ require "array_enumerator"
5
+
6
+ module AwesomeTranslations
7
+ autoload :Config, "#{File.dirname(__FILE__)}/awesome_translations/config"
8
+ autoload :ErbInspector, "#{File.dirname(__FILE__)}/awesome_translations/erb_inspector"
9
+ autoload :Handlers, "#{File.dirname(__FILE__)}/awesome_translations/handlers"
10
+ autoload :ObjectExtensions, "awesome_translations/object_extensions"
11
+ autoload :ModelInspector, "awesome_translations/model_inspector"
12
+
13
+ def self.config
14
+ @config ||= AwesomeTranslations::Config.new
15
+ end
16
+ end
17
+
18
+ Object.__send__(:include, AwesomeTranslations::ObjectExtensions)
@@ -0,0 +1,7 @@
1
+ class AwesomeTranslations::Config
2
+ attr_accessor :paths_to_translate
3
+
4
+ def initialize
5
+ @paths_to_translate = [Rails.root.to_s]
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ class AwesomeTranslations::Engine < ::Rails::Engine
2
+ isolate_namespace AwesomeTranslations
3
+ end
@@ -0,0 +1,45 @@
1
+ # Used to find translations in the Rails app by inspecting .erb- and .haml-files.
2
+ class AwesomeTranslations::ErbInspector
3
+ autoload :FileInspector, "#{File.dirname(__FILE__)}/erb_inspector/file_inspector"
4
+ autoload :TranslationInspector, "#{File.dirname(__FILE__)}/erb_inspector/translation_inspector"
5
+
6
+ def initialize(args = {})
7
+ if args[:dirs]
8
+ @dirs = args[:dirs]
9
+ else
10
+ @dirs = AwesomeTranslations.config.paths_to_translate
11
+ end
12
+ end
13
+
14
+ # Yields all relevant .erb- and .haml-files.
15
+ def files
16
+ Enumerator.new do |yielder|
17
+ @dirs.each do |dir|
18
+ scan_dir("", dir, yielder)
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def scan_dir(path, root_path, yielder)
26
+ Dir.foreach("#{root_path}/#{path}") do |file|
27
+ next if file == "." || file == ".."
28
+ file_path = "#{path}"
29
+ file_path << "/" unless file_path.empty?
30
+ file_path << file
31
+
32
+ full_path = "#{root_path}/#{file_path}"
33
+ ext = File.extname(file_path)
34
+
35
+ if File.directory?(full_path)
36
+ scan_dir(file_path, root_path, yielder)
37
+ elsif ext == ".erb" || ext == ".haml"
38
+ yielder << AwesomeTranslations::ErbInspector::FileInspector.new(
39
+ file_path: file_path,
40
+ root_path: root_path
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,88 @@
1
+ class AwesomeTranslations::ErbInspector::FileInspector
2
+ METHOD_NAMES = ["t"]
3
+ VALID_BEGINNING = '(^|\s+|\(|\{|<%=\s*)'
4
+
5
+ attr_reader :root_path, :file_path
6
+
7
+ def initialize(args)
8
+ @args = args
9
+ @root_path, @file_path = args[:root_path], args[:file_path]
10
+ end
11
+
12
+ def translations
13
+ Enumerator.new do |yielder|
14
+ translations_found = {}
15
+
16
+ File.open(full_path, "r") do |fp|
17
+ line_no = 0
18
+ fp.each_line do |line|
19
+ line_no += 1
20
+ parse_content(line_no, line, translations_found, yielder)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def full_path
27
+ "#{@root_path}/#{@file_path}"
28
+ end
29
+
30
+ def basename
31
+ File.basename(@file_path).match(/\A(.+?)\./)[1]
32
+ end
33
+
34
+ private
35
+
36
+ def parse_content(line_no, line, translations_found, yielder)
37
+ METHOD_NAMES.each do |method_name|
38
+ # Scan for the various valid formats.
39
+ line.scan(/#{VALID_BEGINNING}(#{Regexp.escape(method_name)})\s*\("(.+?)"/) do |match|
40
+ add_translation(line_no, match[1], match[2], translations_found, yielder)
41
+ end
42
+
43
+ line.scan(/#{VALID_BEGINNING}(#{Regexp.escape(method_name)})\s*"(.+?)"/) do |match|
44
+ add_translation(line_no, match[1], match[2], translations_found, yielder)
45
+ end
46
+
47
+ line.scan(/#{VALID_BEGINNING}(#{Regexp.escape(method_name)})\s*\('(.+?)'/) do |match|
48
+ add_translation(line_no, match[1], match[2], translations_found, yielder)
49
+ end
50
+
51
+ line.scan(/#{VALID_BEGINNING}(#{Regexp.escape(method_name)})\s*'(.+?)'/) do |match|
52
+ add_translation(line_no, match[1], match[2], translations_found, yielder)
53
+ end
54
+ end
55
+ end
56
+
57
+ def add_translation(line_no, method, key, translations_found, yielder)
58
+ translation_inspector = AwesomeTranslations::ErbInspector::TranslationInspector.new(
59
+ root_path: @root_path,
60
+ file_path: @file_path,
61
+ line_no: line_no,
62
+ method: method,
63
+ key: key
64
+ )
65
+
66
+ unless translation_with_key_exists?(translations_found, translation_inspector.key)
67
+ yielder << translation_inspector
68
+ end
69
+ end
70
+
71
+ def translation_with_key_exists?(translations_found, translation_key)
72
+ translations_found.select { |t| t.key == translation_key }.any?
73
+ end
74
+
75
+ def translation_key_from_dir_file_and_key(dir, file, key)
76
+ return key unless key.starts_with?(".")
77
+
78
+ file = file.gsub(/\A_/, "") # Remove partial indicator.
79
+
80
+ translation_key = dir
81
+ translation_key = translation_key.gsub(/\Aapp\//, "")
82
+ translation_key << "/#{file}"
83
+ translation_key.gsub!("/", ".")
84
+ translation_key << key
85
+
86
+ return translation_key
87
+ end
88
+ end
@@ -0,0 +1,69 @@
1
+ class AwesomeTranslations::ErbInspector::TranslationInspector
2
+ attr_reader :dir, :file_path, :line_no, :method, :key, :full_key, :full_path, :root_path
3
+
4
+ def initialize(args)
5
+ @dir, @file_path, @full_path, @line_no = args[:dir], args[:file_path], args[:full_path], args[:line_no]
6
+ @method, @key, @root_path = args[:method], args[:key], args[:root_path]
7
+
8
+ @full_path = "#{@root_path}/#{@file_path}"
9
+
10
+ generate_dir
11
+ generate_full_key
12
+ end
13
+
14
+ def model
15
+ AwesomeTranslations::Translation.new(
16
+ key: @full_key,
17
+ dir: @dir,
18
+ full_path: @full_path,
19
+ file_path: @file_path,
20
+ line_no: @line_no
21
+ )
22
+ end
23
+
24
+ private
25
+
26
+ def generate_full_key
27
+ if @method == "t" && @key.start_with?(".")
28
+ @full_key = File.dirname(@file_path)
29
+
30
+ if @full_key.start_with?("app/views/")
31
+ # Remove "app/views" from view-translations since that doesn't get used in keys.
32
+ @full_key = @full_key.gsub(/\Aapp\/views\//, "")
33
+ elsif @full_key.start_with?("app/")
34
+ # Remove "app" from controller- and helper-translations since that doesn't get used.
35
+ @full_key = @full_key.gsub(/\Aapp\//, "")
36
+ end
37
+
38
+ @full_key = @full_key.gsub("/", ".")
39
+ @full_key << "."
40
+ @full_key << file_key(@file_path)
41
+ @full_key << "."
42
+ @full_key << @key.gsub(/\A\./, "")
43
+ elsif @method == "t"
44
+ @full_key = @key
45
+ else
46
+ raise "Unknown method-name: '#{@method}'."
47
+ end
48
+ end
49
+
50
+ def file_key(file_path)
51
+ key = File.basename(file_path)
52
+
53
+ # Remove extension
54
+ key = key.match(/\A(.+?)\./)[1]
55
+
56
+ # Remove leading "_" from partials
57
+ key = key.gsub(/\A_/, "")
58
+
59
+ return key
60
+ end
61
+
62
+ def generate_dir
63
+ if @key.start_with?(".")
64
+ @dir = "#{Rails.root}/config/locales/awesome_translations/#{File.dirname(@file_path)}"
65
+ else
66
+ @dir = "#{Rails.root}/config/locales/awesome_translations"
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,25 @@
1
+ class AwesomeTranslations::Handlers
2
+ @handlers = []
3
+
4
+ Dir.foreach("#{File.dirname(__FILE__)}/handlers") do |file|
5
+ match = file.match(/\A(.+)_handler\.rb\Z/)
6
+ next unless match
7
+
8
+ const_name_snake = "#{match[1]}_handler"
9
+ const_name_camel = StringCases.snake_to_camel(const_name_snake)
10
+
11
+ autoload const_name_camel.to_sym, "#{File.dirname(__FILE__)}/handlers/#{const_name_snake}"
12
+
13
+ unless const_name_snake == "base_handler"
14
+ @handlers << AwesomeTranslations::Handler.new(
15
+ id: const_name_snake,
16
+ const_name: const_name_camel,
17
+ name: const_name_camel
18
+ )
19
+ end
20
+ end
21
+
22
+ def self.list
23
+ @handlers
24
+ end
25
+ end
@@ -0,0 +1,2 @@
1
+ class AwesomeTranslations::Handlers::BaseHandler
2
+ end
@@ -0,0 +1,35 @@
1
+ class AwesomeTranslations::Handlers::ErbHandler < AwesomeTranslations::Handlers::BaseHandler
2
+ METHOD_NAMES = ["_", "t"]
3
+ VALID_BEGINNING = '(^|\s+|\(|\{|<%=\s*)'
4
+
5
+ def groups
6
+ ArrayEnumerator.new do |yielder|
7
+ erb_inspector = AwesomeTranslations::ErbInspector.new
8
+ erb_inspector.files.each do |file|
9
+ yielder << AwesomeTranslations::Group.new(
10
+ id: Base64.urlsafe_encode64(file.full_path),
11
+ handler: self,
12
+ data: {
13
+ name: file.file_path,
14
+ root_path: file.root_path,
15
+ full_path: file.full_path
16
+ }
17
+ )
18
+ end
19
+ end
20
+ end
21
+
22
+ def translations_for_group(group)
23
+ ArrayEnumerator.new do |yielder|
24
+ translations = []
25
+
26
+ # Parse views for translations.
27
+ erb_inspector = AwesomeTranslations::ErbInspector.new
28
+ file = erb_inspector.files.select { |file| file.full_path == group.data[:full_path] }.first
29
+
30
+ file.translations.each do |translation|
31
+ yielder << translation.model
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ class AwesomeTranslations::Handlers::GlobalHandler < AwesomeTranslations::Handlers::BaseHandler
2
+ def groups
3
+ ArrayEnumerator.new do |yielder|
4
+ yielder << AwesomeTranslations::Group.new(
5
+ id: "global",
6
+ handler: self,
7
+ data: {
8
+ name: "Global translations"
9
+ }
10
+ )
11
+ end
12
+ end
13
+
14
+ def translations_for_group(group)
15
+ ArrayEnumerator.new do |yielder|
16
+ translations_found = {}
17
+
18
+ erb_inspector = AwesomeTranslations::ErbInspector.new
19
+ erb_inspector.files.each do |file|
20
+ file.translations.each do |translation|
21
+ next if translation.key.start_with?(".")
22
+
23
+ unless translations_found.key?(translation.full_key)
24
+ translations_found[translation.full_key] = true
25
+ yielder << translation.model
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,95 @@
1
+ class AwesomeTranslations::Handlers::ModelHandler < AwesomeTranslations::Handlers::BaseHandler
2
+ def groups
3
+ ArrayEnumerator.new do |yielder|
4
+ AwesomeTranslations::ModelInspector.model_classes.each do |model_inspector|
5
+ yielder << AwesomeTranslations::Group.new(
6
+ id: model_inspector.clazz.name,
7
+ handler: self
8
+ )
9
+ end
10
+ end
11
+ end
12
+
13
+ def translations_for_group(group)
14
+ ArrayEnumerator.new do |yielder|
15
+ model_inspector = AwesomeTranslations::ModelInspector.model_classes.select { |model_inspector| model_inspector.clazz.name == group.name }.first
16
+ raise "No inspector by that name: #{model_inspector.clazz.name}" unless model_inspector
17
+
18
+ model_names(model_inspector).each { |translation| yielder << translation }
19
+ active_record_attributes(model_inspector).each { |translation| yielder << translation }
20
+ paperclip_attachments(model_inspector).each { |translation| yielder << translation }
21
+ relationships(model_inspector).each { |translation| yielder << translation }
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def dir_path(model_inspector)
28
+ class_name = model_inspector.clazz.name
29
+ class_name = class_name.gsub("::", "_")
30
+ class_name = StringCases.camel_to_snake(class_name)
31
+
32
+ dir_path = "#{Rails.root}/config/locales/awesome_translations/models/#{class_name}"
33
+
34
+ return dir_path
35
+ end
36
+
37
+ def active_record_attributes(model_inspector)
38
+ result = []
39
+
40
+ model_inspector.attributes do |attribute|
41
+ translations = {}
42
+
43
+ I18n.available_locales.each do |locale|
44
+ translations[locale] = I18n.t(attribute.i18n_key, locale: locale)
45
+ end
46
+
47
+ result << AwesomeTranslations::Translation.new(
48
+ key: attribute.i18n_key,
49
+ dir: dir_path(model_inspector)
50
+ )
51
+ end
52
+
53
+ return result
54
+ end
55
+
56
+ def paperclip_attachments(model_inspector)
57
+ result = []
58
+
59
+ model_inspector.paperclip_attachments do |name|
60
+ result << AwesomeTranslations::Translation.new(
61
+ key: model_inspector.i18n_key(name),
62
+ dir: dir_path(model_inspector)
63
+ )
64
+ end
65
+
66
+ return result
67
+ end
68
+
69
+ def model_names(model_inspector)
70
+ result = []
71
+ result << AwesomeTranslations::Translation.new(
72
+ key: model_inspector.gettext_key_one,
73
+ dir: dir_path(model_inspector)
74
+ )
75
+ result << AwesomeTranslations::Translation.new(
76
+ key: model_inspector.gettext_key_other,
77
+ dir: dir_path(model_inspector)
78
+ )
79
+
80
+ return result
81
+ end
82
+
83
+ def relationships(model_inspector)
84
+ result = []
85
+
86
+ model_inspector.relationships do |key, reflection|
87
+ result << AwesomeTranslations::Translation.new(
88
+ key: model_inspector.i18n_key(reflection.name),
89
+ dir: dir_path(model_inspector)
90
+ )
91
+ end
92
+
93
+ return result
94
+ end
95
+ end