Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
netskin-ci committed Sep 21, 2010
0 parents commit ae6e744
Show file tree
Hide file tree
Showing 14 changed files with 473 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .document
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
README.rdoc
lib/**/*.rb
bin/*
features/**/*.feature
LICENSE
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## MAC OS
.DS_Store

## TEXTMATE
*.tmproj
tmtags

## EMACS
*~
\#*
.\#*

## VIM
*.swp

## PROJECT::GENERAL
coverage
rdoc
pkg

## PROJECT::SPECIFIC
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2010-2010 Corin Langosch

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

55 changes: 55 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
=About

I18n backend which allows to store/get the translations from a database using a sequel.

==Install

Simply install it as any other gem:

gem install i18n_backend_sequel

Or when using bundler, add it got your Gemfile:

gem i18n_backend_sequel

This should also install the geokit gem.

==Quick Start

Create the table used to store i18n translations:

create_table :i18n_translations do |t|
String :locale, :null => false
String :key, :null => false
String :value, :text => true
String :interpolations, :text => true
TrueClass :is_proc, :null => false, :default => false
primary_key [:locale, :key]
end

Make I18n use it as its backend:

I18n.backend = I18n::Backend::Sequel.new

If you want sequel to add missing translations to the database prepend this too:

I18n::Backend::Sequel.send(:include, I18n::Backend::Sequel::Missing)

==Todo

* Source documentation (rdoc)
* Tests

==Contributing

If you'd like to contribute a feature or bugfix: Thanks! To make sure your
fix/feature has a high chance of being included, please read the following
guidelines:

1. Fork the project.
2. Make your feature addition or bug fix.
3. Add tests for it. This is important so we don’t break anything in a future version unintentionally.
4. Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
5. Send me a pull request. Bonus points for topic branches.


47 changes: 47 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require 'rubygems'
require 'rake'

begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = 'i18n_backend_sequel'
gem.authors = ['Corin Langosch']
gem.date = Date.today.to_s
gem.email = 'info@netskin.com'
gem.homepage = 'http://github.com/gucki/i18n_backend_sequel'
gem.summary = 'I18n backend which uses a Sequel Model'
gem.description = 'I18n backend which allows to store/get the translations from a database using a sequel.'
gem.add_dependency "sequel", ">= 3.0.0"
gem.add_development_dependency "rspec", ">= 1.2.9"
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
Jeweler::GemcutterTasks.new
rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
end

require 'spec/rake/spectask'
Spec::Rake::SpecTask.new(:spec) do |spec|
spec.libs << 'lib' << 'spec'
spec.spec_files = FileList['spec/**/*_spec.rb']
end

Spec::Rake::SpecTask.new(:rcov) do |spec|
spec.libs << 'lib' << 'spec'
spec.pattern = 'spec/**/*_spec.rb'
spec.rcov = true
end

task :spec => :check_dependencies

task :default => :spec

require 'rake/rdoctask'
Rake::RDocTask.new do |rdoc|
version = File.exist?('VERSION') ? File.read('VERSION') : ""

rdoc.rdoc_dir = 'rdoc'
rdoc.title = "i18n_backend_sequel #{version}"
rdoc.rdoc_files.include('README*')
rdoc.rdoc_files.include('lib/**/*.rb')
end
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.1
41 changes: 41 additions & 0 deletions i18n_backend_sequel.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
# -*- encoding: utf-8 -*-

Gem::Specification.new do |s|
s.name = %q{i18n_backend_sequel}
s.version = "0.0.1"

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Corin Langosch"]
s.date = %q{2010-09-21}
s.description = %q{I18n backend which allows to store/get the translations from a database using a sequel.}
s.email = %q{info@netskin.com}
s.extra_rdoc_files = [
"LICENSE",
"README.rdoc"
]
s.homepage = %q{http://github.com/gucki/i18n_backend_sequel}
s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["lib"]
s.rubygems_version = %q{1.3.7}
s.summary = %q{I18n backend which uses a Sequel Model}

if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3

if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<sequel>, [">= 3.0.0"])
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
else
s.add_dependency(%q<sequel>, [">= 3.0.0"])
s.add_dependency(%q<rspec>, [">= 1.2.9"])
end
else
s.add_dependency(%q<sequel>, [">= 3.0.0"])
s.add_dependency(%q<rspec>, [">= 1.2.9"])
end
end

