interpret 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.rspec +1 -0
  2. data/.travis.yml +14 -0
  3. data/README.md +2 -0
  4. data/app/controllers/interpret/base_controller.rb +10 -14
  5. data/app/controllers/interpret/missing_translations_controller.rb +41 -10
  6. data/app/controllers/interpret/search_controller.rb +15 -3
  7. data/app/controllers/interpret/tools_controller.rb +2 -2
  8. data/app/controllers/interpret/translations_controller.rb +15 -12
  9. data/app/models/interpret/ability.rb +9 -0
  10. data/app/models/interpret/translation.rb +38 -3
  11. data/app/views/interpret/missing_translations/blank.html.erb +35 -0
  12. data/app/views/interpret/missing_translations/index.html.erb +25 -14
  13. data/app/views/interpret/missing_translations/stale.html.erb +43 -0
  14. data/app/views/interpret/missing_translations/unused.html.erb +27 -0
  15. data/app/views/interpret/tools/index.html.erb +15 -25
  16. data/app/views/interpret/translations/_listing.html.erb +3 -15
  17. data/app/views/interpret/translations/index.html.erb +3 -0
  18. data/app/views/layouts/interpret.html.erb +26 -6
  19. data/config/environment.rb +0 -0
  20. data/config/routes.rb +4 -1
  21. data/interpret.gemspec +4 -1
  22. data/lib/generators/interpret/templates/migration.rb +1 -1
  23. data/lib/interpret.rb +23 -2
  24. data/lib/interpret/controller_filter.rb +0 -10
  25. data/lib/interpret/helpers.rb +2 -2
  26. data/lib/interpret/version.rb +1 -1
  27. data/public/javascripts/interpret.js +0 -3
  28. data/public/stylesheets/interpret_style.css +0 -6
  29. data/spec/integration/missing_translations_spec.rb +61 -0
  30. data/spec/integration/search_spec.rb +88 -0
  31. data/spec/integration/stale_translations_spec.rb +28 -0
  32. data/spec/integration/tools_spec.rb +86 -0
  33. data/spec/integration/translations_spec.rb +26 -0
  34. data/spec/models/translation_spec.rb +58 -25
  35. data/spec/observers/expiration_observer_spec.rb +2 -0
  36. data/spec/spec_helper.rb +3 -15
  37. data/spec/support/selenium_db_hack.rb +19 -0
  38. data/spec/support/utils.rb +89 -0
  39. data/test_app/Gemfile +1 -1
  40. data/test_app/app/controllers/application_controller.rb +2 -4
  41. data/test_app/app/models/interpret_ability.rb +7 -0
  42. data/test_app/app/models/user.rb +0 -3
  43. data/test_app/app/views/layouts/application.html.erb +4 -7
  44. data/test_app/config/initializers/interpret.rb +2 -2
  45. data/test_app/config/initializers/rack_patch.rb +13 -0
  46. data/test_app/config/locales/es.yml +1 -1
  47. data/test_app/db/migrate/20110219173536_create_users.rb +0 -2
  48. data/test_app/db/migrate/{20110219143622_interpret_create_translations.rb → 20111021100344_interpret_create_translations.rb} +1 -1
  49. data/test_app/db/schema.rb +2 -3
  50. data/test_app/db/seeds.rb +1 -1
  51. data/test_app/public/javascripts/interpret.js +0 -3
  52. data/test_app/public/stylesheets/interpret_style.css +0 -6
  53. metadata +122 -119
  54. data/spec/database_helpers.rb +0 -15
