trestle-mobility 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 321983d8b2ced10b0bfcf36a909b5503b3bd35dac0bb1bd7ba72ef1eea860645
4
- data.tar.gz: 5be8fc9e56a4a004549e2ee14a907e170d323daab6909afee3496a7cd8e7015d
3
+ metadata.gz: a43a43d7175e12ad8e187b457104e27f4d273a0fb94f8f83f8f6f39fb2e409fa
4
+ data.tar.gz: f6b84afec6c7eb6f418ae541cc8b907a6043feeec9aebd7788f3807e8871788d
5
5
  SHA512:
6
- metadata.gz: 5f57c749ce315c62befd711d087c24c220057b2c96f75489965ec16f5e7096a9792fcf2e32bb21029e3e6617b45cbb302bf869c4ee27fee5c007962c9313f28b
7
- data.tar.gz: bb2974fe1ec3be058228357629021e5ceae82a65d20f8ab42749ea3f666012b44d27bd56a9aa3fb065217d44ea6a302070558142cdcfa75dc0cbc39afa32f0ba
6
+ metadata.gz: 72d5f7c872fc6aa8b0700458cbce9de3f96ea49b658a74b4921d3a6e1948a77507dac6993de77c371433808f7c30bf95444fc09be4faaf8ef32bfdd9d16e3b7d
7
+ data.tar.gz: 956dd0052b15112ed083ece196ab65642fd5f0ad01eda5f8ea2d9a1863a8718af92df66ee502c94f6099feab3da3522e8c24c668a7d5890982ed875a290bab79
data/README.md CHANGED
@@ -7,6 +7,8 @@
7
7
  ## Features / problems
8
8
 
9
9
  - Manage Mobility translations with a space-efficient dropdown interface in Trestle