54 changes: 54 additions & 0 deletions lib/i18n_backend_sequel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
module I18n
module Backend
class Sequel
autoload :Missing, 'i18n_backend_sequel/missing'
autoload :StoreProcs, 'i18n_backend_sequel/store_procs'
autoload :Translation, 'i18n_backend_sequel/translation'

module Implementation
include Base, Flatten

def available_locales
Translation.available_locales
end

def store_translations(locale, data, options = {})
escape = options.fetch(:escape, true)
flatten_translations(locale, data, escape, false).each do |key, value|
Translation.locale(locale).lookup(expand_keys(key)).delete_all
Translation.create(:locale => locale.to_s, :key => key.to_s, :value => value)
end
end

protected

def lookup(locale, key, scope = [], options = {})
key = normalize_flat_keys(locale, key, scope, options[:separator])
result = Translation.locale(locale).lookup(key).all

if result.empty?
nil
elsif result.first.key == key
result.first.value
else
chop_range = (key.size + FLATTEN_SEPARATOR.size)..-1
result = result.inject({}) do |hash, r|
hash[r.key.slice(chop_range)] = r.value
hash
end
result.deep_symbolize_keys
end
end

# For a key :'foo.bar.baz' return ['foo', 'foo.bar', 'foo.bar.baz']
def expand_keys(key)
key.to_s.split(FLATTEN_SEPARATOR).inject([]) do |keys, key|
keys << [keys.last, key].compact.join(FLATTEN_SEPARATOR)
end
end
end

include Implementation
end
end
end
65 changes: 65 additions & 0 deletions lib/i18n_backend_sequel/missing.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# This extension stores translation stub records for missing translations to
# the database.
#
# This is useful if you have a web based translation tool. It will populate
# the database with untranslated keys as the application is being used. A
# translator can then go through these and add missing translations.
#
# Example usage:
#
# I18n::Backend::Chain.send(:include, I18n::Backend::Sequel::Missing)
# I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Sequel.new, I18n::Backend::Simple.new)
#
# Stub records for pluralizations will also be created for each key defined
# in i18n.plural.keys.
#
# For example:
#
# # en.yml
# en:
# i18n:
# plural:
# keys: [:zero, :one, :other]
#
# # pl.yml
# pl:
# i18n:
# plural:
# keys: [:zero, :one, :few, :other]
#
# It will also persist interpolation keys in Translation#interpolations so
# translators will be able to review and use them.
module I18n
module Backend
class Sequel
module Missing
include Flatten

def store_default_translations(locale, key, options = {})
count, scope, default, separator = options.values_at(:count, :scope, :default, :separator)
separator ||= I18n.default_separator
key = normalize_flat_keys(locale, key, scope, separator)

if Sequel::Translation.locale(locale).lookup(key).empty?
interpolations = options.keys - Base::RESERVED_KEYS
keys = count ? I18n.t('i18n.plural.keys', :locale => locale).map { |k| [key, k].join(FLATTEN_SEPARATOR) } : [key]
keys.each { |key| store_default_translation(locale, key, interpolations) }
end
end

def store_default_translation(locale, key, interpolations)
translation = Sequel::Translation.new(:locale => locale.to_s, :key => key)
translation.interpolations = interpolations
translation.save(:validate => false)
end

def translate(locale, key, options = {})
super
rescue I18n::MissingTranslationData => e
self.store_default_translations(locale, key, options)
raise e
end
end
end
end
end
38 changes: 38 additions & 0 deletions lib/i18n_backend_sequel/store_procs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# This module is intended to be mixed into the Sequel backend to allow
# storing Ruby Procs as translation values in the database.
#
# I18n.backend = I18n::Backend::Sequel.new
# I18n::Backend::Sequel::Translation.send(:include, I18n::Backend::Sequel::StoreProcs)
#
# The StoreProcs module requires the ParseTree and ruby2ruby gems and therefor
# was extracted from the original backend.
#
# ParseTree is not compatible with Ruby 1.9.

begin
require 'ruby2ruby'
require 'parse_tree'
require 'parse_tree_extensions'
rescue LoadError => e
puts "can't use StoreProcs because: #{e.message}"
end

module I18n
module Backend
class Sequel
module StoreProcs
def value=(v)
case v
when Proc
write_attribute(:value, v.to_ruby)
write_attribute(:is_proc, true)
else
write_attribute(:value, v)
end
end

Translation.send(:include, self) if method(:to_s).respond_to?(:to_ruby)
end
end
end
end
Loading

0 comments on commit ae6e744

Please sign in to comment.