couch_i18n 0.2.0 → 0.2.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.
@@ -6,4 +6,5 @@
6
6
  //
7
7
  //= require jquery
8
8
  //= require jquery_ujs
9
- //= require_tree .
9
+ //= require twitter/bootstrap
10
+ //= require_directory .
@@ -1,2 +1,3 @@
1
1
  $(function(){
2
+ $('input[type=submit]').addClass('btn').addClass('btn-primary');
2
3
  });
@@ -3,5 +3,5 @@
3
3
  * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4
4
  * the top of the compiled file, but it's generally better to create a new file per style scope.
5
5
  *= require_self
6
- *= require_tree .
7
- */
6
+ *= require_directory .
7
+ */
@@ -0,0 +1,5 @@
1
+ @import "twitter/bootstrap/bootstrap";
2
+
3
+ body { padding-top: 60px; }
4
+
5
+ @import "twitter/bootstrap/responsive";
@@ -1,16 +1,13 @@
1
1
  html, body{
2
- margin: 0;
3
- padding: 0;
4
2
  }
5
3
  body{
6
- background-color: #ddf;
7
4
  }
8
5
  h1, h2, h3, h4, h5, h6{
9
- margin: 0;
10
- padding: 0;
11
6
  }
12
7
  h1{
13
- font-size: 22px;
8
+ }
9
+ form{
10
+ margin-bottom: 0; /* bootstrap fix */
14
11
  }
15
12
  #page-wrapper{
16
13
  width: 922px;
@@ -34,9 +31,6 @@ h1{
34
31
  }
35
32
  }
36
33
  }
37
- tr.even{
38
- background-color: #ddf;
39
- }
40
34
  #page-links{
41
35
  margin-top: 8px;
42
36
  margin-bottom: 8px;
@@ -49,7 +43,9 @@ tr.even{
49
43
  }
50
44
  }
51
45
  }
52
-
46
+ .untranslated-label{
47
+ display: inline;
48
+ }
53
49
  .offset-navigation-block{
54
50
  border-style: double;
55
51
  border-color: #444;
@@ -77,3 +73,12 @@ tr.even{
77
73
  .clearing{
78
74
  clear: both;
79
75
  }
76
+
77
+ .pagination{
78
+ ul{
79
+ list-style: none;
80
+ li{
81
+ float: left;
82
+ }
83
+ }
84
+ }
@@ -6,7 +6,9 @@ module CouchI18n
6
6
  private
7
7
 
8
8
  def authorize_user
9
- if respond_to?(:current_user) && current_user.present? && current_user.respond_to?(:is_admin) && !current_user.is_admin.present?
9
+ if respond_to?(:authorize_couch_i18n)
10
+ authorize_couch_i18n
11
+ elsif respond_to?(:current_user) && current_user.present? && current_user.respond_to?(:is_admin) && !current_user.is_admin.present?
10
12
  redirect_to '/', :alert => I18n.t('couch_i18n.general.not_authorized')
11
13
  end
12
14
  end
@@ -18,7 +18,7 @@ module CouchI18n
18
18
  if(doc.ruby_class && doc.ruby_class == 'CouchI18n::Translation') {
19
19
  emit(doc.key.split('.').slice(0, -1), 1);
20
20
  }
21
- }|, type: :raw, reduce_function: :_sum
21
+ }|, type: :raw, reduce_function: '_sum'
22
22
 
23
23
  view :untranslated_view, key: :key, conditions: "!doc['translated']"
24
24
  view :by_value, key: :value
@@ -69,9 +69,9 @@ module CouchI18n
69
69
 
70
70
  # Expire I18n when record is update
71
71
  def reload_i18n
72
- Rails.cache.write(key, value)
73
- I18n.reload!
74
- I18n.cache_store.clear if I18n.respond_to?(:cache_store) && I18n.cache_store.respond_to?(:clear)
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)
75
75
  end
76
76
  end
77
77
  end
