i18nline 0.0.2.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.
- checksums.yaml +7 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/i18nline/application.js +15 -0
- data/app/assets/javascripts/i18nline_to_host.js +7 -0
- data/app/assets/stylesheets/i18nline/_base.css +15 -0
- data/app/assets/stylesheets/i18nline/application.css +13 -0
- data/app/assets/stylesheets/i18nline_to_host.css +3 -0
- data/app/controllers/i18nline/application_controller.rb +13 -0
- data/app/controllers/i18nline/translations_controller.rb +95 -0
- data/app/helpers/i18nline/application_helper.rb +4 -0
- data/app/helpers/i18nline/translations_helper.rb +4 -0
- data/app/models/i18nline/translation.rb +55 -0
- data/app/views/i18nline/translations/_search_form.html.erb +26 -0
- data/app/views/i18nline/translations/edit_key.html.erb +56 -0
- data/app/views/i18nline/translations/index.html.erb +31 -0
- data/app/views/layouts/i18nline/application.html.erb +18 -0
- data/config/initializers/kaminari_config.rb +10 -0
- data/config/initializers/locale.rb +25 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20131112155848_create_i18nline_translations.rb +18 -0
- data/lib/generators/i18nline/install_generator.rb +12 -0
- data/lib/generators/i18nline/templates/config/initializers/i18nline.rb +21 -0
- data/lib/i18nline/action_view_extension.rb +40 -0
- data/lib/i18nline/engine.rb +5 -0
- data/lib/i18nline/railtie.rb +10 -0
- data/lib/i18nline/version.rb +3 -0
- data/lib/i18nline.rb +28 -0
- data/lib/tasks/i18nline_tasks.rake +4 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/javascripts/hello.js +2 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/assets/stylesheets/hello.css +4 -0
- data/test/dummy/app/controllers/application_controller.rb +26 -0
- data/test/dummy/app/controllers/hello_controller.rb +11 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/hello_helper.rb +2 -0
- data/test/dummy/app/views/hello/hello.html.erb +11 -0
- data/test/dummy/app/views/layouts/application.html.erb +15 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/i18nline.rb +21 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +29 -0
- data/test/dummy/config/routes.rb +9 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +28 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +30443 -0
- data/test/dummy/log/test.log +17 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/test/helpers/hello_helper_test.rb +4 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/0f717e3c4863aa83b5ef697e89d0efa0 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/14a79238d484a545d971e3d941fe86e4 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/1fed974ece9b46e9543a13bd2cfd39c6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/219e4ef52e71a2dd3142d36271626492 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/28cbea362ca86359d6a456435223469f +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/29331726baea36717bf28565c0be1881 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/29b9855933ef5ef7acb1d219e791dc2a +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/3c733f688711d6713374183251bc756e +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/4584795e7f513db14ffca10dab44759e +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/54cc037ce34a10f6cb709215e938d464 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/628fc32a4e0873a940ebf8a823e19ff7 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/637e3c52efb900d9d1a7e9be4606c8e0 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/68dc686a51587b32dfe7df0ed46af6e5 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/68ec19b2e986f843a7153c1c4e947469 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/72a227156d935c44e2aad8718b3952fb +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/75609286c4c1330bd547dae66258418b +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/8b4ee98cc6fbdab0922b4e98c2f95b4b +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/8c166e9c73eb969d1fffacccbebb7a28 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/8d41b05a7a0374a80a66fecb003b19fa +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/90b42249c96ca020cc4d4e5d209e3662 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/98cb4932cde5ab6aac080dfe2c1a666c +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/9bdaf3e65b045b8b71837f5662d72c5a +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/af81f90be8ad8a467e0198c5dae0bce6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/b009f80f9687a780c4fab949cb1bcc60 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/bd646ad5989b27aa4beddd353406e7c2 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/c4f0ac344bd4304d32c569c9d1b50912 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/c50a18c681d1e0b8bdc1d2f4569776ca +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/c5d518b12d9d712aa81c6c98a57ad3b5 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cfea650552ed221f83ea2c8fc3198c53 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d3db0fcbbd3e669299cb370b3eba8a3f +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/e27275f4020fd1fc40de79a1e5db4c96 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/e5eea083daff4fcf6e9167de82c0ee77 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f0bca3bde3594952f22b26df6fea76a8 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/helpers/i18nline/translations_helper_test.rb +6 -0
- data/test/i18nline_test.rb +7 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- metadata +313 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9735908d64a162fd6609bad31eeff6eb39c8f4fe
|
4
|
+
data.tar.gz: d220b2d3f964c7b9bb7b3687807f55c6fbf6969a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 21507271b19bc58d5f1e6ce01ef3b2a87ad466a662d45efa65fdb3253b467ec48c25e917a9d9ce87f5cae424a966f29736ead8b59b2182f1d69cae62348d647e
|
7
|
+
data.tar.gz: 6975c6965347bc646affd6aa9fc578dd479b2c4ec210e143fe178e441d6c7a739759eb4d26127edb184325318839ae4b56f5b1fdf1b53012ba0078948e0eb57a
|
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,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,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,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
|
data/config/routes.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateI18nlineTranslations < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :i18nline_translations do |t|
|
4
|
+
t.string :locale
|
5
|
+
t.string :key
|
6
|
+
t.text :value
|
7
|
+
t.text :interpolations
|
8
|
+
t.boolean :is_proc, :default => false
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
add_index :i18nline_translations, [:locale, :key], unique: true
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :i18nline_translations
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module I18nline
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc "Copy i18nline default files"
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
def copy_config
|
8
|
+
template "config/initializers/i18nline.rb"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Use this setup block to configure all options available in i18nline.
|
2
|
+
I18nline.setup do |config|
|
3
|
+
|
4
|
+
# A helper method available in your views so we can ask if there is a current user.
|
5
|
+
#config.current_user_method = "current_user"
|
6
|
+
|
7
|
+
# A method your current_user has to respond to affirmatively to be able to
|
8
|
+
# interact with i18nline administration features, like inline markers and
|
9
|
+
# translation management views.
|
10
|
+
# This method will be tried in the instance returned by the 'current_user' helper
|
11
|
+
# specified above: current_user.can_translate?
|
12
|
+
#config.can_translate_method = "can_translate?"
|
13
|
+
|
14
|
+
# A route available in your application to redirect the user to login
|
15
|
+
# when he tries to access to protected views. This route should be
|
16
|
+
# available on your 'rake routes'.
|
17
|
+
#config.login_route = "\login_url"
|
18
|
+
|
19
|
+
# Missing translations will be generated for this locales.
|
20
|
+
#config.enabled_locales = %w(en es it)
|
21
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module I18nline
|
2
|
+
module ActionViewExtension
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def current_user_can_translate?
|
7
|
+
current_user = send I18nline.current_user_method
|
8
|
+
if current_user
|
9
|
+
if current_user.try I18nline.can_translate_method
|
10
|
+
I18nline.current_user = current_user
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def i18nline_assets_inclusion_tag
|
19
|
+
if current_user_can_translate?
|
20
|
+
assets = ""
|
21
|
+
assets << i18nline_host_styles << "\n"
|
22
|
+
assets << i18nline_host_javascripts << "\n"
|
23
|
+
assets.html_safe
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Javascripts that will be loaded on host application:
|
30
|
+
def i18nline_host_javascripts
|
31
|
+
javascript_include_tag("i18nline_to_host.js")
|
32
|
+
end
|
33
|
+
|
34
|
+
# Css that will be loaded on host application:
|
35
|
+
def i18nline_host_styles
|
36
|
+
stylesheet_link_tag("i18nline_to_host.css")
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'action_view_extension')
|
2
|
+
module I18nline
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
initializer "i18nline.configure_rails_initialization" do
|
5
|
+
ActiveSupport.on_load(:action_view) do
|
6
|
+
::ActionView::Base.send :include, I18nline::ActionViewExtension
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/i18nline.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "i18nline/engine"
|
2
|
+
require 'i18nline/railtie' if defined?(Rails)
|
3
|
+
|
4
|
+
module I18nline
|
5
|
+
|
6
|
+
## CONFIGURATION OPTIONS:
|
7
|
+
|
8
|
+
mattr_accessor :current_user_method
|
9
|
+
@@current_user_method = "current_user"
|
10
|
+
|
11
|
+
mattr_accessor :can_translate_method
|
12
|
+
@@can_translate_method = "can_translate?"
|
13
|
+
|
14
|
+
mattr_accessor :login_route
|
15
|
+
@@login_route = "/login"
|
16
|
+
|
17
|
+
mattr_accessor :enabled_locales
|
18
|
+
@@enabled_locales = %w(en es it)
|
19
|
+
|
20
|
+
def self.setup
|
21
|
+
yield self
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
mattr_accessor :current_user
|
26
|
+
@@current_user ||= nil
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/test/dummy/Rakefile
ADDED