From 57d1382013c85a7b11ac8ce5e683f6006b12b328 Mon Sep 17 00:00:00 2001 From: hukl Date: Thu, 14 Jan 2010 22:21:43 +0100 Subject: Updated globalize2 to latest version. Modified existing code accoringly --- vendor/plugins/globalize2/lib/globalize.rb | 15 ++ .../globalize2/lib/globalize/active_record.rb | 194 +++++++++++++++++++++ .../lib/globalize/active_record/adapter.rb | 80 +++++++++ .../lib/globalize/active_record/attributes.rb | 25 +++ .../lib/globalize/active_record/migration.rb | 40 +++++ .../globalize2/lib/globalize/backend/chain.rb | 102 ----------- .../lib/globalize/backend/pluralizing.rb | 37 ---- .../globalize2/lib/globalize/backend/static.rb | 60 ------- .../i18n/missing_translations_log_handler.rb | 41 ----- .../i18n/missing_translations_raise_handler.rb | 27 --- .../plugins/globalize2/lib/globalize/load_path.rb | 63 ------- .../globalize2/lib/globalize/locale/fallbacks.rb | 63 ------- .../lib/globalize/locale/language_tag.rb | 81 --------- .../lib/globalize/model/active_record.rb | 45 ----- .../lib/globalize/model/active_record/adapter.rb | 96 ---------- .../globalize/model/active_record/translated.rb | 164 ----------------- .../globalize2/lib/globalize/translation.rb | 32 ---- .../lib/i18n/missing_translations_log_handler.rb | 41 +++++ .../lib/i18n/missing_translations_raise_handler.rb | 25 +++ vendor/plugins/globalize2/lib/locale/root.yml | 3 - .../globalize2/lib/rails_edge_load_path_patch.rb | 40 ----- 21 files changed, 420 insertions(+), 854 deletions(-) create mode 100644 vendor/plugins/globalize2/lib/globalize.rb create mode 100644 vendor/plugins/globalize2/lib/globalize/active_record.rb create mode 100644 vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb create mode 100644 vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb create mode 100644 vendor/plugins/globalize2/lib/globalize/active_record/migration.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/backend/chain.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/backend/pluralizing.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/backend/static.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/load_path.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/locale/fallbacks.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/model/active_record.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb delete mode 100644 vendor/plugins/globalize2/lib/globalize/translation.rb create mode 100644 vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb create mode 100644 vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb delete mode 100644 vendor/plugins/globalize2/lib/locale/root.yml delete mode 100644 vendor/plugins/globalize2/lib/rails_edge_load_path_patch.rb (limited to 'vendor/plugins/globalize2/lib') diff --git a/vendor/plugins/globalize2/lib/globalize.rb b/vendor/plugins/globalize2/lib/globalize.rb new file mode 100644 index 00000000..67c1878e --- /dev/null +++ b/vendor/plugins/globalize2/lib/globalize.rb @@ -0,0 +1,15 @@ +module Globalize + autoload :ActiveRecord, 'globalize/active_record' + + class << self + def fallbacks? + I18n.respond_to?(:fallbacks) + end + + def fallbacks(locale) + fallbacks? ? I18n.fallbacks[locale] : [locale.to_sym] + end + end +end + +ActiveRecord::Base.send(:include, Globalize::ActiveRecord) diff --git a/vendor/plugins/globalize2/lib/globalize/active_record.rb b/vendor/plugins/globalize2/lib/globalize/active_record.rb new file mode 100644 index 00000000..d2a843f9 --- /dev/null +++ b/vendor/plugins/globalize2/lib/globalize/active_record.rb @@ -0,0 +1,194 @@ +module Globalize + class MigrationError < StandardError; end + class MigrationMissingTranslatedField < MigrationError; end + class BadMigrationFieldType < MigrationError; end + + module ActiveRecord + autoload :Adapter, 'globalize/active_record/adapter' + autoload :Attributes, 'globalize/active_record/attributes' + autoload :Migration, 'globalize/active_record/migration' + + def self.included(base) + base.extend ActMacro + end + + class << self + def build_translation_class(target, options) + options[:table_name] ||= "#{target.table_name.singularize}_translations" + + klass = target.const_defined?(:Translation) ? + target.const_get(:Translation) : + target.const_set(:Translation, Class.new(::ActiveRecord::Base)) + + klass.class_eval do + set_table_name(options[:table_name]) + belongs_to target.name.underscore.gsub('/', '_') + def locale; read_attribute(:locale).to_sym; end + def locale=(locale); write_attribute(:locale, locale.to_s); end + end + + klass + end + end + + module ActMacro + def locale + (defined?(@@locale) && @@locale) + end + + def locale=(locale) + @@locale = locale + end + + def translates(*attr_names) + return if translates? + options = attr_names.extract_options! + + class_inheritable_accessor :translation_class, :translated_attribute_names + self.translation_class = ActiveRecord.build_translation_class(self, options) + self.translated_attribute_names = attr_names.map(&:to_sym) + + include InstanceMethods + extend ClassMethods, Migration + + after_save :save_translations! + has_many :translations, :class_name => translation_class.name, + :foreign_key => class_name.foreign_key, + :dependent => :delete_all, + :extend => HasManyExtensions + + named_scope :with_translations, lambda { |locale| + conditions = required_attributes.map do |attribute| + "#{quoted_translation_table_name}.#{attribute} IS NOT NULL" + end + conditions << "#{quoted_translation_table_name}.locale = ?" + { :include => :translations, :conditions => [conditions.join(' AND '), locale] } + } + + attr_names.each { |attr_name| translated_attr_accessor(attr_name) } + end + + def translates? + included_modules.include?(InstanceMethods) + end + end + + module HasManyExtensions + def by_locale(locale) + first(:conditions => { :locale => locale.to_s }) + end + + def by_locales(locales) + all(:conditions => { :locale => locales.map(&:to_s) }) + end + end + + module ClassMethods + delegate :set_translation_table_name, :to => :translation_class + + def with_locale(locale) + previous_locale, self.locale = self.locale, locale + result = yield + self.locale = previous_locale + result + end + + def translation_table_name + translation_class.table_name + end + + def quoted_translation_table_name + translation_class.quoted_table_name + end + + def required_attributes + validations = reflect_on_all_validations.select do |validation| + validation.macro == :validates_presence_of + end.map(&:name) + end + + def respond_to?(method, *args, &block) + method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym) || super + end + + def method_missing(method, *args) + if method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym) + find_first_by_translated_attr_and_locales($1, args.first) + else + super + end + end + + protected + + def find_first_by_translated_attr_and_locales(name, value) + query = "#{translated_attr_name(name)} = ? AND #{translated_attr_name('locale')} IN (?)" + locales = Globalize.fallbacks(locale || I18n.locale).map(&:to_s) + find(:first, :joins => :translations, :conditions => [query, value, locales]) + end + + def translated_attr_accessor(name) + define_method "#{name}=", lambda { |value| + globalize.write(self.class.locale || I18n.locale, name, value) + self[name] = value + } + define_method name, lambda { |*args| + globalize.fetch(args.first || self.class.locale || I18n.locale, name) + } + alias_method "#{name}_before_type_cast", name + end + + def translated_attr_name(name) + "#{translation_class.table_name}.#{name}" + end + end + + module InstanceMethods + def globalize + @globalize ||= Adapter.new self + end + + def attributes=(attributes, *args) + if attributes.respond_to?(:delete) && locale = attributes.delete(:locale) + self.class.with_locale(locale) { super } + else + super + end + end + + def available_locales + translations.scoped(:select => 'DISTINCT locale').map(&:locale) + end + + def translated_locales + translations.map(&:locale) + end + + def translated_attributes + translated_attribute_names.inject({}) do |attributes, name| + attributes.merge(name => send(name)) + end + end + + def set_translations(options) + options.keys.each do |locale| + translation = translations.find_by_locale(locale.to_s) || + translations.build(:locale => locale.to_s) + translation.update_attributes!(options[locale]) + end + end + + def reload(options = nil) + translated_attribute_names.each { |name| @attributes.delete(name.to_s) } + globalize.reset + super(options) + end + + protected + + def save_translations! + globalize.save_translations! + end + end + end +end diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb b/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb new file mode 100644 index 00000000..12f89ec0 --- /dev/null +++ b/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb @@ -0,0 +1,80 @@ +module Globalize + module ActiveRecord + class Adapter + # The cache caches attributes that already were looked up for read access. + # The stash keeps track of new or changed values that need to be saved. + attr_reader :record, :cache, :stash + + def initialize(record) + @record = record + @cache = Attributes.new + @stash = Attributes.new + end + + def fetch(locale, attr_name) + cache.contains?(locale, attr_name) ? + cache.read(locale, attr_name) : + cache.write(locale, attr_name, fetch_attribute(locale, attr_name)) + end + + def write(locale, attr_name, value) + stash.write(locale, attr_name, value) + cache.write(locale, attr_name, value) + end + + def save_translations! + stash.each do |locale, attrs| + translation = record.translations.find_or_initialize_by_locale(locale.to_s) + attrs.each { |attr_name, value| translation[attr_name] = value } + translation.save! + end + stash.clear + end + + def reset + cache.clear + # stash.clear + end + + protected + + def fetch_translation(locale) + locale = locale.to_sym + record.translations.loaded? ? record.translations.detect { |t| t.locale == locale } : + record.translations.by_locale(locale) + end + + def fetch_translations(locale) + # only query if not already included with :include => translations + record.translations.loaded? ? record.translations : + record.translations.by_locales(Globalize.fallbacks(locale)) + end + + def fetch_attribute(locale, attr_name) + translations = fetch_translations(locale) + value, requested_locale = nil, locale + + Globalize.fallbacks(locale).each do |fallback| + translation = translations.detect { |t| t.locale == fallback } + value = translation && translation.send(attr_name) + locale = fallback && break if value + end + + set_metadata(value, :locale => locale, :requested_locale => requested_locale) + value + end + + def set_metadata(object, metadata) + if object.respond_to?(:translation_metadata) + object.translation_metadata.merge!(meta_data) + end + end + + def translation_metadata_accessor(object) + return if obj.respond_to?(:translation_metadata) + class << object; attr_accessor :translation_metadata end + object.translation_metadata ||= {} + end + end + end +end diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb b/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb new file mode 100644 index 00000000..7bd923ce --- /dev/null +++ b/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb @@ -0,0 +1,25 @@ +# Helper class for storing values per locale. Used by Globalize::Adapter +# to stash and cache attribute values. +module Globalize + module ActiveRecord + class Attributes < Hash + def [](locale) + locale = locale.to_sym + self[locale] = {} unless has_key?(locale) + self.fetch(locale) + end + + def contains?(locale, attr_name) + self[locale].has_key?(attr_name) + end + + def read(locale, attr_name) + self[locale][attr_name] + end + + def write(locale, attr_name, value) + self[locale][attr_name] = value + end + end + end +end diff --git a/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb b/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb new file mode 100644 index 00000000..ebff3b64 --- /dev/null +++ b/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb @@ -0,0 +1,40 @@ +module Globalize + module ActiveRecord + module Migration + def create_translation_table!(fields) + translated_attribute_names.each do |f| + raise MigrationMissingTranslatedField, "Missing translated field #{f}" unless fields[f] + end + + fields.each do |name, type| + if translated_attribute_names.include?(name) && ![:string, :text].include?(type) + raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text" + end + end + + self.connection.create_table(translation_table_name) do |t| + t.references self.table_name.singularize + t.string :locale + fields.each do |name, type| + t.column name, type + end + t.timestamps + end + + self.connection.add_index(translation_table_name, "#{self.table_name.singularize}_id", :name => translation_index_name) + end + + def translation_index_name + require 'digest/sha1' + # FIXME what's the max size of an index name? + index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id" + index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}" + end + + def drop_translation_table! + self.connection.remove_index(translation_table_name, :name => translation_index_name) rescue nil + self.connection.drop_table(translation_table_name) + end + end + end +end diff --git a/vendor/plugins/globalize2/lib/globalize/backend/chain.rb b/vendor/plugins/globalize2/lib/globalize/backend/chain.rb deleted file mode 100644 index bb8679ec..00000000 --- a/vendor/plugins/globalize2/lib/globalize/backend/chain.rb +++ /dev/null @@ -1,102 +0,0 @@ -module I18n - class << self - def chain_backends(*args) - self.backend = Globalize::Backend::Chain.new(*args) - end - end -end - -module Globalize - module Backend - class Chain - def initialize(*args) - add(*args) unless args.empty? - end - - # Change this to a) accept any number of backends and b) accept classes. - # When classes are passed instantiate them and add the instances as backends. - # Return the added backends from #add. - # - # Add an initialize method that accepts the same arguments and passes them - # to #add, so we could: - # I18n.backend = Globalize::Backend::Chain.new(Globalize::Backend::Foo, Globalize::Backend::Bar) - # Globalize::Backend::Chain.new(:foo, :bar) - # Globalize.chain_backends :foo, :bar - def add(*backends) - backends.each do |backend| - backend = Globalize::Backend.const_get(backend.to_s.capitalize) if backend.is_a? Symbol - backend = backend.new if backend.is_a? Class - self.backends << backend - end - end - - def load_translations(*args) - backends.each{|backend| backend.load_translations(*args) } - end - - # For defaults: - # Never pass any default option to the backends but instead implement our own default - # mechanism (e.g. symbols as defaults would need to be passed to the whole chain to - # be translated). - # - # For namespace lookup: - # Only return if the result is not a hash OR count is not present, otherwise merge them. - # So in effect the count variable would control whether we have a namespace lookup or a - # pluralization going on. - # - # Exceptions: - # Make sure that we catch MissingTranslationData exceptions and raise - # one in the end when no translation was found at all. - # - # For bulk translation: - # If the key is an array we need to call #translate for each of the - # keys and collect the results. - - def translate(locale, key, options = {}) - raise I18n::InvalidLocale.new(locale) if locale.nil? - return key.map{|k| translate locale, k, options } if key.is_a? Array - - default = options.delete(:default) - result = backends.inject({}) do |namespace, backend| - begin - translation = backend.translate(locale.to_sym, key, options) - if namespace_lookup?(translation, options) - namespace.merge! translation - elsif translation - return translation - end - rescue I18n::MissingTranslationData - end - end - result || default(locale, default, options) || raise(I18n::MissingTranslationData.new(locale, key, options)) - end - - def localize(locale, object, format = :default) - backends.each do |backend| - result = backend.localize(locale, object, format) and return result - end - end - - protected - def backends - @backends ||= [] - end - - def default(locale, default, options = {}) - case default - when String then default - when Symbol then translate locale, default, options - when Array then default.each do |obj| - result = default(locale, obj, options.dup) and return result - end and nil - end - rescue I18n::MissingTranslationData - nil - end - - def namespace_lookup?(result, options) - result.is_a?(Hash) and not options.has_key?(:count) - end - end - end -end \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/globalize/backend/pluralizing.rb b/vendor/plugins/globalize2/lib/globalize/backend/pluralizing.rb deleted file mode 100644 index 80016f20..00000000 --- a/vendor/plugins/globalize2/lib/globalize/backend/pluralizing.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'i18n/backend/simple' - -module Globalize - module Backend - class Pluralizing < I18n::Backend::Simple - def pluralize(locale, entry, count) - return entry unless entry.is_a?(Hash) and count - key = :zero if count == 0 && entry.has_key?(:zero) - key ||= pluralizer(locale).call(count) - raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key) - translation entry[key], :plural_key => key - end - - def add_pluralizer(locale, pluralizer) - pluralizers[locale.to_sym] = pluralizer - end - - def pluralizer(locale) - pluralizers[locale.to_sym] || default_pluralizer - end - - protected - def default_pluralizer - pluralizers[:en] - end - - def pluralizers - @pluralizers ||= { :en => lambda{|n| n == 1 ? :one : :other } } - end - - # Overwrite this method to return something other than a String - def translation(string, attributes) - string - end - end - end -end \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/globalize/backend/static.rb b/vendor/plugins/globalize2/lib/globalize/backend/static.rb deleted file mode 100644 index fb9e1fe2..00000000 --- a/vendor/plugins/globalize2/lib/globalize/backend/static.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'globalize/backend/pluralizing' -require 'globalize/locale/fallbacks' -require 'globalize/translation' - -module Globalize - module Backend - class Static < Pluralizing - def initialize(*args) - add(*args) unless args.empty? - end - - def translate(locale, key, options = {}) - result, default, fallback = nil, options.delete(:default), nil - I18n.fallbacks[locale].each do |fallback| - begin - result = super(fallback, key, options) and break - rescue I18n::MissingTranslationData - end - end - result ||= default locale, default, options - - attrs = {:requested_locale => locale, :locale => fallback, :key => key, :options => options} - translation(result, attrs) || raise(I18n::MissingTranslationData.new(locale, key, options)) - end - - protected - - alias :orig_interpolate :interpolate unless method_defined? :orig_interpolate - def interpolate(locale, string, values = {}) - result = orig_interpolate(locale, string, values) - translation = translation(string) - translation.nil? ? result : translation.replace(result) - end - - def translation(result, meta = nil) - return unless result - - case result - when Numeric - result - when String - result = Translation::Static.new(result) unless result.is_a? Translation::Static - result.set_meta meta - result - when Hash - Hash[*result.map do |key, value| - [key, translation(value, meta)] - end.flatten] - when Array - result.map do |value| - translation(value, meta) - end - else - result - # raise "unexpected translation type: #{result.inspect}" - end - end - end - end -end \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb b/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb deleted file mode 100644 index 3f06ac24..00000000 --- a/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb +++ /dev/null @@ -1,41 +0,0 @@ -# A simple exception handler that behaves like the default exception handler -# but additionally logs missing translations to a given log. -# -# Useful for identifying missing translations during testing. -# -# E.g. -# -# require 'globalize/i18n/missing_translations_log_handler -# I18n.missing_translations_logger = RAILS_DEFAULT_LOGGER -# I18n.exception_handler = :missing_translations_log_handler -# -# To set up a different log file: -# -# logger = Logger.new("#{RAILS_ROOT}/log/missing_translations.log") -# I18n.missing_translations_logger = logger - -module I18n - @@missing_translations_logger = nil - - class << self - def missing_translations_logger - @@missing_translations_logger ||= begin - require 'logger' unless defined?(Logger) - Logger.new(STDOUT) - end - end - - def missing_translations_logger=(logger) - @@missing_translations_logger = logger - end - - def missing_translations_log_handler(exception, locale, key, options) - if MissingTranslationData === exception - missing_translations_logger.warn(exception.message) - return exception.message - else - raise exception - end - end - end -end \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb b/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb deleted file mode 100644 index e32be280..00000000 --- a/vendor/plugins/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb +++ /dev/null @@ -1,27 +0,0 @@ -# A simple exception handler that behaves like the default exception handler -# but also raises on missing translations. -# -# Useful for identifying missing translations during testing. -# -# E.g. -# -# require 'globalize/i18n/missing_translations_raise_handler -# I18n.exception_handler = :missing_translations_raise_handler -module I18n - class << self - def missing_translations_raise_handler(exception, locale, key, options) - raise exception - end - end - -# self.exception_handler = :missing_translations_raise_handler -end - -I18n.exception_handler = :missing_translations_raise_handler - -ActionView::Helpers::TranslationHelper.module_eval do - def translate(key, options = {}) - I18n.translate(key, options) - end - alias :t :translate -end diff --git a/vendor/plugins/globalize2/lib/globalize/load_path.rb b/vendor/plugins/globalize2/lib/globalize/load_path.rb deleted file mode 100644 index a49825b3..00000000 --- a/vendor/plugins/globalize2/lib/globalize/load_path.rb +++ /dev/null @@ -1,63 +0,0 @@ -# Locale load_path and Locale loading support. -# -# To use this include the Globalize::LoadPath::I18n module to I18n like this: -# -# I18n.send :include, Globalize::LoadPath::I18n -# -# Clients can add load_paths using: -# -# I18n.load_path.add load_path, 'rb', 'yml' # pass any number of extensions like this -# I18n.load_path << 'path/to/dir' # usage without an extension, defaults to 'yml' -# -# And load locale data using either of: -# -# I18n.load_locales 'en-US', 'de-DE' -# I18n.load_locale 'en-US' -# -# This will lookup all files named like: -# -# 'path/to/dir/all.yml' -# 'path/to/dir/en-US.yml' -# 'path/to/dir/en-US/*.yml' -# -# The filenames will be passed to I18n.load_translations which delegates to -# the backend. So the actual behaviour depends on the implementation of the -# backend. I18n::Backend::Simple will be able to read YAML and plain Ruby -# files. See the documentation for I18n.load_translations for details. - -module Globalize - class LoadPath < Array - def extensions - @extensions ||= ['rb', 'yml'] - end - attr_writer :extensions - - def locales - @locales ||= ['*'] - end - attr_writer :locales - - def <<(path) - push path - end - - def push(*paths) - super(*paths.map{|path| filenames(path) }.flatten.uniq.sort) - end - - protected - - def filenames(path) - return [path] if File.file? path - patterns(path).map{|pattern| Dir[pattern] } - end - - def patterns(path) - locales.map do |locale| - extensions.map do |extension| - %W(#{path}/all.#{extension} #{path}/#{locale}.#{extension} #{path}/#{locale}/**/*.#{extension}) - end - end.flatten.uniq - end - end -end \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/globalize/locale/fallbacks.rb b/vendor/plugins/globalize2/lib/globalize/locale/fallbacks.rb deleted file mode 100644 index c4acd57a..00000000 --- a/vendor/plugins/globalize2/lib/globalize/locale/fallbacks.rb +++ /dev/null @@ -1,63 +0,0 @@ -require 'globalize/locale/language_tag' - -module I18n - @@fallbacks = nil - - class << self - # Returns the current fallbacks. Defaults to +Globalize::Locale::Fallbacks+. - def fallbacks - @@fallbacks ||= Globalize::Locale::Fallbacks.new - end - - # Sets the current fallbacks. Used to set a custom fallbacks instance. - def fallbacks=(fallbacks) - @@fallbacks = fallbacks - end - end -end - -module Globalize - module Locale - class Fallbacks < Hash - def initialize(*defaults) - @map = {} - map defaults.pop if defaults.last.is_a?(Hash) - - defaults = [I18n.default_locale.to_sym] if defaults.empty? - self.defaults = defaults - end - - def defaults=(defaults) - @defaults = defaults.map{|default| compute(default, false) }.flatten << :root - end - attr_reader :defaults - - def [](tag) - tag = tag.to_sym - has_key?(tag) ? fetch(tag) : store(tag, compute(tag)) - end - - def map(mappings) - mappings.each do |from, to| - from, to = from.to_sym, Array(to) - to.each do |to| - @map[from] ||= [] - @map[from] << to.to_sym - end - end - end - - protected - - def compute(tags, include_defaults = true) - result = Array(tags).collect do |tag| - tags = LanguageTag::tag(tag.to_sym).parents(true).map! {|t| t.to_sym } - tags.each{|tag| tags += compute(@map[tag]) if @map[tag] } - tags - end.flatten - result.push *defaults if include_defaults - result.uniq - end - end - end -end diff --git a/vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb b/vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb deleted file mode 100644 index d9aae54f..00000000 --- a/vendor/plugins/globalize2/lib/globalize/locale/language_tag.rb +++ /dev/null @@ -1,81 +0,0 @@ -# for specifications see http://en.wikipedia.org/wiki/IETF_language_tag -# -# SimpleParser does not implement advanced usages such as grandfathered tags - -module Globalize - module Locale - module Rfc4646 - SUBTAGS = [:language, :script, :region, :variant, :extension, :privateuse, :grandfathered] - FORMATS = {:language => :downcase, :script => :capitalize, :region => :upcase, :variant => :downcase} - end - - class LanguageTag < Struct.new(*Rfc4646::SUBTAGS) - class << self - def parser - @@parser ||= SimpleParser - end - - def parser=(parser) - @@parser = parser - end - - def tag(tag) - matches = parser.match(tag) - new *matches if matches - end - end - - Rfc4646::FORMATS.each do |name, format| - define_method(name) { self[name].send(format) unless self[name].nil? } - end - - def to_sym - to_s.to_sym - end - - def to_s - @tag ||= to_a.compact.join("-") - end - - def to_a - members.collect {|attr| self.send(attr) } - end - - def parent - segs = to_a.compact - segs.length < 2 ? nil : LanguageTag.tag(segs[0..(segs.length-2)].join('-')) - end - - def parents(include_self = true) - result, parent = [], self.dup - result << parent if include_self - while parent = parent.parent - result << parent - end - result - end - - module SimpleParser - PATTERN = %r{\A(?: - ([a-z]{2,3}(?:(?:-[a-z]{3}){0,3})?|[a-z]{4}|[a-z]{5,8}) # language - (?:-([a-z]{4}))? # script - (?:-([a-z]{2}|\d{3}))? # region - (?:-([0-9a-z]{5,8}|\d[0-9a-z]{3}))* # variant - (?:-([0-9a-wyz](?:-[0-9a-z]{2,8})+))* # extension - (?:-(x(?:-[0-9a-z]{1,8})+))?| # privateuse subtag - (x(?:-[0-9a-z]{1,8})+)| # privateuse tag - /* ([a-z]{1,3}(?:-[0-9a-z]{2,8}){1,2}) */ # grandfathered - )\z}xi - - class << self - def match(tag) - c = PATTERN.match(tag.to_s).captures - c[0..4] << (c[5].nil? ? c[6] : c[5]) << c[7] # TODO c[7] is grandfathered, throw a NotImplemented exception here? - rescue - false - end - end - end - end - end -end diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record.rb deleted file mode 100644 index 9218054c..00000000 --- a/vendor/plugins/globalize2/lib/globalize/model/active_record.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'globalize/translation' -require 'globalize/locale/fallbacks' -require 'globalize/model/active_record/adapter' -require 'globalize/model/active_record/translated' - -module Globalize - module Model - module ActiveRecord - class << self - def create_proxy_class(klass) - module_names = klass.name.split('::') - klass_name = module_names.pop - target = module_names.empty? ? Object : module_names.join('::').constantize - - target.const_set "#{klass_name}Translation", Class.new(::ActiveRecord::Base) { - belongs_to "#{klass.name.underscore.gsub('/', '_')}".intern - - def locale - read_attribute(:locale).to_sym - end - - def locale=(locale) - write_attribute(:locale, locale.to_s) - end - } - end - - def define_accessors(klass, attr_names) - attr_names.each do |attr_name| - klass.send :define_method, attr_name, lambda { - globalize.fetch self.class.locale, attr_name - } - klass.send :define_method, "#{attr_name}_before_type_cast", lambda { - globalize.fetch self.class.locale, attr_name - } - klass.send :define_method, "#{attr_name}=", lambda {|val| - globalize.stash self.class.locale, attr_name, val - self[attr_name] = val - } - end - end - end - end - end -end \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb deleted file mode 100644 index 93355b87..00000000 --- a/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb +++ /dev/null @@ -1,96 +0,0 @@ -module Globalize - module Model - class AttributeStash < Hash - def contains?(locale, attr_name) - locale = locale.to_sym - self[locale] ||= {} - self[locale].has_key? attr_name - end - - def read(locale, attr_name) - locale = locale.to_sym - self[locale] ||= {} - self[locale][attr_name] - end - - def write(locale, attr_name, value) - locale = locale.to_sym - self[locale] ||= {} - self[locale][attr_name] = value - end - end - - class Adapter - def initialize(record) - @record = record - - # TODO what exactly are the roles of cache and stash - @cache = AttributeStash.new - @stash = AttributeStash.new - end - - def fetch(locale, attr_name) - # locale = I18n.locale - is_cached = @cache.contains?(locale, attr_name) - is_cached ? @cache.read(locale, attr_name) : begin - value = fetch_attribute locale, attr_name - @cache.write locale, attr_name, value if value && value.locale == locale - value - end - end - - def stash(locale, attr_name, value) - @stash.write locale, attr_name, value - @cache.write locale, attr_name, value - end - - def update_translations! - @stash.each do |locale, attrs| - translation = @record.globalize_translations.find_or_initialize_by_locale(locale.to_s) - attrs.each{|attr_name, value| translation[attr_name] = value } - translation.save! - end - @stash.clear - end - - # Clears the cache - def clear - @cache.clear - @stash.clear - end - - private - - def fetch_attribute(locale, attr_name) - fallbacks = I18n.fallbacks[locale].map{|tag| tag.to_s}.map(&:to_sym) - - # If the translations were included with - # :include => globalize_translations - # there is no need to query them again. - unless @record.globalize_translations.loaded? - translations = @record.globalize_translations.by_locales(fallbacks) - else - translations = @record.globalize_translations - end - result, requested_locale = nil, locale - - # Walk through the fallbacks, starting with the current locale itself, and moving - # to the next best choice, until we find a match. - # Check the @globalize_set_translations cache first to see if we've just changed the - # attribute and not saved yet. - fallbacks.each do |fallback| - # TODO should we be checking stash or just cache? - result = @stash.read(fallback, attr_name) || begin - translation = translations.detect {|tr| tr.locale == fallback } - translation && translation.send(attr_name) - end - if result - locale = fallback - break - end - end - result && Translation::Attribute.new(result, :locale => locale, :requested_locale => requested_locale) - end - end - end -end diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb deleted file mode 100644 index 4f75c8ae..00000000 --- a/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb +++ /dev/null @@ -1,164 +0,0 @@ -require 'digest/sha1' - -module Globalize - module Model - class MigrationError < StandardError; end - class MigrationMissingTranslatedField < MigrationError; end - class BadMigrationFieldType < MigrationError; end - - module ActiveRecord - module Translated - def self.included(base) - base.extend ActMethods - end - - module ActMethods - def translates(*attr_names) - options = attr_names.extract_options! - options[:translated_attributes] = attr_names - - # Only set up once per class - unless included_modules.include? InstanceMethods - class_inheritable_accessor :globalize_options, :globalize_proxy - - include InstanceMethods - extend ClassMethods - - self.globalize_proxy = Globalize::Model::ActiveRecord.create_proxy_class(self) - has_many( - :globalize_translations, - :class_name => globalize_proxy.name, - :extend => Extensions, - :dependent => :delete_all, - :foreign_key => class_name.foreign_key - ) - - after_save :update_globalize_record - end - - self.globalize_options = options - Globalize::Model::ActiveRecord.define_accessors(self, attr_names) - - # Import any callbacks that have been defined by extensions to Globalize2 - # and run them. - extend Callbacks - Callbacks.instance_methods.each { |callback| send(callback) } - end - - def locale=(locale) - @@locale = locale - end - - def locale - (defined?(@@locale) && @@locale) || I18n.locale - end - end - - # Dummy Callbacks module. Extensions to Globalize2 can insert methods into here - # and they'll be called at the end of the translates class method. - module Callbacks - end - - # Extension to the has_many :globalize_translations association - module Extensions - def by_locales(locales) - find :all, :conditions => { :locale => locales.map(&:to_s) } - end - end - - module ClassMethods - def method_missing(method, *args) - if method.to_s =~ /^find_by_(\w+)$/ && globalize_options[:translated_attributes].include?($1.to_sym) - find(:first, :joins => :globalize_translations, - :conditions => [ "#{i18n_attr($1)} = ? AND #{i18n_attr('locale')} IN (?)", - args.first,I18n.fallbacks[I18n.locale].map{|tag| tag.to_s}]) - else - super - end - end - - def create_translation_table!(fields) - translated_fields = self.globalize_options[:translated_attributes] - translated_fields.each do |f| - raise MigrationMissingTranslatedField, "Missing translated field #{f}" unless fields[f] - end - - fields.each do |name, type| - if translated_fields.include?(name) && ![:string, :text].include?(type) - raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text" - end - end - - self.connection.create_table(translation_table_name) do |t| - t.references self.table_name.singularize - t.string :locale - fields.each do |name, type| - t.column name, type - end - t.timestamps - end - - self.connection.add_index(translation_table_name, "#{self.table_name.singularize}_id", :name => translation_index_name) - end - - def translation_table_name - self.name.underscore.gsub('/', '_') + '_translations' - end - - def translation_index_name - # FIXME what's the max size of an index name? - index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id" - index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}" - end - - def drop_translation_table! - self.connection.remove_index(translation_table_name, :name => translation_index_name) - self.connection.drop_table translation_table_name - end - - private - - def i18n_attr(attribute_name) - self.base_class.name.underscore.gsub('/', '_') + "_translations.#{attribute_name}" - end - end - - module InstanceMethods - def reload(options = nil) - globalize.clear - - # clear all globalized attributes - # TODO what's the best way to handle this? - self.class.globalize_options[:translated_attributes].each do |attr| - @attributes.delete(attr.to_s) - end - - super(options) - end - - def globalize - @globalize ||= Adapter.new self - end - - def update_globalize_record - globalize.update_translations! - end - - def translated_locales - globalize_translations.scoped(:select => 'DISTINCT locale').map do |translation| - translation.locale.to_sym - end - end - - def set_translations options - options.keys.each do |key| - translation = globalize_translations.find_by_locale(key.to_s) || - globalize_translations.build(:locale => key.to_s) - translation.update_attributes!(options[key]) - end - end - end - end - end - end -end \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/globalize/translation.rb b/vendor/plugins/globalize2/lib/globalize/translation.rb deleted file mode 100644 index a80afcd7..00000000 --- a/vendor/plugins/globalize2/lib/globalize/translation.rb +++ /dev/null @@ -1,32 +0,0 @@ -module Globalize - # Translations are simple value objects that carry some context information - # alongside the actual translation string. - - class Translation < String - class Attribute < Translation - attr_accessor :requested_locale, :locale, :key - end - - class Static < Translation - attr_accessor :requested_locale, :locale, :key, :options, :plural_key, :original - - def initialize(string, meta = nil) - self.original = string - super - end - end - - def initialize(string, meta = nil) - set_meta meta - super string - end - - def fallback? - locale.to_sym != requested_locale.to_sym - end - - def set_meta(meta) - meta.each {|name, value| send :"#{name}=", value } if meta - end - end -end \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb b/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb new file mode 100644 index 00000000..24c10890 --- /dev/null +++ b/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb @@ -0,0 +1,41 @@ +# A simple exception handler that behaves like the default exception handler +# but additionally logs missing translations to a given log. +# +# Useful for identifying missing translations during testing. +# +# E.g. +# +# require 'globalize/i18n/missing_translations_log_handler' +# I18n.missing_translations_logger = RAILS_DEFAULT_LOGGER +# I18n.exception_handler = :missing_translations_log_handler +# +# To set up a different log file: +# +# logger = Logger.new("#{RAILS_ROOT}/log/missing_translations.log") +# I18n.missing_translations_logger = logger + +module I18n + @@missing_translations_logger = nil + + class << self + def missing_translations_logger + @@missing_translations_logger ||= begin + require 'logger' unless defined?(Logger) + Logger.new(STDOUT) + end + end + + def missing_translations_logger=(logger) + @@missing_translations_logger = logger + end + + def missing_translations_log_handler(exception, locale, key, options) + if MissingTranslationData === exception + missing_translations_logger.warn(exception.message) + return exception.message + else + raise exception + end + end + end +end diff --git a/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb b/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb new file mode 100644 index 00000000..18237b15 --- /dev/null +++ b/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb @@ -0,0 +1,25 @@ +# A simple exception handler that behaves like the default exception handler +# but also raises on missing translations. +# +# Useful for identifying missing translations during testing. +# +# E.g. +# +# require 'globalize/i18n/missing_translations_raise_handler' +# I18n.exception_handler = :missing_translations_raise_handler +module I18n + class << self + def missing_translations_raise_handler(exception, locale, key, options) + raise exception + end + end +end + +I18n.exception_handler = :missing_translations_raise_handler + +ActionView::Helpers::TranslationHelper.module_eval do + def translate(key, options = {}) + I18n.translate(key, options) + end + alias :t :translate +end diff --git a/vendor/plugins/globalize2/lib/locale/root.yml b/vendor/plugins/globalize2/lib/locale/root.yml deleted file mode 100644 index 2ec2b3bf..00000000 --- a/vendor/plugins/globalize2/lib/locale/root.yml +++ /dev/null @@ -1,3 +0,0 @@ -root: - bidi: - direction: left-to-right \ No newline at end of file diff --git a/vendor/plugins/globalize2/lib/rails_edge_load_path_patch.rb b/vendor/plugins/globalize2/lib/rails_edge_load_path_patch.rb deleted file mode 100644 index e6f90d81..00000000 --- a/vendor/plugins/globalize2/lib/rails_edge_load_path_patch.rb +++ /dev/null @@ -1,40 +0,0 @@ -module I18n - @@load_path = nil - @@default_locale = :'en-US' - - class << self - def load_path - @@load_path ||= [] - end - - def load_path=(load_path) - @@load_path = load_path - end - end -end - -I18n::Backend::Simple.module_eval do - def initialized? - @initialized ||= false - end - - protected - - def init_translations - load_translations(*I18n.load_path) - @initialized = true - end - - def lookup(locale, key, scope = []) - return unless key - init_translations unless initialized? - keys = I18n.send :normalize_translation_keys, locale, key, scope - keys.inject(translations){|result, k| result[k.to_sym] or return nil } - end -end - -rails_dir = File.expand_path "#{File.dirname(__FILE__)}/../../../rails/" -paths = %w(actionpack/lib/action_view/locale/en-US.yml - activerecord/lib/active_record/locale/en-US.yml - activesupport/lib/active_support/locale/en-US.yml) -paths.each{|path| I18n.load_path << "#{rails_dir}/#{path}" } -- cgit v1.3