Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

...
  • 14 commits
  • 56 files changed
  • 0 commit comments
  • 2 contributors
Showing with 870 additions and 1,217 deletions.
  1. +6 −0 .gitignore
  2. +2 −0  Gemfile
  3. +93 −0 Gemfile.lock
  4. +37 −0 Rakefile
  5. +9 −13 {lib → app}/controllers/locales_controller.rb
  6. +8 −18 {lib → app}/controllers/translations_controller.rb
  7. +66 −0 app/models/locale.rb
  8. +46 −0 app/models/translation.rb
  9. 0  {lib → app}/models/translation_option.rb
  10. +15 −0 app/views/layouts/translations.html.erb
  11. +11 −0 app/views/locales/edit.html.erb
  12. +18 −0 app/views/locales/index.html.erb
  13. +10 −0 app/views/locales/new.html.erb
  14. +9 −0 app/views/locales/show.html.erb
  15. 0  {lib → app}/views/translations/asset_translations.html.erb
  16. +18 −0 app/views/translations/edit.html.erb
  17. +4 −8 {lib → app}/views/translations/index.html.erb
  18. +11 −0 app/views/translations/new.html.erb
  19. +13 −0 app/views/translations/show.html.erb
  20. +24 −0 app/views/translations/translations.html.erb
  21. 0  {lib → app}/views/translations/update.rjs
  22. +7 −0 config/routes.rb
  23. +55 −0 data/default_localized_translations.yml
  24. +3 −4 generators/i18n_backend_database/i18n_backend_database_generator.rb
  25. +20 −0 i18n_backend_database.gemspec
  26. +0 −1  init.rb
  27. +3 −4 lib/ext/i18n.rb
  28. +10 −7 lib/i18n_backend_database.rb
  29. +235 −225 lib/i18n_backend_database/database.rb
  30. +16 −0 lib/i18n_backend_database/railtie.rb
  31. +3 −0  lib/i18n_backend_database/version.rb
  32. +44 −25 lib/i18n_util.rb
  33. +0 −67 lib/models/locale.rb
  34. +0 −46 lib/models/translation.rb
  35. BIN  lib/public/images/custom1_bar.gif
  36. BIN  lib/public/images/custom1_box.gif
  37. BIN  lib/public/images/percentImage.png
  38. BIN  lib/public/images/percentImage_back.png
  39. BIN  lib/public/images/percentImage_back1.png
  40. BIN  lib/public/images/percentImage_back2.png
  41. BIN  lib/public/images/percentImage_back3.png
  42. BIN  lib/public/images/percentImage_back4.png
  43. +0 −509 lib/public/javascripts/jsProgressBarHandler.js
  44. +0 −15 lib/routing.rb
  45. +74 −0 lib/tasks/i18n.rake
  46. +0 −23 lib/views/layouts/translations.html.erb
  47. +0 −20 lib/views/locales/edit.html.erb
  48. +0 −22 lib/views/locales/index.html.erb
  49. +0 −19 lib/views/locales/new.html.erb
  50. +0 −14 lib/views/locales/show.html.erb
  51. +0 −35 lib/views/translations/edit.html.erb
  52. +0 −19 lib/views/translations/new.html.erb
  53. +0 −32 lib/views/translations/show.html.erb
  54. +0 −28 lib/views/translations/translations.html.erb
  55. +0 −3  routes.rb
  56. +0 −60 tasks/i18n.rake
