couch_i18n 0.2.1 → 0.3.1

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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/README.rdoc +1 -2
  3. data/app/assets/javascripts/couch_i18n/application.js.coffee +8 -0
  4. data/app/assets/stylesheets/couch_i18n/application.sass +4 -0
  5. data/app/assets/stylesheets/couch_i18n/components/_buttons.sass +11 -0
  6. data/app/assets/stylesheets/couch_i18n/components/_forms.sass +45 -0
  7. data/app/assets/stylesheets/couch_i18n/components/_offset_navigation.sass +19 -0
  8. data/app/assets/stylesheets/couch_i18n/foundation_and_overrides.scss +1447 -0
  9. data/app/assets/stylesheets/couch_i18n/{structure.css.scss → structure.scss} +0 -24
  10. data/app/controllers/couch_i18n/application_controller.rb +16 -4
  11. data/app/controllers/couch_i18n/translations_controller.rb +37 -33
  12. data/app/models/couch_i18n/translation.rb +133 -26
  13. data/app/views/couch_i18n/application/_error_messages.html.slim +6 -0
  14. data/app/views/couch_i18n/translations/_form.html.slim +15 -0
  15. data/app/views/couch_i18n/translations/edit.html.slim +2 -0
  16. data/app/views/couch_i18n/translations/index.html.slim +91 -0
  17. data/app/views/couch_i18n/translations/new.html.slim +2 -0
  18. data/app/views/kaminari/couch_i18n/_first_page.html.erb +3 -0
  19. data/app/views/kaminari/couch_i18n/_first_page.html.slim +2 -0
  20. data/app/views/kaminari/couch_i18n/_gap.html.erb +3 -0
  21. data/app/views/kaminari/couch_i18n/_gap.html.slim +2 -0
  22. data/app/views/kaminari/couch_i18n/_last_page.html.erb +3 -0
  23. data/app/views/kaminari/couch_i18n/_last_page.html.slim +2 -0
  24. data/app/views/kaminari/couch_i18n/_next_page.html.erb +3 -0
  25. data/app/views/kaminari/couch_i18n/_next_page.html.slim +2 -0
  26. data/app/views/kaminari/couch_i18n/_page.html.erb +3 -0
  27. data/app/views/kaminari/couch_i18n/_page.html.slim +2 -0
  28. data/app/views/kaminari/couch_i18n/_paginator.html.erb +17 -0
  29. data/app/views/kaminari/couch_i18n/_paginator.html.slim +12 -0
  30. data/app/views/kaminari/couch_i18n/_prev_page.html.erb +3 -0
  31. data/app/views/kaminari/couch_i18n/_prev_page.html.slim +2 -0
  32. data/app/views/layouts/couch_i18n/application.html.slim +28 -0
  33. data/config/initializers/assets.rb +1 -0
  34. data/config/locales/couch_i18n.en.yml +9 -2
  35. data/config/routes.rb +2 -1
  36. data/lib/couch_i18n/active_model_errors.rb +2 -2
  37. data/lib/couch_i18n/backend.rb +1 -5
  38. data/lib/couch_i18n/engine.rb +12 -0
  39. data/lib/couch_i18n/store.rb +24 -12
  40. data/lib/couch_i18n/version.rb +3 -0
  41. data/lib/couch_i18n.rb +30 -9
  42. metadata +51 -42
  43. data/app/assets/javascripts/couch_i18n/application.js +0 -10
  44. data/app/assets/stylesheets/couch_i18n/application.css +0 -7
  45. data/app/assets/stylesheets/couch_i18n/bootstrap_and_override.css.less +0 -5
  46. data/app/views/couch_i18n/application/_error_messages.html.haml +0 -6
  47. data/app/views/couch_i18n/translations/_form.html.haml +0 -16
  48. data/app/views/couch_i18n/translations/edit.html.haml +0 -4
  49. data/app/views/couch_i18n/translations/index.html.haml +0 -82
  50. data/app/views/couch_i18n/translations/new.html.haml +0 -4
  51. data/app/views/layouts/couch_i18n/application.html.haml +0 -35
  52. /data/app/assets/stylesheets/couch_i18n/{alerts.css.scss → alerts.scss} +0 -0
  53. /data/app/views/couch_i18n/application/{_alerts.html.haml → _alerts.html.slim} +0 -0