@@ -0,0 +1,77 @@
1
+ module CouchI18n
2
+ class Translation
3
+ include SimplyStored::Couch
4
+ per_page_method :limit_value
5
+
6
+ property :key
7
+ property :value
8
+ property :translated, type: :boolean, default: true
9
+
10
+ validates_uniqueness_of :key
11
+
12
+ after_save :reload_i18n
13
+
14
+ view :all_documents, :key => :key
15
+ view :by_key, :key => :key
16
+
17
+ view :with_key_array, map_function: %|function(doc){
18
+ if(doc.ruby_class && doc.ruby_class == 'CouchI18n::Translation') {
19
+ emit(doc.key.split('.').slice(0, -1), 1);
20
+ }
21
+ }|, type: :raw, reduce_function: '_sum'
22
+
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){
26
+ 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
+ }
31
+ }
32
+ }|, reduce_function: '_count'
33
+
34
+ def self.get_keys_by_level(level = 0, options = {})
35
+ data = database.view(with_key_array(options.merge(:group_level => level.succ)))["rows"]
36
+ # data = data.select{|h| h["key"].size > level } # Only select ones that have a deeper nesting
37
+ data.map{|h| h['key'][level].try(:to_sym)}.compact
38
+ end
39
+
40
+ # Shorthand for selecting all stored with a given offset
41
+ def self.with_offset(offset, options = {})
42
+ CouchI18n::Translation.find_all_by_key("#{offset}.".."#{offset}.ZZZZZZZZZ", options)
43
+ end
44
+
45
+ # Find all records having the term part in their key
46
+ # nl.action.one
47
+ # en.action.two
48
+ # en.activemodel.plural.models.user
49
+ # and using
50
+ # find_all_by_part('action')
51
+ # will return the first two since they have action as key part
52
+ def self.find_all_by_key_part(part, options = {})
53
+ total_entries = database.view(by_key_part(key: part, reduce: true))
54
+ 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)))
56
+ end
57
+ end
58
+
59
+ def self.untranslated(options = {})
60
+ total_entries = database.view(untranslated_view(options.select{|k,v| [:key, :keys, :startkey, :endkey].include?(k)}.merge(reduce: true)))
61
+ with_pagination_options options.merge(total_entries: total_entries) do |options|
62
+ database.view(untranslated_view(options))
63
+ end
64
+ end
65
+
66
+ def self.untranslated_with_offset(offset, options = {})
67
+ CouchI18n::Translation.untranslated(options.merge(key: "#{offset}.".."#{offset}.ZZZZZZZZZ"))
68
+ end
69
+
70
+ # Expire I18n when record is update
71
+ def reload_i18n
72
+ Rails.cache.write(key, value)
73
+ I18n.reload!
74
+ I18n.cache_store.clear if I18n.respond_to?(:cache_store) && I18n.cache_store.respond_to?(:clear)
75
+ end
76
+ end
77
+ end
@@ -1,13 +1,16 @@
1
- = form_for @translation do |f|
1
+ = form_for @translation, html: {class: 'form-horizontal'} do |f|
2
2
  = render 'error_messages', :target => @translation
