forked from discourse/discourse-translator
-
Notifications
You must be signed in to change notification settings - Fork 3
/
plugin.rb
151 lines (119 loc) · 4.69 KB
/
plugin.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# frozen_string_literal: true
# name: discourse-translator
# about: Provides inline translation of posts.
# version: 0.3.0
# authors: Alan Tan
# url: https://github.com/discourse/discourse-translator
enabled_site_setting :translator_enabled
register_asset "stylesheets/common/post.scss"
after_initialize do
module ::DiscourseTranslator
PLUGIN_NAME = "discourse_translator".freeze
DETECTED_LANG_CUSTOM_FIELD = 'post_detected_lang'.freeze
TRANSLATED_CUSTOM_FIELD = 'translated_text'.freeze
autoload :Microsoft, "#{Rails.root}/plugins/discourse-translator/services/discourse_translator/microsoft"
autoload :Google, "#{Rails.root}/plugins/discourse-translator/services/discourse_translator/google"
autoload :Yandex, "#{Rails.root}/plugins/discourse-translator/services/discourse_translator/yandex"
autoload :Deepl, "#{Rails.root}/plugins/discourse-translator/services/discourse_translator/deepl"
class Engine < ::Rails::Engine
engine_name PLUGIN_NAME
isolate_namespace DiscourseTranslator
end
end
require_dependency "application_controller"
class DiscourseTranslator::TranslatorController < ::ApplicationController
before_action :ensure_logged_in
def translate
raise PluginDisabled if !SiteSetting.translator_enabled
if !current_user.staff?
RateLimiter.new(current_user, "translate_post", SiteSetting.max_translations_per_minute, 1.minute).performed!
end
params.require(:post_id)
post = Post.find_by(id: params[:post_id])
raise Discourse::InvalidParameters.new(:post_id) if post.blank?
guardian.ensure_can_see!(post)
begin
detected_lang, translation = "DiscourseTranslator::#{SiteSetting.translator}".constantize.translate(post)
render json: { translation: translation, detected_lang: detected_lang }, status: 200
rescue ::DiscourseTranslator::TranslatorError => e
render_json_error e.message, status: 422
end
end
end
Post.register_custom_field_type(::DiscourseTranslator::TRANSLATED_CUSTOM_FIELD, :json)
require_dependency "post"
class ::Post < ActiveRecord::Base
before_update :clear_translator_custom_fields, if: :raw_changed?
private
def clear_translator_custom_fields
return if !SiteSetting.translator_enabled
self.custom_fields.delete(DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD)
self.custom_fields.delete(DiscourseTranslator::TRANSLATED_CUSTOM_FIELD)
end
end
require_dependency "jobs/base"
module ::Jobs
class TranslatorMigrateToAzurePortal < ::Jobs::Onceoff
def execute_onceoff(args)
["translator_client_id", "translator_client_secret"].each do |name|
DB.exec <<~SQL
DELETE FROM site_settings WHERE name = '#{name}'
SQL
end
DB.exec <<~SQL
UPDATE site_settings
SET name = 'translator_azure_subscription_key'
WHERE name = 'azure_subscription_key'
SQL
end
end
class DetectTranslation < ::Jobs::Base
sidekiq_options retry: false
def execute(args)
return if !SiteSetting.translator_enabled
post = Post.find_by(id: args[:post_id])
return unless post
DistributedMutex.synchronize("detect_translation_#{post.id}") do
"DiscourseTranslator::#{SiteSetting.translator}".constantize.detect(post)
post.save_custom_fields unless post.custom_fields_clean?
post.publish_change_to_clients! :revised
end
end
end
end
def post_process(post)
return if !SiteSetting.translator_enabled
Jobs.enqueue(:detect_translation, post_id: post.id)
end
listen_for :post_process
# TODO Drop after Discourse 2.6.0 release
if TopicView.respond_to?(:add_post_custom_fields_allowlister)
TopicView.add_post_custom_fields_allowlister do |user|
[::DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD]
end
else
TopicView.add_post_custom_fields_whitelister do |user|
[::DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD]
end
end
require_dependency "post_serializer"
class ::PostSerializer
attributes :can_translate
def can_translate
return false if !SiteSetting.translator_enabled
detected_lang = post_custom_fields[::DiscourseTranslator::DETECTED_LANG_CUSTOM_FIELD]
if !detected_lang
Jobs.enqueue(:detect_translation, post_id: object.id)
false
else
detected_lang != "DiscourseTranslator::#{SiteSetting.translator}::SUPPORTED_LANG".constantize[I18n.locale]
end
end
end
DiscourseTranslator::Engine.routes.draw do
post "translate" => "translator#translate"
end
Discourse::Application.routes.append do
mount ::DiscourseTranslator::Engine, at: "translator"
end
end