@@ -0,0 +1,27 @@
1
+ <% unless @unused_translations %>
2
+ <p>There are no useless translations</p>
3
+ <% else %>
4
+ <p>There are <%= @unused_translations.size %> translations that exists for
5
+ the [ <%= I18n.locale %> ] language, but DO NOT exists for [ <%= I18n.default_locale %> ].
6
+ You probably want to do something about it.
7
+ </p>
8
+
9
+ <table>
10
+ <thead>
11
+ <tr class="header">
12
+ <th>Key</th>
13
+ <th>Value in [ <%= I18n.locale %> ]</th>
14
+ <th>Delete</th>
15
+ </tr>
16
+ </thead>
17
+ <% @unused_translations.each do |trans| %>
18
+ <tr>
19
+ <td><%= trans.key %></td>
20
+ <td><%= trans.value %></td>
21
+ <td>
22
+ <%= link_to "Destroy it", trans, :method => :delete, :confirm => "Are you sure?" %>
23
+ </td>
24
+ </tr>
25
+ <% end%>
26
+ </table>
27
+ <% end %>
@@ -1,40 +1,30 @@
1
1
  <% interpret_title "Interpret - Tools" %>
2
2
 
3
3
  <div class="header">
4
- <h1>Tools for import/export locale data</h1>
4
+ <h1>Download the current .yml file for language [ <%= I18n.locale %> ]</h1>
5
5
  </div>
6
6
 
7
- <p><%= link_to "Download", export_interpret_tools_path %> the current translations for '<%= I18n.locale %>' language as .yml file</p>
8
- <p>Upload your .yml file for '<%= I18n.locale %>' language</p>
9
- <p>
10
- <%= form_tag import_interpret_tools_path, :multipart => true do %>
11
- <%= label_tag "File:" %>
12
- <%= file_field_tag :file %>
13
- <%= submit_tag "Upload" %>
14
- <% end %>
15
-
16
-
17
- <div class="header">
18
- <h1>Update contents from yml locale files</h1>
19
- </div>
7
+ <p>With the following button you can download a "<%= I18n.locale %>.yml" file with the current translations for this language.</p>
20
8
 
21
- <p>Update all your application translations from the yml files.<br/>
9
+ <p>
10
+ <%= button_to "Download", export_interpret_tools_path, :method => :get %>
22
11
  </p>
23
- <%= button_to "Update", run_update_interpret_tools_path %>
24
-
25
12
 
26
13
  <div class="header">
27
- <h1>Dump .yml contents into database</h1>
14
+ <h1>Import translations from a .yml file</h1>
28
15
  </div>
29
16
 
30
- <p>With this option you can export all of your *.yml contents into the database backend<br/>
31
- <b>Be aware!!</b> All of your current database translations will be updated to match with your current *.yml files.
17
+ <p>This action will let you update the translations from a standard .yml file.
18
+ All existing translations in that file will be copied into the application,
19
+ and if they already exists they will be overwritten.
32
20
  </p>
33
21
 
34
- <% if Rails.env == "production" %>
35
- <p><b>MY GOD!!! You're in PRODUCTION!! You're sure you wanna do this??</b></p>
36
- <% end %>
37
-
38
22
  <p>
39
- <%= button_to "Dump", dump_interpret_tools_path %>
23
+ Remember that the first key of the YAML file you're uploading must match the current locale.
40
24
  </p>
25
+
26
+ <%= form_tag import_interpret_tools_path, :multipart => true do %>
27
+ <%= label_tag "File:" %>
28
+ <%= file_field_tag :file %>
29
+ <%= submit_tag "Upload" %>
30
+ <% end %>
@@ -1,4 +1,4 @@
1
- <table>
1
+ <table id="results">
2
2
  <thead>
3
3
  <tr class="header">
4
4
  <% if @references %>
@@ -8,15 +8,12 @@
8
8
  <th>Key</th>
9
9
  <% end %>
10
10
  <th>Content [<%= I18n.locale %>]</th>
11
- <% if @interpret_admin && @references.nil? %>
12
- <th style="width:5%">Protected?</th>
13
- <% end %>
14
11
  </tr>
15
12
  </thead>
16
13
  <tbody>
17
14
  <% unless @references %>
18
15
  <% @translations.each do |x| %>