@@ -46,30 +46,6 @@ form{
46
46
  .untranslated-label{
47
47
  display: inline;
48
48
  }
49
- .offset-navigation-block{
50
- border-style: double;
51
- border-color: #444;
52
- border-left-width: 0;
53
- border-right-width: 0;
54
- padding: 5px 0;
55
- margin-top: 5px;
56
- .offset-navigation-deeper, .offset-navigation-higher{
57
- a{
58
- float: left;
59
- margin-right: 5px;
60
- margin-top: 5px;
61
- padding: 4px;
62
- border: 1px solid #aaa;
63
- &:hover {
64
- background-color: #ddd;
65
- border-color: black;
66
- }
67
- }
68
- }
69
- .offset-navigation-form{
70
- margin-top: 5px;
71
- }
72
- }
73
49
  .clearing{
74
50
  clear: both;
75
51
  }
@@ -1,14 +1,26 @@
1
1
  module CouchI18n
2
- class ApplicationController < ActionController::Base
3
- before_filter :authorize_user
4
- layout 'couch_i18n/application'
2
+ class ApplicationController < ::ApplicationController
3
+ before_action :authorize_user
4
+ layout :couch_i18n_layout
5
5
 
6
6
  private
7
7
 
8
+ def cmtool_user
9
+ main_app.cmtool_user
10
+ end
11
+
12
+ def couch_i18n_layout
13
+ defined?(Cmtool) ? 'cmtool/application' : 'couch_i18n/application'
14
+ # Does not integrate well with cmtool layout at the moment (2012-12-17)
15
+ 'couch_i18n/application'
16
+ end
17
+
8
18
  def authorize_user
9
19
  if respond_to?(:authorize_couch_i18n)
10
20
  authorize_couch_i18n
11
- elsif respond_to?(:current_user) && current_user.present? && current_user.respond_to?(:is_admin) && !current_user.is_admin.present?
21
+ elsif defined?(Cmtool)
22
+ authorize_cmtool
23
+ elsif respond_to?(:current_user) && current_user.respond_to?(:is_admin) && !current_user.is_admin.present?
12
24
  redirect_to '/', :alert => I18n.t('couch_i18n.general.not_authorized')
13
25
  end
14
26
  end
@@ -5,52 +5,51 @@ module CouchI18n
5
5
  @available_deeper_offsets = []
6
6
  per_page = params[:per_page].presence.try(:to_i) || 30
7
7
  if params[:partfinder].present?
8
- @translations = CouchI18n::Translation.find_all_by_key_part(params[:offset], page: params[:page], per_page: per_page)
8
+ if untranslated?
9
+ @translations = CouchI18n::Translation.find_all_untranslated_by_key_part(params[:offset], page: params[:page], per_page: per_page)
10
+ else
11
+ @translations = CouchI18n::Translation.find_all_by_key_part(params[:offset], page: params[:page], per_page: per_page)
12
+ end
9
13
  elsif params[:valuefinder].present?
10
- @translations = CouchI18n::Translation.find_all_by_value(params[:offset], page: params[:page], per_page: per_page)
14
+ if untranslated?
15
+ @translations = CouchI18n::Translation.find_all_untranslated_by_value(params[:offset], page: params[:page], per_page: per_page)
16
+ else
17
+ @translations = CouchI18n::Translation.find_all_by_value(params[:offset], page: params[:page], per_page: per_page)
18
+ end
11
19
  else
12
20
  if params[:offset].present?
13
- @levels = params[:offset].split('.')
14
- # Add higher levels. Do not add the last level, since it is the current one => 0..-2
15
- @levels[0..-2].each_with_index do |level_name, i|
16
- @available_higher_offsets << {
17
- :name => level_name,
18
- :offset => @levels[0..i].join('.')
19
- }
20
- end
21
21
  if untranslated?
22
22
  @translations = CouchI18n::Translation.untranslated_with_offset(params[:offset], :page => params[:page], :per_page => per_page)
23
23
  else
24
24
  @translations = CouchI18n::Translation.with_offset(params[:offset], :page => params[:page], :per_page => per_page)
25
25
  end
26
- @available_deeper_offsets = CouchI18n::Translation.get_keys_by_level(@levels.size, :startkey => @levels, :endkey => @levels + [{}]).
27
- map{|dl| {:name => dl, :offset => [params[:offset], dl].join('.')}}
28
26
  else
29
27
  if untranslated?
30
28
  @translations = CouchI18n::Translation.untranslated(:page => params[:page], :per_page => per_page)
31
29
  else
32
30
  @translations = CouchI18n::Translation.all(:page => params[:page], :per_page => per_page)
33
31
  end
34
- @available_deeper_offsets = CouchI18n::Translation.get_keys_by_level(0).map{|dl| {:name => dl, :offset => dl}}
35
32
  end
33
+ @available_higher_offsets = CouchI18n::Translation.higher_keys_for_offset(params[:offset])
34
+ @available_deeper_offsets = CouchI18n::Translation.deeper_keys_for_offset(params[:offset])
36
35
  end
37
36
  end
38
37
 
39
38
  def show
40
- @translation = CouchI18n::Translation.find(params[:id])
39
+ redirect_to action: :edit
41
40
  end
42
41
 
43
42
  def new
44
- @translation = CouchI18n::Translation.new :key => params[:offset]
43
+ @translation = CouchI18n::Translation.new translation_key: params[:offset]
45
44
  end
46
45
 
47
46
  def create
48
- @translation = CouchI18n::Translation.new params[:translation]
47
+ @translation = CouchI18n::Translation.new translation_params
49
48
  if @translation.value.present? && params[:is_json].present?
50
49
  @translation.value = JSON.parse(@translation.value)
51
50
  end
52
51
  if @translation.save
53
- redirect_to({:action => :index, :offset => @translation.key.to_s.sub(/\.[\w\s-]+$/, '')}, :notice => I18n.t('couch_i18n.action.create.successful', :model => CouchI18n::Translation.model_name.human))
52
+ redirect_to({:action => :index, :offset => @translation.translation_key.to_s.sub(/\.[\w\s-]+$/, '')}, :notice => I18n.t('couch_i18n.action.create.successful', :model => CouchI18n::Translation.model_name.human))
54
53
  else
55
54
  render :action => :new
56
55
  end
@@ -65,11 +64,12 @@ module CouchI18n
65
64
  def update
66
65
  @translation = CouchI18n::Translation.find(params[:id])
67
66
  @translation.translated = true
68
- if params[:translation]["value"].present? && params[:is_json].present?
69
- params[:translation]["value"] = JSON.parse(params[:translation]["value"])
67
+ tparams = translation_params
68
+ if tparams["value"].present? && params[:is_json].present?
69
+ tparams["value"] = JSON.parse(tparams["value"])
70
70
  end
71
- if @translation.update_attributes(params[:translation])
72
- redirect_to({:action => :index, :offset => @translation.key.to_s.sub(/\.[\w\s-]+$/, '')}, :notice => I18n.t('couch_i18n.action.update.successful', :model => CouchI18n::Translation.model_name.human))
71
+ if @translation.update_attributes(tparams)
72
+ redirect_to({:action => :index, :offset => @translation.translation_key.to_s.sub(/\.[\w\s-]+$/, '')}, :notice => I18n.t('couch_i18n.action.update.successful', :model => CouchI18n::Translation.model_name.human))
73
73
  else
74
74
  render :action => :edit
75
75
  end
@@ -80,7 +80,7 @@ module CouchI18n
80
80
  if @translation.destroy
81
81
  flash[:notice] = I18n.t('couch_i18n.action.destroy.successful', :model => CouchI18n::Translation.model_name.human)
82
82
  end
83
- redirect_to({:action => :index, :offset => @translation.key.to_s.sub(/\.\w+$/, '')})
83
+ redirect_to({:action => :index, :offset => @translation.translation_key.to_s.sub(/\.\w+$/, '')})
84
84
  end
85
85
 
86
86
  # POST /couch_i18n/translations/export
@@ -103,12 +103,12 @@ module CouchI18n
103
103
  if params[:exportformat] == 'csv'
104
104
  response.headers['Content-Type'] = 'text/csv'
105
105
  response.headers['Content-Disposition'] = %{attachment; filename="#{base_filename}.csv"}
106
- render :text => @translations.map{|s| [s.key, s.value.to_json].join(',')}.join("\n")
106
+ render :text => @translations.map{|s| [s.translation_key, s.translation_value.to_json].join(',')}.join("\n")
107
107
  elsif params[:exportformat] == 'json'
108
108
  response.headers['Content-Type'] = 'application/json'
109
109
  response.headers['Content-Disposition'] = %{attachment; filename="#{base_filename}.json"}
110
110
  # render :text => CouchI18n.indent_keys(@translations).to_json # for indented json
111
- render :json => @translations.map{|s| {s.key => s.value}}.to_json
111
+ render :json => @translations.map{|s| {s.translation_key => s.translation_value}}.to_json
112
112
  else #yaml
113
113
  response.headers['Content-Type'] = 'application/x-yaml'
114
114
  response.headers['Content-Disposition'] = %{attachment; filename="#{base_filename}.yml"}
@@ -119,28 +119,28 @@ module CouchI18n
119
119
  # POST /couch_i18n/translations/import
120
120
  # Import yml files
121
121
  def import
122
- redirect_to({:action => :index, :offset => params[:offset]}, :alert => I18n.t('couch_i18n.translation.no import file given')) and return unless params[:importfile].present?
122
+ redirect_to({:action => :index, :offset => params[:offset]}, :alert => I18n.t('couch_i18n.import.no_file_given')) and return unless params[:importfile].present?
123
123
  filename = params[:importfile].original_filename
124
124
  extension = filename.sub(/.*\./, '')
125
125
  if extension == 'yml'
126
126
  hash = YAML.load_file(params[:importfile].tempfile.path) rescue nil
127
- redirect_to({:action => :index, :offset => params[:offset]}, :alert => I18n.t('couch_i18n.translation.cannot parse yaml')) and return unless hash
127
+ redirect_to({:action => :index, :offset => params[:offset]}, :alert => I18n.t('couch_i18n.import.cannot_parse')) and return unless hash
128
128
  CouchI18n.traverse_flatten_keys(hash).each do |key, value|
129
- existing = CouchI18n::Translation.find_by_key(key)
129
+ existing = CouchI18n::Translation.find_by_translation_key(key)
130
130
  if existing
131
- if existing.value != value
132
- existing.value = value
131
+ if existing.translation_value != value || !existing.translated?
132
+ existing.translation_value = value
133
133
  existing.translated = true
134
134
  existing.save
135
135
  end
136
136
  else
137
- CouchI18n::Translation.create :key => key, :value => value
137
+ CouchI18n::Translation.create translation_key: key, translation_value: value
138
138
  end
139
139
  end
140
140
  else
141
- redirect_to({:action => :index, :offset => params[:offset]}, :alert => I18n.t('couch_i18n.translation.no proper import extension', :extension => extension)) and return
141
+ redirect_to({:action => :index, :offset => params[:offset]}, :alert => I18n.t('couch_i18n.import.extension_not_valid', :extension => extension)) and return
142
142
  end
143
- redirect_to({:action => :index, :offset => params[:offset]}, :notice => I18n.t('couch_i18n.translation.file imported', :filename => filename))
143
+ redirect_to({:action => :index, :offset => params[:offset]}, :notice => I18n.t('couch_i18n.import.notice', :filename => filename))
144
144
  end
145
145
 
146
146
  # Very dangarous action, please handle this with care, large removals are supported!
@@ -152,7 +152,7 @@ module CouchI18n
152
152
  @translations = CouchI18n::Translation.all
153
153
  end
154
154
  @translations.map(&:destroy)
155
- redirect_to({:action => :index}, :notice => I18n.t('couch_i18n.translation.offset deleted', :count => @translations.size, :offset => params[:offset]))
155
+ redirect_to({:action => :index}, :notice => I18n.t('couch_i18n.general.offset_deleted_notice', :count => @translations.size, :offset => params[:offset]))
156
156
  end
157
157
 
158
158
  private
@@ -161,5 +161,9 @@ module CouchI18n
161
161
  params[:untranslated].presence
162
162
  end
163
163
  helper_method :untranslated?
164
+
165
+ def translation_params
166
+ params.require(:translation).permit(:translation_key, :translation_value, :translated)
167
+ end
164
168
  end
165
169
  end
@@ -3,43 +3,86 @@ module CouchI18n
3
3
  include SimplyStored::Couch
4
4
  per_page_method :limit_value
5
5
 
6
- property :key
7
- property :value
6
+ property :translation_value
8
7
  property :translated, type: :boolean, default: true
9
8
 
10
- validates_uniqueness_of :key
9
+ def translation_key
10
+ id.present? ? id[3..-1] : nil
11
+ end
11
12
 
12
- after_save :reload_i18n
13
+ def key
14
+ translation_key
15
+ end
13
16
 
14
- view :all_documents, :key => :key
15
- view :by_key, :key => :key
17
+ view :all_documents, map_function: %|function(doc){
18
+ if(doc.ruby_class && doc.ruby_class == 'CouchI18n::Translation') {
19
+ emit(doc._id.substr(3), 1);
20
+ }
21
+ }|, type: :custom, reduce_function: '_sum'
22
+ #view :by_key, :key => :key
16
23
 
17
24
  view :with_key_array, map_function: %|function(doc){
18
25
  if(doc.ruby_class && doc.ruby_class == 'CouchI18n::Translation') {
19
- emit(doc.key.split('.').slice(0, -1), 1);
26
+ emit(doc._id.substr(3).split('.').slice(0, -1), 1);
20
27
  }
21
28
  }|, type: :raw, reduce_function: '_sum'
22
29
 
23
- view :untranslated_view, key: :key, conditions: "!doc['translated']"
24
- view :by_value, key: :value
25
- view :by_key_part, type: :custom, map_function: %|function(doc){
30
+ view :untranslated_view, map_function: %|function(doc){
31
+ if(doc.ruby_class && doc.ruby_class == 'CouchI18n::Translation' && !doc.translated) {
32
+ emit(doc._id.substr(3), 1);
33
+ }
34
+ }|, type: :custom, reduce_function: '_sum'
35
+ view :by_translation_value, key: :translation_value
36
+ view :untranslated_by_translation_value, key: :translation_value, conditions: "!doc['translated']"
37
+ view :by_translation_key_part, type: :custom, map_function: %|function(doc){
26
38
  if(doc.ruby_class && doc.ruby_class == 'CouchI18n::Translation') {
27
- var parts = doc.key.split('.');
28
- for(var i = 0; i < parts.length; i++){
29
- emit(parts[i], 1);
30
- }
39
+ doc._id.substr(3).split('.').forEach(function(key_part){
40
+ emit(key_part, 1)
41
+ })
31
42
  }
32
43
  }|, reduce_function: '_count'
33
44
 
34
- def self.get_keys_by_level(level = 0, options = {})
35
- data = database.view(with_key_array(options.merge(:group_level => level.succ)))["rows"]
45
+ view :untranslated_by_translation_key_part, type: :custom, map_function: %|function(doc){
46
+ if(doc.ruby_class && doc.ruby_class == 'CouchI18n::Translation' && !doc.translated) {
47
+ doc._id.substr(3).split('.').forEach(function(key_part){
48
+ emit(key_part, 1)
49
+ })
50
+ }
51
+ }|, reduce_function: '_count'
52
+
53
+ def self.get_translation_keys_by_level(level = 0, options = {})
54
+ data = database.view(with_key_array(options.merge(group_level: level.succ)))["rows"]
36
55
  # data = data.select{|h| h["key"].size > level } # Only select ones that have a deeper nesting
37
56
  data.map{|h| h['key'][level].try(:to_sym)}.compact
38
57
  end
39
58
 
59
+ def translation_key=(val)
60
+ self.id = "t::#{val}"
61
+ end
62
+
40
63
  # Shorthand for selecting all stored with a given offset
41
64
  def self.with_offset(offset, options = {})
42
- CouchI18n::Translation.find_all_by_key("#{offset}.".."#{offset}.ZZZZZZZZZ", options)
65
+ key = "#{offset}.".."#{offset}.ZZZZZZZZZ"
66
+ total_entries = database.view(all_documents(key: key, reduce: true))
67
+ with_pagination_options options.merge(total_entries: total_entries) do |options|
68
+ database.view(all_documents(options.merge(key: key, reduce: false, include_docs: true)))
69
+ end
70
+ end
71
+
72
+ def self.all(options = {})
73
+ total_entries = database.view(all_documents(reduce: true))
74
+ with_pagination_options options.merge(total_entries: total_entries) do |options|
75
+ database.view(all_documents(options.merge(reduce: false, include_docs: true)))
76
+ end
77
+ end
78
+
79
+ def self.find_by_translation_key(key)
80
+ begin
81
+ find("t::#{key}")
82
+ rescue SimplyStored::RecordNotFound
83
+ CouchI18n.handle_missing_key(key)
84
+ nil
85
+ end
43
86
  end
44
87
 
45
88
  # Find all records having the term part in their key
@@ -50,16 +93,59 @@ module CouchI18n
50
93
  # find_all_by_part('action')
51
94
  # will return the first two since they have action as key part
52
95
  def self.find_all_by_key_part(part, options = {})
53
- total_entries = database.view(by_key_part(key: part, reduce: true))
96
+ total_entries = database.view(by_translation_key_part(key: part, reduce: true))
54
97
  with_pagination_options options.merge(total_entries: total_entries) do |options|
55
- database.view(by_key_part(options.merge(key: part, reduce: false, include_docs: true)))
98
+ database.view(by_translation_key_part(options.merge(key: part, reduce: false, include_docs: true)))
56
99
  end
57
100
  end
58
101
 
102
+ # Find all untranslated records having the term part in their key
103
+ # nl.action.one
104
+ # en.action.two
105
+ # en.activemodel.plural.models.user
106
+ # and using
107
+ # find_all_by_part('action')
108
+ # will return the first two since they have action as key part
109
+ def self.find_all_untranslated_by_key_part(part, options = {})
110
+ total_entries = database.view(untranslated_by_translation_key_part(key: part, reduce: true))
111
+ with_pagination_options options.merge(total_entries: total_entries) do |options|
112
+ database.view(untranslated_by_translation_key_part(options.merge(key: part, reduce: false, include_docs: true)))
113
+ end
114
+ end
115
+
116
+ # Find all untranslated records having the term part as value
117
+ # nl.action.one: 'Value', translated: true
118
+ # en.action.two: 'Value', translated: false
119
+ # en.activemodel.plural.models.user: 'Other Value', translated: false
120
+ # and using
121
+ # find_all_untranslated_by_value('Value')
122
+ # will return en.action.two
123
+ def self.find_all_untranslated_by_value(part, options = {})
124
+ total_entries = database.view(untranslated_by_translation_value(key: part, reduce: true))
125
+ with_pagination_options options.merge(total_entries: total_entries) do |options|
126
+ database.view(untranslated_by_translation_value(options.merge(key: part, reduce: false, include_docs: true)))
127
+ end
128
+ end
129
+
130
+ # Find all untranslated records having the term part as value
131
+ # nl.action.one: 'Value', translated: true
132
+ # en.action.two: 'Value', translated: false
133
+ # en.activemodel.plural.models.user: 'Other Value', translated: false
134
+ # and using
135
+ # find_all_untranslated_by_value('Value')
136
+ # will return en.action.two
137
+ def self.find_all_by_value(part, options = {})
138
+ total_entries = database.view(by_translation_value(key: part, reduce: true))
139
+ with_pagination_options options.merge(total_entries: total_entries) do |options|
140
+ database.view(by_translation_value(options.merge(key: part, reduce: false, include_docs: true)))
141
+ end
142
+ end
143
+
144
+
59
145
  def self.untranslated(options = {})
60
- total_entries = database.view(untranslated_view(options.select{|k,v| [:key, :keys, :startkey, :endkey].include?(k)}.merge(reduce: true)))
146
+ total_entries = database.view(untranslated_view(options.slice(:key, :keys, :startkey, :endkey).merge(reduce: true)))
61
147
  with_pagination_options options.merge(total_entries: total_entries) do |options|
62
- database.view(untranslated_view(options))
148
+ database.view(untranslated_view(options.merge(reduce: false, include_docs: true)))
63
149
  end
64
150
  end
65
151
 
@@ -67,11 +153,32 @@ module CouchI18n
67
153
  CouchI18n::Translation.untranslated(options.merge(key: "#{offset}.".."#{offset}.ZZZZZZZZZ"))
68
154
  end
69
155
 
70
- # Expire I18n when record is update
71
- def reload_i18n
72
- Rails.cache.write("couch_i18n-#{key}", value)
73
- #I18n.reload!
74
- #I18n.cache_store.clear if I18n.respond_to?(:cache_store) && I18n.cache_store.respond_to?(:clear)
156
+ def self.get_keys_by_level(level = 0, options = {})
157
+ data = database.view(with_key_array(options.merge(group_level: level.succ)))["rows"]
158
+ # data = data.select{|h| h["key"].size > level } # Only select ones that have a deeper nesting
159
+ data.map{|h| h['key'][level].try(:to_sym)}.compact
160
+ end
161
+
162
+ def self.deeper_keys_for_offset( offset )
163
+ return get_keys_by_level(0).map{|dl| {:name => dl, :offset => dl}} unless offset.present?
164
+ levels = offset.split('.')
165
+ get_keys_by_level(levels.size, :startkey => levels, :endkey => levels + [{}]).
166
+ map{|dl| {:name => dl, :offset => [offset, dl].join('.')}}
167
+ end
168
+
169
+ def self.higher_keys_for_offset( offset )
170
+ return [] unless offset.present?
171
+ higher_keys = []
172
+ levels = offset.split('.')
173
+ return [] unless levels.size > 1
174
+ # Add higher levels. Do not add the last level, since it is the current one => 0..-2
175
+ levels[0..-2].each_with_index do |level_name, i|
176
+ higher_keys<< {
177
+ :name => level_name,
178
+ :offset => levels[0..i].join('.')
179
+ }
180
+ end
181
+ higher_keys
75
182
  end
76
183
  end
77
184
  end
@@ -0,0 +1,6 @@
1
+ -if target.errors.any?
2
+ #errorExplanation
3
+ h2= t('couch_i18n.errors.title', :count => target.errors.count)
4
+ ul
5
+ - target.errors.full_messages.each do |msg|
6
+ li= msg
@@ -0,0 +1,15 @@
1
+ = form_for @translation, html: {class: 'form-horizontal'} do |f|
2
+ = hidden_field_tag 'offset', params[:offset]
3
+ = render 'error_messages', :target => @translation
4
+ .form-row
5
+ .form-label= f.label :translation_key, class: 'control-label'
6
+ .form-field.full= f.text_field :translation_key, :size => 70, class: 'input-xxlarge'
7
+ .form-row
8
+ .form-label= f.label :translation_value, class: 'control-label'
9
+ .form-field.full= f.text_field :translation_value, :size => 70, class: 'input-xxlarge'
10
+ .form-row
11
+ .form-label= label_tag :is_json, t('couch_i18n.general.is_json'), class: 'control-label'
12
+ .form-field= check_box_tag :is_json, 1, f.object.translation_value.to_s =~ /^\{|^\[/
13
+ .form-row: .form-actions
14
+ = link_to link_to_index_content(:translations), couch_i18n.translations_path(:offset => params[:offset] || @translation.key.to_s.sub(/\.[\w\s-]+$/, '')), class: 'secondary button'
15
+ = f.submit local_assigns[:submit] || update_button_text, class: 'button'
@@ -0,0 +1,2 @@
1
+ - title t("couch_i18n.action.edit.title")
2
+ = render 'form'
@@ -0,0 +1,91 @@
1
+ - if params[:offset].present?
2
+ - title params[:offset]
3
+ - else
4
+ - title t("couch_i18n.action.index.title")
5
+ .row.top-buttons: .small-12.columns
6
+ a.import-button data-reveal-id="import-modal" href="#" = t('couch_i18n.import.label')
7
+ a.export-button data-reveal-id="export-modal" href="#" = t('couch_i18n.export.label')
8
+ = link_to t('couch_i18n.action.destroy.offset_link'), couch_i18n.destroy_offset_translations_path(offset: params[:offset]), method: :delete, data: {confirm: (defined?(:are_you_sure) ? are_you_sure : t('couch_i18n.general.are_you_sure'))}, class: 'delete-all-from-offset-button'
9
+
10
+ #import-modal.reveal-modal data-reveal=true
11
+ a.close-reveal-modal &#215
12
+ = form_tag({action: :import}, multipart: true) do
13
+ .modal-header
14
+ h3= t('couch_i18n.import.label')
15
+ .modal-body
16
+ p= t('couch_i18n.import.description')
17
+ = file_field_tag :importfile
18
+ .modal-footer
19
+ = submit_tag I18n.t('couch_i18n.import.button'), class: 'warning button'
20
+ #export-modal.reveal-modal data-reveal=true
21
+ a.close-reveal-modal &#215
22
+ = form_tag action: :export do
23
+ = hidden_field_tag :offset, params[:offset]
24
+ .modal-header
25
+ - if params[:offset].present?
26
+ h3= t('couch_i18n.export.from_offset', offset: params[:offset])
27
+ - else
28
+ h3= t('couch_i18n.export.label')
29
+ .row.modal-body
30
+ .small-6.columns= select_tag :exportformat, options_for_select(%w[yml csv json], params[:exportformat])
31
+ .small-6.columns
32
+ = check_box_tag :untranslated
33
+ = label_tag :untranslated, t('couch_i18n.export.untranslated'), class: 'untranslated-label'
34
+ .modal-footer
35
+ = submit_tag I18n.t('couch_i18n.export.execute'), class: 'success button'
36
+ .offset-navigation-block.block
37
+ .row
38
+ .small-12.columns
39
+ ul.button-group
40
+ - for offset in @available_higher_offsets
41
+ li= link_to offset[:name], {offset: offset[:offset], untranslated: params[:untranslated]}, class: 'secondary tiny button'
42
+ = form_tag({}, method: :get )do
43
+ .row
44
+ .small-5.columns
45
+ .row.collapse
46
+ .small-2.columns
47
+ - if params[:offset].present?
48
+ = link_to 'x' || I18n.t('couch_i18n.general.go_to_zero_offset'), {offset: nil}, class: 'prefix button'
49
+ .small-10.columns= text_field_tag :offset, params[:offset], size: 60
50
+ .small-4.columns
51
+ ul.button-group
52
+ li: input.tiny.button type="submit" name="commit" value=I18n.t('couch_i18n.general.go_to_offset')
53
+ li: input.tiny.button type="submit" name="partfinder" value=I18n.t('couch_i18n.general.find_part')
54
+ li: input.tiny.button type="submit" name="valuefinder" value=I18n.t('couch_i18n.general.find_value')
55
+ .small-3.columns
56
+ = "(#{@translations.total_count})"
57
+ = check_box_tag :untranslated, 1, untranslated?, id: :untranslated_listing
58
+ = label_tag :untranslated_listing, I18n.t('couch_i18n.general.untranslated_label'), class: 'untranslated-label'
59
+ .row
60
+ .small-12.columns
61
+ ul.button-group
62
+ - for offset in @available_deeper_offsets
63
+ li= link_to offset[:name], {offset: offset[:offset], untranslated: params[:untranslated]}, class: 'secondary tiny button'
64
+ - if @translations.any?
65
+ .row: .small-12.columns= paginate @translations, right: 3, left: 3, theme: 'couch_i18n'
66
+ .row: .small-12.columns
67
+ table.table.table-striped
68
+ thead
69
+ tr
70
+ th= CouchI18n::Translation.human_attribute_name(:translation_key)
71
+ th= CouchI18n::Translation.human_attribute_name(:translation_value)
72
+ th= CouchI18n::Translation.human_attribute_name(:translated)
73
+ th.action.edit
74
+ th.action.destroy
75
+ tbody
76
+ - @translations.each do |translation|
77
+ tr class=cycle('odd', 'even')
78
+ td
79
+ - if partfinder? || valuefinder?
80
+ = link_to translation.translation_key.to_s.sub(/^\./, ''), couch_i18n.edit_translation_path(translation, offset: params[:offset])
81
+ - else
82
+ = link_to translation.translation_key.to_s[(params[:offset].try(:size) || 0)..-1].sub(/^\./, ''), couch_i18n.edit_translation_path(translation, offset: params[:offset])
83
+ td= link_to translation.translation_value, couch_i18n.edit_translation_path(translation, offset: params[:offset])
84
+ td.boolean= boolean_show(translation.translated)
85
+ td.action.edit= link_to link_to_edit_content(translation), couch_i18n.edit_translation_path(translation, offset: params[:offset]), class: 'tiny warning button'
86
+ td.action.destroy= link_to link_to_destroy_content(translation),couch_i18n.translation_path(translation, offset: params[:offset]), data: {confirm: are_you_sure}, method: :delete, class: 'destroy-translation-button'
87
+ - else
88
+ .row: .small-12.columns: h3= t("couch_i18n.general.none_found")
89
+
90
+ - content_for :page_links do
91
+ = link_to link_to_new_content(:translation), couch_i18n.new_translation_path(offset: params[:offset]), class: 'button'
@@ -0,0 +1,2 @@
1
+ - title t("couch_i18n.action.new.title")
2
+ = render 'form', submit: create_button_text
@@ -0,0 +1,3 @@
1
+ <li>
2
+ <%= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote %>
3
+ </li>
@@ -0,0 +1,2 @@
1
+ li
2
+ = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote
@@ -0,0 +1,3 @@
1
+ <li class="unavailable">
2
+ <%= link_to raw(t 'views.pagination.truncate'), '#' %>
3
+ </li>
@@ -0,0 +1,2 @@
1
+ li.unavailable
2
+ = link_to raw(t 'views.pagination.truncate'), '#'
@@ -0,0 +1,3 @@
1
+ <li>
2
+ <%= link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote} %>
3
+ </li>
@@ -0,0 +1,2 @@
1
+ li
2
+ = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote}
@@ -0,0 +1,3 @@
1
+ <li>
2
+ <%= link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote %>
3
+ </li>
@@ -0,0 +1,2 @@
1
+ li
2
+ = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote
@@ -0,0 +1,3 @@
1
+ <li class="<%= 'current' if page.current? %>">
2
+ <%= link_to page, page.current? ? '#' : url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %>
3
+ </li>
@@ -0,0 +1,2 @@
1
+ li class: "#{'current' if page.current?}"
2
+ = link_to page, page.current? ? '#' : url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil}
@@ -0,0 +1,17 @@
1
+ <%= paginator.render do -%>
2
+ <div class="pagination-centered">
3
+ <ul class="pagination">
4
+ <%= first_page_tag unless current_page.first? %>
5
+ <%= prev_page_tag unless current_page.first? %>
6
+ <% each_page do |page| -%>
7
+ <% if page.left_outer? || page.right_outer? || page.inside_window? -%>
8
+ <%= page_tag page %>
9
+ <% elsif !page.was_truncated? -%>
10
+ <%= gap_tag %>
11
+ <% end -%>
12
+ <% end -%>
13
+ <%= next_page_tag unless current_page.last? %>
14
+ <%= last_page_tag unless current_page.last? %>
15
+ </ul>
16
+ </div>
17
+ <% end -%>
@@ -0,0 +1,12 @@
1
+ = paginator.render do
2
+ .pagination-centered
3
+ ul.pagination
4
+ = first_page_tag unless current_page.first?
5
+ = prev_page_tag unless current_page.first?
6
+ - each_page do |page|
7
+ - if page.left_outer? || page.right_outer? || page.inside_window?
8
+ = page_tag page
9
+ - elsif !page.was_truncated?
10
+ = gap_tag
11
+ = next_page_tag unless current_page.last?
12
+ = last_page_tag unless current_page.last?
@@ -0,0 +1,3 @@
1
+ <li>
2
+ <%= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %>
3
+ </li>
@@ -0,0 +1,2 @@
1
+ li
2
+ = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote