No commit activity in last 3 years
No release in over 3 years
Datamapper support for localization of content in multilanguage applications
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 0.10.0
 Project Readme

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.