i18nline-rails 0.0.5.alpha

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 (114) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +34 -0
  3. data/app/assets/javascripts/i18nline/application.js +15 -0
  4. data/app/assets/javascripts/i18nline_to_host.js +7 -0
  5. data/app/assets/stylesheets/i18nline/_base.css +15 -0
  6. data/app/assets/stylesheets/i18nline/application.css +13 -0
  7. data/app/assets/stylesheets/i18nline_to_host.css +3 -0
  8. data/app/controllers/i18nline/application_controller.rb +13 -0
  9. data/app/controllers/i18nline/translations_controller.rb +95 -0
  10. data/app/helpers/i18nline/application_helper.rb +4 -0
  11. data/app/helpers/i18nline/translations_helper.rb +4 -0
  12. data/app/models/i18nline/translation.rb +55 -0
  13. data/app/views/i18nline/translations/_search_form.html.erb +26 -0
  14. data/app/views/i18nline/translations/edit_key.html.erb +56 -0
  15. data/app/views/i18nline/translations/index.html.erb +31 -0
  16. data/app/views/layouts/i18nline/application.html.erb +18 -0
  17. data/config/initializers/locale.rb +25 -0
  18. data/config/routes.rb +6 -0
  19. data/db/migrate/20131112155848_create_i18nline_translations.rb +18 -0
  20. data/lib/generators/i18nline/install_generator.rb +12 -0
  21. data/lib/generators/i18nline/templates/config/initializers/i18nline.rb +21 -0
  22. data/lib/i18nline.rb +29 -0
  23. data/lib/i18nline/action_view_extension.rb +40 -0
  24. data/lib/i18nline/engine.rb +5 -0
  25. data/lib/i18nline/railtie.rb +10 -0
  26. data/lib/i18nline/version.rb +3 -0
  27. data/lib/tasks/i18nline_tasks.rake +4 -0
  28. data/test/dummy/README.rdoc +28 -0
  29. data/test/dummy/Rakefile +6 -0
  30. data/test/dummy/app/assets/javascripts/application.js +15 -0
  31. data/test/dummy/app/assets/javascripts/hello.js +2 -0
  32. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  33. data/test/dummy/app/assets/stylesheets/hello.css +4 -0
  34. data/test/dummy/app/controllers/application_controller.rb +26 -0
  35. data/test/dummy/app/controllers/hello_controller.rb +11 -0
  36. data/test/dummy/app/helpers/application_helper.rb +2 -0
  37. data/test/dummy/app/helpers/hello_helper.rb +2 -0
  38. data/test/dummy/app/views/hello/hello.html.erb +11 -0
  39. data/test/dummy/app/views/layouts/application.html.erb +15 -0
  40. data/test/dummy/bin/bundle +3 -0
  41. data/test/dummy/bin/rails +4 -0
  42. data/test/dummy/bin/rake +4 -0
  43. data/test/dummy/config.ru +4 -0
  44. data/test/dummy/config/application.rb +25 -0
  45. data/test/dummy/config/boot.rb +5 -0
  46. data/test/dummy/config/database.yml +25 -0
  47. data/test/dummy/config/environment.rb +5 -0
  48. data/test/dummy/config/environments/development.rb +29 -0
  49. data/test/dummy/config/environments/production.rb +80 -0
  50. data/test/dummy/config/environments/test.rb +36 -0
  51. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  52. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  53. data/test/dummy/config/initializers/i18nline.rb +21 -0
  54. data/test/dummy/config/initializers/inflections.rb +16 -0
  55. data/test/dummy/config/initializers/mime_types.rb +5 -0
  56. data/test/dummy/config/initializers/secret_token.rb +12 -0
  57. data/test/dummy/config/initializers/session_store.rb +3 -0
  58. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  59. data/test/dummy/config/locales/en.yml +29 -0
  60. data/test/dummy/config/routes.rb +9 -0
  61. data/test/dummy/db/development.sqlite3 +0 -0
  62. data/test/dummy/db/schema.rb +28 -0
  63. data/test/dummy/db/test.sqlite3 +0 -0
  64. data/test/dummy/log/development.log +30666 -0
  65. data/test/dummy/log/test.log +17 -0
  66. data/test/dummy/public/404.html +58 -0
  67. data/test/dummy/public/422.html +58 -0
  68. data/test/dummy/public/500.html +57 -0
  69. data/test/dummy/public/favicon.ico +0 -0
  70. data/test/dummy/test/helpers/hello_helper_test.rb +4 -0
  71. data/test/dummy/tmp/cache/assets/development/sprockets/0f717e3c4863aa83b5ef697e89d0efa0 +0 -0
  72. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  73. data/test/dummy/tmp/cache/assets/development/sprockets/14a79238d484a545d971e3d941fe86e4 +0 -0
  74. data/test/dummy/tmp/cache/assets/development/sprockets/1fed974ece9b46e9543a13bd2cfd39c6 +0 -0
  75. data/test/dummy/tmp/cache/assets/development/sprockets/219e4ef52e71a2dd3142d36271626492 +0 -0
  76. data/test/dummy/tmp/cache/assets/development/sprockets/28cbea362ca86359d6a456435223469f +0 -0
  77. data/test/dummy/tmp/cache/assets/development/sprockets/29331726baea36717bf28565c0be1881 +0 -0
  78. data/test/dummy/tmp/cache/assets/development/sprockets/29b9855933ef5ef7acb1d219e791dc2a +0 -0
  79. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  80. data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  81. data/test/dummy/tmp/cache/assets/development/sprockets/3c733f688711d6713374183251bc756e +0 -0
  82. data/test/dummy/tmp/cache/assets/development/sprockets/4584795e7f513db14ffca10dab44759e +0 -0
  83. data/test/dummy/tmp/cache/assets/development/sprockets/54cc037ce34a10f6cb709215e938d464 +0 -0
  84. data/test/dummy/tmp/cache/assets/development/sprockets/628fc32a4e0873a940ebf8a823e19ff7 +0 -0
  85. data/test/dummy/tmp/cache/assets/development/sprockets/637e3c52efb900d9d1a7e9be4606c8e0 +0 -0
  86. data/test/dummy/tmp/cache/assets/development/sprockets/68dc686a51587b32dfe7df0ed46af6e5 +0 -0
  87. data/test/dummy/tmp/cache/assets/development/sprockets/68ec19b2e986f843a7153c1c4e947469 +0 -0
  88. data/test/dummy/tmp/cache/assets/development/sprockets/72a227156d935c44e2aad8718b3952fb +0 -0
  89. data/test/dummy/tmp/cache/assets/development/sprockets/75609286c4c1330bd547dae66258418b +0 -0
  90. data/test/dummy/tmp/cache/assets/development/sprockets/8b4ee98cc6fbdab0922b4e98c2f95b4b +0 -0
  91. data/test/dummy/tmp/cache/assets/development/sprockets/8c166e9c73eb969d1fffacccbebb7a28 +0 -0
  92. data/test/dummy/tmp/cache/assets/development/sprockets/8d41b05a7a0374a80a66fecb003b19fa +0 -0
  93. data/test/dummy/tmp/cache/assets/development/sprockets/90b42249c96ca020cc4d4e5d209e3662 +0 -0
  94. data/test/dummy/tmp/cache/assets/development/sprockets/98cb4932cde5ab6aac080dfe2c1a666c +0 -0
  95. data/test/dummy/tmp/cache/assets/development/sprockets/9bdaf3e65b045b8b71837f5662d72c5a +0 -0
  96. data/test/dummy/tmp/cache/assets/development/sprockets/af81f90be8ad8a467e0198c5dae0bce6 +0 -0
  97. data/test/dummy/tmp/cache/assets/development/sprockets/b009f80f9687a780c4fab949cb1bcc60 +0 -0
  98. data/test/dummy/tmp/cache/assets/development/sprockets/bd646ad5989b27aa4beddd353406e7c2 +0 -0
  99. data/test/dummy/tmp/cache/assets/development/sprockets/c4f0ac344bd4304d32c569c9d1b50912 +0 -0
  100. data/test/dummy/tmp/cache/assets/development/sprockets/c50a18c681d1e0b8bdc1d2f4569776ca +0 -0
  101. data/test/dummy/tmp/cache/assets/development/sprockets/c5d518b12d9d712aa81c6c98a57ad3b5 +0 -0
  102. data/test/dummy/tmp/cache/assets/development/sprockets/cfea650552ed221f83ea2c8fc3198c53 +0 -0
  103. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  104. data/test/dummy/tmp/cache/assets/development/sprockets/d3db0fcbbd3e669299cb370b3eba8a3f +0 -0
  105. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  106. data/test/dummy/tmp/cache/assets/development/sprockets/e27275f4020fd1fc40de79a1e5db4c96 +0 -0
  107. data/test/dummy/tmp/cache/assets/development/sprockets/e5eea083daff4fcf6e9167de82c0ee77 +0 -0
  108. data/test/dummy/tmp/cache/assets/development/sprockets/f0bca3bde3594952f22b26df6fea76a8 +0 -0
  109. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  110. data/test/helpers/i18nline/translations_helper_test.rb +6 -0
  111. data/test/i18nline_test.rb +7 -0
  112. data/test/integration/navigation_test.rb +10 -0
  113. data/test/test_helper.rb +15 -0
  114. metadata +326 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 542c12dec29aa1727b2064c8eb6c99a2904e1467
