interpret 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.
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