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.
@@ -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>&nbsp;</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>&nbsp;</p>
57
+ <% end %>
58
+ </div>
@@ -0,0 +1,8 @@
1
+ <%= form_tag "/tolk/search", :method => :get do %>
2
+ <%= hidden_field_tag :locale, locale.name %>
3
+ Search for
4
+ <%= scope_selector_for(@locale) %>
5
+ phrase:
6
+ <%= text_field_tag :q, params[:q] %>
7
+ <%= submit_tag "Search", :name => nil %>
8
+ <% end %>
@@ -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
+ &nbsp;
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>
@@ -0,0 +1,7 @@
1
+ Rails.application.routes.draw do |map|
2
+ map.namespace('tolk') do |tolk|
3
+ tolk.root :controller => 'locales'
4
+ tolk.resources :locales, :member => {:all => :get, :updated => :get}
5
+ tolk.resource :search
6
+ end
7
+ end
data/init.rb ADDED
@@ -0,0 +1,8 @@
1
+ Mime::Type.register_alias "text/yaml", :yml
2
+
3
+ $KCODE = 'UTF8'
4
+ begin
5
+ require 'ya2yaml'
6
+ rescue LoadError => e
7
+ Rails.logger.debug "[Tolk] Could not load ya2yaml"
8
+ end
@@ -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