Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Luca Guidi
committed
Apr 5, 2009
1 parent
b9fe322
commit 4682487
Showing
46 changed files
with
239 additions
and
344 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
2 changes: 1 addition & 1 deletion
2
templates/locales_controller.rb → app/controllers/translations_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module TranslationsHelper | ||
end |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.