2020-12-19 23:40:37 +01:00
<!DOCTYPE html>
2023-01-05 20:36:50 +01:00
< html lang = "{{ current_locale }}" >
2020-12-19 23:40:37 +01:00
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
2023-01-05 20:36:50 +01:00
{% for al in alternate_locales %}< link rel = "alternate" hreflang = "{{ al.lang }}" href = "{{ al.link }}" / >
{% endfor %}
2023-03-11 20:01:39 +01:00
{% if web_version %}
2023-10-19 19:20:23 +02:00
< title > LibreTranslate - {{ _h("Free and Open Source Machine Translation API") }} 🌐< / title >
2023-01-04 23:54:07 +01:00
< meta name = "description" content = "{{ _h('Free and Open Source Machine Translation API. Self-hosted, offline capable and easy to setup. Run your own API server in just a few minutes.') }}" >
< meta name = "keywords" content = "{{ _h('translation') }},{{ _h('api') }}" >
2023-03-11 20:01:39 +01:00
{% endif %}
2023-07-04 20:38:35 +02:00
2023-07-29 20:42:20 +02:00
< link rel = "shortcut icon" href = "{{ url_for('static', filename='favicon.ico') }}" >
2022-08-06 20:16:01 +02:00
< link rel = "preload" href = "{{ url_for('static', filename='icon.svg') }}" as = "image" / >
< link rel = "preload" href = "{{ url_for('static', filename='js/vue@2.js') }}" as = "script" >
< link rel = "preload" href = "{{ url_for('static', filename='js/materialize.min.js') }}" as = "script" >
< link rel = "preload" href = "{{ url_for('static', filename='js/prism.min.js') }}" as = "script" >
2023-01-06 17:50:51 +01:00
< link rel = "preload" href = "js/app.js?v={{ version }}" as = "script" >
2022-08-06 20:16:01 +02:00
< link rel = "preload" href = "{{ url_for('static', filename='css/materialize.min.css') }}" as = "style" / >
< link rel = "preload" href = "{{ url_for('static', filename='css/material-icons.css') }}" as = "style" / >
< link rel = "preload" href = "{{ url_for('static', filename='css/prism.min.css') }}" as = "style" / >
< link rel = "preload" href = "{{ url_for('static', filename='css/main.css') }}?v={{ version }}" as = "style" / >
2023-07-04 20:38:35 +02:00
2023-01-05 19:12:35 +01:00
< meta property = "og:title" content = "LibreTranslate - {{ _h('Free and Open Source Machine Translation API') }}" / >
2022-08-06 20:16:01 +02:00
< meta property = "og:type" content = "website" / >
< meta property = "og:url" content = "https://libretranslate.com" / >
< meta property = "og:image" content = "https://user-images.githubusercontent.com/1951843/102724116-32a6df00-42db-11eb-8cc0-129ab39cdfb5.png" / >
2023-01-04 23:54:07 +01:00
< meta property = "og:description" name = "description" class = "swiftype" content = "{{ _h('Free and Open Source Machine Translation API. Self-hosted, offline capable and easy to setup. Run your own API server in just a few minutes.') }}" / >
2020-12-20 20:03:53 +01:00
2021-05-16 16:42:58 +02:00
< script src = "{{ url_for('static', filename='js/vue@2.js') }}" > < / script >
2022-08-06 20:16:01 +02:00
2020-12-20 20:03:53 +01:00
{% if gaId %}
<!-- Global site tag (gtag.js) - Google Analytics -->
< script async src = "https://www.googletagmanager.com/gtag/js?id={{ gaId }}" > < / script >
< script >
2022-08-06 20:16:01 +02:00
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ gaId }}');
2020-12-20 20:03:53 +01:00
< / script >
2021-06-02 22:54:06 +02:00
{% endif %}
2022-08-06 20:16:01 +02:00
<!-- Compiled and minified CSS -->
< link rel = "stylesheet" href = "{{ url_for('static', filename='css/materialize.min.css') }}" >
< link rel = "stylesheet" href = "{{ url_for('static', filename='css/material-icons.css') }}" / >
< link rel = "stylesheet" href = "{{ url_for('static', filename='css/prism.min.css') }}" / >
< link rel = "stylesheet" href = "{{ url_for('static', filename='css/main.css') }}?v={{ version }}" / >
2020-12-19 23:40:37 +01:00
< / head >
2021-06-02 22:54:06 +02:00
2023-07-04 20:38:35 +02:00
< body >
2021-06-02 22:54:06 +02:00
< header >
2023-07-04 20:38:35 +02:00
< nav role = "navigation" >
2021-06-02 22:54:06 +02:00
< div class = "nav-wrapper container" >
2022-01-17 20:09:20 +01:00
< button data-target = "nav-mobile" class = "sidenav-trigger" > < i class = "material-icons" > menu< / i > < / button >
2023-07-04 20:38:35 +02:00
< a id = "logo-container" href = "/" class = "brand-logo noline" >
2023-01-06 18:25:42 +01:00
< img src = "{{ url_for('static', filename='icon.svg') }}" alt = "" class = "logo" >
2023-01-05 19:12:35 +01:00
< span > LibreTranslate< / span >
2021-06-02 22:54:06 +02:00
< / a >
2023-01-06 16:27:39 +01:00
< ul id = "nav" class = "right hide-on-med-and-down top-nav position-relative" >
2023-01-05 20:54:56 +01:00
{% set menulinks %}
< li > < a href = "{{ swagger_url }}" > {{ _h("API Docs") }}< / a > < / li >
{% if get_api_key_link %}
< li > < a href = "{{ get_api_key_link }}" > {{ _h("Get API Key") }}< / a > < / li >
{% endif %}
< li > < a href = "https://github.com/LibreTranslate/LibreTranslate" rel = "noopener noreferrer" > {{ _h("GitHub") }}< / a > < / li >
{% if api_keys %}
2023-01-06 19:07:07 +01:00
< li > < a class = "noline" href = "javascript:setApiKey()" title = "{{ _h('Set API Key') }}" aria-label = "{{ _h('Set API Key') }}" > < i class = "material-icons" > vpn_key< / i > < / a > < / li >
2023-01-05 20:54:56 +01:00
{% endif %}
2023-01-06 19:37:34 +01:00
< li class = "change-language" > < a class = "noline" href = "javascript:void(0)" title = "{{ _h('Change language') }}" > < i class = "material-icons" > language< / i > < / a >
2023-01-05 22:06:19 +01:00
< / li >
2023-07-04 20:38:35 +02:00
< li class = "locale-panel" >
2023-01-06 17:50:51 +01:00
< select id = "locales" onchange = "changeLocale(this)" >
2023-01-06 16:27:39 +01:00
{% for l in available_locales %}< option value = "{{ l['code'] }}" { { ' selected ' if current_locale = = l [ ' code ' ] else ' ' } } > {{ l['name'] }}< / option > {% endfor %}
2023-01-05 22:06:19 +01:00
< / select >
2023-01-06 21:03:26 +01:00
< a href = "https://hosted.weblate.org/projects/libretranslate/app/{{ current_locale }}/" > {{ _h("Edit") }}< i class = "material-icons" > create< / i > < / a >
2023-01-05 22:06:19 +01:00
< / li >
2023-10-09 21:15:39 +02:00
< li class = "change-theme" > < a class = "noline" href = "javascript:toggleColorScheme()" title = "{{ _h('Toggle dark/light mode') }}" > < i class = "material-icons" > lightbulb_outline< / i > < / a >
< / li >
2023-01-05 20:54:56 +01:00
{% endset %}
{{ menulinks }}
2021-06-02 22:54:06 +02:00
< / ul >
2023-07-04 20:38:35 +02:00
< ul id = "nav-mobile" class = "sidenav" >
2023-01-05 20:54:56 +01:00
{{ menulinks }}
2021-06-02 22:54:06 +02:00
< / ul >
2023-01-06 19:37:34 +01:00
< script >
var localeLinks = {
{% for al in alternate_locales %}"{{ al.lang }}": "{{ al.link }}"{% if not loop.last %},{% endif %}
{% endfor %}
};
2023-07-04 20:38:35 +02:00
2023-01-06 19:37:34 +01:00
function changeLocale(slt){
var lang = slt.value;
if (localeLinks[lang]) location.href = localeLinks[lang];
else location.href = '?lang=' + slt.value;
}
2023-07-04 20:38:35 +02:00
2023-01-06 19:37:34 +01:00
var btnChangeLangs = document.getElementsByClassName("change-language");
var localePanels = document.getElementsByClassName("locale-panel");
2023-01-10 16:02:12 +01:00
2023-01-06 19:37:34 +01:00
for (var i = 0; i < btnChangeLangs.length ; i + + ) {
(function(btn){
btn.addEventListener('click', function(e){
e.stopPropagation();
btn.classList.toggle('clicked');
});
})(btnChangeLangs[i]);
}
for (var i = 0; i < localePanels.length ; i + + ) {
localePanels[i].addEventListener('click', function(e){
e.stopPropagation();
});
}
document.addEventListener('click', function(){
for (var i = 0; i < btnChangeLangs.length ; i + + ) {
btnChangeLangs[i].classList.remove('clicked');
}
});
< / script >
2021-06-02 22:54:06 +02:00
< / div >
< / nav >
< / header >
< main id = "app" >
< div class = "section no-pad-bot center" v-if = "loading" >
< div class = "container" >
< div class = "row" >
< div class = "preloader-wrapper active" >
< div class = "spinner-layer spinner-blue-only" >
< div class = "circle-clipper left" >
< div class = "circle" > < / div >
< / div > < div class = "gap-patch" >
< div class = "circle" > < / div >
< / div > < div class = "circle-clipper right" >
< div class = "circle" > < / div >
< / div >
< / div >
< / div >
2020-12-20 17:55:56 +01:00
< / div >
< / div >
< / div >
2021-06-02 22:54:06 +02:00
2023-10-09 20:36:20 +02:00
< div v-else-if = "error" class = "component" >
2021-06-02 22:54:06 +02:00
< div class = "section no-pad-bot" >
< div class = "container" >
< div class = "row" >
2023-10-09 20:36:20 +02:00
< div class = "col s12 m12" >
2021-06-02 22:54:06 +02:00
< div class = "card horizontal" >
< div class = "card-stacked" >
< div class = "card-content" >
< i class = "material-icons" > warning< / i > < p > [[ error ]]< / p >
< / div >
< div class = "card-action" >
2023-01-04 23:54:07 +01:00
< a href = "#" @ click = "dismissError" > {{ _h("Dismiss") }}< / a >
2021-06-02 22:54:06 +02:00
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
2020-12-20 19:45:34 +01:00
< / div >
< / div >
2021-06-02 22:54:06 +02:00
2023-10-09 20:36:20 +02:00
< div v-else class = "component" >
2021-06-02 22:54:06 +02:00
< div class = "section no-pad-bot" >
< div class = "container" >
< div class = "row" >
2023-01-04 23:54:07 +01:00
< h3 class = "header center" > {{ _h("Translation API") }}< / h3 >
2022-08-06 20:16:01 +02:00
< div id = "translation-type-btns" class = "s12 center" v-if = "filesTranslation === true" >
< button type = "button" class = "btn btn-switch-type" @ click = "switchType('text')" :class = "{'active': translationType === 'text'}" >
2023-01-06 18:25:42 +01:00
< i aria-hidden = "true" class = "material-icons" > title< / i >
2023-01-04 23:54:07 +01:00
< span class = "btn-text" > {{ _h("Translate Text") }}< / span >
2022-08-06 20:16:01 +02:00
< / button >
< button type = "button" class = "btn btn-switch-type" @ click = "switchType('files')" :class = "{'active': translationType === 'files'}" >
2023-01-06 18:25:42 +01:00
< i aria-hidden = "true" class = "material-icons" > description< / i >
2023-01-04 23:54:07 +01:00
< span class = "btn-text" > {{ _h("Translate Files") }}< / span >
2022-08-06 20:16:01 +02:00
< / button >
< / div >
2022-01-04 20:20:02 +01:00
< form id = "translation-form" class = "col s12" >
2021-06-02 22:54:06 +02:00
< div class = "row mb-0" >
< div class = "col s6 language-select" >
2023-01-06 19:07:07 +01:00
< span id = "sourceLangLabel" > {{ _h("Translate from") }}< / span >
2023-01-04 23:54:07 +01:00
< span v-if = "detectedLangText !== ''" > [[ detectedLangText ]]< / span >
2023-01-06 18:25:42 +01:00
< select aria-labelledby = "sourceLangLabel" class = "browser-default" v-model = "sourceLang" ref = "sourceLangDropdown" @ change = "handleInput" >
2021-06-02 22:54:06 +02:00
< template v-for = "option in langs" >
< option :value = "option.code" > [[ option.name ]]< / option >
< / template >
< / select >
< / div >
< div class = "col s6 language-select" >
2023-01-06 19:07:07 +01:00
< a href = "javascript:void(0)" @ click = "swapLangs" class = "btn-switch-language" aria-label = "{{ _h('Swap source and target languages') }}" >
2021-06-02 22:54:06 +02:00
< i class = "material-icons" > swap_horiz< / i >
2021-06-12 17:28:35 +02:00
< / a >
2023-01-06 19:07:07 +01:00
< span id = "targetLangLabel" > {{ _h("Translate into") }}< / span >
2023-01-06 18:25:42 +01:00
< select aria-labelledby = "targetLangLabel" class = "browser-default" v-model = "targetLang" ref = "targetLangDropdown" @ change = "handleInput" >
2022-12-10 06:21:38 +01:00
< template v-for = "option in targetLangs" >
2021-06-02 22:54:06 +02:00
< option v-if = "option.code !== 'auto'" :value = "option.code" > [[ option.name ]]< / option >
< / template >
2021-10-08 19:02:30 +02:00
< / select >
2020-12-20 19:45:34 +01:00
< / div >
2020-12-20 17:55:56 +01:00
< / div >
2021-06-02 22:54:06 +02:00
2021-10-24 13:15:36 +02:00
< div class = "row" v-if = "translationType === 'text'" >
2023-10-27 16:02:56 +02:00
< div class = "input-field textarea-container col s12 m6" >
2021-06-11 20:30:09 +02:00
< label for = "textarea1" class = "sr-only" >
2023-01-04 23:54:07 +01:00
{{ _h("Text to translate") }}
2021-10-08 19:02:30 +02:00
< / label >
2023-07-08 04:34:53 +02:00
< textarea id = "textarea1" :maxLength = "charactersLimit" v-model = "inputText" @ input = "handleInput" ref = "inputTextarea" dir = "auto" > < / textarea >
2023-01-06 19:07:07 +01:00
< button class = "btn-delete-text" title = "{{ _h('Delete text') }}" aria-label = "{{ _h('Delete text') }}" aria-label = "Delete text" @ click = "deleteText" >
2021-06-02 22:54:06 +02:00
< i class = "material-icons" > close< / i >
2021-10-08 19:02:30 +02:00
< / button >
2021-06-02 22:54:06 +02:00
< div class = "characters-limit-container" v-if = "charactersLimit !== -1" >
< label > [[ inputText.length ]] / [[ charactersLimit ]]< / label >
< / div >
< / div >
2023-10-27 16:02:56 +02:00
< div class = "input-field textarea-container col s12 m6" >
2021-06-11 20:30:09 +02:00
< label for = "textarea2" class = "sr-only" >
2023-01-04 23:54:07 +01:00
{{ _h("Translated text") }}
2021-10-08 19:02:30 +02:00
< / label >
2021-10-09 15:45:58 +02:00
< textarea id = "textarea2" v-model = "translatedText" ref = "translatedTextarea" dir = "auto" v-bind:readonly = "suggestions && !isSuggesting" > < / textarea >
2023-01-04 23:54:07 +01:00
< div class = "actions" >
2023-01-06 19:07:07 +01:00
< button v-if = "suggestions && !loadingTranslation && inputText.length && !isSuggesting" class = "btn-action" @ click = "suggestTranslation" aria-label = "{{ _h('Suggest translation') }}" >
2023-01-04 23:54:07 +01:00
< i class = "material-icons" > edit< / i >
< / button >
< button v-if = "suggestions && !loadingTranslation && inputText.length && isSuggesting" class = "btn-action btn-blue" @ click = "closeSuggestTranslation" >
< span > {{ _h("Cancel") }}< / span >
< / button >
< button v-if = "suggestions && !loadingTranslation && inputText.length && isSuggesting" :disabled = "!canSendSuggestion" class = "btn-action btn-blue" @ click = "sendSuggestion" >
< span > {{ _h("Send") }}< / span >
< / button >
< button v-if = "!isSuggesting" class = "btn-action btn-copy-translated" @ click = "copyText" >
2023-01-06 19:07:07 +01:00
< span > [[ copyTextLabel ]]< / span > < i class = "material-icons" aria-hidden = "true" > content_copy< / i >
2023-01-04 23:54:07 +01:00
< / button >
< / div >
2021-10-08 19:02:30 +02:00
< div class = "position-relative" >
2021-06-11 20:30:09 +02:00
< div class = "progress translate" v-if = "loadingTranslation" >
< div class = "indeterminate" > < / div >
2021-10-08 19:02:30 +02:00
< / div >
2021-06-02 22:54:06 +02:00
< / div >
< / div >
2021-01-18 16:06:43 +01:00
< / div >
2023-01-04 23:54:07 +01:00
< div class = "row" v-if = "translationType === 'files'" >
< div class = "file-dropzone" >
< div v-if = "inputFile === false" class = "dropzone-content" >
< span > {{ _h("Supported file formats:") }} [[ supportedFilesFormatFormatted ]]< / span >
< form action = "#" >
< div class = "file-field input-field" >
< div class = "btn" >
2023-01-06 19:07:07 +01:00
< span id = "fileLabel" > {{ _h("File") }}< / span >
< input aria-labelledby = "fileLabel" type = "file" :accept = "supportedFilesFormatFormatted" @ change = "handleInputFile" ref = "fileInputRef" >
2023-01-04 23:54:07 +01:00
< / div >
< div class = "file-path-wrapper hidden" >
< input class = "file-path validate" type = "text" >
< / div >
< / div >
< / form >
< / div >
< div v-if = "inputFile !== false" class = "dropzone-content" >
< div class = "card" >
< div class = "card-content" >
< div class = "row mb-0" >
< div class = "col s12" >
[[ inputFile.name ]]
2023-01-06 19:07:07 +01:00
< button v-if = "loadingFileTranslation !== true" @ click = "removeFile" class = "btn-flat" aria-label = "{{ _h('Remove file') }}" >
2023-01-04 23:54:07 +01:00
< i class = "material-icons" > close< / i >
< / button >
2022-08-06 20:16:01 +02:00
< / div >
2023-01-04 23:54:07 +01:00
< / div >
< / div >
< / div >
< button @ click = "translateFile" v-if = "translatedFileUrl === false && loadingFileTranslation === false" class = "btn" > {{ _h("Translate") }}< / button >
< a v-if = "translatedFileUrl !== false" :href = "translatedFileUrl" class = "btn" > {{ _h("Download") }}< / a >
< div class = "progress" v-if = "loadingFileTranslation" >
< div class = "indeterminate" > < / div >
< / div >
< / div >
< / div >
< / div >
2020-12-20 17:55:56 +01:00
< / form >
2021-06-02 22:54:06 +02:00
< / div >
< / div >
< / div >
2021-10-26 22:04:50 +02:00
< div class = "section no-pad-bot" v-if = "translationType !== 'files'" >
2021-06-02 22:54:06 +02:00
< div class = "container" >
< div class = "row center" >
< div class = "col s12 m12" >
2023-07-09 13:25:03 +02:00
< div class = "row center code-row-wrapper" >
< div class = "col s12 m12 l6 left-align code-box" >
2023-01-04 23:54:07 +01:00
< p class = "mb-0" > {{ _h("Request") }}< / p >
2021-06-13 19:11:58 +02:00
< pre class = "code mt-0" > < code class = "language-javascript" v-html = "$options.filters.highlight(requestCode)" >
2021-06-02 22:54:06 +02:00
< / code > < / pre >
2020-12-20 17:55:56 +01:00
< / div >
2023-07-09 13:25:03 +02:00
< div class = "col s12 m12 l6 left-align code-box" >
2023-01-04 23:54:07 +01:00
< p class = "mb-0" > {{ _h("Response") }}< / p >
2021-06-13 19:11:58 +02:00
< pre class = "code mt-0" > < code class = "language-javascript" v-html = "$options.filters.highlight(output)" >
2021-06-02 22:54:06 +02:00
< / code > < / pre >
2020-12-20 17:55:56 +01:00
< / div >
< / div >
2021-06-02 22:54:06 +02:00
< / div >
2020-12-20 17:55:56 +01:00
< / div >
< / div >
2021-06-02 22:54:06 +02:00
< / div >
2022-08-06 20:16:01 +02:00
{% if web_version %}
2021-06-11 20:05:59 +02:00
< div class = "section no-pad-bot" >
2021-06-02 22:54:06 +02:00
< div class = "container" >
< div class = "row center" >
< div class = "col s12 m12" >
2023-01-04 23:54:07 +01:00
< h3 class = "header" > {{ _h("Open Source Machine Translation API") }}< / h3 >
< h4 class = "header" > {{ _h("Self-Hosted. Offline Capable. Easy to Setup.") }}< / h4 >
2022-08-06 20:16:01 +02:00
< div id = "download-btn-wrapper" >
< a id = "download-btn" class = "waves-effect waves-light btn btn-large teal darken-2" href = "https://github.com/LibreTranslate/LibreTranslate" rel = "noopener noreferrer" >
2023-01-06 18:25:42 +01:00
< i aria-hidden = "true" class = "material-icons" > cloud_download< / i >
2023-01-04 23:54:07 +01:00
< span class = "btn-text" > {{ _h("Download") }}< / span >
2022-08-06 20:16:01 +02:00
< / a >
< / div >
2021-06-02 22:54:06 +02:00
< / div >
< / div >
< / div >
< / div >
2022-08-06 20:16:01 +02:00
{% endif %}
2020-12-21 05:47:24 +01:00
< / div >
2021-06-02 22:54:06 +02:00
< / main >
2023-07-04 20:38:35 +02:00
< footer class = "page-footer" >
2020-12-20 17:55:56 +01:00
< div class = "container" >
2021-06-02 22:54:06 +02:00
< div class = "row" >
< div class = "col l12 s12" >
2023-01-04 23:54:07 +01:00
< h5 class = "white-text" > {{ _h("LibreTranslate") }}< / h5 >
< p class = "grey-text text-lighten-4" > {{ _h("Free and Open Source Machine Translation API") }}< / p >
2023-01-05 19:12:35 +01:00
< p > {{ _h("License:") }} < a class = "grey-text text-lighten-4" href = "https://www.gnu.org/licenses/agpl-3.0.en.html" rel = "noopener noreferrer" > AGPLv3< / a > < / p >
2021-06-02 22:54:06 +02:00
< / div >
< / div >
2020-12-20 17:55:56 +01:00
< / div >
2021-06-02 22:54:06 +02:00
< div class = "footer-copyright center" >
2022-01-17 20:09:20 +01:00
< p class = "white-text" >
2023-01-05 19:12:35 +01:00
{{ _h("Made with %(heart)s by %(contributors)s and powered by %(engine)s", heart='❤', contributors='< a class = "white-text" href = "https://github.com/LibreTranslate/LibreTranslate/graphs/contributors" rel = "noopener noreferrer" > %s< / a > ' % _h("%(libretranslate)s Contributors", libretranslate="LibreTranslate"), engine='< a class = "white-text text-lighten-3" href = "https://github.com/argosopentech/argos-translate/" rel = "noopener noreferrer" > Argos Translate< / a > ') }}
2021-06-02 22:54:06 +02:00
< / p >
< / div >
< / footer >
2021-01-10 09:07:56 +01:00
2021-06-02 22:54:06 +02:00
< script src = "{{ url_for('static', filename='js/materialize.min.js') }}" > < / script >
< script >
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109& dn=agpl-3.0.txt AGPL-3.0
window.Prism = window.Prism || {};
window.Prism.manual = true;
// @license-end
< / script >
2023-01-04 23:54:07 +01:00
< script src = "{{ url_for('static', filename='js/prism.min.js') }}" > < / script >
2023-01-06 17:50:51 +01:00
< script src = "js/app.js?v={{ version }}" > < / script >
2020-12-19 23:40:37 +01:00
< / body >
2021-01-17 17:58:22 +01:00
< / html >