t9n 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,84 @@
1
+ module Perfectline
2
+ module T9n
3
+ module Models
4
+ module Translation
5
+
6
+ def self.included(base)
7
+ base.__send__(:include, Associations)
8
+ base.__send__(:include, Scopes)
9
+ base.__send__(:include, Validations)
10
+ base.__send__(:include, InstanceMethods)
11
+
12
+ base.extend(ClassMethods)
13
+ end
14
+
15
+ module Associations
16
+
17
+ def self.included(base)
18
+ base.class_eval do
19
+ belongs_to :translatable, :polymorphic => true, :readonly => true
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ module Scopes
26
+
27
+ def self.included(base)
28
+ base.class_eval do
29
+ named_scope :untranslated, :conditions => "value IS NULL OR value = ''"
30
+ named_scope :translated, :conditions => "value IS NOT NULL AND value != ''"
31
+ named_scope :orphans, :conditions => "translatable_id IS NULL"
32
+
33
+ named_scope :locale, lambda{ |locale| {:conditions => {:locale => locale}} }
34
+ named_scope :for, lambda{ |object| {:conditions => {:translatable_id => object.id, :translatable_type => object.class.name}} }
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ module Validations
41
+
42
+ def self.included(base)
43
+ base.class_eval do
44
+ validates_presence_of :locale
45
+ validates_presence_of :key
46
+ validates_length_of :key, :maximum => 255
47
+ validates_uniqueness_of :key, :scope => [:locale, :translatable_id, :translatable_type]
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ module ClassMethods
54
+
55
+ def available_locales
56
+ find(:all, :select => "DISTINCT locale", :order => :locale).map(&:locale)
57
+ end
58
+
59
+ def lookup(key)
60
+ translated.find(:all, :conditions => ["key = ? OR key ILIKE ?", key, "#{key}.%"], :order => :key)
61
+ end
62
+
63
+ def cache_key(locale, key, object)
64
+ if object.nil?
65
+ return "#{locale}:#{key}"
66
+ else
67
+ return "#{locale}:#{key}:#{object.class.name}_#{object.id}"
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ module InstanceMethods
74
+
75
+ def empty?
76
+ value.blank? || value.nil?
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
83
+ end
84
+ end
data/lib/t9n/util.rb ADDED
@@ -0,0 +1,95 @@
1
+ require 'cgi'
2
+ require 'net/http'
3
+
4
+ module Perfectline
5
+ module T9n
6
+ class Util
7
+
8
+ # sync non-default languages from the default one
9
+ def self.populate
10
+ ::Translation.locale(I18n.default_locale).each do |t|
11
+ ::Translation.available_locales.reject!{ |locale| I18n.default_locale?(locale) }.each do |locale|
12
+ unless ::Translation.locale(locale).exists?({:key => t.key, :translatable_id => t.translatable_id, :translatable_type => t.translatable_type})
13
+ ::Translation.create!(
14
+ :locale => locale,
15
+ :key => t.key,
16
+ :value => nil,
17
+ :translatable_id => t.translatable_id,
18
+ :translatable_type => t.translatable_type
19
+ )
20
+ puts "Translation::Populate created a new translation in :#{locale} with key '#{t.key}'"
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ # translate from google
27
+ def self.google_translate
28
+ I18n.available_locales.reject!{ |locale| I18n.default_locale?(locale) }.each do |locale|
29
+ ::Translation.locale(locale).untranslated.each do |translation|
30
+
31
+ unless self.needs_human_eyes?(translation.value)
32
+ interpolation = translation.value.scan(/\{\{(.*?)\}\}/).flatten
33
+
34
+ if interpolation.empty?
35
+ translation.update_attribute(:value, Perfectline::T9n::GoogleTranslator.translate(translation.value, locale, I18n.default_locale))
36
+ else
37
+ placeholders = {}
38
+
39
+ # sub out interpolations
40
+ interpolation.each do |argument|
41
+ placeholder = Time.now.to_i
42
+ translation.value.gsub!("{{#{argument}}}", placeholder)
43
+ placeholders[placeholder] = argument
44
+ end
45
+
46
+ # translate
47
+ translated = Perfectline::T9n::GoogleTranslator.translate(translation.value, locale, I18n.default_locale)
48
+ placeholders.each{|value, argument| translated.gsub!(value, "{{#{argument}}}")}
49
+
50
+ translation.update_attribute(:value, translated)
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def self.needs_human_eyes?(value)
61
+ return true if value.index('%') # date formats
62
+ return true if value =~ /^---(.*)\n/ # YAML
63
+ end
64
+
65
+ end
66
+
67
+ class GoogleTranslator
68
+
69
+ def self.translate(text, to, from='en')
70
+
71
+ base = 'http://ajax.googleapis.com/ajax/services/language/translate'
72
+
73
+ # assemble query params
74
+ params = {
75
+ :langpair => "#{from}|#{to}",
76
+ :q => text,
77
+ :v => 1.0
78
+ }
79
+
80
+ query = params.map{ |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join('&')
81
+
82
+ # send get request
83
+ response = Net::HTTP.get_response( URI.parse( "#{base}?#{query}" ) )
84
+ json = JSON.parse( response.body )
85
+
86
+ if json['responseStatus'] == 200
87
+ json['responseData']['translatedText']
88
+ else
89
+ raise StandardError, response['responseDetails']
90
+ end
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,18 @@
1
+ namespace :translations do
2
+
3
+ desc "Clear translations cache"
4
+ task :clear => :environment do
5
+ I18n.backend.cache_clear!
6
+ end
7
+
8
+ desc "Create empty translations keys from the default locale into other available locales"
9
+ task :populate => :environment do
10
+ Perfectline::T9n::Util.populate
11
+ end
12
+
13
+ desc "Uses google to translate untranslated values. No interpolation"
14
+ task :google => :environment do
15
+ Perfectline::T9n::Util.google_translate
16
+ end
17
+ end
18
+
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 't9n'
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: t9n
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tanel Suurhans
8
+ - Tarmo Lehtpuu
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2010-01-29 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activesupport
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ description: A custom AR backend for I18n, translatable model columns and virtual attributes, languages database with integration and some utilities.
27
+ email:
28
+ - tanel.suurhans@perfectline.ee
29
+ - tarmo.lehtpuu@perfectline.ee
30
+ executables: []
31
+
32
+ extensions: []
33
+
34
+ extra_rdoc_files:
35
+ - README.markdown
36
+ files:
37
+ - MIT-LICENSE
38
+ - README.markdown
39
+ - generators/t9n/t9n_generator.rb
40
+ - generators/t9n/templates/initializer.rb
41
+ - generators/t9n/templates/language.rb
42
+ - generators/t9n/templates/migrations/create_languages.rb
43
+ - generators/t9n/templates/migrations/create_translations.rb
44
+ - generators/t9n/templates/translation.rb
45
+ - init.rb
46
+ - install.rb
47
+ - lib/t9n.rb
48
+ - lib/t9n/active_record/translatable_attribute.rb
49
+ - lib/t9n/backend/active_record.rb
50
+ - lib/t9n/backend/exception_handler.rb
51
+ - lib/t9n/backend/extension.rb
52
+ - lib/t9n/models/language.rb
53
+ - lib/t9n/models/translation.rb
54
+ - lib/t9n/util.rb
55
+ - lib/tasks/t9n.rake
56
+ - rails/init.rb
57
+ has_rdoc: true
58
+ homepage: http://perfectline.co.uk
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options:
63
+ - --charset=UTF-8
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.3.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Translation package including I18n AR backend, translatable attributes and Language database by PerfectLine
85
+ test_files: []
86
+