Skip to content
Snippets Groups Projects
Unverified Commit 62e95410 authored by Marcelo Schmidt's avatar Marcelo Schmidt
Browse files

Automatically display translated texts

parent dfb100eb
No related branches found
No related tags found
No related merge requests found
Meteor.startup(function() {
Tracker.autorun(function() {
if (RocketChat.settings.get('AutoTranslate_Enabled')) {
RocketChat.callbacks.add('renderMessage', (message) => {
if (message.u._id !== Meteor.userId()) {
const subscription = RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1, autoTranslateDisplay: 1 } });
if (subscription && subscription.autoTranslate === true && subscription.autoTranslateDisplay === true && subscription.autoTranslateLanguage) {
const autoTranslateLanguage = subscription.autoTranslateLanguage;
if (!message.translations) {
message.translations = {};
}
message.translations['original'] = message.html;
if (message.translations[autoTranslateLanguage]) {
message.html = message.translations[autoTranslateLanguage];
}
return message;
}
}
}, RocketChat.callbacks.priority.HIGH - 3, 'autotranslate');
} else {
RocketChat.callbacks.remove('renderMessage', 'autotranslate');
}
});
});
...@@ -9,18 +9,10 @@ ...@@ -9,18 +9,10 @@
<li> <li>
<label>{{_ "Enabled"}}</label> <label>{{_ "Enabled"}}</label>
<div> <div>
{{#if editing 'autoTranslate'}} <div class="input checkbox toggle">
<label> <input type="checkbox" id="autoTranslate" name="autoTranslate" value="1" checked="{{$eq autoTranslate true}}" />
<select name="autoTranslate"> <label for="autoTranslate"></label>
<option value="" selected="{{$eq autoTranslate false}}">{{_ "False"}}</option> </div>
<option value="1" selected="{{$eq autoTranslate true}}">{{_ "True"}}</option>
</select>
</label>
<button type="button" class="button cancel">{{_ "Cancel"}}</button>
<button type="button" class="button primary save">{{_ "Save"}}</button>
{{else}}
<span class="current-setting">{{autoTranslateValue}} <i class="icon-pencil" data-edit="autoTranslate"></i></span>
{{/if}}
</div> </div>
</li> </li>
{{#if $eq autoTranslate true}} {{#if $eq autoTranslate true}}
...@@ -38,10 +30,19 @@ ...@@ -38,10 +30,19 @@
<button type="button" class="button cancel">{{_ "Cancel"}}</button> <button type="button" class="button cancel">{{_ "Cancel"}}</button>
<button type="button" class="button primary save">{{_ "Save"}}</button> <button type="button" class="button primary save">{{_ "Save"}}</button>
{{else}} {{else}}
<span class="current-setting">{{autoTranslateLanguage}} <i class="icon-pencil" data-edit="autoTranslateLanguage"></i></span> <span class="current-setting">{{languageName autoTranslateLanguage}} <i class="icon-pencil" data-edit="autoTranslateLanguage"></i></span>
{{/if}} {{/if}}
</div> </div>
</li> </li>
<li>
<label>{{_ "Display_translated_text"}}</label>
<div>
<div class="input checkbox toggle">
<input type="checkbox" id="autoTranslateDisplay" name="autoTranslateDisplay" value="1" checked="{{$eq autoTranslateDisplay true}}"/>
<label for="autoTranslateDisplay"></label>
</div>
</div>
</li>
{{/if}} {{/if}}
</ul> </ul>
</form> </form>
......
...@@ -13,6 +13,17 @@ Template.autoTranslateFlexTab.helpers({ ...@@ -13,6 +13,17 @@ Template.autoTranslateFlexTab.helpers({
return sub && sub.autoTranslate ? true : false; return sub && sub.autoTranslate ? true : false;
}, },
autoTranslateDisplay() {
const sub = ChatSubscription.findOne({
rid: Session.get('openedRoom')
}, {
fields: {
autoTranslateDisplay: 1
}
});
return sub && sub.autoTranslateDisplay ? true : false;
},
autoTranslateValue() { autoTranslateValue() {
const sub = ChatSubscription.findOne({ const sub = ChatSubscription.findOne({
rid: Session.get('openedRoom') rid: Session.get('openedRoom')
...@@ -35,7 +46,7 @@ Template.autoTranslateFlexTab.helpers({ ...@@ -35,7 +46,7 @@ Template.autoTranslateFlexTab.helpers({
const autoTranslateLanguage = sub && sub.autoTranslateLanguage; const autoTranslateLanguage = sub && sub.autoTranslateLanguage;
const supportedLanguages = Template.instance().supportedLanguages.get(); const supportedLanguages = Template.instance().supportedLanguages.get();
const language = _.findWhere(supportedLanguages, { language: autoTranslateLanguage }); const language = _.findWhere(supportedLanguages, { language: autoTranslateLanguage });
return language && (language.name || language.language) || autoTranslateLanguage; return language && language.language || autoTranslateLanguage || (Meteor.user() && Meteor.user().language);
}, },
editing(field) { editing(field) {
...@@ -44,6 +55,12 @@ Template.autoTranslateFlexTab.helpers({ ...@@ -44,6 +55,12 @@ Template.autoTranslateFlexTab.helpers({
supportedLanguages() { supportedLanguages() {
return Template.instance().supportedLanguages.get(); return Template.instance().supportedLanguages.get();
},
languageName(language) {
const supportedLanguages = Template.instance().supportedLanguages.get();
language = _.findWhere(supportedLanguages, { language: language });
return language && language.name;
} }
}); });
...@@ -56,15 +73,13 @@ Template.autoTranslateFlexTab.onCreated(function() { ...@@ -56,15 +73,13 @@ Template.autoTranslateFlexTab.onCreated(function() {
}); });
this.validateSetting = (field) => { this.validateSetting = (field) => {
const value = this.$('select[name='+ field +']').val(); let value;
switch (field) { switch (field) {
case 'autoTranslate': case 'autoTranslate':
if (['', '1'].indexOf(value) === -1) { case 'autoTranslateDisplay':
toastr.error(t('Invalid_setting_s'), value || '');
return false;
}
return true; return true;
case 'autoTranslateLanguage': case 'autoTranslateLanguage':
value = this.$('select[name='+ field +']').val();
if (!_.findWhere(this.supportedLanguages.get(), { language: value })) { if (!_.findWhere(this.supportedLanguages.get(), { language: value })) {
toastr.error(t('Invalid_setting_s', value || '')); toastr.error(t('Invalid_setting_s', value || ''));
return false; return false;
...@@ -75,7 +90,17 @@ Template.autoTranslateFlexTab.onCreated(function() { ...@@ -75,7 +90,17 @@ Template.autoTranslateFlexTab.onCreated(function() {
this.saveSetting = () => { this.saveSetting = () => {
const field = this.editing.get(); const field = this.editing.get();
const value = this.$('select[name='+field+']').val(); let value;
switch (field) {
case 'autoTranslate':
case 'autoTranslateDisplay':
value = this.$('input[name='+field+']').prop('checked') ? '1' : '0';
break;
case 'autoTranslateLanguage':
value = this.$('select[name='+ field +']').val();
break;
}
if (this.validateSetting(field)) { if (this.validateSetting(field)) {
Meteor.call('autoTranslate.saveSettings', Session.get('openedRoom'), field, value, (err/*, result*/) => { Meteor.call('autoTranslate.saveSettings', Session.get('openedRoom'), field, value, (err/*, result*/) => {
if (err) { if (err) {
...@@ -101,6 +126,11 @@ Template.autoTranslateFlexTab.events({ ...@@ -101,6 +126,11 @@ Template.autoTranslateFlexTab.events({
setTimeout(function() { instance.$('input.editing').focus().select(); }, 100); setTimeout(function() { instance.$('input.editing').focus().select(); }, 100);
}, },
'change [type=checkbox]'(e, instance) {
instance.editing.set($(e.currentTarget).attr('name'));
instance.saveSetting();
},
'click .cancel'(e, instance) { 'click .cancel'(e, instance) {
e.preventDefault(); e.preventDefault();
instance.editing.set(); instance.editing.set();
......
...@@ -17,6 +17,7 @@ Package.onUse(function(api) { ...@@ -17,6 +17,7 @@ Package.onUse(function(api) {
api.addFiles([ api.addFiles([
'client/stylesheets/autotranslate.less', 'client/stylesheets/autotranslate.less',
'client/lib/autotranslate.js',
'client/lib/tabBar.js', 'client/lib/tabBar.js',
'client/views/autoTranslateFlexTab.html', 'client/views/autoTranslateFlexTab.html',
'client/views/autoTranslateFlexTab.js' 'client/views/autoTranslateFlexTab.js'
......
...@@ -3,6 +3,7 @@ class AutoTranslate { ...@@ -3,6 +3,7 @@ class AutoTranslate {
this.languages = []; this.languages = [];
this.enabled = RocketChat.settings.get('AutoTranslate_Enabled'); this.enabled = RocketChat.settings.get('AutoTranslate_Enabled');
this.apiKey = RocketChat.settings.get('AutoTranslate_GoogleAPIKey'); this.apiKey = RocketChat.settings.get('AutoTranslate_GoogleAPIKey');
this.supportedLanguages = {};
RocketChat.callbacks.add('afterSaveMessage', this.translateMessage.bind(this), RocketChat.callbacks.priority.MEDIUM, 'AutoTranslate'); RocketChat.callbacks.add('afterSaveMessage', this.translateMessage.bind(this), RocketChat.callbacks.priority.MEDIUM, 'AutoTranslate');
} }
...@@ -66,10 +67,8 @@ class AutoTranslate { ...@@ -66,10 +67,8 @@ class AutoTranslate {
translateMessage(message, room) { translateMessage(message, room) {
if (this.enabled && this.apiKey && message.msg) { if (this.enabled && this.apiKey && message.msg) {
Meteor.defer(() => { Meteor.defer(() => {
// console.log(RocketChat.models.Subscriptions.getAutoTranslateLanguages());
const translations = {}; const translations = {};
const targetLanguages = ['pt', 'es']; const targetLanguages = RocketChat.models.Subscriptions.getAutoTranslateLanguagesByRoom(room._id);
message.html = s.escapeHTML(String(message.msg)); message.html = s.escapeHTML(String(message.msg));
message = this.tokenize(message); message = this.tokenize(message);
...@@ -94,20 +93,33 @@ class AutoTranslate { ...@@ -94,20 +93,33 @@ class AutoTranslate {
getSupportedLanguages(target) { getSupportedLanguages(target) {
if (this.enabled && this.apiKey) { if (this.enabled && this.apiKey) {
if (this.supportedLanguages[target]) {
return this.supportedLanguages[target];
}
let result; let result;
const params = { key: this.apiKey }; const params = { key: this.apiKey };
if (target) { if (target) {
params.target = target; params.target = target;
} }
try { try {
result = HTTP.get('https://translation.googleapis.com/language/translate/v2/languages', { params: params }); result = HTTP.get('https://translation.googleapis.com/language/translate/v2/languages', { params: params });
} catch (e) { } catch (e) {
if (e.response && e.response.statusCode === 400 && e.response.data && e.response.data.error && e.response.data.error.status === 'INVALID_ARGUMENT') { if (e.response && e.response.statusCode === 400 && e.response.data && e.response.data.error && e.response.data.error.status === 'INVALID_ARGUMENT') {
delete params.target; delete params.target;
result = HTTP.get('https://translation.googleapis.com/language/translate/v2/languages', { params: params }); target = 'en';
if (!this.supportedLanguages[target]) {
result = HTTP.get('https://translation.googleapis.com/language/translate/v2/languages', { params: params });
}
} }
} finally { } finally {
return result && result.data && result.data.data && result.data.data.languages; if (this.supportedLanguages[target]) {
return this.supportedLanguages[target];
} else {
this.supportedLanguages[target || 'en'] = result && result.data && result.data.data && result.data.data.languages;
return this.supportedLanguages[target || 'en'];
}
} }
} }
} }
......
...@@ -8,7 +8,7 @@ Meteor.methods({ ...@@ -8,7 +8,7 @@ Meteor.methods({
check(field, String); check(field, String);
check(value, String); check(value, String);
if (['autoTranslate', 'autoTranslateLanguage'].indexOf(field) === -1) { if (['autoTranslate', 'autoTranslateLanguage', 'autoTranslateDisplay'].indexOf(field) === -1) {
throw new Meteor.Error('error-invalid-settings', 'Invalid settings field', { method: 'saveAutoTranslateSettings' }); throw new Meteor.Error('error-invalid-settings', 'Invalid settings field', { method: 'saveAutoTranslateSettings' });
} }
...@@ -21,6 +21,9 @@ Meteor.methods({ ...@@ -21,6 +21,9 @@ Meteor.methods({
case 'autoTranslate': case 'autoTranslate':
RocketChat.models.Subscriptions.updateAutoTranslateById(subscription._id, value === '1' ? true : false); RocketChat.models.Subscriptions.updateAutoTranslateById(subscription._id, value === '1' ? true : false);
break; break;
case 'autoTranslateDisplay':
RocketChat.models.Subscriptions.updateAutoTranslateDisplayById(subscription._id, value === '1' ? true : false);
break;
case 'autoTranslateLanguage': case 'autoTranslateLanguage':
RocketChat.models.Subscriptions.updateAutoTranslateLanguageById(subscription._id, value); RocketChat.models.Subscriptions.updateAutoTranslateLanguageById(subscription._id, value);
break; break;
......
...@@ -35,3 +35,34 @@ RocketChat.models.Subscriptions.updateAutoTranslateLanguageById = function(_id, ...@@ -35,3 +35,34 @@ RocketChat.models.Subscriptions.updateAutoTranslateLanguageById = function(_id,
return this.update(query, update); return this.update(query, update);
}; };
RocketChat.models.Subscriptions.updateAutoTranslateDisplayById = function(_id, autoTranslateDisplay) {
const query = {
_id: _id
};
let update;
if (autoTranslateDisplay) {
update = {
$set: {
autoTranslateDisplay: autoTranslateDisplay
}
};
} else {
update = {
$unset: {
autoTranslateDisplay: 1
}
};
}
return this.update(query, update);
};
RocketChat.models.Subscriptions.getAutoTranslateLanguagesByRoom = function(rid) {
const subscriptionsRaw = RocketChat.models.Subscriptions.model.rawCollection();
const distinct = Meteor.wrapAsync(subscriptionsRaw.distinct, subscriptionsRaw);
const query = {
rid: rid,
autoTranslate: true
};
return distinct('autoTranslateLanguage', query);
};
...@@ -398,6 +398,7 @@ ...@@ -398,6 +398,7 @@
"Direct_message_someone": "Direct message someone", "Direct_message_someone": "Direct message someone",
"Direct_Messages": "Direct Messages", "Direct_Messages": "Direct Messages",
"Display_offline_form": "Display offline form", "Display_offline_form": "Display offline form",
"Display_translated_text": "Display translated text",
"Displays_action_text": "Displays action text", "Displays_action_text": "Displays action text",
"Do_you_want_to_change_to_s_question": "Do you want to change to <strong>%s</strong>?", "Do_you_want_to_change_to_s_question": "Do you want to change to <strong>%s</strong>?",
"Domain": "Domain", "Domain": "Domain",
......
...@@ -22,7 +22,8 @@ const fields = { ...@@ -22,7 +22,8 @@ const fields = {
blocked: 1, blocked: 1,
blocker: 1, blocker: 1,
autoTranslate: 1, autoTranslate: 1,
autoTranslateLanguage: 1 autoTranslateLanguage: 1,
autoTranslateDisplay: 1
}; };
Meteor.methods({ Meteor.methods({
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment