inplace_i18n 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +16 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +93 -0
- data/LICENSE +20 -0
- data/README.md +66 -0
- data/app/assets/javascripts/inplace_i18n/inplace_i18n.js.coffee.erb +50 -0
- data/app/assets/stylesheets/inplace_i18n/inplace_i18n_styles.sass +64 -0
- data/app/controllers/inplace_i18n/translations_controller.rb +25 -0
- data/app/model/inplace_i18n/translation.rb +58 -0
- data/app/views/inplace_i18n/_js.erb +1 -0
- data/app/views/inplace_i18n/_styles.erb +1 -0
- data/config/routes.rb +4 -0
- data/inplace_i18n.gemspec +22 -0
- data/lib/inplace_i18n.rb +5 -0
- data/lib/inplace_i18n/engine.rb +22 -0
- data/lib/inplace_i18n/hash_tools.rb +100 -0
- data/lib/inplace_i18n/helpers/action_view.rb +17 -0
- data/lib/inplace_i18n/translation_helper.rb +27 -0
- data/lib/inplace_i18n/version.rb +3 -0
- data/lib/tasks/inplace_i18n_tasks.rake +4 -0
- metadata +98 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
inplace_i18n (0.0.1)
|
5
|
+
ya2yaml
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
actionmailer (3.2.3)
|
11
|
+
actionpack (= 3.2.3)
|
12
|
+
mail (~> 2.4.4)
|
13
|
+
actionpack (3.2.3)
|
14
|
+
activemodel (= 3.2.3)
|
15
|
+
activesupport (= 3.2.3)
|
16
|
+
builder (~> 3.0.0)
|
17
|
+
erubis (~> 2.7.0)
|
18
|
+
journey (~> 1.0.1)
|
19
|
+
rack (~> 1.4.0)
|
20
|
+
rack-cache (~> 1.2)
|
21
|
+
rack-test (~> 0.6.1)
|
22
|
+
sprockets (~> 2.1.2)
|
23
|
+
activemodel (3.2.3)
|
24
|
+
activesupport (= 3.2.3)
|
25
|
+
builder (~> 3.0.0)
|
26
|
+
activerecord (3.2.3)
|
27
|
+
activemodel (= 3.2.3)
|
28
|
+
activesupport (= 3.2.3)
|
29
|
+
arel (~> 3.0.2)
|
30
|
+
tzinfo (~> 0.3.29)
|
31
|
+
activeresource (3.2.3)
|
32
|
+
activemodel (= 3.2.3)
|
33
|
+
activesupport (= 3.2.3)
|
34
|
+
activesupport (3.2.3)
|
35
|
+
i18n (~> 0.6)
|
36
|
+
multi_json (~> 1.0)
|
37
|
+
arel (3.0.2)
|
38
|
+
builder (3.0.0)
|
39
|
+
erubis (2.7.0)
|
40
|
+
hike (1.2.1)
|
41
|
+
i18n (0.6.0)
|
42
|
+
journey (1.0.3)
|
43
|
+
json (1.7.1)
|
44
|
+
mail (2.4.4)
|
45
|
+
i18n (>= 0.4.0)
|
46
|
+
mime-types (~> 1.16)
|
47
|
+
treetop (~> 1.4.8)
|
48
|
+
mime-types (1.18)
|
49
|
+
multi_json (1.3.4)
|
50
|
+
polyglot (0.3.3)
|
51
|
+
rack (1.4.1)
|
52
|
+
rack-cache (1.2)
|
53
|
+
rack (>= 0.4)
|
54
|
+
rack-ssl (1.3.2)
|
55
|
+
rack
|
56
|
+
rack-test (0.6.1)
|
57
|
+
rack (>= 1.0)
|
58
|
+
rails (3.2.3)
|
59
|
+
actionmailer (= 3.2.3)
|
60
|
+
actionpack (= 3.2.3)
|
61
|
+
activerecord (= 3.2.3)
|
62
|
+
activeresource (= 3.2.3)
|
63
|
+
activesupport (= 3.2.3)
|
64
|
+
bundler (~> 1.0)
|
65
|
+
railties (= 3.2.3)
|
66
|
+
railties (3.2.3)
|
67
|
+
actionpack (= 3.2.3)
|
68
|
+
activesupport (= 3.2.3)
|
69
|
+
rack-ssl (~> 1.3.2)
|
70
|
+
rake (>= 0.8.7)
|
71
|
+
rdoc (~> 3.4)
|
72
|
+
thor (~> 0.14.6)
|
73
|
+
rake (0.9.2.2)
|
74
|
+
rdoc (3.12)
|
75
|
+
json (~> 1.4)
|
76
|
+
sprockets (2.1.3)
|
77
|
+
hike (~> 1.2)
|
78
|
+
rack (~> 1.0)
|
79
|
+
tilt (~> 1.1, != 1.3.0)
|
80
|
+
thor (0.14.6)
|
81
|
+
tilt (1.3.3)
|
82
|
+
treetop (1.4.10)
|
83
|
+
polyglot
|
84
|
+
polyglot (>= 0.3.1)
|
85
|
+
tzinfo (0.3.33)
|
86
|
+
ya2yaml (0.31)
|
87
|
+
|
88
|
+
PLATFORMS
|
89
|
+
ruby
|
90
|
+
|
91
|
+
DEPENDENCIES
|
92
|
+
inplace_i18n!
|
93
|
+
rails (= 3.2.3)
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Gregory Tangey
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# inplace_i18n
|
2
|
+
|
3
|
+
## About
|
4
|
+
|
5
|
+
Add/Edit Translations inside your application by using this gem and mounting its rails engine.
|
6
|
+
|
7
|
+
It makes a few assumptions:
|
8
|
+
* you use **yaml for translations**
|
9
|
+
* your **translations are stored in [locale].yml**
|
10
|
+
|
11
|
+
It does a few things you might not like:
|
12
|
+
* it re-arranges your [locale].yml alphabetically by key
|
13
|
+
* there's ZERO security, anyone can and will play with your translations. Don't be a production dummy.
|
14
|
+
|
15
|
+
## Why?
|
16
|
+
|
17
|
+
I hate trawling through translation files.
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Using inplace_i18n with rails is pretty straight forward, drop this into your Gemfile:
|
22
|
+
|
23
|
+
group :development do
|
24
|
+
gem 'inplace_i18n', git: 'git://github.com/Ruxton/inplace_i18n.git'
|
25
|
+
end
|
26
|
+
|
27
|
+
Then add the javascript and stylesheets to your project, there are 2 helper methods for this. In your head place the stylesheet:
|
28
|
+
|
29
|
+
%head
|
30
|
+
= inplace_i18n_stylesheets
|
31
|
+
|
32
|
+
And wherever you put your javascript:
|
33
|
+
|
34
|
+
= inplace_i18n_js
|
35
|
+
|
36
|
+
Alternatively you can add them to your existing assets using the asset pipeline:
|
37
|
+
|
38
|
+
@import inplace_i18n/inplace_i18n_styles
|
39
|
+
|
40
|
+
and:
|
41
|
+
|
42
|
+
#= require inplace_i18n/inplace_i18n
|
43
|
+
|
44
|
+
Finally, mount the engine somewhere in your applications config/routes.rb file:
|
45
|
+
|
46
|
+
mount InplaceI18n::Engine => '/translate'
|
47
|
+
|
48
|
+
An 'Edit Translations' button will show up in the top right hand corner of your site, clicking it will overlay pencil icons above every translation. Clicking on the pencil will allow you to edit that translation.
|
49
|
+
|
50
|
+
If you have translations inside the attributes of a HTML Element, pass inplace: false as an option to the translation and the editor wont be added for that translation. Currently adding it these will cause your HTML to break.
|
51
|
+
|
52
|
+
image_tag 'awesome-image.png', alt: t('.awesome_image_alt', inplace: false)
|
53
|
+
|
54
|
+
|
55
|
+
## Thanks, Kudos & Legalities
|
56
|
+
|
57
|
+
* Implementation idea & some code adopted from [i18n_locale_editor](http://github.com/n1k/i18n_locale_editor/)
|
58
|
+
* Edit icon c/o [FamFam Silk Iconset](http://www.famfamfam.com/lab/icons/silk/)
|
59
|
+
|
60
|
+
## Copyright
|
61
|
+
|
62
|
+
Copyright (c) 2011 [Gregory Tangey](http://ignite.digitalignition.net/). See LICENSE for details.
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
jQuery ($) ->
|
2
|
+
addTranslationButton()
|
3
|
+
registerTranslationClick()
|
4
|
+
|
5
|
+
addTranslationButton = () ->
|
6
|
+
$('body').append '<div id="inplace_i18n">Edit Translations</div>'
|
7
|
+
target = $('#inplace_i18n')
|
8
|
+
target.on 'click', (e) ->
|
9
|
+
e.preventDefault
|
10
|
+
$('span.inplace_i18n').toggle()
|
11
|
+
|
12
|
+
inplaceI18nUrl = (key) ->
|
13
|
+
<%
|
14
|
+
path = InplaceI18n::Engine.routes.url_helpers.translation_path('1')
|
15
|
+
%>
|
16
|
+
url = '<%= path %>'
|
17
|
+
url = url.replace('/1','/'+key)
|
18
|
+
return url
|
19
|
+
|
20
|
+
updateTranslation = (key,value) ->
|
21
|
+
|
22
|
+
url = inplaceI18nUrl(key)
|
23
|
+
|
24
|
+
if value? and key?
|
25
|
+
request = $.ajax
|
26
|
+
type: "PUT"
|
27
|
+
url: url
|
28
|
+
data:
|
29
|
+
value: value
|
30
|
+
|
31
|
+
async: true
|
32
|
+
success: ->
|
33
|
+
console.log 'Success'
|
34
|
+
|
35
|
+
error: ->
|
36
|
+
alert "error posting data to url:" + url
|
37
|
+
|
38
|
+
registerTranslationClick = () ->
|
39
|
+
$('span.inplace_i18n').on 'click', (e) ->
|
40
|
+
e.preventDefault()
|
41
|
+
key = e.srcElement.id
|
42
|
+
url = inplaceI18nUrl(key)
|
43
|
+
|
44
|
+
request = $.ajax
|
45
|
+
type: "GET"
|
46
|
+
url: url
|
47
|
+
|
48
|
+
request.success (msg) ->
|
49
|
+
a = prompt('Translation',request.responseText)
|
50
|
+
updateTranslation(key,a)
|
@@ -0,0 +1,64 @@
|
|
1
|
+
.i18n_translation
|
2
|
+
position: relative
|
3
|
+
width: 0px
|
4
|
+
height: 0px
|
5
|
+
.inplace_i18n
|
6
|
+
display: none
|
7
|
+
width: 16px
|
8
|
+
height: 16px
|
9
|
+
position: absolute
|
10
|
+
top: -20px
|
11
|
+
right: -20px
|
12
|
+
z-index: 99999999
|
13
|
+
|
14
|
+
background: #e3e3e3
|
15
|
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFUSURBVDjLrZM/SAJxGIZdWwuDlnCplkAEm1zkaIiGFFpyMIwGK5KGoK2lphDKkMDg3LLUSIJsSKhIi+684CokOtTiMizCGuzEU5K3vOEgKvtBDe/2Pc8H3x8NAM1fQlx4H9M3pcOWp6TXWmM8A7j0629v1nraiAVC0IrrwATKIgs5xyG5QiE+Z4iQdoeU2oAsnqCSO1NSTu+D9VhqRLD8nIB8F0Q2MgmJDyipCzjvYJkIfpN2UBLG8MpP4dxvQ3ZzGuyyBQ2H+AnOOCBd9aL6soh81A5hyYSGWyCFvxUcerqI4S+CvYVOFPMHxLAq8I3qdHVY5LbBhJzEsCrwutpRFBlUHy6wO2tEYtWAzLELPN2P03kjfj3luqDycV2F8AgefWbEnVqEHa2IznSD6BdsVDNStB0lfh0FPoQjdx8RrAqGzC0YprSgxzsUMOY2bf37N/6Ud1Vc9yYcH50CAAAAAElFTkSuQmCC)
|
16
|
+
border: 1px solid #bbb
|
17
|
+
-webkit-border-radius: 3px
|
18
|
+
-moz-border-radius: 3px
|
19
|
+
border-radius: 3px
|
20
|
+
-webkit-box-shadow: inset 0 0 1px 1px #f6f6f6
|
21
|
+
-moz-box-shadow: inset 0 0 1px 1px #f6f6f6
|
22
|
+
box-shadow: inset 0 0 1px 1px #f6f6f6
|
23
|
+
color: #333
|
24
|
+
font: bold 12px "helvetica neue", helvetica, arial, sans-serif
|
25
|
+
height: 16px
|
26
|
+
width: 16px
|
27
|
+
text-align: center
|
28
|
+
text-shadow: 0 1px 0 #fff
|
29
|
+
|
30
|
+
#inplace_i18n
|
31
|
+
position: absolute
|
32
|
+
top: 10px
|
33
|
+
right: 20px
|
34
|
+
display: block
|
35
|
+
z-index: 99999999
|
36
|
+
|
37
|
+
background: #e3e3e3
|
38
|
+
border: 1px solid #bbb
|
39
|
+
-webkit-border-radius: 3px
|
40
|
+
-moz-border-radius: 3px
|
41
|
+
border-radius: 3px
|
42
|
+
-webkit-box-shadow: inset 0 0 1px 1px #f6f6f6
|
43
|
+
-moz-box-shadow: inset 0 0 1px 1px #f6f6f6
|
44
|
+
box-shadow: inset 0 0 1px 1px #f6f6f6
|
45
|
+
color: #333
|
46
|
+
font: bold 12px "helvetica neue", helvetica, arial, sans-serif
|
47
|
+
line-height: 1
|
48
|
+
padding: 8px 0 9px
|
49
|
+
text-align: center
|
50
|
+
text-shadow: 0 1px 0 #fff
|
51
|
+
width: 150px
|
52
|
+
&:hover
|
53
|
+
background: #d9d9d9
|
54
|
+
-webkit-box-shadow: inset 0 0 1px 1px #eaeaea
|
55
|
+
-moz-box-shadow: inset 0 0 1px 1px #eaeaea
|
56
|
+
box-shadow: inset 0 0 1px 1px #eaeaea
|
57
|
+
color: #222
|
58
|
+
cursor: pointer
|
59
|
+
&:active
|
60
|
+
background: #d0d0d0
|
61
|
+
-webkit-box-shadow: inset 0 0 1px 1px #e3e3e3
|
62
|
+
-moz-box-shadow: inset 0 0 1px 1px #e3e3e3
|
63
|
+
box-shadow: inset 0 0 1px 1px #e3e3e3
|
64
|
+
color: #000
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module InplaceI18n
|
2
|
+
class TranslationsController < ApplicationController
|
3
|
+
|
4
|
+
before_filter :set_language
|
5
|
+
|
6
|
+
def show
|
7
|
+
value = Translation.all(@language).find_by_path(params[:path])
|
8
|
+
render :text => value
|
9
|
+
end
|
10
|
+
|
11
|
+
def update
|
12
|
+
Translation.update_by_path(@language, params[:path], params[:value])
|
13
|
+
I18n.reload!
|
14
|
+
render :text => "OK"
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def set_language
|
20
|
+
@language = params[:path].split(".").first if not params[:path].nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ya2yaml'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class InplaceI18n::Translation
|
6
|
+
|
7
|
+
def self.all(locale)
|
8
|
+
locale = locale.to_s
|
9
|
+
file = File.join(Rails.root, "config/locales","#{locale}.yml")
|
10
|
+
hash = YAML::load_file file
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.update_by_path(locale,path,value)
|
14
|
+
locale = locale.to_s
|
15
|
+
|
16
|
+
file = File.join(Rails.root, "config/locales","#{locale}.yml")
|
17
|
+
hash = YAML::load_file file
|
18
|
+
hash.update_by_path(path,value)
|
19
|
+
File.open(file + ".new",'w') do |f|
|
20
|
+
f.puts hash.ya2yaml
|
21
|
+
end
|
22
|
+
FileUtils.mv(file + ".new", file)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.merge_locales locales_array, only_missing = false
|
26
|
+
#available_locales = I18n.available_locales.map{|loc| loc.to_s}
|
27
|
+
#locales_array.each{|loc| raise "#{loc} locale not found" if not available_locales.include? loc.to_s }
|
28
|
+
|
29
|
+
paths = []
|
30
|
+
translations = {}
|
31
|
+
locales_array.each do |locale|
|
32
|
+
translations[locale] = translation = Translation.all(locale)
|
33
|
+
paths = paths + translation.paths.map{|path| path.gsub(/^#{locale.to_s}\./,"")}
|
34
|
+
end
|
35
|
+
paths = paths.uniq
|
36
|
+
|
37
|
+
aggreg = {}
|
38
|
+
paths.each do |path|
|
39
|
+
aggreg[path] = {}
|
40
|
+
locales_array.each do |locale|
|
41
|
+
aggreg[path][locale] = translations[locale].find_by_path(locale.to_s + '.' + path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
if only_missing
|
45
|
+
return aggreg.delete_if do |path,translation|
|
46
|
+
ret = true
|
47
|
+
translation.each do |language, value|
|
48
|
+
ret = false if value.blank?
|
49
|
+
end
|
50
|
+
|
51
|
+
ret
|
52
|
+
end
|
53
|
+
else
|
54
|
+
return aggreg
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= javascript_include_tag 'inplace_i18n/inplace_i18n' %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= stylesheet_link_tag 'inplace_i18n/inplace_i18n_styles' %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
InplaceI18n::Engine.routes.draw do
|
2
|
+
put '/translations/:path', as: :translation, controller: :translations, to: :update, :constraints => { :path => /[\w.]+?/, format: false }
|
3
|
+
get '/translations/:path', as: :translation, controller: :translations, to: :show, :constraints => { :path => /[\w.]+?/ , format: false }
|
4
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "inplace_i18n/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "inplace_i18n"
|
6
|
+
s.summary = "Inplace editing for rails i18n."
|
7
|
+
s.description = "inplace_i18n is an Engine that provides Inplace editing for rails i18n."
|
8
|
+
s.version = InplaceI18n::VERSION
|
9
|
+
|
10
|
+
s.authors = ["Ruxton"]
|
11
|
+
s.email = ["ruxton@thefrontiergroup.com.au"]
|
12
|
+
s.homepage = "http://ignite.digitalignition.net/"
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.rubyforge_project = "inplace_i18n"
|
20
|
+
|
21
|
+
s.add_dependency "ya2yaml"
|
22
|
+
end
|
data/lib/inplace_i18n.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'inplace_i18n'
|
2
|
+
|
3
|
+
module InplaceI18n
|
4
|
+
|
5
|
+
class Engine < ::Rails::Engine
|
6
|
+
isolate_namespace InplaceI18n
|
7
|
+
|
8
|
+
require 'inplace_i18n/hash_tools'
|
9
|
+
Hash.send :include, InplaceI18n::HashTools
|
10
|
+
|
11
|
+
initializer 'inplace_i18n.register_view_helper' do
|
12
|
+
require 'inplace_i18n/helpers/action_view'
|
13
|
+
ActionView::Base.send :include, InplaceI18n::Helpers::ActionView
|
14
|
+
end
|
15
|
+
|
16
|
+
initializer "inplace_i18n.install_translation_helper", after: 'i18n.callbacks' do
|
17
|
+
require 'inplace_i18n/translation_helper'
|
18
|
+
ActionView::Helpers::TranslationHelper.send :include, InplaceI18n::TranslationHelper
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module InplaceI18n
|
2
|
+
module HashTools
|
3
|
+
|
4
|
+
def find_by_path(path)
|
5
|
+
e ="self"
|
6
|
+
path_to_a(path).each{|i| e = e+"['"+ escape_for_eval(i)+ "']" }
|
7
|
+
begin
|
8
|
+
eval(e)
|
9
|
+
rescue NoMethodError
|
10
|
+
return nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def update_by_path(path, string)
|
15
|
+
return false if find_by_path(path).class == "Hash"
|
16
|
+
create_path_if_not_exist(path)
|
17
|
+
e ="self"
|
18
|
+
path_a = path_to_a(path)
|
19
|
+
path_a.each{|i| e = e+"['"+escape_for_eval(i)+"']" }
|
20
|
+
string = string.gsub(/^[ \t]+/,"")
|
21
|
+
|
22
|
+
string = escape_for_eval(string)
|
23
|
+
e = e+"='"+string+"'"
|
24
|
+
begin
|
25
|
+
eval(e)
|
26
|
+
return true
|
27
|
+
rescue => e
|
28
|
+
return [false, e]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_by_path_wo_parents(path, string)
|
33
|
+
return false if find_by_path(path).class.to_s == "Hash" && find_by_path(path).length > 0
|
34
|
+
e ="self"
|
35
|
+
path_a = path_to_a(path)
|
36
|
+
path_a.each{|i| e = e+"['"+ escape_for_eval(i)+"']" }
|
37
|
+
string = escape_for_eval(string)
|
38
|
+
e = e+"="+string.inspect+""
|
39
|
+
|
40
|
+
begin
|
41
|
+
eval(e)
|
42
|
+
return true
|
43
|
+
rescue
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_empty_node(path)
|
49
|
+
return false if not find_by_path(path).nil?
|
50
|
+
update_by_path_wo_parents(path, {})
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_path_if_not_exist(path)
|
54
|
+
aa = path_to_a(path)
|
55
|
+
new_aa = []
|
56
|
+
aa.each do |a|
|
57
|
+
new_aa << a
|
58
|
+
create_empty_node(a_to_path(new_aa))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def nodes_array(path = [])
|
63
|
+
ret = []
|
64
|
+
self.each do |key,value|
|
65
|
+
if value.class == Hash
|
66
|
+
ret = ret + value.nodes_array(path + [key])
|
67
|
+
else
|
68
|
+
ret << path + [key]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
ret
|
72
|
+
end
|
73
|
+
|
74
|
+
def next_path(path)
|
75
|
+
paths = self.paths
|
76
|
+
paths[paths.index(path) + 1]
|
77
|
+
end
|
78
|
+
|
79
|
+
def previous_path(path)
|
80
|
+
paths = self.paths
|
81
|
+
paths[paths.index(path) - 1]
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
def path_to_a(string)
|
86
|
+
string.split(".")
|
87
|
+
end
|
88
|
+
|
89
|
+
def a_to_path(array)
|
90
|
+
array.join(".")
|
91
|
+
end
|
92
|
+
|
93
|
+
def escape_for_eval(string)
|
94
|
+
string.gsub!("'", "\\\\'") if string.class == String
|
95
|
+
string
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
Hash.send(:include, InplaceI18n::HashTools)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module InplaceI18n
|
2
|
+
module TranslationHelper
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
alias_method_chain :translate, :inplace_editing
|
7
|
+
alias :t :translate_with_inplace_editing
|
8
|
+
end
|
9
|
+
|
10
|
+
def translate_with_inplace_editing(key, options = {})
|
11
|
+
key = scope_key_by_partial(key).to_s
|
12
|
+
inplace = true
|
13
|
+
inplace = options[:inplace] unless options.blank?
|
14
|
+
|
15
|
+
translation = translate_without_inplace_editing(key, options)
|
16
|
+
|
17
|
+
if inplace
|
18
|
+
key = I18n.locale.to_s + '.'+key
|
19
|
+
translation = " " if translation.blank?
|
20
|
+
translation = '<span class="i18n_translation"><span id="'+key+'" class="inplace_i18n"></span></span>' + translation
|
21
|
+
end
|
22
|
+
|
23
|
+
translation.html_safe
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: inplace_i18n
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ruxton
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-05-10 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: ya2yaml
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: inplace_i18n is an Engine that provides Inplace editing for rails i18n.
|
35
|
+
email:
|
36
|
+
- ruxton@thefrontiergroup.com.au
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- Gemfile.lock
|
47
|
+
- LICENSE
|
48
|
+
- README.md
|
49
|
+
- app/assets/javascripts/inplace_i18n/inplace_i18n.js.coffee.erb
|
50
|
+
- app/assets/stylesheets/inplace_i18n/inplace_i18n_styles.sass
|
51
|
+
- app/controllers/inplace_i18n/translations_controller.rb
|
52
|
+
- app/model/inplace_i18n/translation.rb
|
53
|
+
- app/views/inplace_i18n/_js.erb
|
54
|
+
- app/views/inplace_i18n/_styles.erb
|
55
|
+
- config/routes.rb
|
56
|
+
- inplace_i18n.gemspec
|
57
|
+
- lib/inplace_i18n.rb
|
58
|
+
- lib/inplace_i18n/engine.rb
|
59
|
+
- lib/inplace_i18n/hash_tools.rb
|
60
|
+
- lib/inplace_i18n/helpers/action_view.rb
|
61
|
+
- lib/inplace_i18n/translation_helper.rb
|
62
|
+
- lib/inplace_i18n/version.rb
|
63
|
+
- lib/tasks/inplace_i18n_tasks.rake
|
64
|
+
homepage: http://ignite.digitalignition.net/
|
65
|
+
licenses: []
|
66
|
+
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 3
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project: inplace_i18n
|
93
|
+
rubygems_version: 1.8.10
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: Inplace editing for rails i18n.
|
97
|
+
test_files: []
|
98
|
+
|