4
+ data.tar.gz: 1f44fcafb0c33d17ab0d3481e52e17edaaab29db
5
+ SHA512:
6
+ metadata.gz: 59a57c01112dfe68f794773ebe6eaee7382e7b3fc0ad852277f9ea75f570dd3c5f686f20aa0458e051a5b177f3989d93995271f69deb4c8c45cfcb00b6835148
7
+ data.tar.gz: 72c68a8644094a82d2e04406f426f78da0147869977a84778c44df2b8153497a8f5be4ad5bf4e84c50a7b094f28ff8eade834d7e35b946912dd989590b03669f
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'I18nline'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,7 @@
1
+ $(document).ready(function() {
2
+ $('span.translation_missing').contextmenu(function(event) {
3
+ key = $(this).attr("title").split(":")[1].trim()
4
+ window.open("/i18nline/find_by_key?key=" + key, "_blank");
5
+ return false; //prevent context menu to show
6
+ });
7
+ });
@@ -0,0 +1,15 @@
1
+ #edit_key_set .panel-danger{
2
+ background-color: #EED3D7;
3
+ }
4
+
5
+ body {
6
+ font-size: 14px !important;
7
+ }
8
+ .form-control {
9
+ font-size: 14px !important;
10
+ height: 36px !important;
11
+ }
12
+ .btn {
13
+ padding: 6px 10px !important;
14
+ font-size: 14px !important;
15
+ }
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,3 @@
1
+ span.translation_missing {
2
+ border-bottom: 2px solid red;
3
+ }
@@ -0,0 +1,13 @@
1
+ module I18nline
2
+ class ApplicationController < ActionController::Base
3
+ before_action :check_authenticated_user
4
+
5
+ private
6
+
7
+ def check_authenticated_user
8
+ unless(I18nline.current_user and I18nline.current_user.try(I18nline.can_translate_method))
9
+ redirect_to I18nline::login_route, error: "You need to login first"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,95 @@
1
+ require_dependency "i18nline/application_controller"
2
+
3
+ module I18nline
4
+ class TranslationsController < ApplicationController
5
+ before_action :set_translation, only: [:show, :edit, :update, :destroy]
6
+
7
+ def find_by_key
8
+ tokens = params[:key].split(".")
9
+ locale_at_inline_key = tokens.delete_at(0)
10
+ key = tokens.join(".")
11
+ translations = Translation.where("key = ?", key)
12
+ if translations.none?
13
+ redirect_to :root, error: "Something went wrong. No translations found." and return
14
+ end
15
+
16
+ # This is needed to preserve nil values
17
+ # otherwise 'update action' receives ""
18
+ # and stores an empty string
19
+ translations.each do |a_tr|
20
+ if a_tr.value.nil?
21
+ a_tr.make_nil = true
22
+ end
23
+ end
24
+
25
+ require 'ostruct'
26
+ @tr_set = OpenStruct.new(
27
+ translations: translations,
28
+ key: key,
29
+ locale_at_inline_key: locale_at_inline_key,
30
+ interpolations: translations.first.interpolations.to_s,
31
+ is_proc: translations.first.is_proc
32
+ )
33
+
34
+ render "edit_key" and return
35
+ end
36
+
37
+ # GET /translations
38
+ def index
39
+ q = Translation.search_key(params[:search_key])
40
+ .search_value(params[:search_value])
41
+ .in_locale(params[:search_locale])
42
+ .not_translated(params[:search_not_translated])
43
+ .blank_value(params[:search_blank_value])
44
+ @translations = q.page(params[:page]).per(25)
45
+ end
46
+
47
+ def update_key_set
48
+ unless params[:tr_set]
49
+ redirect_to :root, error: "Something went wrong. No translations found." and return
50
+ end
51
+ is_proc = params[:tr_set][:is_proc]
52
+ params[:tr_set][:translation].each do |translation|
53
+ db_translation = Translation.find(translation.first)
54
+ if db_translation
55
+ db_translation.value = translation.last[:value]
56
+ db_translation.is_proc = is_proc
57
+ if translation.last[:make_nil].presence == "1"
58
+ # it is likely that if value was nil and now is not, 'make_nil' has been left marked
59
+ # as a mistake, so in that case we ignore it and apply the new value:
60
+ unless db_translation.value_changed? and db_translation.value_was.nil?
61
+ db_translation.value = nil
62
+ end
63
+ end
64
+ if db_translation.changed?
65
+ db_translation.save
66
+ end
67
+ end
68
+ end
69
+ redirect_to :translations, notice: "Update successful."
70
+ end
71
+
72
+ # PATCH/PUT /translations/1
73
+ def update
74
+ if translation_params[:make_nil].presence == "1"
75
+ params[:translation][:value] = nil
76
+ end
77
+ if @translation.update(translation_params)
78
+ redirect_to @translation, notice: 'Translation was successfully updated.'
79
+ else
80
+ render action: 'edit'
81
+ end
82
+ end
83
+
84
+ private
85
+ # Use callbacks to share common setup or constraints between actions.
86
+ def set_translation
87
+ @translation = Translation.find(params[:id])
88
+ end
89
+
90
+ # Only allow a trusted parameter "white list" through.
91
+ def translation_params
92
+ params.require(:translation).permit(:value, :is_proc, :make_nil)
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,4 @@
1
+ module I18nline
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module I18nline
2
+ module TranslationsHelper
3
+ end
4
+ end
@@ -0,0 +1,55 @@
1
+ module I18nline
2
+ class Translation < ActiveRecord::Base
3
+ after_save :update_caches
4
+ attr_accessor :make_nil
5
+ serialize :value
6
+ serialize :interpolations, Array
7
+
8
+ default_scope { order("created_at desc") }
9
+
10
+ def self.not_translated(apply_this = "1")
11
+ if apply_this.present?
12
+ where("value is null")
13
+ else
14
+ scoped
15
+ end
16
+ end
17
+
18
+ def self.blank_value(apply_this = "1")
19
+ if apply_this.present?
20
+ #value is serialized so searching for empty is complicated:
21
+ where("value like ?", "".to_yaml)
22
+ else
23
+ scoped
24
+ end
25
+ end
26
+
27
+ def self.in_locale(locale)
28
+ if locale.present?
29
+ where("locale = ?", locale)
30
+ else
31
+ scoped
32
+ end
33
+ end
34
+
35
+ def self.search_key(to_search)
36
+ if to_search.present?
37
+ where("key like ?", "%#{to_search}%")
38
+ else
39
+ scoped
40
+ end
41
+ end
42
+
43
+ def self.search_value(to_search)
44
+ if to_search.present?
45
+ where("value like ?", "%#{to_search}%")
46
+ else
47
+ scoped
48
+ end
49
+ end
50
+
51
+ def update_caches
52
+ TRANSLATION_STORE.reload!
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,26 @@
1
+ <%= form_tag translations_path, :method => 'get', class: "form-inline", role: "form" do %>
2
+ <div class="form-group">
3
+ <label class="sr-only" for="search_key"> key:</label>
4
+ <%= text_field_tag :search_key, params[:search_key], class: "form-control", placeholder: "Search key" %>
5
+ </div>
6
+ <div class="form-group">
7
+ <label class="sr-only" for="search_value"> value:</label>
8
+ <%= text_field_tag :search_value, params[:search_value], class: "form-control", placeholder: "Search value" %>
9
+ </div>
10
+ <div class="form-group">
11
+ <%= select_tag :search_locale, options_for_select(I18nline::enabled_locales, params[:search_locale]), class: "form-control", prompt: "all locales" %>
12
+ </div>
13
+ <div class="checkbox">
14
+ <label>
15
+ <%= check_box_tag :search_not_translated, "1", params[:search_not_translated] == "1" %>
16
+ Not translated
17
+ </label>
18
+ </div>
19
+ <div class="checkbox">
20
+ <label>
21
+ <%= check_box_tag :search_blank_value, "1", params[:search_blank_value] == "1" %>
22
+ Has blank value
23
+ </label>
24
+ </div>
25
+ <%= submit_tag "Search", :name => nil, class: "btn btn-default" %>
26
+ <% end %>
@@ -0,0 +1,56 @@
1
+ <h1>Editing translation</h1>
2
+
3
+ <div id="edit_key_set" class="panel panel-default">
4
+ <div class="panel-heading">
5
+ <h3 class="panel-title">Key: <%= @tr_set.key %></h3>
6
+ </div>
7
+ <div class="panel-body">
8
+ <%= form_for(@tr_set, as: :tr_set, url: update_key_set_path, method: :put, html: { class: 'form-horizontal', role: 'form' }) do |f| %>
9
+ <div class="form-group">
10
+ <label class="col-sm-2 control-label">Interpolations</label>
11
+ <div class="col-sm-10">
12
+ <%= f.text_field :interpolations, class: "form-control", disabled: :disabled %>
13
+ </div>
14
+ </div>
15
+ <div class="form-group">
16
+ <div class="col-sm-offset-2 col-sm-10">
17
+ <div class="checkbox">
18
+ <label>
19
+ <%= f.check_box :is_proc %>
20
+ Is a proc?
21
+ </label>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ <% @tr_set.translations.each do |translation| %>
26
+ <% panel_color = translation.value.nil? ? "panel-danger" : "panel-info" %>
27
+ <div class="panel panel-default <%= panel_color %>">
28
+ <div class="panel-body">
29
+ <%= f.fields_for "translation[]", translation do |tl_form| %>
30
+ <div class="input-group col-sm-offset-2">
31
+ <span class="input-group-addon"><%= translation.locale %></span>
32
+ <% rows = (translation.value.to_s.length / 100) + 1 %>
33
+ <%= tl_form.text_area :value, class: "form-control", rows: "#{rows}" %>
34
+ </div>
35
+ <div class="form-group">
36
+ <div class="col-sm-offset-2 col-sm-10">
37
+ <div class="checkbox">
38
+ <label>
39
+ <%= tl_form.check_box :make_nil %>
40
+ Make nil to cause missing_translation?
41
+ </label>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ <% end %>
46
+ </div>
47
+ </div>
48
+ <% end %>
49
+ <div class="actions">
50
+ <%= f.submit "Save changes", class: "btn btn-primary" %>
51
+ <%= link_to 'Cancel', translations_path, class: "btn btn-default" %>
52
+ </div>
53
+ <% end %>
54
+ </div>
55
+ </div>
56
+
@@ -0,0 +1,31 @@
1
+ <h1>Listing translations</h1>
2
+
3
+ <%= render "search_form" %>
4
+
5
+ <table class="table table-hover">
6
+ <thead>
7
+ <tr>
8
+ <th>Locale</th>
9
+ <th>Key</th>
10
+ <th>Value</th>
11
+ <th>Modified at</th>
12
+ <th>Action</th>
13
+ </tr>
14
+ </thead>
15
+
16
+ <tbody>
17
+ <% @translations.each do |translation| %>
18
+ <% tr_color = translation.value.nil? ? "danger" : "" %>
19
+ <tr class="<%= tr_color %>">
20
+ <td><%= translation.locale %></td>
21
+ <td><%= translation.key %></td>
22
+ <td><%= translation.value.to_s.truncate(50) %></td>
23
+ <td class="date"><%= translation.updated_at.strftime("%T, %d %b %Y") %></td>
24
+ <td><%= link_to 'Edit', find_by_key_path(key: "#{translation.locale}.#{translation.key}") %></td>
25
+ </tr>
26
+ <% end %>
27
+ </tbody>
28
+ </table>
29
+
30
+ <%= paginate @translations %>
31
+
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>I18nline</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <%= stylesheet_link_tag "i18nline/application", media: "all" %>
7
+ <%= javascript_include_tag "i18nline/application" %>
8
+ <%= stylesheet_link_tag "//netdna.bootstrapcdn.com/bootswatch/3.0.1/readable/bootstrap.min.css", media: "all" %>
9
+ <%= javascript_include_tag "//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css" %>
10
+ <%= javascript_include_tag "//netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js" %>
11
+ <%= csrf_meta_tags %>
12
+ </head>
13
+ <body>
14
+ <div class="container">
15
+ <%= yield %>
16
+ </div>
17
+ </body>
18
+ </html>
@@ -0,0 +1,25 @@
1
+ require 'i18n/backend/active_record'
2
+ module I18nline
3
+ class MyBackend < I18n::Backend::ActiveRecord
4
+ Translation.table_name = "i18nline_translations"
5
+ include I18n::Backend::ActiveRecord::Missing
6
+ include I18n::Backend::Memoize
7
+
8
+ def available_locales
9
+ I18nline::enabled_locales
10
+ end
11
+ end
12
+ end
13
+ TRANSLATION_STORE = I18nline::MyBackend.new
14
+ I18n.backend = I18n::Backend::Chain.new(TRANSLATION_STORE, I18n::Backend::Simple.new)
15
+ module I18n
16
+ class JustRaiseExceptionHandler < ExceptionHandler
17
+ def call(exception, locale, key, options)
18
+ if exception.is_a?(MissingTranslation)
19
+ TRANSLATION_STORE.store_default_translations(locale, key, options)
20
+ end
21
+ super
22
+ end
23
+ end
24
+ end
25
+ I18n.exception_handler = I18n::JustRaiseExceptionHandler.new