6 .gitignore
View
@@ -0,0 +1,6 @@
+.bundle/
+log/*.log
+pkg/
+test/dummy/db/*.sqlite3
+test/dummy/log/*.log
+test/dummy/tmp/
2  Gemfile
View
@@ -0,0 +1,2 @@
+source "http://rubygems.org"
+gemspec
93 Gemfile.lock
View
@@ -0,0 +1,93 @@
+PATH
+ remote: .
+ specs:
+ i18n_backend_database (0.0.1)
+ rails (>= 3)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ actionmailer (3.1.1)
+ actionpack (= 3.1.1)
+ mail (~> 2.3.0)
+ actionpack (3.1.1)
+ activemodel (= 3.1.1)
+ activesupport (= 3.1.1)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ i18n (~> 0.6)
+ rack (~> 1.3.2)
+ rack-cache (~> 1.1)
+ rack-mount (~> 0.8.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.0.2)
+ activemodel (3.1.1)
+ activesupport (= 3.1.1)
+ builder (~> 3.0.0)
+ i18n (~> 0.6)
+ activerecord (3.1.1)
+ activemodel (= 3.1.1)
+ activesupport (= 3.1.1)
+ arel (~> 2.2.1)
+ tzinfo (~> 0.3.29)
+ activeresource (3.1.1)
+ activemodel (= 3.1.1)
+ activesupport (= 3.1.1)
+ activesupport (3.1.1)
+ multi_json (~> 1.0)
+ arel (2.2.1)
+ builder (3.0.0)
+ erubis (2.7.0)
+ hike (1.2.1)
+ i18n (0.6.0)
+ json (1.6.1)
+ mail (2.3.0)
+ i18n (>= 0.4.0)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ mime-types (1.17.2)
+ multi_json (1.0.3)
+ polyglot (0.3.3)
+ rack (1.3.5)
+ rack-cache (1.1)
+ rack (>= 0.4)
+ rack-mount (0.8.3)
+ rack (>= 1.0.0)
+ rack-ssl (1.3.2)
+ rack
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ rails (3.1.1)
+ actionmailer (= 3.1.1)
+ actionpack (= 3.1.1)
+ activerecord (= 3.1.1)
+ activeresource (= 3.1.1)
+ activesupport (= 3.1.1)
+ bundler (~> 1.0)
+ railties (= 3.1.1)
+ railties (3.1.1)
+ actionpack (= 3.1.1)
+ activesupport (= 3.1.1)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (~> 0.14.6)
+ rake (0.9.2.2)
+ rdoc (3.11)
+ json (~> 1.4)
+ sprockets (2.0.3)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ thor (0.14.6)
+ tilt (1.3.3)
+ treetop (1.4.10)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.31)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ i18n_backend_database!
37 Rakefile
View
@@ -0,0 +1,37 @@
+#!/usr/bin/env rake
+begin
+ require 'bundler/setup'
+rescue LoadError
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
+end
+begin
+ require 'rdoc/task'
+rescue LoadError
+ require 'rdoc/rdoc'
+ require 'rake/rdoctask'
+ RDoc::Task = Rake::RDocTask
+end
+
+RDoc::Task.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'I18nBackendDatabase'
+ rdoc.options << '--line-numbers'
+ rdoc.rdoc_files.include('README.rdoc')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+
+
+Bundler::GemHelper.install_tasks
+
+require 'rake/testtask'
+
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = false
+end
+
+
+task :default => :test
22 lib/controllers/locales_controller.rb → app/controllers/locales_controller.rb
View
@@ -3,8 +3,7 @@ class LocalesController < ActionController::Base
# GET /locales
# GET /locales.xml
def index
- @locales = Locale.find(:all)
-
+ @locales = I18n::Backend::Locale.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @locales }
@@ -14,8 +13,7 @@ def index
# GET /locales/1
# GET /locales/1.xml
def show
- @locale = Locale.find_by_code(params[:id])
-
+ @locale = I18n::Backend::Locale.find_by_code(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @locale }
@@ -25,8 +23,7 @@ def show
# GET /locales/new
# GET /locales/new.xml
def new
- @locale = Locale.new
-
+ @locale = I18n::Backend::Locale.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @locale }
@@ -35,20 +32,20 @@ def new
# GET /locales/1/edit
def edit
- @locale = Locale.find_by_code(params[:id])
+ @locale = I18n::Backend::Locale.find_by_code(params[:id])
end
# POST /locales
# POST /locales.xml
def create
- @locale = Locale.new(params[:locale])
-
+ @locale = I18n::Backend::Locale.new(params[:locale])
respond_to do |format|
if @locale.save
flash[:notice] = 'Locale was successfully created.'
format.html { redirect_to(@locale) }
format.xml { render :xml => @locale, :status => :created, :location => @locale }
else
+ flash[:error] = @locale.errors.to_a
format.html { render :action => "new" }
format.xml { render :xml => @locale.errors, :status => :unprocessable_entity }
end
@@ -58,14 +55,14 @@ def create
# PUT /locales/1
# PUT /locales/1.xml
def update
- @locale = Locale.find_by_code(params[:id])
-
+ @locale = I18n::Backend::Locale.find_by_code(params[:id])
respond_to do |format|
if @locale.update_attributes(params[:locale])
flash[:notice] = 'Locale was successfully updated.'
format.html { redirect_to(@locale) }
format.xml { head :ok }
else
+ flash[:error] = @locale.errors.to_a
format.html { render :action => "edit" }
format.xml { render :xml => @locale.errors, :status => :unprocessable_entity }
end
@@ -75,9 +72,8 @@ def update
# DELETE /locales/1
# DELETE /locales/1.xml
def destroy
- @locale = Locale.find_by_code(params[:id])
+ @locale = I18n::Backend::Locale.find_by_code(params[:id])
@locale.destroy
-
respond_to do |format|
format.html { redirect_to(locales_url) }
format.xml { head :ok }
26 lib/controllers/translations_controller.rb → app/controllers/translations_controller.rb
View
@@ -1,5 +1,5 @@
class TranslationsController < ActionController::Base
- prepend_view_path(File.join(File.dirname(__FILE__), "..", "views"))
+
layout 'translations'
before_filter :find_locale
@@ -9,7 +9,6 @@ class TranslationsController < ActionController::Base
# GET /translations.xml
def index
@translations = @locale.translations.find(:all, :order => "raw_key, pluralization_index")
-
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @translations }
@@ -19,15 +18,13 @@ def index
# GET /translations
# GET /translations.xml
def translations
- @locale ||= Locale.default_locale
+ @locale ||= I18n::Backend::Locale.default_locale
@translation_option = TranslationOption.find(params[:translation_option])
-
if @translation_option == TranslationOption.translated
@translations = @locale.translations.translated
else
@translations = @locale.translations.untranslated
end
-
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @translations }
@@ -37,19 +34,16 @@ def translations
# GET /asset_translations
# GET /asset_translations.xml
def asset_translations
- @locale ||= Locale.default_locale
+ @locale ||= I18n::Backend::Locale.default_locale
@translation_option = TranslationOption.find(params[:translation_option])
-
@asset_translations = I18n.asset_translations
@untranslated_assets = I18n.untranslated_assets(@locale.code)
- @percentage_translated = (((@asset_translations.size - @untranslated_assets.size).to_f / @asset_translations.size.to_f * 100).round) rescue 0
-
+ @percentage_translated = (((@asset_translations.size - @untranslated_assets.size).to_f / @asset_translations.size.to_f * 100).round) rescue 0
if @translation_option == TranslationOption.translated
@asset_translations = @asset_translations.reject{|e| @untranslated_assets.include?(e)}
else
@asset_translations = @untranslated_assets
end
-
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @untranslated_assets }
@@ -60,7 +54,6 @@ def asset_translations
# GET /translations/1.xml
def show
@translation = @locale.translations.find(params[:id])
-
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @translation }
@@ -71,7 +64,6 @@ def show
# GET /translations/new.xml
def new
@translation = Translation.new
-
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @translation }
@@ -105,7 +97,6 @@ def create
def update
@translation = @locale.translations.find(params[:id])
@first_time_translating = @translation.value.nil?
-
respond_to do |format|
if @translation.update_attributes(params[:translation])
format.html do
@@ -133,9 +124,8 @@ def destroy
end
end
- private
-
- def find_locale
- @locale = Locale.find_by_code(params[:locale_id])
- end
+private
+ def find_locale
+ @locale = I18n::Backend::Locale.find_by_code(params[:locale_id])
+ end
end
66 app/models/locale.rb
View
@@ -0,0 +1,66 @@
+module I18n::Backend
+ class Locale < ActiveRecord::Base
+ validates_presence_of :code
+ validates_uniqueness_of :code
+
+ has_many :translations, :dependent => :destroy
+ scope :non_defaults, :conditions => ["code != ?", I18n.default_locale.to_s]
+
+ # scope :english, lambda { |m| { return Hash.new if m.nil?; :conditions => "locales.locale = '#{m}'" } }
+ # scope :in_city, lambda { |m| { return {} if m.nil?; :joins => [cities], :conditions => "cities.name = '#{m}' } }
+
+ def self.default_locale
+ @@default_locale ||= self.find(:first, :conditions => {:code => I18n.default_locale.to_s})
+ end
+
+ def self.reset_default_locale
+ @@default_locale = nil
+ end
+
+ def translation_from_key(key)
+ self.translations.find(:first, :conditions => {:key => Translation.hk(key)})
+ end
+
+ def create_translation(key, value, pluralization_index=1)
+ conditions = {:key => key, :raw_key => key.to_s, :pluralization_index => pluralization_index}
+
+ # set the key as the value if we're using the default locale and the key is a string
+ conditions.merge!({:value => value}) if (self.code == I18n.default_locale.to_s && key.is_a?(String))
+ translation = self.translations.create(conditions)
+
+ # hackity hack. bug #922 maybe?
+ self.connection.commit_db_transaction unless Rails.env.test?
+ translation
+ end
+
+ def find_translation_or_copy_from_default_locale(key, pluralization_index)
+ self.translations.find_by_key_and_pluralization_index(Translation.hk(key), pluralization_index) || copy_from_default(key, pluralization_index)
+ end
+
+ def copy_from_default(key, pluralization_index)
+ if !self.default_locale? && I18n::Backend::Locale.default_locale.has_translation?(key, pluralization_index)
+ create_translation(key, key, pluralization_index)
+ end
+ end
+
+ def has_translation?(key, pluralization_index=1)
+ self.translations.exists?(:key => Translation.hk(key), :pluralization_index => pluralization_index)
+ end
+
+ def percentage_translated
+ (self.translations.translated.count.to_f / self.translations.count.to_f * 100).round rescue 100
+ end
+
+ def self.available_locales
+ all.map(&:code).map(&:to_sym) rescue []
+ end
+
+ def default_locale?
+ self == I18n::Backend::Locale.default_locale
+ end
+
+ def to_param
+ self.code
+ end
+ end
+end
46 app/models/translation.rb
View
@@ -0,0 +1,46 @@
+require 'digest/md5'
+class Translation < ActiveRecord::Base
+ belongs_to :locale
+ validates_presence_of :key
+ before_validation :generate_hash_key, :on => :create
+ after_update :update_cache
+
+ scope :untranslated, :conditions => {:value => nil}, :order => :raw_key
+ scope :translated, :conditions => "value IS NOT NULL", :order => :raw_key
+
+ def default_locale_value(rescue_value = 'No default locale value')
+ begin
+ I18n::Backend::Locale.default_locale.translations.find_by_key_and_pluralization_index(self.key, self.pluralization_index).value
+ rescue
+ rescue_value
+ end
+ end
+
+ def value_or_default
+ value = self.value || self.default_locale_value(self.raw_key)
+ value =~ /^---(.*)\n/ ? YAML.load(value) : value # supports using YAML e.g. order: [ :year, :month, :day ] values are stored as Symbols "--- :year\n", "--- :month\n", "--- :day\n"
+ end
+
+ # create hash key
+ def self.hk(key)
+ Base64.encode64(Digest::MD5.hexdigest(key.to_s)).gsub(/\n/, '')
+ end
+
+ # create cache key
+ def self.ck(locale, key, hash=true)
+ key = self.hk(key) if hash
+ "#{locale.code}:#{key}"
+ end
+
+protected
+ def generate_hash_key
+ self.raw_key = key.to_s
+ self.key = Translation.hk(key)
+ end
+
+ def update_cache
+ new_cache_key = Translation.ck(self.locale, self.key, false)
+ I18n.backend.cache_store.write(new_cache_key, self.value)
+ end
+end
+
0  lib/models/translation_option.rb → app/models/translation_option.rb
View
File renamed without changes
15 app/views/layouts/translations.html.erb
View
@@ -0,0 +1,15 @@
+<!DOCTYPE>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+ <title>Translation Administration: <%= controller.action_name %></title>
+ <%= javascript_include_tag 'jquery.min' %>
+ <%= javascript_include_tag 'rails' %>
+</head>
+<body class="content">
+ <p><%= link_to 'Textual Translations', translations_url %> &middot; <%= link_to 'Asset Translations', asset_translations_url %></p>
+ <div class="content">
+ <%= yield %>
+ </div>
+</body>
+</html>
11 app/views/locales/edit.html.erb
View
@@ -0,0 +1,11 @@
+<h1>Editing locale</h1>
+
+<%= display_flash %>
+
+<% form_for(@locale, :url => locales_path(@locale), :method => :put) do |f| %>
+ <p><%= f.label :code, 'Code' %><%= f.text_field :code %></p>
+ <p><%= f.label :name, 'Name' %><%= f.text_field :name %></p>
+ <p><%= f.submit "Update" %></p>
+<% end %>
+
+<p><%= link_to 'Show', locale_path(@locale) %> | <%= link_to 'Back', locales_path %></p>
18 app/views/locales/index.html.erb
View
@@ -0,0 +1,18 @@
+<h1>Listing locales</h1>
+<table>
+ <tr>
+ <th>Code</th>
+ <th>Name</th>
+ </tr>
+ <% for locale in @locales %>
+ <tr>
+ <td><%=h locale.code %></td>
+ <td><%=h locale.name %></td>
+ <td><%= link_to 'Show', locale_path(locale) %></td>
+ <td><%= link_to 'Edit', edit_locale_path(locale) %></td>
+ <td><%= link_to 'Destroy', locale_path(locale), :confirm => 'Are you sure?', :method => :delete %></td>
+ </tr>
+ <% end %>
+</table>
+
+<p><%= link_to 'New locale', new_locale_path %></p>
10 app/views/locales/new.html.erb
View
@@ -0,0 +1,10 @@
+<h1>New locale</h1>
+
+<%= form_for(@locale, :url => locales_path, :html => {:method => :post}) do |f| %>
+ <%= display_flash %>
+ <p><%= f.label :code, 'Code' %><%= f.text_field :code %></p>
+ <p><%= f.label :name, 'Name' %><%= f.text_field :name %></p>
+ <p><%= f.submit "Create" %></p>
+<% end %>
+
+<p><%= link_to 'Back', locales_path %></p>
9 app/views/locales/show.html.erb
View
@@ -0,0 +1,9 @@
+<p><b>Code:</b><%= @locale.code %></p>
+
+<p><b>Name:</b><%= @locale.name %></p>
+
+<p>
+ <%= link_to 'Edit', edit_locale_path(@locale) %> |
+ <%= link_to 'Translations', locale_translations_path(@locale) %> |
+ <%= link_to 'Back', locales_path %>
+</p>
0  lib/views/translations/asset_translations.html.erb → app/views/translations/asset_translations.html.erb
View
File renamed without changes
18 app/views/translations/edit.html.erb
View
@@ -0,0 +1,18 @@
+<h1>Editing translation for <%= @locale.code %></h1>
+
+<p><b>Key:</b><%=h @translation.key %></p>
+
+<p><b>Raw Key:</b><%=h @translation.raw_key %></p>
+
+<p><b>Pluralization Index:</b><%=h @translation.pluralization_index %></p>
+
+<p><b>Default Locale Value:</b><%=h @translation.default_locale_value %></p>
+
+<%= display_flash %>
+
+<%= form_for(@translation, :as => :translation, :url => locale_translation_path(@locale, @translation)) do |f| %>
+ <p><%= f.label :value, 'Value' %><%= f.text_field :value %></p>
+ <p><%= f.submit "Update" %></p>
+<% end %>
+
+<p><%= link_to 'Show', locale_translation_path(@locale, @translation) %> | <%= link_to 'Back', locale_translations_path %></p>
12 lib/views/translations/index.html.erb → app/views/translations/index.html.erb
View
@@ -7,8 +7,7 @@
<th>Value</th>
<th>Default Locale Value</th>
</tr>
-
-<% for translation in @translations %>
+ <% for translation in @translations %>
<tr>
<td><%=h translation.key %></td>
<td><%=h translation.raw_key %></td>
@@ -16,12 +15,9 @@
<td><%=h translation.default_locale_value %></td>
<td><%= link_to 'Show', locale_translation_path(@locale, translation) %></td>
<td><%= link_to 'Edit', edit_locale_translation_path(@locale, translation) %></td>
- <td><%= link_to 'Destroy', locale_translation_path(@locale, translation), :confirm => 'Are you sure?', :method => :delete %></td>
+ <td><%= button_to 'Destroy', locale_translation_path(@locale, translation), :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
-<% end %>
+ <% end %>
</table>
-<br />
-
-<%= link_to 'New translation', new_locale_translation_path %> |
-<%= link_to 'Back', locales_path %>
+<p><%= link_to 'New translation', new_locale_translation_path %> | <%= link_to 'Back', locales_path %></p>
11 app/views/translations/new.html.erb
View
@@ -0,0 +1,11 @@
+<h1>New translation</h1>
+
+<%= display_flash %>
+
+<%= form_for(@translation, :as => :translation, :url => locale_translations_path(@locale), :method => :post) do |f| %>
+ <p><%= f.label :key, 'Key' %><%= f.text_field :key %></p>
+ <p><%= f.label :value, 'Value' %><%= f.text_field :value %></p>
+ <p><%= f.submit "Create" %></p>
+<% end %>
+
+<p><%= link_to 'Back', locale_translations_path %></p>
13 app/views/translations/show.html.erb
View
@@ -0,0 +1,13 @@
+<p><b>Locale:</b><%=h @locale.code %></p>
+
+<p><b>Key:</b><%=h @translation.key %></p>
+
+<p><b>Raw Key:</b><%=h @translation.raw_key %></p>
+
+<p><b>Pluralization Index:</b><%=h @translation.pluralization_index %></p>
+
+<p><b>Default Locale Value:</b><%=h @translation.default_locale_value %></p>
+
+<p><b>Value:</b><%=h @translation.value %></p>
+
+<p><%= link_to 'Edit', edit_locale_translation_path(@locale, @translation) %> | <%= link_to 'Back', locale_translations_path %></p>
24 app/views/translations/translations.html.erb
View
@@ -0,0 +1,24 @@
+<%= form_tag translations_url do %>
+ <%= select_tag :locale_id, options_from_collection_for_select(Locale.all, :code, :name, @locale.code) %>
+ <%= select_tag :translation_option,
+ options_from_collection_for_select(TranslationOption.all, :code, :description, @translation_option.code) %>
+ <%= submit_tag 'Go' %>
+<% end %>
+
+<p>Textual Translation progress: <strong><%= @locale.percentage_translated %>%</strong></p>
+
+<h2><%= @translation_option.description %>: <%= @locale.name %></h2>
+
+<% if @translations.empty? %>
+ <h3>No records for this criteria.</h3>
+<% end %>
+
+<% for translation in @translations %>
+ <div id="<%= "translation_#{translation.class}_#{translation.id}" %>">
+ <%= form_for(translation, :as => :translation, :url => locale_translation_path(@locale, translation), :remote => true) do |f| %>
+ <p><%= h translation.default_locale_value || translation.raw_key %></p>
+ <p><%= f.text_field :value, :size => 128 %> <%= f.submit "Update" %></p>
+ <% end %>
+ </div>
+ <hr/>
+<% end %>
0  lib/views/translations/update.rjs → app/views/translations/update.rjs
View
File renamed without changes
7 config/routes.rb
View
@@ -0,0 +1,7 @@
+Rails.application.routes.draw do
+ resources :locales do
+ resources :translations
+ end
+ match '/translations' => 'translations#translations', :as => 'translations'
+ match '/asset_translations' => 'translations#asset_translations', :as => 'asset_translations'
+end
55 data/default_localized_translations.yml
View
@@ -0,0 +1,55 @@
+en:
+ date:
+ formats:
+ default: "%Y-%m-%d"
+ short: "%b %d"
+ long: "%B %d, %Y"
+ day_names:
+ - Sunday
+ - Monday
+ - Tuesday
+ - Wednesday
+ - Thursday
+ - Friday
+ - Saturday
+ abbr_day_names:
+ - Sun
+ - Mon
+ - Tue
+ - Wed
+ - Thu
+ - Fri
+ - Sat
+ month_names:
+ - January
+ - February
+ - March
+ - April
+ - May
+ - June
+ - July
+ - August
+ - September
+ - October
+ - November
+ - December
+ abbr_month_names:
+ - Jan
+ - Feb
+ - Mar
+ - Apr
+ - May
+ - Jun
+ - Jul
+ - Aug
+ - Sep
+ - Oct
+ - Nov
+ - Dec
+ time:
+ formats:
+ default: "%a, %d %b %Y %H:%M:%S %z"
+ short: "%d %b %H:%M"
+ long: "%B %d, %Y %H:%M"
+ am: am
+ pm: pm
7 generators/i18n_backend_database/i18n_backend_database_generator.rb
View
@@ -1,8 +1,7 @@
class I18nBackendDatabaseGenerator < Rails::Generator::Base
def manifest
- record { |m|
- m.migration_template "migrate/create_i18n_tables.rb", "db/migrate",
- :migration_file_name => "create_i18n_tables"
- }
+ record do |m|
+ m.migration_template "migrate/create_i18n_tables.rb", "db/migrate", :migration_file_name => "create_i18n_tables"
+ end
end
end
20 i18n_backend_database.gemspec
View
@@ -0,0 +1,20 @@
+$:.push File.expand_path("../lib", __FILE__)
+
+# Maintain your gem's version:
+require "i18n_backend_database/version"
+
+# Describe your gem and declare its dependencies:
+Gem::Specification.new do |s|
+ s.name = "i18n_backend_database"
+ s.version = I18nBackendDatabase::VERSION
+ s.authors = ["Dylan Stamat"]
+ s.email = ["dstamat@elctech.com"]
+ s.homepage = "http://someplace.com"
+ s.summary = "summary."
+ s.description = "description."
+
+ s.files = Dir["{app,config,db,lib}/**/*"] + ["LICENSE", "Rakefile", "README.textile"]
+ s.test_files = Dir["test/**/*"]
+
+ s.add_dependency "rails", ">= 3"
+end
1  init.rb
View
@@ -1 +0,0 @@
-require 'i18n_backend_database'
7 lib/ext/i18n.rb
View
@@ -1,8 +1,8 @@
module I18n
- APP_DIRECTORY = 'app/views'
+ APP_DIRECTORY = 'app/views'
+
class << self
-
def locale_segment
I18n.locale.to_s == I18n.default_locale.to_s ? "" : "/#{I18n.locale}"
end
@@ -63,6 +63,5 @@ def locale_asset(asset, locale)
def asset_path(asset)
asset[0] == ?/ ? asset : "/images/#{asset}"
end
-
end
-end
+end
17 lib/i18n_backend_database.rb
View
@@ -1,9 +1,12 @@
-require File.dirname(__FILE__) + '/models/locale'
-require File.dirname(__FILE__) + '/models/translation'
-require File.dirname(__FILE__) + '/models/translation_option'
-require File.dirname(__FILE__) + '/routing'
-require File.dirname(__FILE__) + '/controllers/locales_controller'
-require File.dirname(__FILE__) + '/controllers/translations_controller'
+require File.dirname(__FILE__) + '/../app/models/locale'
+require File.dirname(__FILE__) + '/../app/models/translation'
+require File.dirname(__FILE__) + '/../app/models/translation_option'
+require File.dirname(__FILE__) + '/../app/controllers/locales_controller'
+require File.dirname(__FILE__) + '/../app/controllers/translations_controller'
require File.dirname(__FILE__) + '/i18n_backend_database/database'
require File.dirname(__FILE__) + '/ext/i18n'
-ActionController::Routing::RouteSet::Mapper.send(:include, I18n::BackendDatabase::Routing)
+require File.dirname(__FILE__) + '/i18n_backend_database/database'
+require File.dirname(__FILE__) + '/i18n_util'
+require File.dirname(__FILE__) + '/i18n_backend_database'
+
+require 'i18n_backend_database/railtie'
460 lib/i18n_backend_database/database.rb
View
@@ -1,263 +1,273 @@
+module I18n::Backend
+ class Database
+ INTERPOLATION_RESERVED_KEYS = %w(scope default)
+ MATCH = /(\\\\)?%\{([^\}]+)\}/
+
+ attr_accessor :locale
+ attr_accessor :cache_store
+ attr_accessor :localize_text_tag
+
+ def initialize(options = {})
+ store = options.delete(:cache_store)
+ text_tag = options.delete(:localize_text_tag)
+ @cache_store = store ? ActiveSupport::Cache.lookup_store(store) : Rails.cache
+ @localize_text_tag = text_tag ? text_tag : '^^'
+ end
-module I18n
- module Backend
- class Database
- INTERPOLATION_RESERVED_KEYS = %w(scope default)
- MATCH = /(\\\\)?\{\{([^\}]+)\}\}/
-
- attr_accessor :locale
- attr_accessor :cache_store
- attr_accessor :localize_text_tag
-
- def initialize(options = {})
- store = options.delete(:cache_store)
- text_tag = options.delete(:localize_text_tag)
- @cache_store = store ? ActiveSupport::Cache.lookup_store(store) : Rails.cache
- @localize_text_tag = text_tag ? text_tag : '^^'
- end
+ def locale=(code)
+ @locale = I18n::Backend::Locale.find_by_code(code)
+ end
+
+ def cache_store=(store)
+ @cache_store = ActiveSupport::Cache.lookup_store(store)
+ end
+
+ # TODO RAILS3 not sure what this method should do or how it should act yet
+ def transliterate *args
+ args[1]
+ end
- def locale=(code)
- @locale = Locale.find_by_code(code)
+ # Handles the lookup and addition of translations to the database
+ #
+ # On an initial translation, the locale is checked to determine if
+ # this is the default locale. If it is, we'll create a complete
+ # translation record for this locale with both the key and value.
+ #
+ # If the current locale is checked, and it differs from the default
+ # locale, we'll create a translation record with a nil value. This
+ # allows for the lookup of untranslated records in a given locale.
+ def translate(locale, key, options = {})
+ locale_in_context(locale)
+
+ options[:scope] = [options[:scope]] unless options[:scope].is_a?(Array) || options[:scope].blank?
+ key = "#{options[:scope].join('.')}.#{key}".to_sym if options[:scope] && key.is_a?(Symbol)
+ count = options[:count]
+ # pull out values for interpolation
+ values = options.reject { |name, value| [:scope, :default].include?(name) }
+
+ entry = lookup(@locale, key)
+ cache_lookup = true unless entry.nil?
+
+ # if no entry exists for the current locale and the current locale is not the default locale then lookup translations for the default locale for this key
+ unless entry || @locale.default_locale?
+ entry = use_and_copy_default_locale_translations_if_they_exist(@locale, key)
end
- def cache_store=(store)
- @cache_store = ActiveSupport::Cache.lookup_store(store)
+ # if we have no entry and some defaults ... start looking them up
+ unless entry || key.is_a?(String) || options[:default].blank?
+ default = options[:default].is_a?(Array) ? options[:default].shift : options.delete(:default)
+ return translate(@locale.code, default, options.dup)
end
- # Handles the lookup and addition of translations to the database
- #
- # On an initial translation, the locale is checked to determine if
- # this is the default locale. If it is, we'll create a complete
- # translation record for this locale with both the key and value.
- #
- # If the current locale is checked, and it differs from the default
- # locale, we'll create a translation record with a nil value. This
- # allows for the lookup of untranslated records in a given locale.
- def translate(locale, key, options = {})
- @locale = locale_in_context(locale)
-
- options[:scope] = [options[:scope]] unless options[:scope].is_a?(Array) || options[:scope].blank?
- key = "#{options[:scope].join('.')}.#{key}".to_sym if options[:scope] && key.is_a?(Symbol)
- count = options[:count]
- # pull out values for interpolation
- values = options.reject { |name, value| [:scope, :default].include?(name) }
-
- entry = lookup(@locale, key)
- cache_lookup = true unless entry.nil?
-
- # if no entry exists for the current locale and the current locale is not the default locale then lookup translations for the default locale for this key
- unless entry || @locale.default_locale?
- entry = use_and_copy_default_locale_translations_if_they_exist(@locale, key)
- end
+ # this needs to be folded into the above at some point.
+ # this handles the case where the default of the string key is a space
+ if !entry && key.is_a?(String) && options[:default] == " "
+ default = options[:default].is_a?(Array) ? options[:default].shift : options.delete(:default)
+ return translate(@locale.code, default, options.dup)
+ end
- # if we have no entry and some defaults ... start looking them up
- unless entry || key.is_a?(String) || options[:default].blank?
- default = options[:default].is_a?(Array) ? options[:default].shift : options.delete(:default)
- return translate(@locale.code, default, options.dup)
+ # The requested key might not be a parent node in a hierarchy of keys instead of a regular 'leaf' node
+ # that would simply result in a string return. If so, check the database for possible children
+ # and return them in a nested hash if we find them.
+ # We can safely ignore pluralization indeces here since they should never apply to a hash return
+ if !entry && (key.is_a?(String) || key.is_a?(Symbol))
+ #We need to escape % and \. Rails will handle the rest.
+ escaped_key = key.to_s.gsub('\\', '\\\\\\\\').gsub(/%/, '\%')
+ children = @locale.translations.find :all, :conditions => ["raw_key like ?", "#{escaped_key}.%"]
+ if children.size > 0
+ entry = hashify_record_array(key.to_s, children)
+ @cache_store.write(Translation.ck(@locale, key), entry) unless cache_lookup == true
+ return entry
end
+ end
- # this needs to be folded into the above at some point.
- # this handles the case where the default of the string key is a space
- if !entry && key.is_a?(String) && options[:default] == " "
- default = options[:default].is_a?(Array) ? options[:default].shift : options.delete(:default)
- return translate(@locale.code, default, options.dup)
- end
+ # we check the database before creating a translation as we can have translations with nil values
+ # if we still have no blasted translation just go and create one for the current locale!
+ unless entry
+ pluralization_index = (options[:count].nil? || options[:count] == 1) ? 1 : 0
+ translation = @locale.translations.find_by_key_and_pluralization_index(Translation.hk(key), pluralization_index) ||
+ @locale.create_translation(key, key, pluralization_index)
+ entry = translation.value_or_default
+ end
- # The requested key might not be a parent node in a hierarchy of keys instead of a regular 'leaf' node
- # that would simply result in a string return. If so, check the database for possible children
- # and return them in a nested hash if we find them.
- # We can safely ignore pluralization indeces here since they should never apply to a hash return
- if !entry && (key.is_a?(String) || key.is_a?(Symbol))
- #We need to escape % and \. Rails will handle the rest.
- escaped_key = key.to_s.gsub('\\', '\\\\\\\\').gsub(/%/, '\%')
- children = @locale.translations.find :all, :conditions => ["raw_key like ?", "#{escaped_key}.%"]
- if children.size > 0
- entry = hashify_record_array(key.to_s, children)
- @cache_store.write(Translation.ck(@locale, key), entry) unless cache_lookup == true
- return entry
- end
- end
+ # write to cache unless we've already had a successful cache hit
+ @cache_store.write(Translation.ck(@locale, key), entry) unless cache_lookup == true
- # we check the database before creating a translation as we can have translations with nil values
- # if we still have no blasted translation just go and create one for the current locale!
- unless entry
- pluralization_index = (options[:count].nil? || options[:count] == 1) ? 1 : 0
- translation = @locale.translations.find_by_key_and_pluralization_index(Translation.hk(key), pluralization_index) ||
- @locale.create_translation(key, key, pluralization_index)
- entry = translation.value_or_default
- end
+ entry = pluralize(@locale, entry, count)
+ entry = interpolate(@locale.code, entry, values)
+ entry.is_a?(Array) ? entry.dup : entry # array's can get frozen with cache writes
+ end
- # write to cache unless we've already had a successful cache hit
- @cache_store.write(Translation.ck(@locale, key), entry) unless cache_lookup == true
+ # Acts the same as +strftime+, but returns a localized version of the
+ # formatted date string. Takes a key from the date/time formats
+ # translations as a format argument (<em>e.g.</em>, <tt>:short</tt> in <tt>:'date.formats'</tt>).
+ def localize(locale, object, format = :default, options = {})
+ raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime)
- entry = pluralize(@locale, entry, count)
- entry = interpolate(@locale.code, entry, values)
- entry.is_a?(Array) ? entry.dup : entry # array's can get frozen with cache writes
- end
+ locale_in_context(locale)
- # Acts the same as +strftime+, but returns a localized version of the
- # formatted date string. Takes a key from the date/time formats
- # translations as a format argument (<em>e.g.</em>, <tt>:short</tt> in <tt>:'date.formats'</tt>).
- def localize(locale, object, format = :default)
- raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime)
-
+ unless format.to_s.index('%') # Unless a custom format is passed
type = object.respond_to?(:sec) ? 'time' : 'date'
- format = translate(locale, "#{type}.formats.#{format.to_s}") unless format.to_s.index('%') # lookup keyed formats unless a custom format is passed
-
- format.gsub!(/%a/, translate(locale, :"date.abbr_day_names")[object.wday])
- format.gsub!(/%A/, translate(locale, :"date.day_names")[object.wday])
- format.gsub!(/%b/, translate(locale, :"date.abbr_month_names")[object.mon])
- format.gsub!(/%B/, translate(locale, :"date.month_names")[object.mon])
- format.gsub!(/%p/, translate(locale, :"time.#{object.hour < 12 ? :am : :pm}")) if object.respond_to? :hour
-
- object.strftime(format)
- end
-
- # Returns the text string with the text within the localize text tags translated.
- def localize_text(locale, text)
- text_tag = Regexp.escape(localize_text_tag).to_s
- expression = Regexp.new(text_tag + "(.*?)" + text_tag)
- tagged_text = text[expression, 1]
- while tagged_text do
- text = text.sub(expression, translate(locale, tagged_text))
- tagged_text = text[expression, 1]
+ if lookup(@locale, "#{type}.formats.#{format.to_s}") # Translation is in the database
+ format = translate(locale, "#{type}.formats.#{format.to_s}") # lookup keyed formats
+ else # There is no localization translations on the database, loading the default ones
+ I18nUtil.load_default_localizations
+ locale = I18n::Backend::Locale.default_locale.code
+ format = translate(locale, "#{type}.formats.#{format.to_s}")
end
- return text
end
- def available_locales
- Locale.available_locales
- end
+ format.gsub!(/%a/, translate(locale, "date.abbr_day_names")[object.wday])
+ format.gsub!(/%A/, translate(locale, "date.day_names")[object.wday])
+ format.gsub!(/%b/, translate(locale, "date.abbr_month_names")[object.mon])
+ format.gsub!(/%B/, translate(locale, "date.month_names")[object.mon])
+ format.gsub!(/%p/, translate(locale, "time.#{object.hour < 12 ? :am : :pm}")) if object.respond_to? :hour
- def reload!
- # get's called on initialization
- # let's not do anything yet
+ object.strftime(format)
+ end
+
+ # Returns the text string with the text within the localize text tags translated.
+ def localize_text(locale, text)
+ text_tag = Regexp.escape(localize_text_tag).to_s
+ expression = Regexp.new(text_tag + "(.*?)" + text_tag)
+ tagged_text = text[expression, 1]
+ while tagged_text do
+ text = text.sub(expression, translate(locale, tagged_text))
+ tagged_text = text[expression, 1]
end
+ return text
+ end
- protected
- # keep a local copy of the locale in context for use within the translation
- # routine, and also accept an arbitrary locale for one time locale lookups
- def locale_in_context(locale)
- return @locale if @locale && @locale.code == locale.to_s
- #Locale.find_by_code(locale.to_s) rescue nil && (raise InvalidLocale.new(locale))
- locale = Locale.find_by_code(locale.to_s)
- raise InvalidLocale.new(locale) unless locale
- locale
- end
+ def available_locales
+ I18n::Backend::Locale.available_locales
+ end
- # lookup key in cache and db, if the db is hit the value is cached
- def lookup(locale, key)
- cache_key = Translation.ck(locale, key)
- if @cache_store.exist?(cache_key) && value = @cache_store.read(cache_key)
- return value
- else
- translations = locale.translations.find_all_by_key(Translation.hk(key))
- case translations.size
- when 0
- value = nil
- when 1
- value = translations.first.value_or_default
- else
- value = translations.inject([]) do |values, t|
- values[t.pluralization_index] = t.value_or_default
- values
- end
- end
-
- @cache_store.write(cache_key, (value.nil? ? nil : value))
- return value
+ def reload!
+ # get's called on initialization
+ # let's not do anything yet
+ end
+
+ # lookup key in cache and db, if the db is hit the value is cached
+ def lookup(locale, key)
+ cache_key = Translation.ck(locale, key)
+ if @cache_store.exist?(cache_key) && value = @cache_store.read(cache_key)
+ return value
+ else
+ translations = locale.translations.find_all_by_key(Translation.hk(key))
+ case translations.size
+ when 0
+ value = nil
+ when 1
+ value = translations.first.value_or_default
+ else
+ value = translations.inject([]) do |values, t|
+ values[t.pluralization_index] = t.value_or_default
+ values
end
end
+ @cache_store.write(cache_key, (value.nil? ? nil : value))
+ return value
+ end
+ end
- # looks up translations for the default locale, and if they exist untranslated records are created for the locale and the default locale values are returned
- def use_and_copy_default_locale_translations_if_they_exist(locale, key)
- default_locale_entry = lookup(Locale.default_locale, key)
- return unless default_locale_entry
-
- if default_locale_entry.is_a?(Array)
- default_locale_entry.each_with_index do |entry, index|
- locale.create_translation(key, nil, index) if entry
- end
- else
- locale.create_translation(key, nil)
- end
+ protected
+ # keep a local copy of the locale in context for use within the translation
+ # routine, and also accept an arbitrary locale for one time locale lookups
+ def locale_in_context(locale)
+ return @locale if @locale && @locale.code == locale.to_s
+ return @locale unless locale.class == String || locale.class == Symbol
+ @locale = I18n::Backend::Locale.find_or_create_by_code(locale.to_s)
+ raise I18n::InvalidLocale.new(locale) unless @locale
+ end
- return default_locale_entry
- end
+ # looks up translations for the default locale, and if they exist untranslated records are created for the locale and the default locale values are returned
+ def use_and_copy_default_locale_translations_if_they_exist(locale, key)
+ default_locale_entry = lookup(I18n::Backend::Locale.default_locale, key)
+ return unless default_locale_entry
- def pluralize(locale, entry, count)
- return entry unless entry.is_a?(Array) and count
- count = count == 1 ? 1 : 0
- entry.compact[count]
+ if default_locale_entry.is_a?(Array)
+ default_locale_entry.each_with_index do |entry, index|
+ locale.create_translation(key, nil, index) if entry
end
+ else
+ locale.create_translation(key, nil)
+ end
- # Interpolates values into a given string.
- #
- # interpolate "file {{file}} opened by \\{{user}}", :file => 'test.txt', :user => 'Mr. X'
- # # => "file test.txt opened by {{user}}"
- #
- # Note that you have to double escape the <tt>\\</tt> when you want to escape
- # the <tt>{{...}}</tt> key in a string (once for the string and once for the
- # interpolation).
- def interpolate(locale, string, values = {})
- return string unless string.is_a?(String)
-
- if string.respond_to?(:force_encoding)
- original_encoding = string.encoding
- string.force_encoding(Encoding::BINARY)
- end
+ return default_locale_entry
+ end
- result = string.gsub(MATCH) do
- escaped, pattern, key = $1, $2, $2.to_sym
-
- if escaped
- pattern
- elsif INTERPOLATION_RESERVED_KEYS.include?(pattern)
- raise ReservedInterpolationKey.new(pattern, string)
- elsif !values.include?(key)
- raise MissingInterpolationArgument.new(pattern, string)
- else
- values[key].to_s
- end
- end
+ def pluralize(locale, entry, count)
+ return entry unless entry.is_a?(Array) and count
+ count = count == 1 ? 1 : 0
+ entry.compact[count]
+ end
- result.force_encoding(original_encoding) if original_encoding
- result
- end
+ # Interpolates values into a given string.
+ #
+ # interpolate "file {{file}} opened by \\{{user}}", :file => 'test.txt', :user => 'Mr. X'
+ # # => "file test.txt opened by {{user}}"
+ #
+ # Note that you have to double escape the <tt>\\</tt> when you want to escape
+ # the <tt>{{...}}</tt> key in a string (once for the string and once for the
+ # interpolation).
+ def interpolate(locale, string, values = {})
+ return string unless string.is_a?(String)
+
+ string = string.dup # It returns an error if not duplicated
+
+ if string.respond_to?(:force_encoding)
+ original_encoding = string.encoding
+ string.force_encoding(Encoding::BINARY)
+ end
- def strip_root_key(root_key, key)
- return nil if key.nil?
- return key.gsub(/^#{root_key}\./, '')
+ result = string.gsub(MATCH) do
+ escaped, pattern, key = $1, $2, $2.to_sym
+ if escaped
+ pattern
+ elsif INTERPOLATION_RESERVED_KEYS.include?(pattern)
+ raise ReservedInterpolationKey.new(pattern, string)
+ elsif !values.include?(key)
+ raise MissingInterpolationArgument.new(pattern, string)
+ else
+ values[key].to_s
end
+ end
- def hashify_record_array(root_key, record_array)
- return nil if record_array.nil? || record_array.empty?
-
- #Make sure that all of our records have raw_keys
- record_array.reject! {|record| record.raw_key.nil?}
-
- # Start building our return hash
- result = {}
- record_array.each { |record|
- key = strip_root_key(root_key, record.raw_key)
- next unless key.present?
-
- # If we contain a period delimiter, we need to add a sub-hash.
- # Otherwise, we just insert the value at this level.
- if key.index(".")
- internal_node = key.slice(0, key.index('.'))
- new_root = root_key + '.' + internal_node
- new_record_array = record_array.select {|record| record.raw_key.starts_with? new_root}
- result[internal_node.to_sym] = hashify_record_array(new_root, new_record_array)
- else
- value = record.value
- value = value.to_i if value == "0" || value.to_i != 0 #simple integer cast
- result[key.to_sym] = value
- end
- }
- result
- end
+ result.force_encoding(original_encoding) if original_encoding
+ result
+ end
+
+ def strip_root_key(root_key, key)
+ return nil if key.nil?
+ return key.gsub(/^#{root_key}\./, '')
+ end
+ def hashify_record_array(root_key, record_array)
+ return nil if record_array.nil? || record_array.empty?
+
+ #Make sure that all of our records have raw_keys
+ record_array.reject! {|record| record.raw_key.nil?}
+
+ # Start building our return hash
+ result = {}
+ record_array.each do |record|
+ key = strip_root_key(root_key, record.raw_key)
+ next unless key.present?
+
+ # If we contain a period delimiter, we need to add a sub-hash.
+ # Otherwise, we just insert the value at this level.
+ if key.index(".")
+ internal_node = key.slice(0, key.index('.'))
+ new_root = root_key + '.' + internal_node
+ new_record_array = record_array.select {|record| record.raw_key.starts_with? new_root}
+ result[internal_node.to_sym] = hashify_record_array(new_root, new_record_array)
+ else
+ value = record.value
+ value = value.to_i if value == "0" || value.to_i != 0 #simple integer cast
+ result[key.to_sym] = value
+ end
+ end
+ result
end
end
end
16 lib/i18n_backend_database/railtie.rb
View
@@ -0,0 +1,16 @@
+require 'i18n_backend_database'
+require 'rails'
+
+module I18nBackendDatabase
+ class Railtie < Rails::Railtie
+ railtie_name :i18n_backend_database
+
+ initializer "i18n_backend_database.initialize" do |app|
+ I18n.backend = I18n::Backend::Database.new
+ end
+
+ rake_tasks do
+ load File.join(File.dirname(__FILE__), '../tasks/i18n.rake')
+ end
+ end
+end
3  lib/i18n_backend_database/version.rb
View
@@ -0,0 +1,3 @@
+module I18nBackendDatabase
+ VERSION = '0.0.1'
+end
69 lib/i18n_util.rb
View
@@ -1,34 +1,40 @@
class I18nUtil
+ DEFAULT_TRANSLATION_PATH = 'config/translations'
+
+ def self.load_default_locales(path_to_file = nil)
+ path_to_file ||= File.join(File.dirname(__FILE__), "../data", "locales.yml")
+ data = YAML::load(IO.read(path_to_file))
+ data.each do |code, y|
+ I18n::Backend::Locale.create({:code => code, :name => y["name"]}) unless I18n::Backend::Locale.exists?(:code => code)
+ end
+ end
+
+ def self.load_default_localizations
+ I18nUtil.load_from_yml File.join(File.dirname(__FILE__), "../data", "default_localized_translations.yml")
+ end
+
# Create tanslation records from the YAML file. Will create the required locales if they do not exist.
def self.load_from_yml(file_name)
data = YAML::load(IO.read(file_name))
data.each do |code, translations|
- locale = Locale.find_or_create_by_code(code)
- backend = I18n::Backend::Simple.new
- keys = extract_i18n_keys(translations)
- keys.each do |key|
- value = backend.send(:lookup, code, key)
-
+ locale = I18n::Backend::Locale.find_by_code(code)
+ raise "Locale not found: #{code}" unless locale
+ translations_array = extract_translations_from_hash(translations)
+ translations_array.each do |key, value|
pluralization_index = 1
-
- if key.ends_with?('.one')
- key.gsub!('.one', '')
- end
-
+ key.gsub!('.one', '') if key.ends_with?('.one')
if key.ends_with?('.other')
key.gsub!('.other', '')
pluralization_index = 0
end
-
if value.is_a?(Array)
value.each_with_index do |v, index|
- create_translation(locale, "#{key}", index, v) unless v.nil?
+ create_translation(locale, key, index, v) unless v.nil?
end
else
create_translation(locale, key, pluralization_index, value)
end
-
end
end
end
@@ -37,28 +43,29 @@ def self.load_from_yml(file_name)
def self.create_translation(locale, key, pluralization_index, value)
translation = locale.translations.find_by_key_and_pluralization_index(Translation.hk(key), pluralization_index) # find existing record by hash key
unless translation # or build new one with raw key
- translation = locale.translations.build(:key =>key, :pluralization_index => pluralization_index)
- puts "from yaml create translation for #{locale.code} : #{key} : #{pluralization_index}" unless RAILS_ENV['test']
+ translation = locale.translations.build(:key => key, :pluralization_index => pluralization_index)
+ puts "from yaml create translation for #{locale.code} : #{key} : #{pluralization_index}" unless Rails.env.test?
end
translation.value = value
translation.save!
end
- def self.extract_i18n_keys(hash, parent_keys = [])
+ def self.extract_translations_from_hash(hash, parent_keys = [])
hash.inject([]) do |keys, (key, value)|
full_key = parent_keys + [key]
if value.is_a?(Hash)
# Nested hash
- keys += extract_i18n_keys(value, full_key)
+ keys += extract_translations_from_hash(value, full_key)
elsif !value.nil?
# String leaf node
- keys << full_key.join(".")
+ keys << [full_key.join("."), value]
end
keys
end
end
- # Create translation records for all existing locales from translation calls with the application. Ignores errors from tranlations that require objects.
+ # Create translation records for all existing locales from translation calls with the application.
+ # Ignores errors from tranlations that require objects.
def self.seed_application_translations(dir='app')
translated_objects(dir).each do |object|
interpolation_arguments= object.scan(/\{\{(.*?)\}\}/).flatten
@@ -69,7 +76,7 @@ def self.seed_application_translations(dir='app')
puts "translating for #{object} with options #{options.inspect}" unless RAILS_ENV['test']
I18n.t(object, options) # default locale first
- locales = Locale.available_locales
+ locales = I18n::Backend::Locale.available_locales
locales.delete(I18n.default_locale)
# translate for other locales
locales.each do |locale|
@@ -84,7 +91,7 @@ def self.translated_objects(dir='app')
Dir.glob("#{dir}/*").each do |item|
if File.directory?(item)
assets += translated_objects(item) unless item.ends_with?('i18n_backend_database') # ignore self
- else
+ elsif item.ends_with?('.rb') || item.ends_with?('.js') || item.ends_with?('.erb')
File.readlines(item).each do |l|
assets += l.scan(/I18n.t\((.*?)\)/).flatten
end
@@ -95,8 +102,8 @@ def self.translated_objects(dir='app')
# Populate translation records from the default locale to other locales if no record exists.
def self.synchronize_translations
- non_default_locales = Locale.non_defaults
- Locale.default_locale.translations.each do |t|
+ non_default_locales = I18n::Backend::Locale.non_defaults
+ I18n::Backend::Locale.default_locale.translations.each do |t|
non_default_locales.each do |locale|
unless locale.translations.exists?(:key => t.key, :pluralization_index => t.pluralization_index)
value = t.value =~ /^---(.*)\n/ ? t.value : nil # well will copy across YAML, like symbols
@@ -145,4 +152,16 @@ def self.needs_human_eyes?(value)
return true if value.index('%') # date formats
return true if value =~ /^---(.*)\n/ # YAML
end
-end
+
+ def self.process_translation_locales(locales_codes, &action)
+ translation_path = Rails.root + DEFAULT_TRANSLATION_PATH
+ if locales_codes.empty?
+ puts "Nothing to do."
+ else
+ locales_codes.each do | locale_code |
+ raise "Locale '#{locale_code}' not found" unless locale = Locale.find_by_code(locale_code)
+ action.call(locale, translation_path)
+ end
+ end
+ end
+end
67 lib/models/locale.rb
View
@@ -1,67 +0,0 @@
-class Locale < ActiveRecord::Base
- validates_presence_of :code
- validates_uniqueness_of :code
-
- has_many :translations, :dependent => :destroy
- named_scope :non_defaults, :conditions => ["code != ?", I18n.default_locale.to_s]
-
- #named_scope :english, lambda { |m| { return Hash.new if m.nil?; :conditions => "locales.locale = '#{m}'" } }
-# named_scope :in_city, lambda { |m| { return {} if m.nil?; :joins => [cities], :conditions => "cities.name = '#{m}' } }
-
-
- @@default_locale = nil
-
- def self.default_locale
- @@default_locale ||= self.find(:first, :conditions => {:code => I18n.default_locale.to_s})
- end
-
- def self.reset_default_locale
- @@default_locale = nil
- end
-
- def translation_from_key(key)
- self.translations.find(:first, :conditions => {:key => Translation.hk(key)})
- end
-
- def create_translation(key, value, pluralization_index=1)
- conditions = {:key => key, :raw_key => key.to_s, :pluralization_index => pluralization_index}
-
- # set the key as the value if we're using the default locale and the key is a string
- conditions.merge!({:value => value}) if (self.code == I18n.default_locale.to_s && key.is_a?(String))
- translation = self.translations.create(conditions)
-
- # hackity hack. bug #922 maybe?
- self.connection.commit_db_transaction unless RAILS_ENV['test']
- translation
- end
-
- def find_translation_or_copy_from_default_locale(key, pluralization_index)
- self.translations.find_by_key_and_pluralization_index(Translation.hk(key), pluralization_index) || copy_from_default(key, pluralization_index)
- end
-
- def copy_from_default(key, pluralization_index)
- if !self.default_locale? && Locale.default_locale.has_translation?(key, pluralization_index)
- create_translation(key, key, pluralization_index)
- end
- end
-
- def has_translation?(key, pluralization_index=1)
- self.translations.exists?(:key => Translation.hk(key), :pluralization_index => pluralization_index)
- end
-
- def percentage_translated
- (self.translations.translated.count.to_f / self.translations.count.to_f * 100).round rescue 100
- end
-
- def self.available_locales
- all.map(&:code).map(&:to_sym) rescue []
- end
-
- def default_locale?
- self == Locale.default_locale
- end
-
- def to_param
- self.code
- end
-end
46 lib/models/translation.rb
View
@@ -1,46 +0,0 @@
-require 'digest/md5'
-
-class Translation < ActiveRecord::Base
- belongs_to :locale
- validates_presence_of :key
- before_validation_on_create :generate_hash_key
- after_update :update_cache
-
- named_scope :untranslated, :conditions => {:value => nil}, :order => :raw_key
- named_scope :translated, :conditions => "value IS NOT NULL", :order => :raw_key
-
- def default_locale_value(rescue_value='No default locale value')
- begin
- Locale.default_locale.translations.find_by_key_and_pluralization_index(self.key, self.pluralization_index).value
- rescue
- rescue_value
- end
- end
-
- def value_or_default
- value = self.value || self.default_locale_value(self.raw_key)
- value =~ /^---(.*)\n/ ? YAML.load(value) : value # supports using YAML e.g. order: [ :year, :month, :day ] values are stored as Symbols "--- :year\n", "--- :month\n", "--- :day\n"
- end
-
- # create hash key
- def self.hk(key)
- Base64.encode64(Digest::MD5.hexdigest(key.to_s)).gsub(/\n/, '')
- end
-
- # create cache key
- def self.ck(locale, key, hash=true)
- key = self.hk(key) if hash
- "#{locale.code}:#{key}"
- end
-
- protected
- def generate_hash_key
- self.raw_key = key.to_s
- self.key = Translation.hk(key)
- end
-
- def update_cache
- new_cache_key = Translation.ck(self.locale, self.key, false)
- I18n.backend.cache_store.write(new_cache_key, self.value)
- end
-end
BIN  lib/public/images/custom1_bar.gif
View
Deleted file not rendered
BIN  lib/public/images/custom1_box.gif
View
Deleted file not rendered
BIN  lib/public/images/percentImage.png
View
Deleted file not rendered
BIN  lib/public/images/percentImage_back.png
View
Deleted file not rendered
BIN  lib/public/images/percentImage_back1.png
View
Deleted file not rendered
BIN  lib/public/images/percentImage_back2.png
View
Deleted file not rendered
BIN  lib/public/images/percentImage_back3.png
View
Deleted file not rendered
BIN  lib/public/images/percentImage_back4.png
View
Deleted file not rendered
509 lib/public/javascripts/jsProgressBarHandler.js
View
@@ -1,509 +0,0 @@
-/*****************************************************************
- *
- * jsProgressBarHandler 0.3.3 - by Bramus! - http://www.bram.us/
- *
- * v 0.3.3 - 2008.11.10 - UPD: fixed IE compatibility issue (thanks Kevin - Sep 19 2008 / 6pm)
- * - UPD: setPercentage now parses the targetPercentage to an Integer to avoid infinite loop (thanks Jack - Sep 07 2008 / 9pm)
- * - UPD: Moved from Event.Observe(window, 'load', fn) to document.observe('dom:loaded', fn) in order to force people to use an up to date Prototype release.
- * - UPD: setPercentage now takes an overrideQueue param. If set the current queue is cleared.
- * - ADD: Added onTick callback event which gets called when the percentage is updated.
- * - ADD: Added stable (as in "non-crashing") versions of the additions which first surfaced in the (unreleased) 0.3.2 release
- * Preloading support partially implemented in IE as all versions (IE6,7&8) are quite hard to tame (one time they work, the next reload they don't anymore)
- * v 0.3.2 - 2008.04.09 (*UNRELEASED*)
- * - ADD: implemented preloading of images to avoid slight flicker when switching images (BUGGY!)
- * - ADD: percentage image now has class percentImage and percentage Text now has class percentText; This allows you to style the output easily.
- * v 0.3.1 - 2008.02.20 - UPD: fixed queue bug when animate was set to false (thanks Jamie Chong)
- * - UPD: update Prototype to version 1.6.0.2
- * v 0.3.0 - 2008.02.01 - ADD: animation queue, prevents from the progressbar getting stuck when multiple calls are made during an animation
- * - UPD: multiple barImages now work properly in Safari
- * v 0.2.1 - 2007.12.20 - ADD: option : set boxImage
- * ADD: option : set barImage (one or more)
- * ADD: option : showText
- * v 0.2 - 2007.12.13 - SYS: rewrite in 2 classs including optimisations
- * ADD: Config options
- * v 0.1 - 2007.08.02 - initial release
- *
- * @see http://www.barenakedapp.com/the-design/displaying-percentages on how to create a progressBar Background Image!
- *
- * Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
- *
- *****************************************************************/
-
-
- /**
- * CONFIG
- * -------------------------------------------------------------
- */
-
- // Should jsProgressBarHandler hook itself to all span.progressBar elements? - default : true
- var autoHook = true;
-
- // Default Options
- var defaultOptions = {
- animate : true, // Animate the progress? - default: true
- showText : true, // show text with percentage in next to the progressbar? - default : true
- width : 120, // Width of the progressbar - don't forget to adjust your image too!!!
- barImage : Array(
- 'images/percentImage_back4.png',
- 'images/percentImage_back3.png',
- 'images/percentImage_back2.png',
- 'images/percentImage_back1.png'
- ),
- boxImage : 'images/percentImage.png', // boxImage : image around the progress bar
- /*barImage : 'images/percentImage_back.png',*/ // Image to use in the progressbar. Can be an array of images too.
- height : 12, // Height of the progressbar - don't forget to adjust your image too!!!
- onTick : function(pbObj) { return true }
- }
-
- /**
- * NO NEED TO CHANGE ANYTHING BENEATH THIS LINE
- * -------------------------------------------------------------
- */
-
- /**
- * JS_BRAMUS Object
- * -------------------------------------------------------------
- */
-
- if (!JS_BRAMUS) { var JS_BRAMUS = new Object(); }
-
-
- /**
- * ProgressBar Class
- * -------------------------------------------------------------
- */
-
- JS_BRAMUS.jsProgressBar = Class.create();
-
- JS_BRAMUS.jsProgressBar.prototype = {
-
-
- /**
- * Datamembers
- * -------------------------------------------------------------
- */
-
- el : null, // Element where to render the progressBar in
- id : null, // Unique ID of the progressbar
- percentage : null, // Percentage of the progressbar
-
- options : null, // The options
-
- initialPos : null, // Initial postion of the background in the progressbar
- initialPerc : null, // Initial percentage the progressbar should hold
- pxPerPercent : null, // Number of pixels per 1 percent
-
- backIndex : null, // index in the array of background images currently used
- numPreloaded : null, // number of images preloaded
-
- running : null, // is this one running (being animated) or not?
-
- queue : false, // queue of percentages to set to
-
-
- /**
- * Constructor
- *
- * @param HTMLElement el
- * @param string id
- * @param int percentage
- * @return void
- * -------------------------------------------------------------
- */
-
- initialize : function(el, percentage, options) {
-
- // get the options
- this.options = Object.clone(defaultOptions);
- Object.extend(this.options, options || {});
-
- // datamembers from arguments
- this.el = $(el);
- this.id = $(el).id;
- this.percentage = 0; // Set to 0 intially, we'll change this later.
- this.backIndex = 0; // Set to 0 initially
- this.numPreloaded = 0; // Set to 0 initially
- this.running = false; // Set to false initially
- this.queue = Array(); // Set to empty Array initially
-
- // datamembers which are calculatef
- this.imgWidth = this.options.width * 2; // define the width of the image (twice the width of the progressbar)
- this.initialPos = this.options.width * (-1); // Initial postion of the background in the progressbar (0% is the middle of our image!)
- this.pxPerPercent = this.options.width / 100; // Define how much pixels go into 1%
- this.initialPerc = percentage; // Store this, we'll need it later.
-
- // enfore backimage array
- if (this.options.barImage.constructor != Array) { // used to be (but doesn't work in Safari): if (this.options.barImage.constructor.toString().indexOf("Array") == -1) {
- this.options.barImage = Array(this.options.barImage);
- }
-
- // preload Images
- this.preloadImages();
-
- },
-
-
- /**
- * Preloads the images needed for the progressbar
- *
- * @return void
- * -------------------------------------------------------------
- */
-
- preloadImages : function() {
-
- // loop all barimages
- for (i = 0; i < this.options.barImage.length; i++) {
-
- // create new image ref
- var newImage = null;
- newImage = new Image();
-
- // set onload, onerror and onabort functions
- newImage.onload = function() { this.numPreloaded++; }.bind(this);
- newImage.onerror = function() { this.numPreloaded++; }.bind(this);
- newImage.onabort = function() { this.numPreloaded++; }.bind(this);
-
- // set image source (preload it!)
- newImage.src = this.options.barImage[i];
-
- // image is in cache
- if (newImage.complete) {
- this.numPreloaded++;
- }
-
- }
-
- // if not IE, check if they're loaded
- if (!Prototype.Browser.IE) {
- this.checkPreloadedImages();
-
- // if IE, just init the visuals as it's quite hard to tame all IE's
- } else {
- this.initVisuals();
- }
-
- },
-
-
- /**
- * Check whether all images are preloaded and loads the percentage if so
- *
- * @return void
- * -------------------------------------------------------------
- */
-
- checkPreloadedImages : function() {
-
- // all images are loaded, go init the visuals
- if (parseInt(this.numPreloaded,10) >= parseInt(this.options.barImage.length,10) ) {
-
- // initVisuals
- this.initVisuals();
-
- // not all images are loaded ... wait a little and then retry
- } else {
-
- if ( parseInt(this.numPreloaded,10) <= parseInt(this.options.barImage.length,10) ) {
- // $(this.el).update(this.id + ' : ' + this.numPreloaded + '/' + this.options.barImage.length);
- setTimeout(function() { this.checkPreloadedImages(); }.bind(this), 100);
- }
-
- }
-
- },
-
-
- /**
- * Intializes the visual output and sets the percentage
- *
- * @return void
- * -------------------------------------------------------------
- */
-
- initVisuals : function () {
-
- // create the visual aspect of the progressBar
- $(this.el).update(
- '<img id="' + this.id + '_percentImage" src="' + this.options.boxImage + '" alt="0%" style="width: ' + this.options.width + 'px; height: ' + this.options.height + 'px; background-position: ' + this.initialPos + 'px 50%; background-image: url(' + this.options.barImage[this.backIndex] + '); padding: 0; margin: 0;" class="percentImage" />' +
- ((this.options.showText == true)?'<span id="' + this.id + '_percentText" class="percentText">0%</span>':''));
-
- // set the percentage
- this.setPercentage(this.initialPerc);
- },
-
-
- /**
- * Sets the percentage of the progressbar
- *
- * @param string targetPercentage
- * @param boolen clearQueue
- * @return void
- * -------------------------------------------------------------
- */
- setPercentage : function(targetPercentage, clearQueue) {
-
- // if clearQueue is set, empty the queue and then set the percentage
- if (clearQueue) {
-
- this.percentage = (this.queue.length != 0) ? this.queue[0] : targetPercentage;
- this.timer = null;
- this.queue = [];
-
- setTimeout(function() { this.setPercentage(targetPercentage); }.bind(this), 10);
-
- // no clearQueue defined, set the percentage
- } else {
-
- // add the percentage on the queue
- this.queue.push(targetPercentage);
-
- // process the queue (if not running already)
- if (this.running == false) {
- this.processQueue();
- }
- }
-
- },
-
-
- /**
- * Processes the queue
- *
- * @return void
- * -------------------------------------------------------------
- */
-
- processQueue : function() {
-
- // stuff on queue?
- if (this.queue.length > 0) {
-
- // tell the world that we're busy
- this.running = true;
-
- // process the entry
- this.processQueueEntry(this.queue[0]);
-
- // no stuff on queue
- } else {
-
- // return;
- return;
-
- }
-
- },
-
-
- /**
- * Processes an entry from the queue (viz. animates it)
- *
- * @param string targetPercentage
- * @return void
- * -------------------------------------------------------------
- */
-
- processQueueEntry : function(targetPercentage) {
-
- // get the current percentage
- var curPercentage = parseInt(this.percentage,10);
-
- // define the new percentage
- if ((targetPercentage.toString().substring(0,1) == "+") || (targetPercentage.toString().substring(0,1) == "-")) {
- targetPercentage = curPercentage + parseInt(targetPercentage);
- }
-
- // min and max percentages
- if (targetPercentage < 0) targetPercentage = 0;
- if (targetPercentage > 100) targetPercentage = 100;
-
- // if we don't need to animate, just change the background position right now and return
- if (this.options.animate == false) {
-
- // remove the entry from the queue
- this.queue.splice(0,1); // @see: http://www.bram.us/projects/js_bramus/jsprogressbarhandler/#comment-174878
-
- // Change the background position (and update this.percentage)
- this._setBgPosition(targetPercentage);
-
- // call onTick
- if (!this.options.onTick(this)) {
- return;
- }
-
- // we're not running anymore
- this.running = false;
-
- // continue processing the queue
- this.processQueue();
-
- // we're done!
- return;
- }
-
- // define if we need to add/subtract something to the current percentage in order to reach the target percentage
- if (targetPercentage != curPercentage) {
- if (curPercentage < targetPercentage) {
- newPercentage = curPercentage + 1;
- } else {
- newPercentage = curPercentage - 1;
- }
- callTick = true;
- } else {
- newPercentage = curPercentage;
- callTick = false;
- }
-
- // Change the background position (and update this.percentage)
- this._setBgPosition(newPercentage);
-
- // call onTick
- if (callTick && !this.options.onTick(this)) {
- return;
- }
-
- // Percentage not reached yet : continue processing entry
- if (curPercentage != newPercentage) {
-
- this.timer = setTimeout(function() { this.processQueueEntry(targetPercentage); }.bind(this), 10);
-
- // Percentage reached!
- } else {
-
- // remove the entry from the queue
- this.queue.splice(0,1);
-
- // we're not running anymore
- this.running = false;
-
- // unset timer
- this.timer = null;
-
- // process the rest of the queue
- this.processQueue();
-
- // we're done!
- return;
- }
-
- },
-
-
- /**
- * Gets the percentage of the progressbar
- *
- * @return int
- */
- getPercentage : function(id) {
- return this.percentage;
- },
-
-
- /**
- * Set the background position
- *
- * @param int percentage
- */
- _setBgPosition : function(percentage) {
- // adjust the background position
- $(this.id + "_percentImage").style.backgroundPosition = (this.initialPos + (percentage * this.pxPerPercent)) + "px 50%";
-
- // adjust the background image and backIndex
- var newBackIndex = Math.floor((percentage-1) / (100/this.options.barImage.length));
-
- if ((newBackIndex != this.backIndex) && (this.options.barImage[newBackIndex] != undefined)) {
- $(this.id + "_percentImage").style.backgroundImage = "url(" + this.options.barImage[newBackIndex] + ")";
- }
-
- this.backIndex = newBackIndex;
-
- // Adjust the alt & title of the image
- $(this.id + "_percentImage").alt = percentage + "%";
- $(this.id + "_percentImage").title = percentage + "%";
-
- // Update the text
- if (this.options.showText == true) {
- $(this.id + "_percentText").update("" + percentage + "%");
- }
-
- // adjust datamember to stock the percentage
- this.percentage = percentage;
- }
- }
-
-
- /**
- * ProgressHandlerBar Class - automatically create ProgressBar instances
- * -------------------------------------------------------------
- */
-
- JS_BRAMUS.jsProgressBarHandler = Class.create();
-
-
- JS_BRAMUS.jsProgressBarHandler.prototype = {
-
-
- /**
- * Datamembers
- * -------------------------------------------------------------
- */
-
- pbArray : new Array(), // Array of progressBars
-
-
- /**
- * Constructor
- *
- * @return void
- * -------------------------------------------------------------
- */
-
- initialize : function() {
-
- // get all span.progressBar elements
- $$('span.progressBar').each(function(el) {
-
- // create a progressBar for each element
- this.pbArray[el.id] = new JS_BRAMUS.jsProgressBar(el, parseInt(el.innerHTML.replace("%","")));
-
- }.bind(this));
- },
-
-
- /**
- * Set the percentage of a progressbar
- *
- * @param string el
- * @param string percentage
- * @return void
- * -------------------------------------------------------------
- */
- setPercentage : function(el, percentage, clearQueue) {
- this.pbArray[el].setPercentage(percentage, clearQueue);
- },
-
-
- /**
- * Get the percentage of a progressbar
- *
- * @param string el
- * @return int percentage
- * -------------------------------------------------------------
- */
- getPercentage : function(el) {
- return this.pbArray[el].getPercentage();
- }
-
- }
-
-
- /**
- * ProgressHandlerBar Class - hook me or not?
- * -------------------------------------------------------------
- */
-
- if (autoHook == true) {
- function initProgressBarHandler() { myJsProgressBarHandler = new JS_BRAMUS.jsProgressBarHandler(); }
- document.observe('dom:loaded', initProgressBarHandler, false);
- }
15 lib/routing.rb
View
@@ -1,15 +0,0 @@
-module I18n
- module BackendDatabase
- module Routing
- # Loads the set of routes from within a plugin and
- # evaluates them at this point within an application’s
- # main routes.rb file.
- def from_plugin(name)
- map = self # to make 'map' available within the plugin route file
- plugin_root = File.join(RAILS_ROOT, 'vendor', 'plugins')
- routes_path = File.join(plugin_root, name.to_s, 'routes.rb')
- eval(IO.read(routes_path), binding, routes_path) if File.file?(routes_path)
- end
- end
- end
-end
74 lib/tasks/i18n.rake
View
@@ -0,0 +1,74 @@
+namespace :i18n do
+ desc 'Clear cache'
+ task :clear_cache => :environment do
+ I18n.backend.cache_store.clear
+ end
+
+ desc 'Extracts translation data from database into fixtures'
+ task :export_translations => :environment do
+ locale_codes = ENV['locale'] || I18n::Backend::Locale.all.map(&:code).join(',')
+ I18nUtil.process_translation_locales(locale_codes.split(',')) do |locale, translation_path|
+ translations = Translation.all :conditions => {:locale_id => locale.id}, :select => 'raw_key as `key`, value, pluralization_index'
+ raise "No translations found for '#{locale.code}'" if translations.empty?
+ puts "Export #{translations.length} translations for '#{locale.code}'..."
+ FileUtils.mkpath(translation_path)
+ File.open(translation_path + "#{locale.code}.yml",'w'){|file| file.write translations.collect{|entry| entry.attributes}.to_yaml}