{# /** * Translate plugin for Craft CMS 5.x * * Panel shown in the sidebar of an element's edit screen. This is how an * author discovers that the plugin can translate what they're looking at, so * it explains itself even when it can't do anything yet. * * Uses Craft's own `.meta > .field` markup so the rows line up with Slug, * Author and Post Date above rather than inventing a second layout. * * @link https://enupal.com * @copyright Copyright (c) 2018 Enupal */ #} {% import "_includes/forms" as forms %} {% if currentUser.can('enupal-translate:translateContent') %} {% set ready = craft.enupaltranslate.isContentTranslationReady() %} {% set providerName = craft.enupaltranslate.getContentProviderName() %} {% set providers = ready ? craft.enupaltranslate.getEnabledProviders() : {} %} {% set defaultProvider = craft.enupaltranslate.getContentProviderHandle() %} {% set targets = ready ? craft.enupaltranslate.getTranslationTargets(element) : [] %} {# Translation always reads the saved entry, never the editor's current state, so say so whenever the two can differ. A provisional draft only exists once the author has changed something, which makes it a reliable signal that there are unsaved edits. #} {% set hasUnsavedChanges = element.isProvisionalDraft %} {% set isRealDraft = element.getIsDraft() and not element.isProvisionalDraft %} {% set sourceNote = null %} {% if hasUnsavedChanges %} {% set sourceNote = "You have unsaved changes. Translating uses the last saved version of this entry — save first if you want your changes included."|t('enupal-translate') %} {% elseif isRealDraft or element.getIsRevision() %} {% set sourceNote = "Translating uses the saved version of this entry, not this draft."|t('enupal-translate') %} {% endif %}
{% js %} (function () { var panel = document.querySelector('.enupal-translate-panel'); if (!panel) { return; } var button = document.getElementById('enupal-translate-submit'); var spinner = document.getElementById('enupal-translate-spinner'); var result = document.getElementById('enupal-translate-result'); var resultText = document.getElementById('enupal-translate-result-text'); function busy(isBusy) { button.disabled = isBusy; button.classList.toggle('disabled', isBusy); spinner.classList.toggle('hidden', !isBusy); } function report(message, url, label, isError) { resultText.className = isError ? 'error' : ''; resultText.textContent = message + ' '; if (url) { var link = document.createElement('a'); link.href = url; link.textContent = label; resultText.appendChild(link); } result.classList.remove('hidden'); } button.addEventListener('click', function () { var target = document.getElementById('enupal-translate-target'); var provider = document.getElementById('enupal-translate-provider'); busy(true); result.classList.add('hidden'); Craft.sendActionRequest('POST', 'enupal-translate/content/translate', { data: { elementId: panel.dataset.elementId, elementType: panel.dataset.elementType, sourceSiteId: panel.dataset.sourceSiteId, targetSiteId: target.value, providerHandle: provider ? provider.value : '' } }).then(function (response) { var data = (response && response.data) || {}; if (data.success) { Craft.cp.displayNotice(data.message); report(data.message, data.targetUrl, data.targetLabel, false); } else { Craft.cp.displayError(data.message || {{ "Translation failed."|t('enupal-translate')|json_encode|raw }}); report(data.message || '', null, null, true); } }).catch(function (error) { var data = (error && error.response && error.response.data) || {}; var message = data.message || data.error || {{ "Translation failed. Check the logs."|t('enupal-translate')|json_encode|raw }}; Craft.cp.displayError(message); report(message, null, null, true); }).finally(function () { busy(false); }); }); })(); {% endjs %} {% css %} .enupal-translate-legend { display: flex; align-items: center; gap: 5px; } .enupal-translate-legend svg { width: 14px; height: 14px; flex: 0 0 auto; } /* The icon ships with Craft's text colour baked into each shape, so recolour only those and leave the transparent ones alone. */ .enupal-translate-legend svg [style*="3f4d5a"] { fill: currentColor !important; } .enupal-translate-actions { flex: 1 1 auto; justify-content: space-between; gap: 8px; } .enupal-translate-meta { display: flex; align-items: center; gap: 10px; font-size: 12px; white-space: nowrap; } .enupal-translate-link { display: inline-flex; align-items: center; gap: 4px; } .enupal-translate-link svg { width: 12px; height: 12px; flex: 0 0 auto; } #enupal-translate-result-text.error { color: var(--error-color, #cf1124); } #enupal-translate-spinner { margin-inline-start: 6px; } {% endcss %} {% endif %}