19
- <tr<%= " class='protected'" if x.protected %>>
16
+ <tr>
20
17
  <td class='key'><%= x.key %></td>
21
18
  <td class="content" id="translation_<%= x.id %>">
22
19
  <%= best_in_place x, :value,
@@ -25,21 +22,12 @@
25
22
  :activator => "#translation_#{x.id}",
26
23
  :sanitize => false %>
27
24
  </td>
28
- <% if @interpret_admin %>
29
- <td style="width:5%" class='protection_input' id="protection_<%= x.id %>">
30
- <%= best_in_place x, :protected,
31
- :type => :checkbox,
32
- :path => interpret_translation_path(x),
33
- :activator => "#protection_#{x.id}"
34
- %>
35
- </td>
36
- <% end %>
37
25
  </tr>
38
26
  <% end %>
39
27
  <% else %>
40
28
  <% @references.each do |x| %>
41
29
  <% trans = @translations.detect{|y| y.key == x.key} %>
42
- <tr<%= " id='translation_#{trans.id}'" if trans %><%= " class='protected'" if x.protected %>>
30
+ <tr<%= " id='translation_#{trans.id}'" if trans %>>
43
31
  <td style='width:5%'><%= x.key %></td>
44
32
  <td style='width:50%'><%= x.value %></td>
45
33
  <td style='width:50%'>
@@ -4,6 +4,9 @@
4
4
  <h1>Translations for [<%= I18n.locale %>]</h1>
5
5
  </div>
6
6
  <p>
7
+ There is a total of <%= @total_keys_number %> translations for [ <%= I18n.locale %> ].
8
+ </p>
9
+ <p>
7
10
  Below are the translations without any particulary key in your application.
8
11
  That use to be some global names or terms for common use along all the site,
9
12
  which doesn't belong to any page or section in particulary. To dive into the
@@ -6,17 +6,37 @@
6
6
  </div>
7
7
  <% end %>
8
8
  <div class="menu grid_12">
9
- <%= interpret_section_link_to "Overview", interpret_root_path %> |
10
- <% unless @interpret_user && !@interpret_admin %>
11
- <%= interpret_section_link_to "Tools", interpret_tools_path %> |
9
+ <%= interpret_section_link_to "Overview", interpret_root_path %>
10
+
11
+ <% if can? :use, :tools %>
12
+ | <%= interpret_section_link_to "Tools", interpret_tools_path %>
13
+ <% end %>
14
+
15
+ <% if can? :use, :search %>
16
+ | <%= interpret_section_link_to "Search", interpret_search_path %>
17
+ <% end %>
18
+
19
+ <% if can? :read, :missing_translations %>
20
+ | <%= link_to "Missing translations", interpret_missing_translations_path, :class => controller_name == "missing_translations" && action_name == "index" ? "current" : "" %>
21
+ <% end %>
22
+
23
+ <% if can? :read, :stale_translations %>
24
+ | <%= link_to "Stale translations", interpret_stale_translations_path, :class => controller_name == "missing_translations" && action_name == "stale" ? "current" : "" %>
25
+ <% end %>
26
+
27
+ <% if can? :read, :blank_translations %>
28
+ | <%= link_to "Blank translations", interpret_blank_translations_path, :class => controller_name == "missing_translations" && action_name == "blank" ? "current" : "" %>
29
+ <% end %>
30
+
31
+ <% if can? :read, :unused_translations %>
32
+ | <%= link_to "Unused translations", interpret_unused_translations_path, :class => controller_name == "missing_translations" && action_name == "unused" ? "current" : "" %>
12
33
  <% end %>
13
- <%= interpret_section_link_to "Search", interpret_search_path %> |
14
- <%= interpret_section_link_to "Missing translations", interpret_missing_translations_path %>
15
34
  <hr />
16
35
  </div>
17
- <div class="menu grid_4">
36
+ <div class="menu grid_4" id='languages_nav'>
18
37
  Languages:
19
38
  <% Interpret::Translation.available_locales.each do |locale| %>
39
+ <% next unless can? :use, :"interpret_in_#{locale}" %>
20
40
  <% opts = {:locale => locale} %>
21
41
  <% opts[:key] = params[:key] if params[:key] %>
22
42
  <% opts[:value] = params[:value] if params[:value] %>
File without changes
data/config/routes.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  Rails.application.routes.draw do
2
2
  scope Interpret.scope do
3
3
  namespace :interpret do
4
- resources :translations, :only => [:edit, :update, :create] do
4
+ resources :translations, :only => [:destroy, :edit, :update, :create] do
5
5
  collection do
6
6
  get :live_edit
7
7
  end
@@ -18,6 +18,9 @@ Rails.application.routes.draw do
18
18
 
19
19
  match "search", :to => "search#index"
20
20
  resources :missing_translations
21
+ match "blank", :to => "missing_translations#blank", :as => "blank_translations"
22
+ match "unused", :to => "missing_translations#unused", :as => "unused_translations"
23
+ match "stale", :to => "missing_translations#stale", :as => "stale_translations"
21
24
 
22
25
  root :to => "translations#index"
23
26
  end
data/interpret.gemspec CHANGED
@@ -23,8 +23,11 @@ Gem::Specification.new do |s|
23
23
  s.add_dependency "i18n", "~> 0.5.0"
24
24
  s.add_dependency "i18n-active_record"
25
25
  s.add_dependency "ya2yaml", ">= 0.30.0"
26
- s.add_dependency "best_in_place", ">= 0.1.7"
26
+ s.add_dependency "best_in_place", "~> 0.2.2"
27
27
  s.add_dependency "lazyhash", ">= 0.1.1"
28
+ s.add_dependency "cancan", "~> 1.6.0"
28
29
 
29
30
  s.add_development_dependency "rspec-rails", "~> 2.5"
31
+ s.add_development_dependency "capybara", "~> 1.0.1"
32
+ s.add_development_dependency "launchy"
30
33
  end
@@ -6,7 +6,7 @@ class InterpretCreateTranslations < ActiveRecord::Migration
6
6
  t.text :value
7
7
  t.text :interpolations
8
8
  t.boolean :is_proc, :default => false
9
- t.boolean :protected, :default => false
9
+ t.boolean :stale, :default => false
10
10
  end
11
11
  end
12
12
 
data/lib/interpret.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'best_in_place'
2
2
  require 'lazyhash'
3
+ require 'cancan'
3
4
 
4
5
  module Interpret
5
6
  mattr_accessor :backend
@@ -9,21 +10,41 @@ module Interpret
9
10
  mattr_accessor :registered_envs
10
11
  mattr_accessor :scope
11
12
  mattr_accessor :current_user
12
- mattr_accessor :admin
13
13
  mattr_accessor :layout
14
14
  mattr_accessor :soft
15
15
  mattr_accessor :live_edit
16
+ mattr_accessor :black_list
17
+ mattr_accessor :ability
16
18
 
17
- @@controller = "action_controller/base"
19
+ @@parent_controller = "application_controller"
18
20
  @@registered_envs = [:production, :staging]
19
21
  @@scope = ""
20
22
  @@layout = "interpret_base"
21
23
  @@soft = false
22
24
  @@live_edit = false
25
+ @@black_list = []
26
+ @@current_user = "current_user"
27
+ @@ability = "interpret/ability"
23
28
 
24
29
  def self.configure
25
30
  yield self
26
31
  end
32
+
33
+ def self.fixed_blacklist
34
+ @@black_list.select{|x| !x.include?("*")}
35
+ end
36
+
37
+ def self.wild_blacklist
38
+ @@black_list.select{|x| x.include?("*")}.map{|x| x.gsub("*", "")}
39
+ end
40
+
41
+ def self.ability
42
+ unless @@ability.is_a?(Class)
43
+ @@ability.classify.constantize
44
+ else
45
+ @@ability
46
+ end
47
+ end
27
48
  end
