tolk 1.0
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.
- data/MIT-LICENSE +20 -0
- data/README +60 -0
- data/app/controllers/tolk/application_controller.rb +17 -0
- data/app/controllers/tolk/locales_controller.rb +46 -0
- data/app/controllers/tolk/searches_controller.rb +15 -0
- data/app/helpers/tolk/application_helper.rb +33 -0
- data/app/models/tolk/locale.rb +246 -0
- data/app/models/tolk/phrase.rb +22 -0
- data/app/models/tolk/translation.rb +91 -0
- data/app/views/layouts/tolk/application.html.erb +33 -0
- data/app/views/tolk/locales/all.html.erb +64 -0
- data/app/views/tolk/locales/index.html.erb +35 -0
- data/app/views/tolk/locales/show.atom.builder +11 -0
- data/app/views/tolk/locales/show.html.erb +58 -0
- data/app/views/tolk/searches/_form.html.erb +8 -0
- data/app/views/tolk/searches/show.html.erb +55 -0
- data/config/routes.rb +7 -0
- data/init.rb +8 -0
- data/lib/generators/tolk_migration/templates/migrate/create_tolk_tables.rb +38 -0
- data/lib/generators/tolk_migration/tolk_migration_generator.rb +19 -0
- data/lib/tasks/tolk_tasks.rake +43 -0
- data/lib/tolk.rb +6 -0
- data/lib/tolk/engine.rb +7 -0
- data/lib/tolk/import.rb +47 -0
- data/lib/tolk/sync.rb +74 -0
- data/public/tolk/reset.css +30 -0
- data/public/tolk/screen.css +336 -0
- metadata +122 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
module Tolk
|
2
|
+
class Translation < ActiveRecord::Base
|
3
|
+
set_table_name "tolk_translations"
|
4
|
+
|
5
|
+
scope :containing_text, lambda {|query| where("tolk_translations.text LIKE ?", "%#{query}%") }
|
6
|
+
|
7
|
+
serialize :text
|
8
|
+
validates_presence_of :text, :if => proc {|r| r.primary.blank? && !r.explicit_nil }
|
9
|
+
|
10
|
+
validates_uniqueness_of :phrase_id, :scope => :locale_id
|
11
|
+
|
12
|
+
belongs_to :phrase, :class_name => 'Tolk::Phrase'
|
13
|
+
belongs_to :locale, :class_name => 'Tolk::Locale'
|
14
|
+
|
15
|
+
attr_accessor :force_set_primary_update
|
16
|
+
before_save :set_primary_updated
|
17
|
+
|
18
|
+
before_save :set_previous_text
|
19
|
+
|
20
|
+
attr_accessor :primary
|
21
|
+
before_validation :fix_text_type, :unless => proc {|r| r.primary }
|
22
|
+
|
23
|
+
attr_accessor :explicit_nil
|
24
|
+
before_validation :set_explicit_nil
|
25
|
+
|
26
|
+
def up_to_date?
|
27
|
+
not out_of_date?
|
28
|
+
end
|
29
|
+
|
30
|
+
def out_of_date?
|
31
|
+
primary_updated?
|
32
|
+
end
|
33
|
+
|
34
|
+
def primary_translation
|
35
|
+
@_primary_translation ||= begin
|
36
|
+
if locale && !locale.primary?
|
37
|
+
phrase.translations.primary
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def text=(value)
|
43
|
+
super unless value.to_s == text
|
44
|
+
end
|
45
|
+
|
46
|
+
def value
|
47
|
+
if text.is_a?(String) && /^\d+$/.match(text)
|
48
|
+
text.to_i
|
49
|
+
else
|
50
|
+
text
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def set_explicit_nil
|
57
|
+
if self.text == '~'
|
58
|
+
self.text = nil
|
59
|
+
self.explicit_nil = true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def fix_text_type
|
64
|
+
if primary_translation.present?
|
65
|
+
if self.text.is_a?(String) && !primary_translation.text.is_a?(String)
|
66
|
+
self.text = begin
|
67
|
+
YAML.load(self.text.strip)
|
68
|
+
rescue ArgumentError
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
self.text = nil if primary_translation.text.class != self.text.class
|
75
|
+
end
|
76
|
+
|
77
|
+
true
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_primary_updated
|
81
|
+
self.primary_updated = self.force_set_primary_update ? true : false
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
def set_previous_text
|
86
|
+
self.previous_text = self.text_was if text_changed?
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= Tolk::Locale.primary_locale_name %>" lang="<%= Tolk::Locale.primary_locale_name %>">
|
4
|
+
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
7
|
+
<title>Tolk</title>
|
8
|
+
|
9
|
+
<% if respond_to?(:sprockets_include_tag) %>
|
10
|
+
<%= sprockets_include_tag %>
|
11
|
+
<% else %>
|
12
|
+
<%= javascript_include_tag :defaults %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<%= stylesheet_link_tag "/tolk/reset", "/tolk/screen" %>
|
16
|
+
<%= yield :head %>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<div id="container">
|
21
|
+
<div id="head">
|
22
|
+
<h1><span class="home"><%= link_to "Tolk", tolk_root_path %></span><%= yield :locale %></h1>
|
23
|
+
</div>
|
24
|
+
<%= yield %>
|
25
|
+
</div>
|
26
|
+
|
27
|
+
<script type="text/javascript">
|
28
|
+
$$('td textarea').each(function(element) {
|
29
|
+
element.setStyle({height: element.up('td').measure('height')+'px'});
|
30
|
+
});
|
31
|
+
</script>
|
32
|
+
</body>
|
33
|
+
</html>
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<% content_for :locale do %><span class="locale"><%= @locale.language_name %></span>
|
2
|
+
<% end %>
|
3
|
+
|
4
|
+
<h3 class="switch">Completed translations <span>(<%= link_to 'See phrases missing translation', @locale %>)</span></h3>
|
5
|
+
|
6
|
+
<% if @locale.has_updated_translations? && action_name != 'updated' %>
|
7
|
+
<span class="notice">Some phrases have changed. <%= link_to "Update translations", updated_tolk_locale_path(@locale) %>.</span>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<div class="search">
|
11
|
+
<%= render :partial => "tolk/searches/form", :locals => { :locale => @locale } %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="translations">
|
15
|
+
<% if @phrases.any? %>
|
16
|
+
<%= form_for @locale do |locale_form| %>
|
17
|
+
<table class="translations">
|
18
|
+
<tr>
|
19
|
+
<th class="translation"><%= @locale.language_name -%></th>
|
20
|
+
<th class="key"><%= Tolk::Locale.primary_language_name -%></th>
|
21
|
+
</tr>
|
22
|
+
<% @phrases.each do |phrase| %>
|
23
|
+
<% if phrase.translations.primary %>
|
24
|
+
<tr>
|
25
|
+
<td class="translation">
|
26
|
+
<%= hidden_field_tag :"translations[][id]", phrase.translation.id %>
|
27
|
+
<%= hidden_field_tag :"translations[][locale_id]", phrase.translation.locale_id %>
|
28
|
+
<%= text_area_tag :"translations[][text]", format_i18n_text_area_value(phrase.translation.text), :class => 'locale',
|
29
|
+
:onfocus => "$(this).up('tr').addClassName('active');", :onblur => "$(this).up('tr').removeClassName('active');" %>
|
30
|
+
</td>
|
31
|
+
<td class="phrase">
|
32
|
+
|
33
|
+
<% if action_name == 'updated' %>
|
34
|
+
<div class="updated">
|
35
|
+
<span class="key">Updated</span>
|
36
|
+
<%= format_i18n_value(phrase.translations.primary.text) -%>
|
37
|
+
</div>
|
38
|
+
<div class="original">
|
39
|
+
<span class="key">Original</span>
|
40
|
+
<%= format_i18n_value(phrase.translations.primary.previous_text) -%>
|
41
|
+
</div>
|
42
|
+
<% else %>
|
43
|
+
<%= format_i18n_value(phrase.translations.primary.text) -%>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<span class="key"><%= phrase.key %></span>
|
47
|
+
</td>
|
48
|
+
</tr>
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
51
|
+
</table>
|
52
|
+
<div class="table_submit">
|
53
|
+
<p><%= locale_form.submit "Save changes" %></p>
|
54
|
+
</div>
|
55
|
+
<div class="paginate">
|
56
|
+
<%= will_paginate @phrases %>
|
57
|
+
</div>
|
58
|
+
<% end %>
|
59
|
+
<% else %>
|
60
|
+
<p style="text-align: left">There aren't any completed translations for this locale.</p>
|
61
|
+
<p> </p>
|
62
|
+
<% end %>
|
63
|
+
</div>
|
64
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<% content_for :locale do %><span class="locale empty"></span>
|
2
|
+
<% end %>
|
3
|
+
|
4
|
+
<h2>Locales <span>Primary locale is <%= Tolk::Locale.primary_locale.language_name %></span></h2>
|
5
|
+
<% if @locales.any? %>
|
6
|
+
<ul class="locales clearfix">
|
7
|
+
<% @locales.each do |locale| %>
|
8
|
+
<li>
|
9
|
+
<%= link_to locale.language_name, locale %>
|
10
|
+
<% missing_count = locale.count_phrases_without_translation %>
|
11
|
+
<% if missing_count > 0 %>
|
12
|
+
<span class="missing_translations"><%= locale.count_phrases_without_translation %></span>
|
13
|
+
<% end %>
|
14
|
+
</li>
|
15
|
+
<% end %>
|
16
|
+
</ul>
|
17
|
+
|
18
|
+
<% else %>
|
19
|
+
<p>No locales yet.</p>
|
20
|
+
|
21
|
+
<% end %>
|
22
|
+
<%= form_for(Tolk::Locale.new) do |f| %>
|
23
|
+
<div class="submit">
|
24
|
+
<%= f.error_messages %>
|
25
|
+
<p>
|
26
|
+
<%= f.label "Add a new Locale" %>
|
27
|
+
<select id="select_tolk_locale_name" name="tolk_locale[name]">
|
28
|
+
<%= options_for_select tolk_locale_selection %>
|
29
|
+
</select>
|
30
|
+
<%= f.submit 'Add' %>
|
31
|
+
</p>
|
32
|
+
</div>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
atom_feed do |feed|
|
2
|
+
feed.title "Missing Translations for #{@locale.language_name} locale"
|
3
|
+
|
4
|
+
@phrases.each do |phrase|
|
5
|
+
feed.entry(phrase, :url => tolk_locale_url(@locale)) do |entry|
|
6
|
+
entry.title(phrase.key)
|
7
|
+
entry.content(phrase.key)
|
8
|
+
entry.author {|author| author.name("Tolk") }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
<% content_for :locale do %>
|
2
|
+
<span class="locale"><%= @locale.language_name %></span>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :head do %>
|
6
|
+
<link rel="alternate" type="application/rss+xml" title="RSS" href="<%= tolk_locale_path(@locale, :format => 'atom') -%>" />
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<h3 class="switch">Phrases missing translation (<%= @locale.count_phrases_without_translation %>) <span>(<%= link_to 'See completed translations', all_tolk_locale_path(@locale) %>)</span></h3>
|
10
|
+
|
11
|
+
<% if @locale.has_updated_translations? && action_name != 'updated' %>
|
12
|
+
<span class="notice">Some phrases have changed. <%= link_to "Update translations", updated_tolk_locale_path(@locale) %>.</span>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<div class="search">
|
16
|
+
<%= render :partial => "tolk/searches/form", :locals => { :locale => @locale } %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div class="translations">
|
20
|
+
<% if @phrases.any? %>
|
21
|
+
<%= form_for @locale do |locale_form| %>
|
22
|
+
<table class="translations">
|
23
|
+
<tr>
|
24
|
+
<th class="translation"><%= @locale.language_name -%></th>
|
25
|
+
<th class="key"><%= Tolk::Locale.primary_language_name -%></th>
|
26
|
+
</tr>
|
27
|
+
<% @phrases.each do |phrase| %>
|
28
|
+
<tr>
|
29
|
+
<% translation = Tolk::Translation.new(:locale => @locale, :phrase => phrase) %>
|
30
|
+
<td class="translation">
|
31
|
+
<%= hidden_field_tag :"translations[][id]", translation.id, :id => "#{translation.object_id}_id" %>
|
32
|
+
<%= hidden_field_tag :"translations[][phrase_id]", phrase.id, :id => "#{translation.object_id}_phrase_id" %>
|
33
|
+
<%= hidden_field_tag :"translations[][locale_id]", translation.locale_id, :id => "#{translation.object_id}_locale_id" %>
|
34
|
+
<%= text_area_tag :"translations[][text]", format_i18n_text_area_value(translation.text), :class => "locale", :id => "#{translation.object_id}_text", :onfocus => "$(this).up('tr').addClassName('active');", :onblur => "$(this).up('tr').removeClassName('active');" %>
|
35
|
+
</td>
|
36
|
+
<td class="phrase">
|
37
|
+
<% if params[:q].present? -%>
|
38
|
+
<%= highlight(format_i18n_value(phrase.translations.primary.text), params[:q]) -%>
|
39
|
+
<% else -%>
|
40
|
+
<%= format_i18n_value(phrase.translations.primary.text) -%>
|
41
|
+
<% end -%>
|
42
|
+
<span class="key" title="<%= phrase.key %>"><%= truncate(phrase.key, :length => 100) %></span>
|
43
|
+
</td>
|
44
|
+
</tr>
|
45
|
+
<% end %>
|
46
|
+
</table>
|
47
|
+
<div class="table_submit">
|
48
|
+
<p><%= locale_form.submit "Save changes" %></p>
|
49
|
+
</div>
|
50
|
+
<% end %>
|
51
|
+
<div class="paginate">
|
52
|
+
<%= will_paginate @phrases %>
|
53
|
+
</div>
|
54
|
+
<% else %>
|
55
|
+
<p style="text-align: left">There aren't any missing or updated phrases that need translation.</p>
|
56
|
+
<p> </p>
|
57
|
+
<% end %>
|
58
|
+
</div>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<% content_for :locale do %>
|
2
|
+
<span class="locale"><%= @locale.language_name %></span>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<h3 class="search">
|
6
|
+
<%= render :partial => "form", :locals => { :locale => @locale } %>
|
7
|
+
</h3>
|
8
|
+
|
9
|
+
<div class="search_exits">
|
10
|
+
<%= link_to "Phrases missing translation", @locale %>
|
11
|
+
|
12
|
+
<%= link_to "Completed translations", all_tolk_locale_path(@locale) %>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class="translations">
|
16
|
+
<% if @phrases.any? %>
|
17
|
+
<%= form_for @locale do |locale_form| %>
|
18
|
+
<table class="translations">
|
19
|
+
<tr>
|
20
|
+
<th class="translation"><%= @locale.language_name -%></th>
|
21
|
+
<th class="key"><%= Tolk::Locale.primary_language_name -%></th>
|
22
|
+
</tr>
|
23
|
+
<% @phrases.each do |phrase| %>
|
24
|
+
|
25
|
+
<% if translation = phrase.translations.find_by_locale_id(@locale.id) || Tolk::Translation.new(:locale => @locale, :phrase => phrase) %>
|
26
|
+
<tr>
|
27
|
+
<td class="translation">
|
28
|
+
<%= hidden_field_tag :"translations[][id]", translation.id, :id => "#{translation.object_id}_id" %>
|
29
|
+
<%= hidden_field_tag :"translations[][phrase_id]", phrase.id, :id => "#{translation.object_id}_phrase_id" %>
|
30
|
+
<%= hidden_field_tag :"translations[][locale_id]", translation.locale_id, :id => "#{translation.object_id}_locale_id" %>
|
31
|
+
<%= text_area_tag :"translations[][text]", format_i18n_text_area_value(translation.text), :class => "locale", :id => "#{translation.object_id}_text", :onfocus => "$(this).up('tr').addClassName('active');", :onblur => "$(this).up('tr').removeClassName('active');" %>
|
32
|
+
</td>
|
33
|
+
<td class="phrase">
|
34
|
+
<% if params[:q].present? -%>
|
35
|
+
<%= highlight(format_i18n_value(phrase.translations.primary.text), params[:q]) -%>
|
36
|
+
<% else -%>
|
37
|
+
<%= format_i18n_value(phrase.translations.primary.text) -%>
|
38
|
+
<% end -%>
|
39
|
+
<span class="key" title="<%= phrase.key %>"><%= truncate(phrase.key, :length => 100) %></span>
|
40
|
+
</td>
|
41
|
+
</tr>
|
42
|
+
<% end %>
|
43
|
+
<% end %>
|
44
|
+
</table>
|
45
|
+
<div class="table_submit">
|
46
|
+
<p><%= locale_form.submit "Save changes" %></p>
|
47
|
+
</div>
|
48
|
+
<% end %>
|
49
|
+
<div class="paginate">
|
50
|
+
<%= will_paginate @phrases %>
|
51
|
+
</div>
|
52
|
+
<% else %>
|
53
|
+
<p style="text-align: left">No search results.</p>
|
54
|
+
<% end %>
|
55
|
+
</div>
|
data/config/routes.rb
ADDED
data/init.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
class CreateTolkTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :tolk_locales do |t|
|
4
|
+
t.string :name
|
5
|
+
t.datetime :created_at
|
6
|
+
t.datetime :updated_at
|
7
|
+
end
|
8
|
+
|
9
|
+
add_index :tolk_locales, :name, :unique => true
|
10
|
+
|
11
|
+
create_table :tolk_phrases do |t|
|
12
|
+
t.text :key
|
13
|
+
t.datetime :created_at
|
14
|
+
t.datetime :updated_at
|
15
|
+
end
|
16
|
+
|
17
|
+
create_table :tolk_translations do |t|
|
18
|
+
t.integer :phrase_id
|
19
|
+
t.integer :locale_id
|
20
|
+
t.text :text
|
21
|
+
t.text :previous_text
|
22
|
+
t.boolean :primary_updated, :default => false
|
23
|
+
t.datetime :created_at
|
24
|
+
t.datetime :updated_at
|
25
|
+
end
|
26
|
+
|
27
|
+
add_index :tolk_translations, [:phrase_id, :locale_id], :unique => true
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.down
|
31
|
+
remove_index :tolk_translations, :column => [:phrase_id, :locale_id]
|
32
|
+
remove_index :tolk_locales, :column => :name
|
33
|
+
|
34
|
+
drop_table :tolk_translations
|
35
|
+
drop_table :tolk_phrases
|
36
|
+
drop_table :tolk_locales
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class TolkMigrationGenerator < Rails::Generators::Base
|
2
|
+
include Rails::Generators::Migration
|
3
|
+
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
5
|
+
|
6
|
+
def create_migration_file
|
7
|
+
migration_template "migrate/create_tolk_tables.rb", "db/migrate/create_tolk_tables.rb"
|
8
|
+
end
|
9
|
+
|
10
|
+
# Implement the required interface for Rails::Generators::Migration.
|
11
|
+
def self.next_migration_number(dirname) #:nodoc:
|
12
|
+
next_migration_number = current_migration_number(dirname) + 1
|
13
|
+
if ActiveRecord::Base.timestamped_migrations
|
14
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
15
|
+
else
|
16
|
+
"%.3d" % next_migration_number
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
namespace :tolk do
|
2
|
+
desc "Add database tables, copy over the assets, and import existing translations"
|
3
|
+
task :setup => :environment do
|
4
|
+
Rake::Task['tolk:import_assets'].invoke
|
5
|
+
system("rails generate tolk_migration")
|
6
|
+
Rake::Task['db:migrate'].invoke
|
7
|
+
Rake::Task['tolk:sync'].invoke
|
8
|
+
Rake::Task['tolk:import'].invoke
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Sync Tolk with the default locale's yml file"
|
12
|
+
task :sync => :environment do
|
13
|
+
Tolk::Locale.sync!
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Generate yml files for all the locales defined in Tolk"
|
17
|
+
task :dump_all => :environment do
|
18
|
+
Tolk::Locale.dump_all
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Imports data all non default locale yml files to Tolk"
|
22
|
+
task :import => :environment do
|
23
|
+
Rake::Task['tolk:sync'].invoke
|
24
|
+
Tolk::Locale.import_secondary_locales
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Show all the keys potentially containing HTML values and no _html postfix"
|
28
|
+
task :html_keys => :environment do
|
29
|
+
bad_translations = Tolk::Locale.primary_locale.translations_with_html
|
30
|
+
bad_translations.each do |bt|
|
31
|
+
puts "#{bt.phrase.key} - #{bt.text}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Copies required assets from tolk to application's public/ directory"
|
36
|
+
task :import_assets do
|
37
|
+
tolk_assets = File.expand_path(File.join(File.dirname(__FILE__), '../../public/tolk'))
|
38
|
+
command = "cp -R #{tolk_assets} #{Rails.root}/public/"
|
39
|
+
puts command
|
40
|
+
system(command)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|