globalize-automatic 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +249 -0
- data/Rakefile +23 -0
- data/lib/globalize-automatic.rb +3 -0
- data/lib/globalize/automatic.rb +241 -0
- data/lib/globalize/automatic/translation.rb +78 -0
- data/lib/globalize/automatic/translation_job.rb +10 -0
- data/lib/globalize/automatic/translator.rb +26 -0
- data/lib/globalize/automatic/translator/easy_translate.rb +12 -0
- data/lib/globalize/automatic/version.rb +7 -0
- metadata +180 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 735aec99e5cfd71d44624e9eddbc04f9c5f7946d
|
4
|
+
data.tar.gz: 570d8ecb6a353dc1bebeeff4a43888d4b701b90d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f9f3068d5461d17d96fc53315cf17a875f052a3b1b567515982d5dcc1a5d56a735ea6dab3b05264775bb0068a55d87ce14bae8e1b1ee7c851bc1ecd9eceeb1e9
|
7
|
+
data.tar.gz: 6ed69374b69a9564e233d4da95bc2d2cec43f86a7457a0bdb9856574dd1e21ed99a10f840ecdd54d67a0be7b765092cd3f2d74eed4fbcfad128c969bb2aace2a
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Yuichi Takeuchi
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
Globalize Automatic
|
2
|
+
-
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
gem install globalize-automatic
|
8
|
+
```
|
9
|
+
|
10
|
+
### Rails 5.0
|
11
|
+
|
12
|
+
In your Gemfile
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'globalize-automatic', github: 'takeyuweb/globalize-automatic', branch: 'rails-5-0'
|
16
|
+
```
|
17
|
+
|
18
|
+
and
|
19
|
+
|
20
|
+
```bash
|
21
|
+
bundle install
|
22
|
+
```
|
23
|
+
|
24
|
+
## Configuration
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
# config/initializers/globalize_automatic.rb
|
28
|
+
require 'globalize-automatic'
|
29
|
+
Globalize::Automatic.translator =
|
30
|
+
Globalize::Automatic::Translator::EasyTranslate.new
|
31
|
+
|
32
|
+
# EasyTranslate configuration
|
33
|
+
EasyTranslate.api_key = 'xxx'
|
34
|
+
```
|
35
|
+
|
36
|
+
## Example
|
37
|
+
|
38
|
+
### 宣言
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
class Post
|
42
|
+
# Automatically translated from English.
|
43
|
+
translates :title, :text, automatic: :en
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class Post
|
49
|
+
# Automatically translated from English or Japanese. (English preferred)
|
50
|
+
translates :title, :text, automatic: %i(en ja)
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class Post
|
56
|
+
# Automatically translated from English
|
57
|
+
translates :title, :text, automatic: { from: :en, to: %i(ja fr vi) }
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class CreatePostAutomatics < ActiveRecord::Migration
|
63
|
+
def up
|
64
|
+
Post.create_translation_table! title: :string, text: :text
|
65
|
+
Post.create_automatic_translation_table! :title, :text
|
66
|
+
end
|
67
|
+
|
68
|
+
def down
|
69
|
+
Post.drop_translation_table!
|
70
|
+
Post.drop_automatic_translation_table!
|
71
|
+
end
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
#### 自動翻訳対象を追加
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
class AddPostAutomatics < ActiveRecord::Migration
|
79
|
+
def up
|
80
|
+
Post.add_translation_fields! description: :text
|
81
|
+
Post.add_automatic_translation_fields! :description
|
82
|
+
end
|
83
|
+
|
84
|
+
def down
|
85
|
+
remove_column :post_automatic_translations, :description
|
86
|
+
remove_column :post_automatic_translations, :description_automatically
|
87
|
+
end
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
### 更新
|
92
|
+
|
93
|
+
#### 自動翻訳
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
I18n.locale = :en
|
97
|
+
post.title = 'globalize'
|
98
|
+
post.save!
|
99
|
+
|
100
|
+
post.title_ja_automatic # => false
|
101
|
+
post.title_vi_automatic # => true
|
102
|
+
|
103
|
+
post.reload
|
104
|
+
|
105
|
+
I18n.locale = :ja
|
106
|
+
post.title # => nil
|
107
|
+
I18n.locale = :vi
|
108
|
+
post.title # => 'โลกาภิวัฒน์'
|
109
|
+
```
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
post.attributes = {
|
113
|
+
title_en: 'globalize',
|
114
|
+
title_ja_automatic: true
|
115
|
+
}
|
116
|
+
post.save!
|
117
|
+
|
118
|
+
post.reload
|
119
|
+
|
120
|
+
I18n.locale = :en
|
121
|
+
post.title # => 'globalize'
|
122
|
+
I18n.locale = :ja
|
123
|
+
post.title # => '国際化'
|
124
|
+
```
|
125
|
+
|
126
|
+
#### 自動翻訳無効化
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
post.attributes = {
|
130
|
+
title_en: 'globalize',
|
131
|
+
title_fr_automatic: false,
|
132
|
+
title_fr: 'Hoge'
|
133
|
+
}
|
134
|
+
post.save!
|
135
|
+
|
136
|
+
post.reload
|
137
|
+
|
138
|
+
I18n.locale = :en
|
139
|
+
post.title # => 'globalize'
|
140
|
+
I18n.locale = :vi
|
141
|
+
post.title # => 'โลกาภิวัฒน์'
|
142
|
+
I18n.locale = :fr
|
143
|
+
post.title # => 'hoge'
|
144
|
+
```
|
145
|
+
|
146
|
+
### 自動翻訳の原文優先順位
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
class Post
|
150
|
+
# Automatically translated from English or Japanese. (English preferred)
|
151
|
+
translates :title, :text, automatic: %i(en ja)
|
152
|
+
end
|
153
|
+
|
154
|
+
post = Post.new
|
155
|
+
post.attributes = {
|
156
|
+
title_en: 'English',
|
157
|
+
title_ja: '日本語'
|
158
|
+
}
|
159
|
+
post.save!
|
160
|
+
|
161
|
+
post.reload
|
162
|
+
|
163
|
+
I18n.locale = :fr
|
164
|
+
post.title # => 'Anglais' # It means 'English'.
|
165
|
+
```
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
class Post
|
169
|
+
# Automatically translated from English or Japanese. (English preferred)
|
170
|
+
translates :title, :text, automatic: %i(en ja)
|
171
|
+
end
|
172
|
+
|
173
|
+
post = Post.new
|
174
|
+
post.attributes = {
|
175
|
+
title_en: nil,
|
176
|
+
title_ja: '日本語'
|
177
|
+
}
|
178
|
+
post.save!
|
179
|
+
|
180
|
+
post.reload
|
181
|
+
|
182
|
+
I18n.locale = :fr
|
183
|
+
post.title # => 'Japonais' # It means '日本語'.
|
184
|
+
```
|
185
|
+
|
186
|
+
### 取得
|
187
|
+
|
188
|
+
#### 翻訳文属性名
|
189
|
+
|
190
|
+
[globalize-accessors](https://github.com/globalize/globalize-accessors)
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
Post.globalize_attribute_names # => [:title_ja, :title_en, :title_fr, :title_vi, :text_ja, :text_en, :text_fr, :text_vi]
|
194
|
+
```
|
195
|
+
|
196
|
+
#### 自動翻訳有効/無効属性名
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
Post.automatic_translation_attribute_names # => [:title_ja_automatically, :title_en_automatically, :title_fr_automatically, :title_vi_automatically, :text_ja_automatically, :text_en_automatically, :text_fr_automatically, :text_vi_automatically]
|
200
|
+
```
|
201
|
+
|
202
|
+
strong parameters
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
permitted = Post.globalize_attribute_names + Post.automatic_translation_attribute_names
|
206
|
+
params.require(:post).permit(*permitted)
|
207
|
+
```
|
208
|
+
|
209
|
+
### 非同期
|
210
|
+
|
211
|
+
ActiveJobを利用による非同期翻訳
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
# config/initializers/globalize_automatic.rb
|
215
|
+
Globalize::Automatic.asynchronously = true
|
216
|
+
```
|
217
|
+
|
218
|
+
### 他の翻訳ライブラリやサービスへの対応
|
219
|
+
|
220
|
+
Translatorクラスを書けば対応できます。
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
class YourTranslator < Globalize::Automatic::Translator
|
224
|
+
def translate(text, from, to)
|
225
|
+
# 適当な翻訳処理を行って訳文を返す
|
226
|
+
return translated
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
Globalize::Automatic.translator = YourTranslator::EasyTranslate.new
|
231
|
+
```
|
232
|
+
|
233
|
+
## TODO
|
234
|
+
|
235
|
+
- EasyTranslate依存の切り出し
|
236
|
+
- 他の翻訳ライブラリやサービスへの対応。
|
237
|
+
- Microsoft Translator
|
238
|
+
- Gengo etc
|
239
|
+
|
240
|
+
|
241
|
+
## Contributing
|
242
|
+
|
243
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/takeyuweb/globalize_automatic. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
|
244
|
+
|
245
|
+
## Licence
|
246
|
+
|
247
|
+
Copyright (c) 2017 Yuichi Takeuchi released under the MIT license
|
248
|
+
|
249
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'GlobalizeAutomatic'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
@@ -0,0 +1,241 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'globalize'
|
4
|
+
require 'globalize-accessors'
|
5
|
+
require 'globalize/automatic/translation'
|
6
|
+
require 'globalize/automatic/translation_job'
|
7
|
+
require 'globalize/automatic/translator/easy_translate'
|
8
|
+
require 'after_commit_action'
|
9
|
+
|
10
|
+
module Globalize::Automatic
|
11
|
+
mattr_accessor :asynchronously, :translator
|
12
|
+
|
13
|
+
module TranslatedExtension
|
14
|
+
extend ActiveSupport::Concern
|
15
|
+
|
16
|
+
included do
|
17
|
+
class_attribute :automatic_translation_attribute_names,
|
18
|
+
:automatic_translation_field_locales,
|
19
|
+
:automatic_translated_field_locales
|
20
|
+
self.automatic_translation_attribute_names = []
|
21
|
+
self.automatic_translation_field_locales = Hash.new { [] }
|
22
|
+
self.automatic_translated_field_locales = Hash.new { [] }
|
23
|
+
end
|
24
|
+
|
25
|
+
class_methods do
|
26
|
+
def automatic_translation_class
|
27
|
+
return @automatic_translation_class if defined?(@automatic_translation_class)
|
28
|
+
if self.const_defined?(:AutomaticTranslation, false)
|
29
|
+
klass = self.const_get(AutomaticTranslation, false)
|
30
|
+
else
|
31
|
+
klass = Class.new(Globalize::Automatic::Translation)
|
32
|
+
self.const_set(:AutomaticTranslation, klass)
|
33
|
+
end
|
34
|
+
foreign_key = name.foreign_key
|
35
|
+
klass.belongs_to :automatic_translated_model,
|
36
|
+
class_name: name,
|
37
|
+
foreign_key: foreign_key,
|
38
|
+
inverse_of: :automatic_translations
|
39
|
+
klass.define_singleton_method(:automatic_translated_model_foreign_key) do
|
40
|
+
foreign_key
|
41
|
+
end
|
42
|
+
@automatic_translation_class = klass
|
43
|
+
end
|
44
|
+
|
45
|
+
# 翻訳元フィールドと言語
|
46
|
+
def add_automatic_translation_field_locales!(fields, locales)
|
47
|
+
fields.each do |field|
|
48
|
+
automatic_translation_field_locales[field] = locales
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# 翻訳先フィールドと言語
|
53
|
+
def add_automatic_translated_field_locales!(fields, locales)
|
54
|
+
fields.each do |field|
|
55
|
+
automatic_translated_field_locales[field] = locales
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# field が locale で自動翻訳元指定されているか
|
60
|
+
def translate_field_automatically?(field, locale)
|
61
|
+
automatic_translation_field_locales[field].include?(locale)
|
62
|
+
end
|
63
|
+
|
64
|
+
# field が locale で自動翻訳先指定されているか
|
65
|
+
def translated_field_automatically?(field, locale)
|
66
|
+
automatic_translated_field_locales[field].include?(locale)
|
67
|
+
end
|
68
|
+
|
69
|
+
public
|
70
|
+
def create_automatic_translation_table!(*fields)
|
71
|
+
automatic_translation_class.create_table!(*fields)
|
72
|
+
end
|
73
|
+
|
74
|
+
def drop_automatic_translation_table!
|
75
|
+
automatic_translation_class.drop_table!
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_automatic_translation_fields!(*fields)
|
79
|
+
automatic_translation_class.add_fields!(*fields)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def automatic_translation_for(locale)
|
85
|
+
automatic_translations.where(locale: locale).
|
86
|
+
first_or_initialize(default_translation_automatically(locale))
|
87
|
+
end
|
88
|
+
|
89
|
+
# from_locale から attribute_names を自動翻訳
|
90
|
+
# 自動翻訳が対象でない場合なにもしない
|
91
|
+
def run_automatic_translation(from_locale: , attribute_names:)
|
92
|
+
attribute_names.each do |attr_name|
|
93
|
+
# 自動翻訳対象以外
|
94
|
+
next unless automatic_translation_field_locales[attr_name].include?(from_locale)
|
95
|
+
# 自動翻訳先としては無効化されている
|
96
|
+
next if automatic_translation_for(from_locale)[:"#{attr_name}_automatically"]
|
97
|
+
automatic_translated_field_locales[attr_name].each do |to_locale|
|
98
|
+
next if to_locale == from_locale
|
99
|
+
automatic_translation_for(to_locale).translate(attr_name)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
# 自動翻訳元言語
|
106
|
+
# attr_nameの自動変換が有効なとき
|
107
|
+
# 現在設定されている中で一番優先度の高い翻訳元localeを返す
|
108
|
+
# どの言語も設定されてない場合は一番優先度の高いもの
|
109
|
+
# 自動翻訳元でない場合nil
|
110
|
+
def automatic_translation_locale(attr_name)
|
111
|
+
locales = automatic_translation_field_locales[attr_name]
|
112
|
+
locales.each do |locale|
|
113
|
+
return locale unless translation_for(locale)[attr_name].blank?
|
114
|
+
end
|
115
|
+
locales.first
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
def default_translation_automatically(locale)
|
120
|
+
# 自動翻訳元指定されていなくて、
|
121
|
+
# 自動翻訳先指定されているものを
|
122
|
+
# デフォルトで自動翻訳ONにする
|
123
|
+
translated_attribute_names.inject({}) do |defaults, attr_name|
|
124
|
+
defaults[:"#{attr_name}_automatically"] =
|
125
|
+
self.class.translated_field_automatically?(attr_name, locale) &&
|
126
|
+
!self.class.translate_field_automatically?(attr_name, locale)
|
127
|
+
defaults
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
module TranslationExtension
|
134
|
+
extend ActiveSupport::Concern
|
135
|
+
included do
|
136
|
+
include AfterCommitAction unless include?(AfterCommitAction)
|
137
|
+
after_save :after_save
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
def after_save
|
142
|
+
changed_attr_names =
|
143
|
+
globalized_model.translated_attribute_names & changes.keys.map(&:to_sym)
|
144
|
+
|
145
|
+
execute_after_commit do
|
146
|
+
globalized_model.run_automatic_translation(from_locale: locale,
|
147
|
+
attribute_names: changed_attr_names)
|
148
|
+
true
|
149
|
+
end
|
150
|
+
true
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
module_function
|
155
|
+
|
156
|
+
def setup_automatic_translation!(klass, attr_names, options)
|
157
|
+
automatic_options = validate_options(parse_options(options))
|
158
|
+
locales = (automatic_options[:from] + automatic_options[:to]).uniq
|
159
|
+
klass.globalize_accessors locales: locales, attributes: attr_names
|
160
|
+
unless klass.include?(Globalize::Automatic::TranslatedExtension)
|
161
|
+
klass.include Globalize::Automatic::TranslatedExtension
|
162
|
+
|
163
|
+
klass.has_many :automatic_translations,
|
164
|
+
dependent: :destroy,
|
165
|
+
autosave: true,
|
166
|
+
class_name: klass.automatic_translation_class.name,
|
167
|
+
foreign_key: klass.name.foreign_key,
|
168
|
+
inverse_of: :automatic_translated_model
|
169
|
+
automatic_table_name = "#{klass.table_name.singularize}_automatic_translations"
|
170
|
+
klass.automatic_translation_class.table_name = automatic_table_name
|
171
|
+
klass.automatic_translation_class.define_singleton_method(:table_name) { automatic_table_name }
|
172
|
+
end
|
173
|
+
|
174
|
+
klass.add_automatic_translation_field_locales!(attr_names, automatic_options[:from])
|
175
|
+
klass.add_automatic_translated_field_locales!(attr_names, automatic_options[:to])
|
176
|
+
|
177
|
+
attr_names.each do |attr_name|
|
178
|
+
locales.each do |locale|
|
179
|
+
klass.class_eval(<<"EVAL")
|
180
|
+
def #{attr_name}_#{locale.to_s.underscore}_automatically
|
181
|
+
automatic_translation_for(#{locale.inspect}).#{attr_name}_automatically
|
182
|
+
end
|
183
|
+
|
184
|
+
def #{attr_name}_#{locale.to_s.underscore}_automatically=(automatically)
|
185
|
+
automatic_translation_for(#{locale.inspect}).#{attr_name}_automatically = automatically
|
186
|
+
end
|
187
|
+
|
188
|
+
self.automatic_translation_attribute_names.push(:#{attr_name}_#{locale.to_s.underscore}_automatically)
|
189
|
+
EVAL
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
unless klass.translation_class.include?(Globalize::Automatic::TranslationExtension)
|
194
|
+
klass.translation_class.include Globalize::Automatic::TranslationExtension
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def parse_options(options)
|
199
|
+
case options
|
200
|
+
when Hash
|
201
|
+
from_locales = normalize_locales(options[:from])
|
202
|
+
to_locales = normalize_locales(options[:to])
|
203
|
+
else
|
204
|
+
from_locales = normalize_locales(options)
|
205
|
+
to_locales = I18n.available_locales
|
206
|
+
end
|
207
|
+
{from: from_locales, to: to_locales}
|
208
|
+
end
|
209
|
+
|
210
|
+
def normalize_locales(locales)
|
211
|
+
[locales].flatten.compact.map(&:to_sym)
|
212
|
+
end
|
213
|
+
|
214
|
+
def validate_options(options)
|
215
|
+
if options[:from].empty?
|
216
|
+
raise ArgumentError.new('missing :from option')
|
217
|
+
elsif options[:to].empty?
|
218
|
+
raise ArgumentError.new('missing :to option')
|
219
|
+
else
|
220
|
+
options
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
Globalize::Automatic.asynchronously = false
|
225
|
+
Globalize::Automatic.translator = Globalize::Automatic::Translator::EasyTranslate.new
|
226
|
+
|
227
|
+
Globalize::ActiveRecord::ActMacro.module_eval do
|
228
|
+
|
229
|
+
def translates_with_automatic(*attr_names)
|
230
|
+
translates_without_automatic(*attr_names).tap do
|
231
|
+
options = attr_names.extract_options!
|
232
|
+
automatic_options = options.delete(:automatic)
|
233
|
+
if automatic_options.present?
|
234
|
+
Globalize::Automatic.setup_automatic_translation!(self, attr_names, automatic_options)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
alias_method_chain :translates, :automatic
|
240
|
+
|
241
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class Globalize::Automatic::Translation < ActiveRecord::Base
|
2
|
+
self.abstract_class = true
|
3
|
+
|
4
|
+
def from_locale(attr_name)
|
5
|
+
automatic_translated_model.automatic_translation_locale(attr_name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def translation_from(attr_name)
|
9
|
+
translation_for(from_locale(attr_name))
|
10
|
+
end
|
11
|
+
|
12
|
+
def translation_to
|
13
|
+
translation_for(locale)
|
14
|
+
end
|
15
|
+
|
16
|
+
def translation_for(target_locale)
|
17
|
+
automatic_translated_model.translation_for(target_locale)
|
18
|
+
end
|
19
|
+
|
20
|
+
def translate(attr_name)
|
21
|
+
if automatically_for?(attr_name)
|
22
|
+
Globalize::Automatic.asynchronously ?
|
23
|
+
Globalize::Automatic::TranslationJob.perform_later(self, attr_name) :
|
24
|
+
Globalize::Automatic::TranslationJob.perform_now(self, attr_name)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def resolve(attr_name, translated)
|
29
|
+
obj = translation_to
|
30
|
+
obj.transaction do
|
31
|
+
obj.lock!
|
32
|
+
obj[attr_name] = translated
|
33
|
+
obj.save!(validate: false)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def reject(attr_name, error); end
|
38
|
+
|
39
|
+
private
|
40
|
+
def automatically_for?(attr_name)
|
41
|
+
self[self.class.automatically_column_name(attr_name)]
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
def create_table!(*fields)
|
46
|
+
connection.create_table(table_name) do |t|
|
47
|
+
t.references automatic_translated_model_foreign_key.sub(/_id$/, ''), null: false, index: false
|
48
|
+
t.string :locale, null: false
|
49
|
+
fields.each do |field|
|
50
|
+
t.boolean *automatically_column_args(field)
|
51
|
+
end
|
52
|
+
t.timestamps null: false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def drop_table!
|
57
|
+
connection.drop_table(table_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_fields!(*fields)
|
61
|
+
connection.change_table(table_name) do |t|
|
62
|
+
fields.each do |field|
|
63
|
+
t.boolean *automatically_column_args(field)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def automatically_column_name(field)
|
69
|
+
:"#{field}_automatically"
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def automatically_column_args(field)
|
74
|
+
args = [automatically_column_name(field), default: false, null: false]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Globalize::Automatic::Translator
|
4
|
+
|
5
|
+
def run(automatic_translation, attr_name)
|
6
|
+
translation = automatic_translation.translation_from(attr_name)
|
7
|
+
text = translation[attr_name]
|
8
|
+
from = translation.locale
|
9
|
+
to = automatic_translation.locale
|
10
|
+
_text, _from, _to = before_translate(text, from, to)
|
11
|
+
translated = translate(_text, _from, _to)
|
12
|
+
_text, _from, _to, _translated = after_translate(_text, _from, _to, translated)
|
13
|
+
automatic_translation.resolve(attr_name, _translated)
|
14
|
+
end
|
15
|
+
|
16
|
+
def translate(text, from, to); end
|
17
|
+
|
18
|
+
def before_translate(text, from, to)
|
19
|
+
[text, from, to]
|
20
|
+
end
|
21
|
+
|
22
|
+
def after_translate(text, from, to, result)
|
23
|
+
[text, from, to, result]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'globalize/automatic/translator'
|
4
|
+
require 'easy_translate'
|
5
|
+
|
6
|
+
class Globalize::Automatic::Translator::EasyTranslate < Globalize::Automatic::Translator
|
7
|
+
|
8
|
+
def translate(text, from, to)
|
9
|
+
::EasyTranslate.translate(text, from: from, to: to)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: globalize-automatic
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yuichi Takeuchi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: globalize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: globalize-accessors
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: after_commit_action
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: easy_translate
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activerecord
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activejob
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 4.2.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 4.2.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sqlite3
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec-rails
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Provides support for using automatic translation gems with Globalize.
|
140
|
+
email:
|
141
|
+
- info@takeyu-web.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- MIT-LICENSE
|
147
|
+
- README.md
|
148
|
+
- Rakefile
|
149
|
+
- lib/globalize-automatic.rb
|
150
|
+
- lib/globalize/automatic.rb
|
151
|
+
- lib/globalize/automatic/translation.rb
|
152
|
+
- lib/globalize/automatic/translation_job.rb
|
153
|
+
- lib/globalize/automatic/translator.rb
|
154
|
+
- lib/globalize/automatic/translator/easy_translate.rb
|
155
|
+
- lib/globalize/automatic/version.rb
|
156
|
+
homepage: https://github.com/takeyuweb/globalize-automatic/
|
157
|
+
licenses:
|
158
|
+
- MIT
|
159
|
+
metadata: {}
|
160
|
+
post_install_message:
|
161
|
+
rdoc_options: []
|
162
|
+
require_paths:
|
163
|
+
- lib
|
164
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
requirements: []
|
175
|
+
rubyforge_project:
|
176
|
+
rubygems_version: 2.5.1
|
177
|
+
signing_key:
|
178
|
+
specification_version: 4
|
179
|
+
summary: Adapter for using automatic translation gems with Globalize
|
180
|
+
test_files: []
|