Skip to content

Commit

Permalink
Began with rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
Luca Guidi committed Apr 5, 2009
1 parent b9fe322 commit 4682487
Show file tree
Hide file tree
Showing 46 changed files with 239 additions and 344 deletions.
23 changes: 23 additions & 0 deletions Rakefile
@@ -0,0 +1,23 @@
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'

desc 'Default: run unit tests.'
task :default => :test

desc 'Test the click-to-globalize plugin.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end

desc 'Generate documentation for the click-to-globalize plugin.'
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'Click to Globalize'
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.rdoc_files.include('README')
rdoc.rdoc_files.include('lib/**/*.rb')
end
@@ -1,4 +1,4 @@
class LocalesController < ApplicationController
class TranslationsController < ApplicationController
before_filter :globalize?, :clear_cache

def set
Expand Down
2 changes: 2 additions & 0 deletions app/helpers/translations_helper.rb
@@ -0,0 +1,2 @@
module TranslationsHelper
end
File renamed without changes.
24 changes: 8 additions & 16 deletions init.rb
@@ -1,19 +1,11 @@
# Force Globalize loading.
if Rails::VERSION::STRING.match /^1\.2+/
load_plugin(File.join(RAILS_ROOT, 'vendor', 'plugins', 'globalize'))
else
# Specify the plugins loading order: Click To Globalize should be the last one.
plugins = (Dir["#{config.plugin_paths}/*"] - [ File.dirname(__FILE__) ]).map { |plugin| plugin.split(File::SEPARATOR).last}
Rails::Initializer.run { |config| config.plugins = plugins }
end

Object.send :include, Globalize
require 'click_to_globalize'

unless RAILS_ENV == 'test'
# FIXME
Locale.load_configured_base_language
raise NoBaseLanguageError if Locale.base_language.blank?
else
require File.dirname(__FILE__) + '/test/assertions'
ActionController::Base.class_eval do
include Click::Controller
include Click::Observer::Controller
end

ActionView::Base.class_eval do
include Click::Observer::View
include Click::Helper
end
291 changes: 93 additions & 198 deletions lib/click_to_globalize.rb
@@ -1,240 +1,135 @@
# ClickToGlobalize
require 'yaml'

module Globalize # :nodoc:
class NoConfiguredLocalesError < StandardError #:nodoc:
def to_s
"No configured locales in #{Locale.config_file}"
end
end
module Click
module Observer
module Controller
def self.included(recipient)
recipient.send :include, InstanceMethods
# TODO avoid chain, use super instead
recipient.class_eval do
alias_method_chain :render, :observe
end
end

class NoBaseLanguageError < StandardError #:nodoc:
def to_s
"No configured base language."
module InstanceMethods
protected
def render_with_observe(options = nil, extra_options = {}, &block)
locale_observer = Click::Observer::LocaleObserver.new
@template.add_observer locale_observer
render_without_observe(options, extra_options, &block)
@template.remove_observer locale_observer
session[:__globalize_translations] = locale_observer.translations.stringify_keys
end
end
end
end

class Locale # :nodoc:
# It's the file used to configure the locales in your app.
# Please look at README for more information about the configuration.
@@config_file = RAILS_ROOT + '/config/click.yml'
cattr_accessor :config_file

# Contains an hash of locales configured in config_file
@@all = nil
cattr_writer :all

# It's the formatting style (Textile or Markdown) configured in config_file
@@formatting = nil

class << self
alias_method :__translate, :translate
def translate(key, default = nil, arg = nil, namespace = nil) # :nodoc:
result = __translate(key, default, arg, namespace)
notify_observers(key, result)
result
end

# Returns the active <tt>Locale</tt> or create a new one, checking the choosen base language.
# To easily plug-in this code I need always a ready Locale.
def active
@@active ||= Locale.set(@@base_language_code.locale)
end

# Check if the the class has a current active <tt>Locale</tt>, calling the homonymous method.
# To easily plug-in this code I need always a ready <tt>Locale</tt>.
def active?
!active.nil?
end

def all #:nodoc:
@@all ||= load_locales
end

# Hash representation of config_file.
def configuration
@@configuration ||= begin
result = YAML::load_file(config_file)
raise NoConfiguredLocalesError unless result
result
module View
def self.included(recipient)
recipient.send :include, InstanceMethods
# TODO avoid chain, use super instead
recipient.class_eval do
alias_method_chain :translate, :observe
end
end

# Load all the locales in config_file.
def load_locales
configuration['locales'].symbolize_keys!
end

# Load the base language if configured in config_file.
def load_configured_base_language
language_key = configuration['default']
self.set_base_language(all[language_key]) unless language_key.nil?
end

def notify_observers(key, result) # :nodoc:
observers.each { |observer| observer.update(key, result) }
end

def add_observer(observer) # :nodoc:
observers << observer
end

def remove_observer(observer) # :nodoc:
observers.delete(observer)
end

def observers # :nodoc:
@observers ||= Set.new
end

# Return the current formatting style defined in config_file.
#
# The options available are:
# * textile (RedCloth gem)
# * markdown (BlueCloth gem)
def formatting
return unless configuration['formatting']
@@formatting ||= case configuration['formatting'].to_sym
when :textile then textile? ? :textile : nil
when :markdown then markdown? ? :markdown : nil
else raise ArgumentError