10
+ - Supports text fields, text area's and check boxes
11
+ - Integrates with [DeepL Pro](https://www.deepl.com/pro.html) to automatically translate fields
10
12
  - Developed for usage with Mobility's Postgres container back-end
11
13
  - Probably works with other back-ends but has not been tested
12
14
 
@@ -57,6 +59,16 @@ Or specify it per field:
57
59
  mobility_text_field :subtitle, selected: "nl"
58
60
  ```
59
61
 
62
+ ### DeepL translation
63
+
64
+ <img src="/screenshot-deepl.png?raw=true" width="410" height="241" alt="Trestle Mobility DeepL integration screenshot" />
65
+
66
+ Trestle Mobility can automatically populate empty field values with translations from other languages. This functionality is powered by the excellent [deepl-rb](https://github.com/wikiti/deepl-rb) gem. To make use of this, add `deepl-rb` to your Gemfile and specify your DeepL Pro API key in your Trestle initializer:
67
+
68
+ ```ruby
69
+ config.mobility.deepl_api_key = "YOUR-API-KEY"
70
+ ```
71
+
60
72
  ## Installation
61
73
 
62
74
  These instructions assume you have a working Trestle application. To integrate trestle-mobility, first add it to your application's Gemfile:
@@ -1,46 +1,114 @@
1
1
  Trestle.init(function(e, root) {
2
2
  function init() {
3
3
  $(root).find('.mobility').each(function() {
4
- new Mobility(this);
4
+ var instance = new Mobility(this);
5
+ instance.initEvents();
6
+ instance.chooseLanguage();
5
7
  })
6
8
  }
7
9
 
8
- function Mobility (element) {
9
- var element = $(element);
10
- var activeLocale = element.data('active');
11
- var button = element.find('.mobility-active');
12
- var inputFields = element.find('.mobility-field');
13
- var dropdownItems = element.find('.dropdown-item');
10
+ var Mobility = function (element) {
11
+ this.$element = $(element);
12
+ this.$inputFields = this.$element.find('.mobility-field');
13
+ this.$dropdownItems = this.$element.find('.dropdown-item');
14
+ this.$button = this.$element.find('.mobility-active');
15
+ this.$deeplTranslationAction = this.$element.find('.mobility__deepl');
16
+ this.activeLocale = this.$element.data('active');
17
+ };
14
18
 
15
- function toggle (flag) {
16
- $(inputFields).each(function() {
17
- var field = $(this);
18
- var active = field.data('locale') !== activeLocale;
19
+ Mobility.prototype.chooseLanguage = function (flag) {
20
+ var self = this;
19
21
 
20
- field.toggleClass('hidden', active)
21
- })
22
+ this.$inputFields.each(function() {
23
+ var field = $(this);
24
+ var active = field.data('locale') !== self.activeLocale;
25
+ field.toggleClass('hidden', active)
26
+ })
27
+
28
+ this.$dropdownItems.each(function() {
29
+ var item = $(this);
30
+ var active = item.data('locale') === self.activeLocale;
31
+ item.toggleClass('active', active)
32
+ })
33
+
34
+ if (flag) this.$button.text(flag);
35
+ if (this.$deeplTranslationAction) this.presentDeepl();
36
+ }
22
37
 
23
- $(dropdownItems).each(function() {
24
- var field = $(this);
25
- var active = field.data('locale') === activeLocale;
38
+ Mobility.prototype.getActiveField = function () {
39
+ return this.$element.find('.mobility-field[data-locale="' + this.activeLocale +'"]');
40
+ }
26
41
 
27
- field.toggleClass('active', active)
42
+ Mobility.prototype.getFieldByLocale = function (locale) {
43
+ return this.$element.find('.mobility-field[data-locale="' + locale +'"]');
44
+ }
45
+
46
+ Mobility.prototype.presentDeepl = function () {
47
+ var self = this;
48
+ var actionable = !this.getActiveField().val();
49
+
50
+ this.$deeplTranslationAction.toggleClass('mobility__deepl--actionable', actionable)
51
+
52
+ if (actionable) {
53
+ this.$deeplTranslationAction.find('.dropdown-item').each(function() {
54
+ var item = $(this);
55
+ item.toggleClass('disabled', item.data('locale') === self.activeLocale)
28
56
  })
57
+ }
58
+ }
29
59
 
30
- if (flag) {
31
- button.text(flag);
60
+ Mobility.prototype.dismissDeepl = function () {
61
+ this.$deeplTranslationAction.removeClass('mobility__deepl--actionable')
62
+ }
63
+
64
+ Mobility.prototype.deeplTranslate = function (fromLocale) {
65
+ var self = this;
66
+ var path = this.$deeplTranslationAction.data('remote-path');
67
+ var data = {
68
+ translation: {
69
+ text: this.getFieldByLocale(fromLocale).val(),
70
+ from_locale: fromLocale,
71
+ to_locale: this.activeLocale
32
72
  }
33
73
  }
34
74
 
35
- element.find('.dropdown-item').on('click', function () {
36
- var item = $(this);
37
- activeLocale = item.data('locale');
75
+ this.$deeplTranslationAction.addClass('mobility__deepl--active');
38
76
 
39
- toggle(item.text());
77
+ $.post(path, data, function() {
78
+ self.$deeplTranslationAction.removeClass('mobility__deepl--active');
79
+ }).done(function(text) {
80
+ self.getActiveField().val(text);
81
+ self.dismissDeepl();
40
82
  });
41
-
42
- toggle()
43
83
  }
44
84
 
85
+ Mobility.prototype.initEvents = function () {
86
+ var self = this;
87
+
88
+ this.$element.find('.mobility__languages .dropdown-item').on('click', function () {
89
+ var $item = $(this);
90
+ self.activeLocale = $item.data('locale');
91
+ self.chooseLanguage($item.text());
92
+ });
93
+
94
+ this.$element.find('.mobility__deepl-languages .dropdown-item').on('click', function (e) {
95
+ var $item = $(this);
96
+
97
+ if ($item.hasClass('disabled')) {
98
+ e.preventDefault();
99
+ e.stopPropagation();
100
+ return;
101
+ }
102
+
103
+ self.deeplTranslate($item.data('locale'));
104
+ });
105
+
106
+ if (this.$deeplTranslationAction) {
107
+ this.$inputFields.on('change', function() {
108
+ self.presentDeepl()
109
+ })
110
+ }
111
+ };
112
+
45
113
  init();
46
114
  });
@@ -1,3 +1,15 @@
1
+ .mobility {
2
+ .dropdown-item.disabled,
3
+ .dropdown-item.disabled:visited,
4
+ .dropdown-item.disabled:active,
5
+ .dropdown-item.disabled:hover {
6
+ background-color:#d9d9d9 !important;
7
+ color:#aaa !important;
8
+ opacity: 0.7;
9
+ cursor: default;
10
+ }
11
+ }
12
+
1
13
  .mobility-checkbox {
2
14
  display: flex;
3
15
  align-items:center;
@@ -6,3 +18,31 @@
6
18
  .mobility-checkbox__label {
7
19
  margin-left: 8px;
8
20
  }
21
+
22
+
23
+ .mobility__deepl-progress {
24
+ display: none;
25
+ margin-right: 4px;
26
+ }
27
+
28
+ .mobility__deepl {
29
+ display: none;
30
+ margin-top: 4px;
31
+ text-align: right;
32
+
33
+ .progress {
34
+ display: inline-block;
35
+ width: 97px;
36
+ margin-right: 4px;
37
+ }
38
+
39
+ &--actionable {
40
+ display: block;
41
+ }
42
+
43
+ &--active {
44
+ .mobility__deepl-progress {
45
+ display: inline-block;
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,16 @@
1
+ class Trestle::Mobility::TranslationsController < Trestle::ApplicationController
2
+ def translate
3
+ translation = Trestle::Mobility::Translators::DeeplTranslator.new.translate(
4
+ translation_params[:text],
5
+ translation_params[:from_locale],
6
+ translation_params[:to_locale]
7
+ )
8
+
9
+ render plain: translation
10
+ end
11
+
12
+ private
13
+ def translation_params
14
+ params.require(:translation).permit(:text, :from_locale, :to_locale)
15
+ end
16
+ end
@@ -1,10 +1,10 @@
1
- <div class="form-group">
2
- <div class="input-group mobility" data-active="<%= selected %>">
1
+ <div class="form-group mobility" data-active="<%= selected %>">
2
+ <div class="input-group">
3
3
  <div class="input-group-btn">
4
4
  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
5
5
  <span class="mobility-active"><%= "#{EmojiFlag.new(selected)} #{selected.upcase}" %></span> <span class="caret"></span>
6
6
  </button>
7
- <ul class="dropdown-menu">
7
+ <ul class="dropdown-menu mobility__languages">
8
8
  <% locales.each do |locale| %>
9
9
  <li><a href="#<%= "#{field_name}_#{locale}" %>" class="dropdown-item" data-locale="<%= locale %>"><%= "#{EmojiFlag.new(locale)} #{locale.upcase}" %></a></li>
10
10
  <% end %>
@@ -0,0 +1,14 @@
1
+ <div class="mobility__deepl" data-remote-path="<%= trestle.translate_path %>">
2
+ <small class="mobility__deepl-progress">Translating…</small>
3
+
4
+ <div class="btn-group">
5
+ <button class="btn btn-default btn-xs dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
6
+ Translate from <span class="caret"></span>
7
+ </button>
8
+ <ul class="dropdown-menu mobility__deepl-languages">
9
+ <% locales.each do |locale| %>
10
+ <li><a href="javascript:void(0)" class="dropdown-item" data-locale="<%= locale %>"><%= "#{EmojiFlag.new(locale)} #{locale.upcase}" %></a></li>
11
+ <% end %>
12
+ </ul>
13
+ </div>
14
+ </div>
@@ -1,9 +1,9 @@
1
- <div class="form-group">
2
- <div class="input-group mobility" data-active="<%= selected %>">
1
+ <div class="form-group mobility" data-active="<%= selected %>">
2
+ <div class="input-group">
3
3
  <button type="button" class="btn btn-default dropdown-toggle input-group-addon" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
4
4
  <span class="mobility-active"><%= "#{EmojiFlag.new(selected)} #{selected.upcase}" %></span> <span class="caret"></span>
5
5
  </button>
6
- <ul class="dropdown-menu">
6
+ <ul class="dropdown-menu mobility__languages">
7
7
  <% locales.each do |locale| %>
8
8
  <li><a href="#<%= "#{field_name}_#{locale}" %>" class="dropdown-item" data-locale="<%= locale %>"><%= "#{EmojiFlag.new(locale)} #{locale.upcase}" %></a></li>
9
9
  <% end %>
@@ -12,4 +12,7 @@
12
12
  <%= form.raw_text_area "#{field_name}_#{locale}", class: "form-control mobility-field#{locale == selected ? '' : ' hidden'}", placeholder: "#{label} (#{locale.upcase})", rows: rows, data: { locale: locale } %>
13
13
  <% end %>
14
14
  </div>
15
+
16
+ <%= render(partial: "trestle/mobility/deepl_translation_action",
17
+ locals: { locales: locales }) if Trestle.config.mobility.deepl_api_key %>
15
18
  </div>
@@ -1,10 +1,10 @@
1
- <div class="form-group">
2
- <div class="input-group mobility" data-active="<%= selected %>">
1
+ <div class="form-group mobility" data-active="<%= selected %>">
2
+ <div class="input-group">
3
3
  <div class="input-group-btn">
4
4
  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
5
5
  <span class="mobility-active"><%= "#{EmojiFlag.new(selected)} #{selected.upcase}" %></span> <span class="caret"></span>
6
6
  </button>
7
- <ul class="dropdown-menu">
7
+ <ul class="dropdown-menu mobility__languages">
8
8
  <% locales.each do |locale| %>
9
9
  <li><a href="#<%= "#{field_name}_#{locale}" %>" class="dropdown-item" data-locale="<%= locale %>"><%= "#{EmojiFlag.new(locale)} #{locale.upcase}" %></a></li>
10
10
  <% end %>
@@ -14,4 +14,7 @@
14
14
  <%= form.raw_text_field "#{field_name}_#{locale}", class: "form-control mobility-field#{locale == selected ? '' : ' hidden'}", placeholder: "#{label} (#{locale.upcase})", data: { locale: locale } %>
15
15
  <% end %>
16
16
  </div>
17
+
18
+ <%= render(partial: "trestle/mobility/deepl_translation_action",
19
+ locals: { locales: locales }) if Trestle.config.mobility.deepl_api_key %>
17
20
  </div>
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Trestle::Engine.routes.draw do
4
+ controller "trestle/mobility/translations" do
5
+ post "translate"
6
+ end
7
+ end
@@ -4,6 +4,7 @@ module Trestle
4
4
  include Configurable
5
5
 
6
6
  option :selected
7
+ option :deepl_api_key
7
8
  end
8
9
  end
9
10
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trestle::Mobility::Translators
4
+ class DeeplTranslator
5
+ def initialize(*)
6
+ begin
7
+ require "deepl"
8
+ rescue LoadError
9
+ raise StandardError, "Add the 'deepl-rb' gem to your Gemfile"
10
+ end
11
+
12
+ configure_api_key!
13
+ end
14
+
15
+ def translate(text, from, to)
16
+ DeepL.translate(text, from, to)
17
+ end
18
+
19
+ private
20
+ def configure_api_key!
21
+ DeepL.configure do |config|
22
+ config.auth_key = Trestle.config.mobility.deepl_api_key
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  module Trestle
2
2
  module Mobility
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
@@ -3,6 +3,7 @@ require "emoji_flag"
3
3
  require "trestle"
4
4
  require "trestle/mobility/version"
5
5
  require "trestle/mobility/configuration"
6
+ require "trestle/mobility/translators/deepl_translator"
6
7
  require "trestle/mobility/engine" if defined?(Rails)
7
8
 
8
9
  Trestle::Configuration.option :mobility, Trestle::Mobility::Configuration.new
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trestle-mobility
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Venneman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-15 00:00:00.000000000 Z
11
+ date: 2019-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: emoji_flag
@@ -95,19 +95,24 @@ files:
95
95
  - Rakefile
96
96
  - app/assets/javascript/trestle/mobility.js
97
97
  - app/assets/stylesheets/trestle/mobility.scss
98
+ - app/controllers/trestle/mobility/translations_controller.rb
98
99
  - app/views/trestle/mobility/_check_box.html.erb
100
+ - app/views/trestle/mobility/_deepl_translation_action.html.erb
99
101
  - app/views/trestle/mobility/_text_area.html.erb
100
102
  - app/views/trestle/mobility/_text_field.html.erb
101
103
  - bin/console
102
104
  - bin/setup
103
105
  - config/initializers/trestle.rb
106
+ - config/routes.rb
104
107
  - lib/trestle/mobility.rb
105
108
  - lib/trestle/mobility/configuration.rb
106
109
  - lib/trestle/mobility/engine.rb
107
110
  - lib/trestle/mobility/fields/check_box.rb
108
111
  - lib/trestle/mobility/fields/text_area.rb
109
112
  - lib/trestle/mobility/fields/text_field.rb
113
+ - lib/trestle/mobility/translators/deepl_translator.rb
110
114
  - lib/trestle/mobility/version.rb
115
+ - screenshot-deepl.png
111
116
  - screenshot.png
112
117
  - trestle-mobility.gemspec
113
118
  homepage: https://github.com/richardvenneman/trestle-mobility