28
49
 
29
50
  require 'interpret/engine' if defined? Rails
@@ -7,16 +7,6 @@ class ActionController::Base
7
7
 
8
8
  if Interpret.current_user && defined?(Interpret.current_user.to_sym)
9
9
  @interpret_user = eval(Interpret.current_user)
10
-
11
- if @interpret_user.nil?
12
- @interpret_admin = false
13
- return
14
- end
15
-
16
- @interpret_admin = true
17
- if Interpret.admin && @interpret_user.respond_to?(Interpret.admin)
18
- @interpret_admin = @interpret_user.send(Interpret.admin)
19
- end
20
10
  end
21
11
  end
22
12
  end
@@ -29,7 +29,7 @@ module Interpret
29
29
  end
30
30
 
31
31
  def t(key, options = {})
32
- if Interpret.live_edit && @interpret_admin
32
+ if Interpret.live_edit
33
33
  keys = build_keys(key, options)
34
34
  "<span class='interpret_editable' data-key='#{keys}'>#{translate(key, options)}</span>".html_safe
35
35
  else
@@ -38,7 +38,7 @@ module Interpret
38
38
  end
39
39
 
40
40
  def interpret_live_edition
41
- return unless Interpret.live_edit && @interpret_admin
41
+ return unless Interpret.live_edit
42
42
  content_tag(:div) do
43
43
  concat(javascript_include_tag "facebox-1.3/facebox")
44
44
  concat javascript_tag <<-JS
@@ -1,3 +1,3 @@
1
1
  module Interpret
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -1,7 +1,4 @@
1
1
  $(document).ready(function() {
2
- $("#interpret_container .protection_input").click(function() {
3
- $(this).parent().toggleClass("protected");
4
- });
5
2
  /* Activating Best In Place */
6
3
  $("#interpret_container .best_in_place").best_in_place()
7
4
  });
@@ -382,12 +382,6 @@ html body * dd.clear
382
382
  cursor: pointer;
383
383
  }
384
384
 
385
- #interpret_container tr.protected {
386
- border: 2px dashed red;
387
- background-color: #FFEDED;
388
- }
389
-
390
-
391
385
  #interpret_container tr:hover {
392
386
  background-color: #DDD;