module InstanceMethods
def translate_with_observe(key, options = {})
returning result = translate_without_observe(key, options) do
notify_observers key, result
end
end
end
alias_method :t, :translate_with_observe

# Returns the method for the current formatting style.
#
# The available methods are:
# * textilize_without_paragraph (textile)
# * markdown (markdown)
def formatting_method
@@formatting_method ||= case @@formatting
when :textile then :textilize_without_paragraph
when :markdown then :markdown
def notify_observers(key, result) #:nodoc:
observers.each { |observer| observer.update(key, result) }
end

def add_observer(observer) #:nodoc:
observers << observer
end

def remove_observer(observer) #:nodoc:
observers.delete(observer)
end

def observers #:nodoc:
@observers ||= Set.new
end
end
end

# Implements the Observer Pattern, when <tt>I18n#translate</tt> is called,
# it notify <tt>LocaleObserver</tt>, passing the translation key and the result for
# the current locale.
class LocaleObserver
attr_reader :translations

# Checks if the RedCloth gem is installed and already required.
def textile?
@@textile ||= Object.const_defined?(:RedCloth)
def initialize #:nodoc:
@translations = {}
end

# Checks if the BlueCloth gem is installed and already required.
def markdown?
@@markdown ||= Object.const_defined?(:BlueCloth)

def update(key, result) #:nodoc:
@translations = @translations.merge({key, result})
end
end
end

# Implements the Observer Pattern, when <tt>Locale#translate</tt> is called,
# it notify <tt>LocaleObserver</tt>, passing the translation key and the result for
# the current locale.
class LocaleObserver
attr_reader :translations

def initialize # :nodoc:
@translations = {}
end

module Controller
def self.included(recipient)
recipient.send :include, InstanceMethods
end

def update(key, result) # :nodoc:
@translations = @translations.merge({key, result})

module InstanceMethods
# This is the <b>on/off</b> switch for the Click to Globalize features.
# Override this method in your controllers for custom conditions.
#
# Example:
#
# def globalize?
# current_user.admin?
# end
def globalize?
true
end
end
end
module Helpers # :nodoc:

module Helper
@@click_partial = 'shared/_click_to_globalize'

# Render +app/views/shared/_click_to_globalize.html.erb+.
def click_to_globalize
return unless controller.globalize?
render @@click_partial
render @@click_partial if controller.globalize?
end

# Get form_authenticity_token if the application is protected from forgery.
# See ActionController::RequestForgeryProtection for details.
def authenticity_token
protect_against_forgery? ? form_authenticity_token : ''
end

# Returns the languages defined in Locale#config_file
def languages
Locale.all

def locales
I18n.available_locales
end

# Creates the HTML markup for the languages picker menu.
#
# Example:
# config/click.yml
# locales:
# english: en-US
# italian: it-IT
# I18n.available_locales # => [:en, :it]
# I18n.locale # => :en
#
# <ul>
# <li><a href="/locales/set/en-US" title="* English [en-US]">* English</a></li> |
# <li><a href="/locales/set/it-IT" title="Italian [it-IT]">Italian</a></li>
# <li><a href="/locales/set/en" title="* en">* en</a></li> |
# <li><a href="/locales/set/it" title="it">it</a></li>
# </ul>
def languages_menu
returning result = '<ul>' do
result << languages.map do |language, locale|
language = language.to_s.titleize
language = "* #{language}" if locale == Locale.active.code
"<li>#{link_to language, {:controller => 'locales', :action => 'set', :id => locale}, {:title => "#{language} [#{locale}]"}}</li>"
result << locales.map do |locale|
locale = "* #{locale}" if locale == I18n.locale
"<li>#{link_to locale, {:controller => 'locales', :action => 'set', :id => locale}, {:title => "#{language} [#{locale}]"}}</li>"
end * ' | '
end
result << '</ul>'
end
end

module Controller # :nodoc:
module InstanceMethods # :nodoc:
# This is the <b>on/off</b> switch for the Click to Globalize features.
# Override this method in your controllers for custom conditions.
#
# Example:
#
# def globalize?
# current_user.admin?
# end
def globalize?
true
end

private
# It's used as around_filter method, to add a <tt>LocaleObserver</tt> while the
# request is processed.
# <tt>LocaleObserver</tt> catches all translations and pass them to the session.
def observe_locales
yield and return unless globalize?
locale_observer = LocaleObserver.new
Locale.add_observer(locale_observer)
yield
Locale.remove_observer(locale_observer)
session[:__globalize_translations] = format_translations(locale_observer)
end

# Fetch the translations from the given LocaleObserver.
# If the formatting feature is turned on it also provide to textilize or markdown.
def format_translations(locale_observer)
if Locale.formatting
formatting_method = Locale.formatting_method
locale_observer.translations.inject({}) do |result, translation|
result[translation.first] = self.send(formatting_method, strip_tags(translation.last))
result
end
else
locale_observer.translations
end
end
end
end
end

ActionView::Base.class_eval do #:nodoc:
include Globalize::Helpers
end

ActionController::Base.class_eval do #:nodoc:
include Globalize::Controller::InstanceMethods
include ActionView::Helpers::TextHelper
include ActionView::Helpers::SanitizeHelper
around_filter :observe_locales
end

0 comments on commit 4682487

Please sign in to comment.