couch_i18n 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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