Custom GTT Shortcuts (Merge, Apply to All, etc.) Through Bookmarklets
/*
Usage: Drag to Bookmark Bar, click once when you open a project in GTT,
and use predefined shortcuts until you close or reload the page.
Implemented by Dan Biktashev (katzurki@gmail.com) v1.5 30 Jan 2019
Currently defined are:
Alt+A Apply to All
Alt+S Merge Down
Alt+Z Insert Current Property Name (only for Booking.com projects)
Ctrl+Down, Replace double and trailing spaces
Ctrl/Cmd+J (use Alt+Down if you need to retain them on purpose)
As an added bonus, it prettifies GTT layout making it easier on the eyes.
*/
var iframe = document.querySelectorAll('iframe.gtc-document-frame.jfk-scrollbar')[1]
var iframe2 = document.querySelectorAll('iframe.gtc-document-frame.jfk-scrollbar')[0]
var base = iframe.contentWindow.document.querySelector('#transEditor')
var _document = iframe.contentWindow.document
var __document = iframe2.contentWindow.document
var el = _document.querySelector('#transEditor')
const MERGE_SELECTOR = '#gtc-merge-parent > div.modal-dialog.gtc-merge > div.modal-dialog-buttons > button.goog-buttonset-default'
/* First, let's get fancy with our layout in Target/Source columns */
const H1_CSS = 'h1.notranslate { font-size: 1em; color: MidnightBlue; transition: all 1s; text-decoration:underline;}'
const HR_CSS = 'hr{border:0;height:1px;position:relative;margin:.5em 0}|hr:before{top:-.5em;height:1em}|hr:after{height:.5em;top:1px}|hr:after,hr:before{content:\'\';display:inline;position:absolute;width:100%}|hr,hr:before{bq,0,0,.1) 0,rgba(0,0,0,0) 75%);background:-o-radial-gradient(center,ellipse cover,rgba(0,0,0,.1) 0,rgba(0,0,0,0) 75%);background:-ms-radial-gradient(center,ellipse cover,rgba(0,0,0,.1) 0,rgba(0,0,0,0) 75%);background:radial-gradient(ellipse at center,rgba(0,0,0,.1) 0,rgba(0,0,0,0) 75%)}|body,hr:after{background:#f4f4f4}'
function insertCSS(doc, rules) {
for (var rule of rules.split('|')) {
var h = document.createElement('style'),styleSheet
doc.head.appendChild(h)
styleSheet = h.sheet
styleSheet.insertRule(rule)
}
}
insertCSS(_document, H1_CSS)
insertCSS(__document, H1_CSS)
insertCSS(_document, HR_CSS)
insertCSS(__document, HR_CSS)
/* Attaching to el, instead of document, to get the highest priority,
otherwise GTT does its own stuff first (which breaks our Ctrl+Down, for example) */
el.onkeydown = function(event) {
var current_name = _document.querySelector('#current-hotel-name')
var el = _document.querySelector('#transEditor > div')
if (current_name) { current_name.remove() }
/* keyCode 40 = ArrowDown, keyCode 74 = j */
if ((event.ctrlKey || event.metaKey) && (event.keyCode == 40 || event.keyCode == 74)) { eliminateDoubleSpaces(el) }
if (event.altKey) { current_name = hotelName() }
/* keyCode 90 = z */
if (event.altKey && event.keyCode == 90) {
event.preventDefault()
var sel = iframe.contentWindow.getSelection()
var offset = sel.anchorOffset
var after_paste_offset = current_name.length
var text_before = el.innerText.substring(0, offset)
var text_after = el.innerText.substring(offset)
el.innerText = text_before + current_name + text_after
var range = _document.createRange()
range.setStart(el.childNodes[0], offset + after_paste_offset)
range.collapse(true)
sel.removeAllRanges()
sel.addRange(range)
el.focus()
}
/* keyCode 65 = a */
if (event.altKey && event.keyCode == 65) {
event.preventDefault()
applyToAll()
}
/* keyCode 83 = s */
if (event.altKey && event.keyCode == 83) {
event.preventDefault()
mergeDown()
}
}
_document.onkeyup = function() { fadeOut() }
function eliminateDoubleSpaces(el) {
el.innerText = el.innerText.replace(/ +(?= )/g, '').trim()
}
/* It's easiest to imitate a click and let GTT figure out the Merge Segment logic */
var mergeDown = (function() { document.querySelector(MERGE_SELECTOR).click() })
/* Ditto, but the clicks are more complex, and we have to bubble up from the iframe */
var applyToAll = (function() {
const a = f => new MouseEvent(f, { bubbles: !0 }),
b = f => () => document.querySelector(f).click(),
c = f => `#fnrDialogParent .gtc-rep-modal-dialog .modal-dialog-buttons button[name=${f}]`,
d = {
imgSel: (f => () => {
const g = a('mousedown'),
h = a('mouseup'),
i = document.querySelector(f)
i.dispatchEvent(g), i.dispatchEvent(h)
})('img.jfk-button-img.gtc-img-rep'),
applyToAll: b(c('repDialogReplaceAll')),
exit: b(c('repDialogExit'))
}
d.imgSel(), d.applyToAll(), d.exit()
})
function hotelName() {
var fresh_name = base.parentNode.parentElement.parentElement.parentElement.parentElement.querySelector('a').textContent
if (!_document.querySelector('#current-hotel-name')) {
var hotel_name = _document.createElement('span')
hotel_name.id = 'current-hotel-name'
hotel_name.style.color = 'green'
hotel_name.textContent = ' ' + fresh_name
_document.querySelector('.gtc-editor-info').insertAdjacentElement('beforeEnd', hotel_name)
}
/* In the unlikely but possible case our focus has shifted, let's try for both cases */
return (typeof fresh_name == 'undefined' ? document.querySelector('#current-hotel-name') : fresh_name)
}
function fadeOut() {
var current_name = _document.querySelector('#current-hotel-name')
if (current_name) { fade('out', 500, current_name, true) }
}
/* Gratefully stolen from somewhere on Stackoverflow */
function fade(type, ms, el, remove = false) {
var isIn = type === 'in',
opacity = isIn ? 0 : 1,
interval = 50,
duration = ms,
gap = interval / duration
if (isIn) {
el.style.display = 'inline'
el.style.opacity = opacity
}
function func() {
opacity = isIn ? opacity + gap : opacity - gap
el.style.opacity = opacity
if (opacity <= 0) { remove ? el.remove() : el.style.display = 'none' }
if (opacity <= 0 || opacity >= 1) window.clearInterval(fading)
}
var fading = window.setInterval(func, interval)
}
Navigation |
|
Ctrl+Home |
Select first unit |
Ctrl+End |
Select last unit |
Ctrl+K |
Select previous unit |
Ctrl+J |
Select next unit |
Alt+K |
Select previous untranslated unit |
Alt+J |
Select next untranslated unit |
Alt+L |
Select next invalid unit |
Editing |
|
Ctrl+F |
Find and replace |
Ctrl+S |
Save |
Ctrl+Z |
Undo |
Ctrl+Y |
Redo |
Ctrl+M |
Add comment |
Translation |
|
Ctrl+Shift+K |
Open/close toolkit |
Ctrl+Shift+S |
Replace translation with source |
Ctrl+Shift+M |
Replace translation with machine translation |
Ctrl+Shift+L |
Replace translation with translation memory |
Ctrl+Shift+A |
Start automatic translation search |
Ctrl+Shift+C |
Start custom translation search for highlighted text |
Ctrl+Shift+I |
Automatically insert placeholders |
Ctrl+Shift+U |
Clear all placeholders |
Ctrl+Shift+Space |
Show placeholder menu |