393
387
  -moz-transition: background .4s linear;
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe "Missing translations" do
5
+ before(:all) { User.create! }
6
+ before { load_integration_data }
7
+
8
+ it "should show me nothing when I'm in english language" do
9
+ visit interpret_missing_translations_path(:en)
10
+ page.should have_content("There can't be missing translations for the main language")
11
+ end
12
+
13
+ it "should show the total number of missing translations" do
14
+ visit interpret_missing_translations_path(:es)
15
+ page.should have_content("There are 2 missing translations in [es]")
16
+ end
17
+
18
+ it "should show me a table with all missing translations" do
19
+ visit interpret_missing_translations_path(:es)
20
+ elements = page.all("table#missing_translations tbody tr")
21
+ elements.size.should == 2
22
+ elements.first.should have_content("missings.p1")
23
+ end
24
+
25
+ it "should show me the value in english for a given key" do
26
+ visit interpret_missing_translations_path(:es)
27
+ page.should have_content("Missing one")
28
+ end
29
+
30
+ it "should let me create a new translation in the current language" do
31
+ visit interpret_missing_translations_path(:es)
32
+
33
+ within("table#missing_translations tbody tr:first") do
34
+ page.fill_in "interpret_translation_value", :with => "Uno perdido"
35
+ page.click_button "Create"
36
+ end
37
+
38
+ page.should have_content("New translation created for missings.p1")
39
+ page.all("table#missing_translations tbody tr").size.should == 1
40
+ page.should have_content("Missing two")
41
+ end
42
+
43
+ it "should let me destroy the original translation" do
44
+ visit interpret_missing_translations_path(:es)
45
+
46
+ within("table#missing_translations tbody tr:first") do
47
+ page.click_link "Destroy"
48
+ end
49
+
50
+ page.should have_content("Translation missings.p1 destroyed")
51
+ page.all("table#missing_translations tbody tr").size.should == 1
52
+ page.should have_content("Missing two")
53
+ end
54
+
55
+ it "should not show me blacklisted translations" do
56
+ visit interpret_missing_translations_path(:es)
57
+ page.should have_no_content("missings.black")
58
+ elements = page.all("table#missing_translations tbody tr")
59
+ elements.size.should == 2
60
+ end
61
+ end
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe "Search" do
5
+ before(:all) { User.create! }
6
+ before { load_integration_data }
7
+
8
+ it "should return the correct results searching by text" do
9
+ visit interpret_search_path(:es)
10
+ fill_in "Translation text", :with => "Comentarios"
11
+ click_button "SEARCH"
12
+
13
+ page.all("table#results tbody tr").size.should == 1
14
+ within("table#results") do
15
+ page.should have_content("Comentarios")
16
+ end
17
+ end
18
+
19
+ it "should work with accents and other non ascii chars" do
20
+ visit interpret_search_path(:es)
21
+ fill_in "Translation text", :with => "extraña"
22
+ click_button "SEARCH"
23
+
24
+ page.all("table#results tbody tr").size.should == 1
25
+ within("table#results") do
26
+ page.should have_content("extraña")
27
+ end
28
+ end
29
+
30
+ it "should return the correct results searching by key" do
31
+ visit interpret_search_path(:es)
32
+ fill_in "Key value", :with => "printer"
33
+ click_button "SEARCH"
34
+
35
+ page.all("table#results tbody tr").size.should == 2
36
+ within("table#results") do
37
+ page.should have_content("Para imprimir")
38
+ page.should have_content("Otra impresora")
39
+ end
40
+ end
41
+
42
+ it "should not return blacklisted translations by key" do
43
+ visit interpret_search_path(:es)
44
+ fill_in "Key value", :with => "black_p1"
45
+ click_button "SEARCH"
46
+
47
+ page.all("table#results tbody tr").size.should == 0
48
+ end
49
+
50
+ it "should not return blacklisted translations by text" do
51
+ visit interpret_search_path(:es)
52
+ fill_in "Translation text", :with => "Una frase prohibida"
53
+ click_button "SEARCH"
54
+
55
+ page.all("table#results tbody tr").size.should == 0
56
+ end
57
+
58
+ it "should say the number of results found" do
59
+ visit interpret_search_path(:es)
60
+ fill_in "Key value", :with => "printer"
61
+ click_button "SEARCH"
62
+
63
+ within("#sidebar") do
64
+ page.should have_content("2 results found")
65
+ end
66
+ end
67
+
68
+ it "should be able to switch the language after a search" do
69
+ visit interpret_search_path(:es)
70
+ fill_in "Key value", :with => "printer"
71
+ click_button "SEARCH"
72
+
73
+ within("#languages_nav") { click_link "en" }
74
+ page.all("table#results tbody tr").size.should == 2
75
+ end
76
+
77
+ it "should see the search results in the same order after switching languages" do
78
+ visit interpret_search_path(:es)
79
+ fill_in "Key value", :with => "printer"
80
+ click_button "SEARCH"
81
+ res = page.all("table#results tbody tr").map{|x| x.find("td.key").text}
82
+ res.should == ["printer", "section1.printer"]
83
+
84
+ within("#languages_nav") { click_link "en" }
85
+ res = page.all("table#results tbody tr").map{|x| x.find("td.key").text}
86
+ res.should == ["printer", "section1.printer"]
87
+ end
88
+ end