Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Datamapper support for localization of content in multilanguage applications

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 lib
Octocat-spinner-32 spec
Octocat-spinner-32 tasks
Octocat-spinner-32 .document
Octocat-spinner-32 .gitignore
Octocat-spinner-32 CHANGELOG
Octocat-spinner-32 Gemfile
Octocat-spinner-32 LICENSE
Octocat-spinner-32 README.textile
Octocat-spinner-32 Rakefile
Octocat-spinner-32 TODO
Octocat-spinner-32 dm-is-localizable.gemspec
README.textile

dm-is-localizable

Datamapper support for localization of (user entered) content in multilanguage applications

Schema

  • one xxx_translations table for every translatable resource
  • xxx_translations belongs_to the resource to translate
  • xxx_translations belongs_to a locale
  • properties to be translated are defined in xxx_translations

Advantages

  • Proper normalization and referential integrity
  • Easy to add a new language (add row to xxx_translations)
  • Easy to query
  • Columns keep their names

Disadvantages (not really if you think about it)

  • One extra table for every resource that needs translations

Example definition of a localizable model

The plugin comes with a Locale model that already got required for you. This means that the underlying storage will be created automatically when you run auto_migrate! or auto_upgrade!.


class Item

  include DataMapper::Resource

  property :id, Serial

  translatable do
    property :name, String
    property :desc, String
  end

end

The above Item model will define and thus be able to DataMapper.auto_migrate! the ItemTranslation model. The naming convention used here is "#{ClassToBeLocalized.name}Translation".

Preliminary support for changing this is available by using the :model option like so (note that this isn’t specced yet).


DataMapper::Model.translatable, :model => 'ItemLocalization' do
  # ...
end

Furthermore, the above Item will automatically have the following instance methods defined.


#item_translations_attributes
#item_translations_attributes=

# and handy aliases for the above

#translations_attributes
#translations_attributes=

These are generated by dm-accepts_nested_attributes and allow for easy manipulation of the translatable properties from say forms in a web application. For more information on working with nested attributes, have a look at the documentation at the README for dm-accepts_nested_attributes

Of course you can turn this behavior off by specifying the translatable, :accept_nested_attributes => false do .. end

The resulting model you get when calling Item.translatable { ... } looks like this:


class ItemTranslation

  include DataMapper::Resource

  property :id,         Serial

  property :item_id,    Integer, :required => true, :unique_index => :unique_locales
  property :locale_tag, String,  :required => true, :unique_index => :unique_locales

  property :name,       String
  property :desc,       String

  validates_is_unique :locale_tag, :scope => :item_id

  belongs_to :item
  belongs_to :locale

end

Furthermore, the following API gets defined on the Item class:


class Item

  include DataMapper::Resource

  property :id, Serial

  translatable do
    property :name,        String
    property :description, String
  end

  # -------------------------
  #   added by .translatable
  # -------------------------

  has n, :item_translations
  has n, :locales, :through => :item_translations

  # and a handy alias
  alias :translations :item_translations

  # method to access the i18n proxy for this model
  def self.i18n
    @i18n
  end

  # the proxy instance to delegate api calls to
  def i18n
    @i18n ||= I18n::Resource::Proxy.new(self)
  end

  # translates the :name property to the given locale
  def name(locale_tag = DataMapper::I18n.default_locale_tag)
    i18n.translate(:name, locale_tag)
  end

  # translates the :desc property to the given locale
  def desc(locale_tag = DataMapper::I18n.default_locale_tag)
    i18n.translate(:desc, locale_tag)
  end

  # ----------------------------------------
  #   added by dm-accepts_nested_attributes
  # ----------------------------------------


  def item_translations_attributes
    # ...
  end

  def item_translations_attributes=(attributes_or_attributes_collection)
    # ...
  end

  # and handy aliases for the above

  alias :translations_attributes  :item_translations_attributes
  alias :translations_attributes= :item_translations_attributes
end

# ---------------------------------------------
#   methods accessible via the Item.i18n proxy
# ---------------------------------------------

# helper method to get at ItemTranslation
Item.i18n.translation_model

# list all available locales for the translatable model
Item.i18n.available_locales

# returns all translatable properties of this resource
Item.i18n.translatable_properties

# ---------------------------------------------
#   methods accessible via the Item#i18n proxy
# ---------------------------------------------

# list all available locales for this instance
item.i18n.available_locales

# translates the given attribute to the locale identified by the given locale_code
item.i18n.translate(attribute, locale_tag)

Inspired by (thx guys!)

Copyright

Copyright © 2009 Martin Gamsjaeger (snusnu). See LICENSE for details.

Something went wrong with that request. Please try again.