lit 0.2.1 → 0.2.2
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.
- data/README.md +1 -1
- data/app/assets/javascripts/lit/application.js +0 -2
- data/app/assets/stylesheets/lit/application.css +15 -3
- data/app/controllers/lit/localizations_controller.rb +1 -1
- data/app/controllers/lit/sources_controller.rb +6 -0
- data/app/helpers/lit/localizations_helper.rb +6 -2
- data/app/models/lit/incomming_localization.rb +3 -3
- data/app/models/lit/localization.rb +17 -6
- data/app/models/lit/localization_key.rb +1 -1
- data/app/models/lit/source.rb +21 -5
- data/app/views/layouts/lit/_navigation.html.erb +23 -16
- data/app/views/layouts/lit/application.html.erb +10 -10
- data/app/views/lit/dashboard/index.html.erb +0 -1
- data/app/views/lit/incomming_localizations/index.html.erb +6 -6
- data/app/views/lit/locales/index.html.erb +1 -1
- data/app/views/lit/localization_keys/index.html.erb +8 -6
- data/app/views/lit/localization_keys/star.js.erb +1 -1
- data/app/views/lit/localizations/_form.html.erb +12 -9
- data/app/views/lit/localizations/_previous_versions_rows.html.erb +1 -1
- data/app/views/lit/sources/_form.html.erb +4 -4
- data/app/views/lit/sources/index.html.erb +4 -1
- data/app/views/lit/sources/show.html.erb +1 -0
- data/config/routes.rb +1 -0
- data/lib/generators/lit/install/templates/initializer.rb +7 -0
- data/lib/lit.rb +3 -0
- data/lib/lit/adapters/redis_storage.rb +12 -3
- data/lib/lit/cache.rb +48 -25
- data/lib/lit/engine.rb +0 -1
- data/lib/lit/i18n_backend.rb +20 -20
- data/lib/lit/version.rb +1 -1
- data/lib/tasks/lit_tasks.rake +1 -4
- metadata +3 -20
- data/app/assets/stylesheets/lit/bootstrap_and_overrides.css.scss +0 -43
data/README.md
CHANGED
@@ -47,7 +47,7 @@ You may want to take a look at generated initializer in `config/initializers/lit
|
|
47
47
|
* ~~API~~
|
48
48
|
* ~~Synchronization between environments~~
|
49
49
|
* Rewrite initializer
|
50
|
-
* Rewrite exporter (which is now code from copycopter)
|
50
|
+
* ~~Rewrite exporter (which is now code from copycopter)~~
|
51
51
|
* ~~Support for array types (ie. `date.abbr_day_names`)~~
|
52
52
|
* ~~Generator~~
|
53
53
|
* ~~Support for wysiwyg~~
|
@@ -8,7 +8,6 @@
|
|
8
8
|
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
9
|
* compiled file, but it's generally better to create a new file per style scope.
|
10
10
|
*
|
11
|
-
*= require './bootstrap_and_overrides.css'
|
12
11
|
*= require './jquery-te-1.4.0.css'
|
13
12
|
*= require_self
|
14
13
|
*/
|
@@ -16,7 +15,7 @@
|
|
16
15
|
padding: 10px 0 0 50px;
|
17
16
|
}
|
18
17
|
.detail_wrapper table tr td.locale_row{
|
19
|
-
width:
|
18
|
+
width: 75px;
|
20
19
|
}
|
21
20
|
.localization_key_row .localization_keys_options{
|
22
21
|
display: none;
|
@@ -26,7 +25,7 @@
|
|
26
25
|
display: block;
|
27
26
|
}
|
28
27
|
|
29
|
-
li.key_prefix .
|
28
|
+
li.key_prefix .fa-chevron-right {
|
30
29
|
float: right;
|
31
30
|
margin-top: 2px;
|
32
31
|
margin-right: -6px;
|
@@ -36,3 +35,16 @@ li.key_prefix .icon-chevron-right {
|
|
36
35
|
.hidden{
|
37
36
|
display: none;
|
38
37
|
}
|
38
|
+
i.fa{
|
39
|
+
color: black;
|
40
|
+
}
|
41
|
+
.nav.nav-stacked>li>a {
|
42
|
+
padding: 5px 7px;
|
43
|
+
}
|
44
|
+
.well{
|
45
|
+
background-color: white;
|
46
|
+
border-radius: 0px;
|
47
|
+
}
|
48
|
+
.well label{
|
49
|
+
font-weight: normal;
|
50
|
+
}
|
@@ -10,7 +10,7 @@ module Lit
|
|
10
10
|
|
11
11
|
def update
|
12
12
|
if @localization.update_attributes(clear_params)
|
13
|
-
Lit.init.cache.
|
13
|
+
Lit.init.cache.update_cache @localization.full_key, @localization.get_value
|
14
14
|
end
|
15
15
|
@localization.reload
|
16
16
|
respond_to :js
|
@@ -24,6 +24,12 @@ module Lit
|
|
24
24
|
redirect_to lit.source_incomming_localizations_path(@source)
|
25
25
|
end
|
26
26
|
|
27
|
+
def touch
|
28
|
+
@source = Source.find(params[:id])
|
29
|
+
@source.touch_last_updated_at!
|
30
|
+
redirect_to request.env["HTTP_REFERER"].present? ? :back : @source
|
31
|
+
end
|
32
|
+
|
27
33
|
def create
|
28
34
|
@source = Source.new(clear_params)
|
29
35
|
if @source.save
|
@@ -1,11 +1,15 @@
|
|
1
1
|
module Lit
|
2
2
|
module LocalizationsHelper
|
3
3
|
def draw_icon(icon, opts={})
|
4
|
-
raw("<i class=\"
|
4
|
+
raw("<i class=\"fa fa-#{icon} #{opts[:class]}\" title=\"#{opts[:title]}\" ></i>")
|
5
5
|
end
|
6
6
|
|
7
7
|
def ejs(val)
|
8
8
|
escape_javascript val.to_s
|
9
9
|
end
|
10
|
+
|
11
|
+
def allow_wysiwyg_editor?(key)
|
12
|
+
Lit.all_translations_are_html_safe || key.to_s =~ /(\b|_|\.)html$/
|
13
|
+
end
|
10
14
|
end
|
11
|
-
end
|
15
|
+
end
|
@@ -32,19 +32,19 @@ module Lit
|
|
32
32
|
unless self.locale.present?
|
33
33
|
self.locale = Lit::Locale.new
|
34
34
|
self.locale.locale = self.locale_str
|
35
|
-
self.locale.save
|
35
|
+
self.locale.save!
|
36
36
|
end
|
37
37
|
unless self.localization_key.present?
|
38
38
|
self.localization_key = Lit::LocalizationKey.new
|
39
39
|
self.localization_key.localization_key = self.localization_key_str
|
40
|
-
self.localization_key.save
|
40
|
+
self.localization_key.save!
|
41
41
|
end
|
42
42
|
unless self.localization.present?
|
43
43
|
self.localization = Lit::Localization.new
|
44
44
|
self.localization.locale = self.locale
|
45
45
|
self.localization.localization_key = self.localization_key
|
46
46
|
self.localization.default_value = self.translated_value
|
47
|
-
self.localization.save
|
47
|
+
self.localization.save!
|
48
48
|
end
|
49
49
|
end
|
50
50
|
self.destroy
|
@@ -24,8 +24,10 @@ module Lit
|
|
24
24
|
end
|
25
25
|
|
26
26
|
## BEFORE & AFTER
|
27
|
-
|
28
|
-
|
27
|
+
with_options :if=>:translated_value_changed? do |o|
|
28
|
+
o.before_update :update_is_changed
|
29
|
+
o.before_update :create_version
|
30
|
+
end
|
29
31
|
after_update :mark_localization_key_completed
|
30
32
|
|
31
33
|
def to_s
|
@@ -33,7 +35,7 @@ module Lit
|
|
33
35
|
end
|
34
36
|
|
35
37
|
def full_key
|
36
|
-
|
38
|
+
[self.locale.locale, self.localization_key.localization_key].join('.')
|
37
39
|
end
|
38
40
|
|
39
41
|
def get_value
|
@@ -56,17 +58,26 @@ module Lit
|
|
56
58
|
self.updated_at.to_s(:db)
|
57
59
|
end
|
58
60
|
|
61
|
+
def update_default_value(value)
|
62
|
+
return true if persisted? && default_value == value
|
63
|
+
self.default_value = value
|
64
|
+
self.save!
|
65
|
+
end
|
66
|
+
|
59
67
|
private
|
60
68
|
def update_is_changed
|
61
|
-
|
69
|
+
unless is_changed?
|
70
|
+
self.is_changed = true
|
71
|
+
@should_mark_localization_key_completed = true
|
72
|
+
end
|
62
73
|
end
|
63
74
|
|
64
75
|
def mark_localization_key_completed
|
65
|
-
self.localization_key.mark_completed!
|
76
|
+
self.localization_key.mark_completed! if @should_mark_localization_key_completed
|
66
77
|
end
|
67
78
|
|
68
79
|
def create_version
|
69
|
-
if self.translated_value.present?
|
80
|
+
if self.translated_value.present?
|
70
81
|
l = self.localization_versions.new
|
71
82
|
l.translated_value = self.translated_value_was || self.default_value
|
72
83
|
end
|
data/app/models/lit/source.rb
CHANGED
@@ -20,6 +20,7 @@ module Lit
|
|
20
20
|
end
|
21
21
|
|
22
22
|
## BEFORE & AFTER
|
23
|
+
before_create :set_last_updated_at_upon_creation
|
23
24
|
after_validation :check_if_url_is_valid
|
24
25
|
|
25
26
|
|
@@ -50,13 +51,22 @@ module Lit
|
|
50
51
|
end
|
51
52
|
lc = get_last_change
|
52
53
|
lc = DateTime.parse(lc) unless lc.nil?
|
53
|
-
|
54
|
+
touch_last_updated_at(lc)
|
54
55
|
self.save
|
55
56
|
end
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
60
|
+
def touch_last_updated_at!
|
61
|
+
touch_last_updated_at
|
62
|
+
self.save
|
63
|
+
end
|
64
|
+
|
59
65
|
private
|
66
|
+
def touch_last_updated_at(time=nil)
|
67
|
+
self.last_updated_at = time || Time.now
|
68
|
+
end
|
69
|
+
|
60
70
|
def check_if_url_is_valid
|
61
71
|
if self.errors.empty? && (self.new_record? || self.url_changed?)
|
62
72
|
self.errors.add(:url, "is not accessible") if get_last_change.nil?
|
@@ -65,10 +75,10 @@ module Lit
|
|
65
75
|
|
66
76
|
def get_from_remote(path, query_values={})
|
67
77
|
result = nil
|
68
|
-
|
78
|
+
begin
|
69
79
|
uri = URI(self.url+path)
|
70
80
|
query_values.each do |k,v|
|
71
|
-
params = URI.decode_www_form(uri.query ||
|
81
|
+
params = URI.decode_www_form(uri.query || "") << [k, v]
|
72
82
|
uri.query = URI.encode_www_form(params)
|
73
83
|
end
|
74
84
|
req = Net::HTTP::Get.new(uri.request_uri)
|
@@ -79,9 +89,15 @@ module Lit
|
|
79
89
|
if res.is_a?(Net::HTTPSuccess)
|
80
90
|
result = JSON.parse(res.body)
|
81
91
|
end
|
82
|
-
|
83
|
-
|
92
|
+
rescue
|
93
|
+
end
|
84
94
|
result
|
85
95
|
end
|
96
|
+
|
97
|
+
def set_last_updated_at_upon_creation
|
98
|
+
if self.last_updated_at.blank?
|
99
|
+
touch_last_updated_at if Lit.set_last_updated_at_upon_creation
|
100
|
+
end
|
101
|
+
end
|
86
102
|
end
|
87
103
|
end
|
@@ -1,16 +1,23 @@
|
|
1
|
-
|
2
|
-
<
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
<
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
<
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
1
|
+
<div class="navbar-header">
|
2
|
+
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
3
|
+
<span class="sr-only">Toggle navigation</span>
|
4
|
+
<span class="icon-bar"></span>
|
5
|
+
<span class="icon-bar"></span>
|
6
|
+
<span class="icon-bar"></span>
|
7
|
+
</button>
|
8
|
+
<%= link_to "Lost in translation", root_path, :class=>'navbar-brand' %>
|
9
|
+
</div>
|
10
|
+
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
11
|
+
<ul class="nav navbar-nav">
|
12
|
+
<li><%= link_to "Translate!", lit.localization_keys_path %></li>
|
13
|
+
<li><%= link_to "Synchronize", lit.sources_path %></li>
|
14
|
+
<li class="dropdown">
|
15
|
+
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
16
|
+
Settings
|
17
|
+
<b class="caret"></b>
|
18
|
+
</a>
|
19
|
+
<ul class="dropdown-menu">
|
20
|
+
<li><%= link_to "Locales", lit.locales_path %></li>
|
21
|
+
</ul>
|
22
|
+
</li>
|
23
|
+
</ul>
|
@@ -5,30 +5,30 @@
|
|
5
5
|
<meta charset="utf-8" />
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
8
|
+
<%= stylesheet_link_tag "//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css", :media => "all" %>
|
9
|
+
<%= stylesheet_link_tag "//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css", :media => "all" %>
|
10
|
+
<%= stylesheet_link_tag "//netdna.bootstrapcdn.com/bootswatch/3.0.3/yeti/bootstrap.min.css", :media => "all" %>
|
8
11
|
<%= stylesheet_link_tag "lit/application", :media => "all" %>
|
9
12
|
<%= javascript_include_tag "lit/application" %>
|
13
|
+
<%= javascript_include_tag "//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js" %>
|
10
14
|
<%= csrf_meta_tags %>
|
11
15
|
</head>
|
12
16
|
<body class="<%= params[:controller] %>">
|
13
|
-
<
|
14
|
-
|
15
|
-
|
16
|
-
<%= render 'layouts/lit/navigation' %>
|
17
|
-
</div>
|
18
|
-
</nav>
|
19
|
-
</div>
|
17
|
+
<nav class="navbar navbar-default" role="navigation">
|
18
|
+
<%= render 'layouts/lit/navigation' %>
|
19
|
+
</nav>
|
20
20
|
<div id="main" class="container <%= params[:action] %>" role="main">
|
21
21
|
<div class="row">
|
22
22
|
<% if content_for?(:sidebar) %>
|
23
|
-
<div class="
|
23
|
+
<div class="col-lg-3 col-xs-12 col-sm-3 col-md-3">
|
24
24
|
<%= yield(:sidebar) %>
|
25
25
|
</div>
|
26
|
-
<div class="
|
26
|
+
<div class="col-lg-9 col-xs-12 col-sm-9 col-md-9">
|
27
27
|
<%= render 'layouts/lit/messages' %>
|
28
28
|
<%= yield %>
|
29
29
|
</div>
|
30
30
|
<% else %>
|
31
|
-
<div class="
|
31
|
+
<div class="col-lg-12 col-xs-12 col-sm-12 col-md-12">
|
32
32
|
<%= render 'layouts/lit/messages' %>
|
33
33
|
<%= yield %>
|
34
34
|
</div>
|
@@ -1,4 +1,3 @@
|
|
1
|
-
<h1>Dashboard</h1>
|
2
1
|
<strong>All localization keys</strong> <%= Lit::LocalizationKey.count(:id) %><br/>
|
3
2
|
<% @locales.each do |l| %>
|
4
3
|
<strong><%= image_tag "lit/famfamfam_flags/#{l.locale[0,2]}.png" %> <%= t("lit.locale_to_languages.#{l.locale}", :default=>l.locale) %>:</strong> <span title="<%= "#{l.get_changed_localizations_count}/#{l.get_all_localizations_count}" %>"><%= l.get_translated_percentage %>%</span><br/>
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<h1>Incomming localizations</h1>
|
2
2
|
<div class="row">
|
3
3
|
<span class="pull-right">
|
4
|
-
<%= link_to accept_all_source_incomming_localizations_path(@source), :class=>"btn btn-success", :data=>{:confirm=>t('lit.common.you_sure', :default=>"Are you sure?")} do %>
|
4
|
+
<%= link_to accept_all_source_incomming_localizations_path(@source), :class=>"btn btn-success btn-sm", :data=>{:confirm=>t('lit.common.you_sure', :default=>"Are you sure?")} do %>
|
5
5
|
<%= t('lit.common.accept_all', :default=>"Accept all") %>
|
6
6
|
<% end %>
|
7
|
-
<%= link_to reject_all_source_incomming_localizations_path(@source), :class=>"btn btn-danger", :method=>:post, :data=>{:confirm=>t('lit.common.you_sure', :default=>"Are you sure?")} do %>
|
7
|
+
<%= link_to reject_all_source_incomming_localizations_path(@source), :class=>"btn btn-danger btn-sm", :method=>:post, :data=>{:confirm=>t('lit.common.you_sure', :default=>"Are you sure?")} do %>
|
8
8
|
<%= t('lit.common.reject_all', :default=>"Reject all") %>
|
9
9
|
<% end %>
|
10
10
|
</span>
|
@@ -33,12 +33,12 @@
|
|
33
33
|
<%= render :partial=>"/lit/localization_keys/localization_row", :locals=>{:localization=>il.get_value} %>
|
34
34
|
</td>
|
35
35
|
<td>
|
36
|
-
<%= link_to accept_source_incomming_localization_path(@source, il), :class=>"btn btn-success" do %>
|
37
|
-
<%= draw_icon "
|
36
|
+
<%= link_to accept_source_incomming_localization_path(@source, il), :class=>"btn btn-success btn-sm" do %>
|
37
|
+
<%= draw_icon "check", :class=>"icon-white" %>
|
38
38
|
<%= t('lit.common.accept', :default=>"Accept") %>
|
39
39
|
<% end %>
|
40
|
-
<%= link_to source_incomming_localization_path(@source, il), :class=>"btn btn-danger", :method=>:delete, :data=>{:confirm=>t('lit.common.you_sure', :default=>"Are you sure?")} do %>
|
41
|
-
<%= draw_icon "
|
40
|
+
<%= link_to source_incomming_localization_path(@source, il), :class=>"btn btn-danger btn-sm", :method=>:delete, :data=>{:confirm=>t('lit.common.you_sure', :default=>"Are you sure?")} do %>
|
41
|
+
<%= draw_icon "times", :class=>"icon-white" %>
|
42
42
|
<%= t('lit.common.reject', :default=>"Reject") %>
|
43
43
|
<% end %>
|
44
44
|
</td>
|
@@ -9,10 +9,10 @@
|
|
9
9
|
<span class="badge"><%= Lit.init.cache.get_global_hits_counter(lk.localization_key) %></span>
|
10
10
|
<div class="localization_keys_options">
|
11
11
|
<%= link_to lit.star_localization_key_path(lk), :remote=>true, :class=>"star_icon" do %>
|
12
|
-
<%= draw_icon lk.is_starred? ? 'star' : 'star-
|
12
|
+
<%= draw_icon lk.is_starred? ? 'star' : 'star-o' %>
|
13
13
|
<% end %>
|
14
14
|
<%= link_to lit.localization_key_path(lk), :method=>:delete, :data=>{:confirm=>t('lit.common.you_sure', :default=>"Are you sure?")}, :remote=>true do %>
|
15
|
-
<%= draw_icon 'trash' %>
|
15
|
+
<%= draw_icon 'trash-o' %>
|
16
16
|
<% end %>
|
17
17
|
</div>
|
18
18
|
<div class="detail_wrapper">
|
@@ -53,16 +53,18 @@
|
|
53
53
|
<% if @search_options.has_key?(:key_prefix) %>
|
54
54
|
<%= hidden_field_tag :key_prefix, @search_options[:key_prefix] %>
|
55
55
|
<% end %>
|
56
|
-
<div class="input-
|
57
|
-
<%= text_field_tag :key, @search_options[:key], :class=>"
|
58
|
-
<
|
56
|
+
<div class="input-group">
|
57
|
+
<%= text_field_tag :key, @search_options[:key], :class=>"form-control search-query" %>
|
58
|
+
<div class="input-group-btn">
|
59
|
+
<button type="submit" class="btn btn-default"><%= draw_icon 'search' %></button>
|
60
|
+
</div>
|
59
61
|
</div>
|
60
62
|
<label class="checkbox">
|
61
63
|
<%= check_box_tag :include_completed, '1', @search_options[:include_completed].to_i==1 %>
|
62
64
|
<%= t('.is_completed', :default=>"Include completed") %>
|
63
65
|
</label>
|
64
66
|
<% end %>
|
65
|
-
<ul class="nav nav-
|
67
|
+
<ul class="nav nav-pills nav-stacked">
|
66
68
|
<li class="<%= "active" if params[:action]=='index' %>">
|
67
69
|
<%= link_to lit.localization_keys_path do -%>
|
68
70
|
<%= draw_icon 'list' %>
|
@@ -1 +1 @@
|
|
1
|
-
$('tr.localization_key_row[data-id="<%= @localization_key.id %>"] a.star_icon').html("<%= ejs(draw_icon(@localization_key.is_starred? ? 'star' : 'star-
|
1
|
+
$('tr.localization_key_row[data-id="<%= @localization_key.id %>"] a.star_icon').html("<%= ejs(draw_icon(@localization_key.is_starred? ? 'star' : 'star-o')) %>");
|
@@ -1,20 +1,23 @@
|
|
1
1
|
<%= form_for [@localization_key, @localization], :html=>{:remote=>true} do |f| %>
|
2
|
-
|
2
|
+
<%- f.label :translated_value %>
|
3
3
|
<% if @localization.translated_value.is_a?(Array) %>
|
4
4
|
<ul style="list-style: none;">
|
5
5
|
<% @localization.translated_value.each do |l| %>
|
6
|
-
<li><%= text_field_tag 'localization[translated_value][]', l, :class=>"input-xlarge" %></li>
|
6
|
+
<li><%= text_field_tag 'localization[translated_value][]', l, :class=>"form-control input-xlarge" %></li>
|
7
7
|
<% end %>
|
8
8
|
</ul>
|
9
9
|
<% else %>
|
10
|
-
<%= f.text_area :translated_value, :size=>"40x2", :class=>"input-xxlarge" %>
|
11
|
-
|
12
|
-
|
13
|
-
<
|
14
|
-
|
10
|
+
<%= f.text_area :translated_value, :size=>"40x2", :class=>"form-control input-xxlarge" %>
|
11
|
+
<% if allow_wysiwyg_editor?(@localization_key.localization_key) %>
|
12
|
+
<br />
|
13
|
+
<label>
|
14
|
+
<input type="checkbox" class="wysiwyg_switch" /> use wysiwyg editor
|
15
|
+
</label>
|
16
|
+
<br />
|
17
|
+
<% end %>
|
15
18
|
<% end %>
|
16
19
|
|
17
|
-
<button class="btn" type="submit"><%= t('lit.common.update', :default=>"Update") %></button>
|
18
|
-
<button class="btn
|
20
|
+
<button class="btn btn-primary btn-sm" type="submit"><%= t('lit.common.update', :default=>"Update") %></button>
|
21
|
+
<button class="btn btn-default btn-sm"><%= t('lit.common.cancel', :default=>'Cancel') %></button>
|
19
22
|
<% end %>
|
20
23
|
|
@@ -13,23 +13,23 @@
|
|
13
13
|
<div class="control-group">
|
14
14
|
<%= f.label :identifier, :class=>"control-label" %>
|
15
15
|
<div class="controls">
|
16
|
-
<%= f.text_field :identifier %>
|
16
|
+
<%= f.text_field :identifier, :class=>"form-control" %>
|
17
17
|
</div>
|
18
18
|
</div>
|
19
19
|
<div class="control-group">
|
20
20
|
<%= f.label :url, :class=>"control-label" %>
|
21
21
|
<div class="controls">
|
22
|
-
<%= f.text_field :url, :placeholder=>"http://your_other_env.host/lit" %>
|
22
|
+
<%= f.text_field :url, :placeholder=>"http://your_other_env.host/lit", :class=>"form-control" %>
|
23
23
|
</div>
|
24
24
|
</div>
|
25
25
|
<div class="control-group">
|
26
26
|
<%= f.label :api_key, :class=>"control-label" %>
|
27
27
|
<div class="controls">
|
28
|
-
<%= f.text_field :api_key %>
|
28
|
+
<%= f.text_field :api_key, :class=>"form-control" %>
|
29
29
|
</div>
|
30
30
|
</div>
|
31
31
|
|
32
32
|
<div class="actions">
|
33
|
-
<%= f.submit t('lit.common.save', :default => "Save"), :class=>"btn" %>
|
33
|
+
<%= f.submit t('lit.common.save', :default => "Save"), :class=>"btn btn-primary btn-sm" %>
|
34
34
|
</div>
|
35
35
|
<% end %>
|
@@ -23,8 +23,11 @@
|
|
23
23
|
<%= link_to lit.edit_source_path(source), :title=>t('lit.common.edit', :default=>"Edit") do %>
|
24
24
|
<%= draw_icon 'pencil' %>
|
25
25
|
<% end %>
|
26
|
+
<%= link_to lit.touch_source_path(source), :title=>t('lit.common.touch', :default=>"Touch (update) last_updated_at"), :method => :put, :data => { :confirm => 'Are you sure?' } do %>
|
27
|
+
<%= draw_icon 'clock-o' %>
|
28
|
+
<% end %>
|
26
29
|
<%= link_to lit.source_path(source), :method => :delete, :data => { :confirm => 'Are you sure?' }, :title=>t('lit.common.delete', :default=>"Delete") do %>
|
27
|
-
<%= draw_icon 'trash' %>
|
30
|
+
<%= draw_icon 'trash-o' %>
|
28
31
|
<% end %>
|
29
32
|
</td>
|
30
33
|
</tr>
|
data/config/routes.rb
CHANGED
@@ -11,6 +11,9 @@ Lit.key_value_engine = "<%= @key_value_engine %>"
|
|
11
11
|
# supported at the moment)
|
12
12
|
# Lit.storage_options = { :prefix=>"my_project" }
|
13
13
|
|
14
|
+
# If true all translations are returned as html_safe strings
|
15
|
+
Lit.all_translations_are_html_safe = false
|
16
|
+
|
14
17
|
# Translations without default will be humanized (default string will be added)
|
15
18
|
# ie. scope.page_header will become "Page header"
|
16
19
|
# If `false` then will serve nil instead (but translation will be wrapped in
|
@@ -28,6 +31,10 @@ Lit.api_enabled = false
|
|
28
31
|
# API key is required to authorize third party, if API is enabled
|
29
32
|
Lit.api_key = "<%= @api_key %>"
|
30
33
|
|
34
|
+
# If true, last_updated_at column of synchronizaton source will be set to now
|
35
|
+
# upon record creation
|
36
|
+
Lit.set_last_updated_at_upon_creation = true
|
37
|
+
|
31
38
|
# Initialize lit
|
32
39
|
Lit.init
|
33
40
|
|
data/lib/lit.rb
CHANGED
@@ -13,26 +13,32 @@ module Lit
|
|
13
13
|
def [](key)
|
14
14
|
if Lit.redis.exists(_prefixed_key_for_array(key))
|
15
15
|
Lit.redis.lrange(_prefixed_key(key), 0, -1)
|
16
|
+
elsif Lit.redis.exists(_prefixed_key_for_nil(key))
|
17
|
+
nil
|
16
18
|
else
|
17
19
|
Lit.redis.get(_prefixed_key(key))
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
23
|
def []=(k, v)
|
24
|
+
|
25
|
+
delete(k)
|
22
26
|
if v.is_a?(Array)
|
23
|
-
delete(k)
|
24
27
|
Lit.redis.set(_prefixed_key_for_array(k), "1")
|
25
28
|
v.each do |ve|
|
26
29
|
Lit.redis.rpush(_prefixed_key(k), ve.to_s)
|
27
30
|
end
|
31
|
+
elsif v.nil?
|
32
|
+
Lit.redis.set(_prefixed_key_for_nil(k), "1")
|
33
|
+
Lit.redis.set(_prefixed_key(k), "")
|
28
34
|
else
|
29
|
-
Lit.redis.
|
30
|
-
Lit.redis.set(_prefixed_key(k), v) unless v.nil?
|
35
|
+
Lit.redis.set(_prefixed_key(k), v)
|
31
36
|
end
|
32
37
|
end
|
33
38
|
|
34
39
|
def delete(k)
|
35
40
|
Lit.redis.del(_prefixed_key_for_array(k))
|
41
|
+
Lit.redis.del(_prefixed_key_for_nil(k))
|
36
42
|
Lit.redis.del(_prefixed_key(k))
|
37
43
|
end
|
38
44
|
|
@@ -72,5 +78,8 @@ module Lit
|
|
72
78
|
def _prefixed_key_for_array(key="")
|
73
79
|
_prefix+"array_flags:"+key.to_s
|
74
80
|
end
|
81
|
+
def _prefixed_key_for_nil(key="")
|
82
|
+
_prefix+"nil_flags:"+key.to_s
|
83
|
+
end
|
75
84
|
end
|
76
85
|
end
|
data/lib/lit/cache.rb
CHANGED
@@ -40,7 +40,6 @@ module Lit
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def has_key?(key)
|
43
|
-
# @TODO: change into correct has_key? call
|
44
43
|
@localizations.has_key?(key)
|
45
44
|
end
|
46
45
|
|
@@ -60,6 +59,11 @@ module Lit
|
|
60
59
|
@localizations[key] = localization.get_value if localization
|
61
60
|
end
|
62
61
|
|
62
|
+
def update_cache(key, value)
|
63
|
+
key = key.to_s
|
64
|
+
@localizations[key] = value
|
65
|
+
end
|
66
|
+
|
63
67
|
def delete_locale(key)
|
64
68
|
key = key.to_s
|
65
69
|
locale_key, key_without_locale = split_key(key)
|
@@ -67,16 +71,12 @@ module Lit
|
|
67
71
|
delete_localization(locale, key_without_locale)
|
68
72
|
end
|
69
73
|
|
70
|
-
def load_all_translations
|
71
|
-
doinit = false
|
74
|
+
def load_all_translations
|
72
75
|
first = Localization.order('id ASC').first
|
73
76
|
last = Localization.order('id DESC').first
|
74
77
|
if not first or not last or (not @localizations.has_key?(first.full_key) or
|
75
78
|
not @localizations.has_key?(last.full_key))
|
76
|
-
doinit = true
|
77
|
-
end
|
78
79
|
|
79
|
-
if oninit==false || doinit==true
|
80
80
|
Localization.includes([:locale, :localization_key]).find_each do |l|
|
81
81
|
@localizations[l.full_key] = l.get_value
|
82
82
|
end
|
@@ -123,27 +123,36 @@ module Lit
|
|
123
123
|
|
124
124
|
# this comes directly from copycopter.
|
125
125
|
def export
|
126
|
-
keys = {}
|
127
126
|
reset
|
127
|
+
localizations_scope = Lit::Localization
|
128
|
+
unless ENV['LOCALES'].blank?
|
129
|
+
locale_keys = ENV['LOCALES'].to_s.split(',') || []
|
130
|
+
locale_ids = Lit::Locale.where(locale: locale_keys).pluck(:id)
|
131
|
+
localizations_scope = localizations_scope.where(locale_id: locale_ids) unless locale_ids.empty?
|
132
|
+
end
|
128
133
|
db_localizations = {}
|
129
|
-
|
134
|
+
localizations_scope.find_each do |l|
|
130
135
|
db_localizations[l.full_key] = l.get_value
|
131
136
|
end
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
142
|
-
current = current[key]
|
137
|
+
keys = nested_string_keys_to_hash(db_localizations)
|
138
|
+
keys.to_yaml
|
139
|
+
end
|
140
|
+
|
141
|
+
def nested_string_keys_to_hash(db_localizations)
|
142
|
+
# http://subtech.g.hatena.ne.jp/cho45/20061122
|
143
|
+
deep_proc = Proc.new { |k, s, o|
|
144
|
+
if s.kind_of?(Hash) && o.kind_of?(Hash)
|
145
|
+
next s.merge(o, &deep_proc)
|
143
146
|
end
|
144
|
-
|
147
|
+
next o
|
148
|
+
}
|
149
|
+
keys = {}
|
150
|
+
db_localizations.sort.each do |k,v|
|
151
|
+
key_parts = k.to_s.split('.')
|
152
|
+
converted = key_parts.reverse.inject(v) { |a, n| { n => a } }
|
153
|
+
keys.merge!(converted, &deep_proc)
|
145
154
|
end
|
146
|
-
keys
|
155
|
+
keys
|
147
156
|
end
|
148
157
|
|
149
158
|
def get_global_hits_counter(key)
|
@@ -196,8 +205,7 @@ module Lit
|
|
196
205
|
value = key_without_locale.split('.').last.humanize if value.nil? &&
|
197
206
|
Lit.humanize_key
|
198
207
|
end
|
199
|
-
localization.
|
200
|
-
localization.save!
|
208
|
+
localization.update_default_value(value)
|
201
209
|
end
|
202
210
|
return localization
|
203
211
|
else
|
@@ -205,9 +213,16 @@ module Lit
|
|
205
213
|
end
|
206
214
|
end
|
207
215
|
|
216
|
+
def find_localization_for_delete(locale, key_without_locale)
|
217
|
+
localization_key = find_localization_key_for_delete(key_without_locale)
|
218
|
+
return nil unless localization_key
|
219
|
+
Lit::Localization.where(:locale_id=>locale.id).
|
220
|
+
where(:localization_key_id=>localization_key.id).first
|
221
|
+
end
|
222
|
+
|
208
223
|
def delete_localization(locale, key_without_locale)
|
209
|
-
localization =
|
210
|
-
if localization
|
224
|
+
localization = find_localization_for_delete(locale, key_without_locale)
|
225
|
+
if localization
|
211
226
|
@localizations.delete("#{locale.locale}.#{key_without_locale}")
|
212
227
|
@localization_keys.delete(key_without_locale)
|
213
228
|
localization.destroy # or localization.default_value = nil; localization.save!
|
@@ -231,6 +246,8 @@ module Lit
|
|
231
246
|
end
|
232
247
|
when String then
|
233
248
|
new_value = v
|
249
|
+
when Hash then
|
250
|
+
new_value = nil
|
234
251
|
when Proc then
|
235
252
|
new_value = nil # was v.call - requires more love
|
236
253
|
else
|
@@ -248,6 +265,12 @@ module Lit
|
|
248
265
|
end
|
249
266
|
end
|
250
267
|
|
268
|
+
def find_localization_key_for_delete(key_without_locale)
|
269
|
+
@localization_keys ||= Lit.get_key_value_engine
|
270
|
+
lk = Lit::LocalizationKey.find_by_id(@localization_keys[key_without_locale]) if @localization_keys.has_key?(key_without_locale)
|
271
|
+
lk || Lit::LocalizationKey.where(:localization_key=>key_without_locale).first
|
272
|
+
end
|
273
|
+
|
251
274
|
def split_key(key)
|
252
275
|
key.split('.', 2)
|
253
276
|
end
|
data/lib/lit/engine.rb
CHANGED
data/lib/lit/i18n_backend.rb
CHANGED
@@ -12,7 +12,7 @@ module Lit
|
|
12
12
|
|
13
13
|
def translate(locale, key, options = {})
|
14
14
|
content = super(locale, key, options.merge(:fallback => true))
|
15
|
-
if content.respond_to?(:html_safe)
|
15
|
+
if Lit.all_translations_are_html_safe && content.respond_to?(:html_safe)
|
16
16
|
content.html_safe
|
17
17
|
else
|
18
18
|
content
|
@@ -43,14 +43,26 @@ module Lit
|
|
43
43
|
content = @cache[key_with_locale] || super
|
44
44
|
return content if parts.size <= 1
|
45
45
|
|
46
|
-
newly_created = false
|
47
46
|
unless @cache.has_key?(key_with_locale)
|
48
|
-
@cache.init_key_with_value(key_with_locale, content)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
new_content = @cache.init_key_with_value(key_with_locale, content)
|
48
|
+
content = new_content if content.nil? # Content can change when Lit.humanize is true for example
|
49
|
+
|
50
|
+
if content.nil? && options[:default].present?
|
51
|
+
if options[:default].is_a?(Array)
|
52
|
+
default = options[:default].map do |key|
|
53
|
+
if key.is_a?(Symbol)
|
54
|
+
I18n.normalize_keys(nil, key.to_s, options[:scope], options[:separator]).join('.').to_sym
|
55
|
+
else
|
56
|
+
key
|
57
|
+
end
|
58
|
+
end
|
59
|
+
else
|
60
|
+
default = options[:default]
|
61
|
+
end
|
62
|
+
|
63
|
+
@cache[key_with_locale] = default
|
64
|
+
content = @cache[key_with_locale]
|
65
|
+
end
|
54
66
|
end
|
55
67
|
## return translated content
|
56
68
|
content
|
@@ -75,17 +87,5 @@ module Lit
|
|
75
87
|
super
|
76
88
|
end
|
77
89
|
|
78
|
-
def default(locale, object, subject, options = {})
|
79
|
-
content = super(locale, object, subject, options)
|
80
|
-
if content.respond_to?(:to_str)
|
81
|
-
parts = I18n.normalize_keys(locale, object, options[:scope], options[:separator])
|
82
|
-
if parts.size > 1
|
83
|
-
key = parts.join('.')
|
84
|
-
@cache[key] = content
|
85
|
-
end
|
86
|
-
end
|
87
|
-
content
|
88
|
-
end
|
89
|
-
|
90
90
|
end
|
91
91
|
end
|
data/lib/lit/version.rb
CHANGED
data/lib/tasks/lit_tasks.rake
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
# desc "Explaining what the task does"
|
2
|
-
# task :lit do
|
3
|
-
# # Task goes here
|
4
|
-
# end
|
5
1
|
namespace :lit do
|
2
|
+
desc "Exports translated strings from lit to config/locales/lit.yml file."
|
6
3
|
task :export => :environment do
|
7
4
|
if yml = Lit.init.cache.export
|
8
5
|
PATH = "config/locales/lit.yml"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-04-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -59,22 +59,6 @@ dependencies:
|
|
59
59
|
- - ! '>'
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '3.1'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: bootstrap-sass
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '2.1'
|
70
|
-
type: :runtime
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '2.1'
|
78
62
|
- !ruby/object:Gem::Dependency
|
79
63
|
name: pg
|
80
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -388,7 +372,6 @@ files:
|
|
388
372
|
- app/assets/javascripts/lit/jquery-te-1.4.0.min.js
|
389
373
|
- app/assets/javascripts/lit/localizations.js.coffee
|
390
374
|
- app/assets/stylesheets/lit/application.css
|
391
|
-
- app/assets/stylesheets/lit/bootstrap_and_overrides.css.scss
|
392
375
|
- app/assets/stylesheets/lit/dashboard.css
|
393
376
|
- app/assets/stylesheets/lit/jquery-te-1.4.0.css.scss
|
394
377
|
- app/controllers/lit/api/v1/base_controller.rb
|
@@ -487,7 +470,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
487
470
|
version: '0'
|
488
471
|
requirements: []
|
489
472
|
rubyforge_project:
|
490
|
-
rubygems_version: 1.8.23
|
473
|
+
rubygems_version: 1.8.23.2
|
491
474
|
signing_key:
|
492
475
|
specification_version: 3
|
493
476
|
summary: Database powered i18n backend with web gui
|
@@ -1,43 +0,0 @@
|
|
1
|
-
// Set the correct sprite paths
|
2
|
-
$iconSpritePath: asset-path('glyphicons-halflings.png', image);
|
3
|
-
$iconWhiteSpritePath: asset-path('glyphicons-halflings-white.png', image);
|
4
|
-
$baseFontSize: 13px;
|
5
|
-
$baseLineHeight: 18px;
|
6
|
-
@import "bootstrap";
|
7
|
-
body { padding-top: 60px; }
|
8
|
-
@import "bootstrap-responsive";
|
9
|
-
|
10
|
-
.btn-invite {
|
11
|
-
&:active, &.active {
|
12
|
-
background-color: #99cc99; } }
|
13
|
-
|
14
|
-
.btn-save {
|
15
|
-
&:active, &.active {
|
16
|
-
background-color: #cccc66; } }
|
17
|
-
|
18
|
-
.btn-discard {
|
19
|
-
&:active, &.active {
|
20
|
-
background-color: #cc9999; } }
|
21
|
-
h1 { font-size: 30px; line-height: 36px; }
|
22
|
-
h2 { font-size: 24px; line-height: 36px; }
|
23
|
-
h3 { font-size: 18px; line-height: 27px; }
|
24
|
-
h4 { font-size: 14px; line-height: 18px; }
|
25
|
-
h5 { font-size: 12px; line-height: 18px; }
|
26
|
-
h6 { font-size: 11px; line-height: 18px; }
|
27
|
-
|
28
|
-
h1 small { font-size: 18px; }
|
29
|
-
h2 small { font-size: 18px; }
|
30
|
-
h3 small { font-size: 14px; }
|
31
|
-
h4 small { font-size: 12px; }
|
32
|
-
h1, h2, h3, h4, h5, h6 {
|
33
|
-
color: inherit;
|
34
|
-
font-family: inherit;
|
35
|
-
font-weight: bold;
|
36
|
-
margin: 0;
|
37
|
-
text-rendering: optimizelegibility;
|
38
|
-
}
|
39
|
-
h6 {
|
40
|
-
color: #999999;
|
41
|
-
font-size: 11px;
|
42
|
-
text-transform: uppercase;
|
43
|
-
}
|