Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding support for disabling translations by setting the locale of the

parent object.
  • Loading branch information...
commit f5dca5d31adcac737527b2cb826bccc4760fd4ab 1 parent 06f9a8f
@samlown authored
View
42 README.rdoc
@@ -23,13 +23,16 @@ added to an existing application.
== Updates
+=== 24th September 2009
+
+- Added support for setting the locale variable on the parent, which disables translations. See below.
+
=== 23rd September 2009
- Testing finally added (hope to add more tests soon)
- Validations now only performed by the parent model
- Changed namespace to TranslateColumns (as opposed to Translate::Columns)
-- Parent model's +locale+ variable changed to +translation_locale+ so that it can be
-added as a column/attribute if needed.
+- Parent model's +locale+ variable changed to +translation_locale+ so that it can be added as a column/attribute if needed.
=== 20th May 2009
@@ -176,9 +179,8 @@ won't even notice the plugin is there.
Here's a really basic example of what we can do on the console.
- Loading development environment.
- >> I18n.locale = 'en' # First try default language
- => "en"
+ >> I18n.locale = I18n.default_locale # First try default language
+ => :en
>> doc = Document.find(:first)
-- output hidden --
>> doc.title
@@ -205,6 +207,36 @@ Here's a really basic example of what we can do on the console.
As can be seen, just by setting the locale we are able to edit the data
without having to worry about the details.
+The current version also has support for disabling translations by giving the
+parent object a +locale+ field and setting it to something. This is actually a
+very powerful feature as it allows new objects to be created under a specific locale
+and filtered as such. A typical example would be a blog where most of the posts
+you'd like to be translated into several languages, but occaisionly some posts will only
+be relevant for a specific region:
+
+ >> I18n.locale = I18n.default_locale
+ >> post = Post.new(:title => "Example") # WIN
+ >>
+ >> I18n.locale = 'es'
+ >> post = Post.new(:title => "Ejemplo") # FAIL
+ TranslateColumns::MissingParent: Cannot create translations without a stored parent
+ >>
+ >> post = Post.new(:locale => 'es', :title => "Ejemplo") # WIN
+ >>
+ >> # Provide posts, with either a translation of for the current locale
+ >> posts = Post.paginate(:conditions => ['posts.locale IS NULL OR posts.locale = ?', I18n.locale])
+
+A useful +named_scope+ could be as follows:
+
+ class Post < ActiveRecord::Base
+ # ... translate columns stuff ...
+ named_scope :for_current_locale, :conditions => ['posts.locale IS NULL OR posts.locale = ?', I18n.locale]
+ end
+
+ @posts = Post.for_current_locale.paginate
+
+Of course, if you don't want this funcionality simply do not add a locale attribute or method to
+the parent model.
== How it works
View
46 lib/translate_columns.rb
@@ -51,6 +51,7 @@ def translate_columns( *options )
# Rails magic to override the normal save process
alias_method_chain :save, :translation
alias_method_chain :save!, :translation
+ alias_method_chain :attributes=, :locale
# Generate a module containing methods that override access
# to the ActiveRecord methods.
@@ -133,7 +134,7 @@ def translation_locale
# Setting the locale will always enable translation.
# If set to nil the global locale is used.
def translation_locale=(locale)
- @disable_translation = false
+ enable_translation
# TODO some checks for available translations would be nice.
# I18n.available_locales only available as standard with rails 2.3
@translation_locale = locale.to_s.empty? ? nil : locale.to_s
@@ -143,16 +144,29 @@ def translation_locale=(locale)
def disable_translation
@disable_translation = true
end
+ def enable_translation
+ @disable_translation = false
+ end
+
+ # Important check to see if the parent has a locale method.
+ # If so, translations should be disabled if it is set to something!
+ def has_locale_value?
+ respond_to?(:locale) && !self.locale.to_s.empty?
+ end
+
+ # determine if the conditions are set for a translation to be used
+ def translation_enabled?
+ (!@disable_translation && translation_locale) and !has_locale_value?
+ end
- # If the current object has a locale set, return
- # a translation object from the translations set
+ # Provide a translation object based on the parent and the translation_locale
+ # current value.
def translation
- if !@disable_translation and translation_locale
+ if translation_enabled?
if !@translation || (@translation.locale != translation_locale)
- # try to find entity in translations array
raise MissingParent, "Cannot create translations without a stored parent" if new_record?
- @translation = translations.find_by_locale(translation_locale)
- @translation = self.translations.build(:locale => translation_locale) unless @translation
+ # try to find translation or build a new one
+ @translation = translations.find_by_locale(translation_locale) || translations.build(:locale => translation_locale)
end
@translation
else
@@ -195,13 +209,19 @@ def save_with_translation!
raise
end
-
- protected
+ # Override the default mass assignment method so that the locale variable is always
+ # given preference.
+ def attributes_with_locale=(new_attributes, guard_protected_attributes = true)
+ return if new_attributes.nil?
+ attributes = new_attributes.dup
+ attributes.stringify_keys!
+
+ attributes = remove_attributes_protected_from_mass_assignment(attributes) if guard_protected_attributes
+ send(:locale=, attributes["locale"]) if attributes.has_key?("locale") and respond_to?(:locale=)
+
+ send(:attributes_without_locale=, attributes, guard_protected_attributes)
+ end
- def enable_translation
- @disable_translation = false
- end
-
end
end
View
1  test/fixtures/documents.yml
@@ -7,6 +7,7 @@ document1:
document2:
id: 2
title: Test Document Number 2
+ locale: en
body: This is a second test document with some random content for the body.
published_at: "2009-09-23 21:53:46"
View
1  test/fixtures/schema.rb
@@ -1,5 +1,6 @@
ActiveRecord::Schema.define do
create_table "documents", :force => true do |t|
+ t.column "locale", :string, :length => 8
t.column "title", :string
t.column "body", :text
t.column "published_at", :datetime
View
26 test/translate_columns_test.rb
@@ -1,5 +1,6 @@
-require 'test/unit'
require 'test/lib/activerecord_test_helper'
+require 'test/unit'
+require 'mocha'
require 'init'
class TranslateColumnsTest < Test::Unit::TestCase
@@ -121,5 +122,28 @@ def test_failed_validations_on_translation
assert doc.errors.on(:title)
end
+ def test_locale_attribute_detection
+ doc = Document.find(:first)
+ assert !doc.has_locale_value?
+ doc.locale = "en"
+ assert doc.has_locale_value?
+ end
+
+ def test_locale_attribute_detection_without_attribute
+ doc = Document.find(:first)
+ doc.locale = "en"
+ doc.stubs(:respond_to?).with(:locale).returns(false)
+ assert !doc.has_locale_value?
+ end
+
+ def test_create_new_document_with_specific_locale
+ I18n.locale = 'es'
+ doc = nil
+ assert_nothing_thrown do
+ doc = Document.new(:locale => 'es', :title => "A new document", :body => "Test Body")
+ end
+ assert doc.locale, 'es'
+ assert doc.save
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.