3
- .field
4
- = f.label :key
5
- = f.text_field :key, :size => 70
6
- .field
7
- = f.label :value
8
- = f.text_field :value, :size => 70
9
- .field
10
- = label_tag :is_json
11
- = check_box_tag :is_json, 1, ['{', '['].include?(@translation.value.to_s.first)
12
- .actions
3
+ .control-group
4
+ = f.label :key, class: 'control-label'
5
+ .controls
6
+ = f.text_field :key, :size => 70, class: 'input-xxlarge'
7
+ .control-group
8
+ = f.label :value, class: 'control-label'
9
+ .controls
10
+ = f.text_field :value, :size => 70, class: 'input-xxlarge'
11
+ .control-group
12
+ = label_tag :is_json, t('couch_i18n.general.is_json'), class: 'control-label'
13
+ .controls
14
+ = check_box_tag :is_json, 1, f.object.value.to_s =~ /^\{|^\[/
15
+ .form-actions
13
16
  = f.submit @submit || update_button_text
@@ -1,4 +1,4 @@
1
- - title t("couch_i18n.action..edit.title")
1
+ - title t("couch_i18n.action.edit.title")
2
2
  = render 'form'
3
3
  - content_for :page_links do
4
4
  = link_to link_to_index_content(:translations), couch_i18n.translations_path(:offset => params[:offset] || @translation.key.to_s.sub(/\.[\w\s-]+$/, ''))
@@ -2,26 +2,42 @@
2
2
  - title params[:offset]
3
3
  - else
4
4
  - title t("couch_i18n.action.index.title")
5
- .destroy-link
6
- = link_to t('couch_i18n.action.destroy.offset_link'), couch_i18n.destroy_offset_translations_path(:offset => params[:offset]), :method => :delete, :confirm => (defined?(:are_you_sure) ? are_you_sure : t('couch_i18n.general.are_you_sure'))
7
- .import-form
5
+ - content_for :navbar do
6
+ %a.btn.btn-warning{data: {toggle: "modal"}, href: ".import-form"}= t('couch_i18n.import.label')
7
+ %a.btn.btn-success{data: {toggle: "modal"}, href: ".export-form"}= t('couch_i18n.export.label')
8
+ .pull-right
9
+ = link_to t('couch_i18n.action.destroy.offset_link'), couch_i18n.destroy_offset_translations_path(:offset => params[:offset]), :method => :delete, :confirm => (defined?(:are_you_sure) ? are_you_sure : t('couch_i18n.general.are_you_sure')), class: [:btn, 'btn-danger']
10
+
11
+ .modal.hide.import-form
8
12
  = form_tag({:action => :import}, :multipart => true) do
9
- = label_tag :importfile, t('couch_i18n.import.label')
10
- = file_field_tag :importfile
11
- = submit_tag I18n.t('couch_i18n.import.button')
12
- .export-form
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
+ %a.btn{data: {dismiss: :modal}, href: '#'}= t('couch_i18n.general.close')
20
+ = submit_tag I18n.t('couch_i18n.import.button')
21
+ .modal.hide.export-form
13
22
  = form_tag :action => :export do
14
23
  = hidden_field_tag :offset, params[:offset]
15
- = label_tag :exportformat, t('couch_i18n.export.label')
16
- = select_tag :exportformat, options_for_select(%w[yml csv json], params[:exportformat])
17
- = check_box_tag :untranslated
18
- = label_tag :untranslated, t('couch_i18n.export.untranslated')
19
- = submit_tag I18n.t('couch_i18n.export.execute')
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
+ .modal-body
30
+ = select_tag :exportformat, options_for_select(%w[yml csv json], params[:exportformat])
31
+ = check_box_tag :untranslated
32
+ = label_tag :untranslated, t('couch_i18n.export.untranslated'), class: 'untranslated-label'
33
+ .modal-footer
34
+ %a.btn{data: {dismiss: :modal}, href: '#'}= t('couch_i18n.general.close')
35
+ = submit_tag I18n.t('couch_i18n.export.execute')
20
36
  .offset-navigation-block.block
21
- .offset-navigation-higher
37
+ .btn-toolbar
22
38
  - for offset in @available_higher_offsets
23
- = link_to offset[:name], :offset => offset[:offset]
24
- .clearing
39
+ .btn-group
40
+ = link_to offset[:name], {:offset => offset[:offset], untranslated: params[:untranslated]}, class: :btn
25
41
  .offset-navigation-form
26
42
  = form_tag({}, :method => :get )do
27
43
  - if params[:offset].present?
@@ -31,15 +47,15 @@
31
47
  %input{:type => :submit, :name => :commit, :value => I18n.t('couch_i18n.general.go_to_offset')}
32
48
  %input{:type => :submit, :name => :partfinder, :value => I18n.t('couch_i18n.general.find_part')}
33
49
  %input{:type => :submit, :name => :valuefinder, :value => I18n.t('couch_i18n.general.find_value')}
34
- = check_box_tag :untranslated, 1, untranslated?
35
- = label_tag :untranslated, I18n.t('couch_i18n.general.untranslated_label')
36
- .offset-navigation-deeper
50
+ = check_box_tag :untranslated, 1, untranslated?, id: :untranslated_listing
51
+ = label_tag :untranslated_listing, I18n.t('couch_i18n.general.untranslated_label'), class: 'untranslated-label'
52
+ .btn-toolbar
37
53
  - for offset in @available_deeper_offsets
38
- = link_to offset[:name], :offset => offset[:offset]
39
- .clearing
54
+ .btn-group
55
+ = link_to(offset[:name], {:offset => offset[:offset], untranslated: params[:untranslated]}, class: :btn)
40
56
  - if @translations.any?
41
57
  = paginate @translations, :right => 3, :left => 3
42
- %table.index-table
58
+ %table.table.table-striped
43
59
  %thead
44
60
  %tr
45
61
  %th= CouchI18n::Translation.human_attribute_name(:key)
@@ -57,8 +73,8 @@
57
73
  = link_to translation.key[(params[:offset].try(:size) || 0)..-1].sub(/^\./, ''), couch_i18n.edit_translation_path(translation)
58
74
  %td= link_to translation.value, couch_i18n.edit_translation_path(translation)
59
75
  %td.boolean= boolean_show(translation.translated)
60
- %td.action.edit= link_to link_to_edit_content(translation), couch_i18n.edit_translation_path(translation)
61
- %td.action.destroy= link_to link_to_destroy_content(translation),couch_i18n.translation_path(translation), :confirm => are_you_sure, :method => :delete
76
+ %td.action.edit= link_to link_to_edit_content(translation), couch_i18n.edit_translation_path(translation), class: [:btn]
77
+ %td.action.destroy= link_to link_to_destroy_content(translation),couch_i18n.translation_path(translation), :confirm => are_you_sure, :method => :delete, class: [:btn, 'btn-danger']
62
78
  - else
63
79
  %h3= t("couch_i18n.general.none_found")
64
80
 
@@ -2,12 +2,31 @@
2
2
  %html
3
3
  %head
4
4
  %title= defined?(site_title) ? site_title : I18n.t('couch_i18n.general.site_title')
5
- = csrf_meta_tag
5
+ /[if lt IE 9]
6
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
7
+ = csrf_meta_tags
6
8
  = stylesheet_link_tag 'couch_i18n/application'
7
9
  = javascript_include_tag 'couch_i18n/application'
10
+ %meta{:name => "viewport", :content => "width=device-width, initial-scale=1.0"}
8
11
  = yield :head
9
12
  %body
10
- #page-wrapper
13
+ .navbar.navbar-fixed-top
14
+ .navbar-inner
15
+ .container
16
+ %a.btn.btn-navbar{data: {toggle: "collapse", target: ".nav-collapse"}}
17
+ %span.icon-bar
18
+ %span.icon-bar
19
+ %span.icon-bar
20
+ %a.brand{href: couch_i18n.root_path}= yield :title
21
+ -#.nav-collapse
22
+ %ul.nav
23
+ %li= link_to 'Clear', couch_i18n.root_path
24
+ = yield :navbar
25
+ .container
26
+ = render 'alerts'
27
+ = yield
28
+
29
+ -#page-wrapper
11
30
  #page-header
12
31
  %h1= yield :title
13
32
  #page-content
@@ -4,11 +4,11 @@ en:
4
4
  action:
5
5
  edit:
6
6
  title: Edit translation
7
+ label: Edit
7
8
  destroy:
8
9
  label: Delete
9
10
  offset_link: Delete all from offset
10
- edit:
11
- label: Edit
11
+ successful: '%{model} is successfully removed'
12
12
  index:
13
13
  label: Translations
14
14
  title: Translations
@@ -16,10 +16,14 @@ en:
16
16
  label: New
17
17
  update:
18
18
  button_text: Update
19
+ successful: '%{model} is successfully updated'
20
+ create:
21
+ successful: '%{model} is successfully created'
19
22
  export:
20
23
  execute: Execute
21
24
  untranslated: Untranslated
22
25
  label: Export
26
+ from_offset: 'Export from offset: "%{offset}"'
23
27
  general:
24
28
  are_you_sure: 'Are you sure?'
25
29
  boolean_false: 'no'
@@ -30,10 +34,13 @@ en:
30
34
  find_value: Find value
31
35
  none_found: No translations found
32
36
  site_title: CouchI18n translations
33
- untranslated_title: Untranslated
37
+ untranslated_label: Untranslated
38
+ close: Close
39
+ is_json: 'Is JSON?'
34
40
  import:
35
41
  button: Import
36
42
  label: Import
43
+ description: If you import keys, existing keys will be overwritten
37
44
  activemodel:
38
45
  models:
39
46
  couch_i18n:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couch_i18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
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: 2012-08-04 00:00:00.000000000 Z
12
+ date: 2012-09-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -62,11 +62,13 @@ files:
62
62
  - app/assets/javascripts/couch_i18n/structure.js
63
63
  - app/assets/stylesheets/couch_i18n/alerts.css.scss
64
64
  - app/assets/stylesheets/couch_i18n/application.css
65
+ - app/assets/stylesheets/couch_i18n/bootstrap_and_override.css.less
65
66
  - app/assets/stylesheets/couch_i18n/structure.css.scss
66
67
  - app/controllers/couch_i18n/application_controller.rb
67
68
  - app/controllers/couch_i18n/translations_controller.rb
68
69
  - app/helpers/couch_i18n/application_helper.rb
69
70
  - app/models/couch_i18n/translation.rb
71
+ - app/models/couch_i18n/translation.rb~
70
72
  - app/views/couch_i18n/application/_alerts.html.haml
71
73
  - app/views/couch_i18n/application/_error_messages.html.haml
72
74
  - app/views/couch_i18n/translations/_form.html.haml