Use independent translation for WebUI

This commit is contained in:
Vladimir Golovnev (Glassez) 2018-06-07 20:07:28 +03:00
parent becb002d87
commit c1a4ef1377
No known key found for this signature in database
GPG key ID: 52A2C7DEE2DFA6F7
60 changed files with 92461 additions and 178 deletions

1
.gitignore vendored
View file

@ -22,6 +22,7 @@ qrc_*.cpp
ui_*.h
*.moc
src/lang/qbittorrent_*.qm
src/webui/www/translations/webui_*.qm
.DS_Store
.qmake.stash
src/qbittorrent.app

View file

@ -7,14 +7,15 @@ for(file, TS_FILES) {
}
isEmpty(QMAKE_LRELEASE) {
win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
win32: QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease.exe
else: QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
unix {
equals(QT_MAJOR_VERSION, 5) {
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt5 }
}
} else {
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease }
equals(QT_MAJOR_VERSION, 5) {
!exists($$QMAKE_LRELEASE): QMAKE_LRELEASE = lrelease-qt5
}
}
else {
!exists($$QMAKE_LRELEASE): QMAKE_LRELEASE = lrelease
}
}

View file

@ -11,7 +11,6 @@ api/synccontroller.h
api/torrentscontroller.h
api/transfercontroller.h
api/serialize/serialize_torrent.h
extra_translations.h
webapplication.h
webui.h

View file

@ -1,97 +0,0 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#ifndef EXTRA_TRANSLATIONS_H
#define EXTRA_TRANSLATIONS_H
#include <QObject>
// Additional translations for Web UI
const char *QBT_WEBUI_TRANSLATIONS[] = {
QT_TRANSLATE_NOOP("HttpServer", "Logout"),
QT_TRANSLATE_NOOP("HttpServer", "Exit qBittorrent"),
QT_TRANSLATE_NOOP("HttpServer", "Download Torrents from their URLs or Magnet links"),
QT_TRANSLATE_NOOP("HttpServer", "Only one link per line"),
QT_TRANSLATE_NOOP("HttpServer", "Upload local torrent"),
QT_TRANSLATE_NOOP("HttpServer", "Are you sure you want to delete the selected torrents from the transfer list?"),
QT_TRANSLATE_NOOP("HttpServer", "Global upload rate limit must be greater than 0 or disabled."),
QT_TRANSLATE_NOOP("HttpServer", "Global download rate limit must be greater than 0 or disabled."),
QT_TRANSLATE_NOOP("HttpServer", "Alternative upload rate limit must be greater than 0 or disabled."),
QT_TRANSLATE_NOOP("HttpServer", "Alternative download rate limit must be greater than 0 or disabled."),
QT_TRANSLATE_NOOP("HttpServer", "Maximum active downloads must be greater than -1."),
QT_TRANSLATE_NOOP("HttpServer", "Maximum active uploads must be greater than -1."),
QT_TRANSLATE_NOOP("HttpServer", "Maximum active torrents must be greater than -1."),
QT_TRANSLATE_NOOP("HttpServer", "Maximum number of connections limit must be greater than 0 or disabled."),
QT_TRANSLATE_NOOP("HttpServer", "Maximum number of connections per torrent limit must be greater than 0 or disabled."),
QT_TRANSLATE_NOOP("HttpServer", "Maximum number of upload slots per torrent limit must be greater than 0 or disabled."),
QT_TRANSLATE_NOOP("HttpServer", "Unable to save program preferences, qBittorrent is probably unreachable."),
QT_TRANSLATE_NOOP("HttpServer", "The port used for incoming connections must be between 1 and 65535."),
QT_TRANSLATE_NOOP("HttpServer", "The port used for the Web UI must be between 1 and 65535."),
QT_TRANSLATE_NOOP("HttpServer", "Save"),
QT_TRANSLATE_NOOP("HttpServer", "qBittorrent client is not reachable"),
QT_TRANSLATE_NOOP("HttpServer", "qBittorrent has been shutdown."),
QT_TRANSLATE_NOOP("HttpServer", "Unable to log in, qBittorrent is probably unreachable."),
QT_TRANSLATE_NOOP("HttpServer", "Invalid Username or Password."),
QT_TRANSLATE_NOOP("HttpServer", "Username"),
QT_TRANSLATE_NOOP("HttpServer", "Password"),
QT_TRANSLATE_NOOP("HttpServer", "Login"),
QT_TRANSLATE_NOOP("HttpServer", "Original authors"),
QT_TRANSLATE_NOOP("HttpServer", "Apply"),
QT_TRANSLATE_NOOP("HttpServer", "Add"),
QT_TRANSLATE_NOOP("HttpServer", "Save files to location:"),
QT_TRANSLATE_NOOP("HttpServer", "Cookie:"),
QT_TRANSLATE_NOOP("HttpServer", "Type folder here"),
QT_TRANSLATE_NOOP("HttpServer", "More information"),
QT_TRANSLATE_NOOP("HttpServer", "Information about certificates"),
QT_TRANSLATE_NOOP("HttpServer", "Save Files to"),
QT_TRANSLATE_NOOP("HttpServer", "IRC: #qbittorrent on Freenode"),
QT_TRANSLATE_NOOP("HttpServer", "Invalid category name:\nPlease do not use any special characters in the category name."),
QT_TRANSLATE_NOOP("HttpServer", "Unknown"),
QT_TRANSLATE_NOOP("HttpServer", "Hard Disk"),
QT_TRANSLATE_NOOP("HttpServer", "Share ratio limit must be between 0 and 9998."),
QT_TRANSLATE_NOOP("HttpServer", "Seeding time limit must be between 0 and 525600 minutes."),
QT_TRANSLATE_NOOP("HttpServer", "Set location"),
QT_TRANSLATE_NOOP("HttpServer", "Limit upload rate"),
QT_TRANSLATE_NOOP("HttpServer", "Limit download rate"),
QT_TRANSLATE_NOOP("HttpServer", "Rename torrent"),
QT_TRANSLATE_NOOP("HttpServer", "Unable to create category")
};
const struct { const char *source; const char *comment; } QBT_WEBUI_COMMENTED_TRANSLATIONS[] = {
QT_TRANSLATE_NOOP3("HttpServer", "Other...", "Save Files to: Watch Folder / Default Folder / Other..."),
QT_TRANSLATE_NOOP3("HttpServer", "Monday", "Schedule the use of alternative rate limits on ..."),
QT_TRANSLATE_NOOP3("HttpServer", "Tuesday", "Schedule the use of alternative rate limits on ..."),
QT_TRANSLATE_NOOP3("HttpServer", "Wednesday", "Schedule the use of alternative rate limits on ..."),
QT_TRANSLATE_NOOP3("HttpServer", "Thursday", "Schedule the use of alternative rate limits on ..."),
QT_TRANSLATE_NOOP3("HttpServer", "Friday", "Schedule the use of alternative rate limits on ..."),
QT_TRANSLATE_NOOP3("HttpServer", "Saturday", "Schedule the use of alternative rate limits on ..."),
QT_TRANSLATE_NOOP3("HttpServer", "Sunday", "Schedule the use of alternative rate limits on ..."),
QT_TRANSLATE_NOOP3("HttpServer", "Upload Torrents", "Upload torrent files to qBittorent using WebUI")
};
#endif // EXTRA_TRANSLATIONS_H

View file

@ -34,7 +34,6 @@
#include <stdexcept>
#include <vector>
#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
#include <QFile>
@ -91,46 +90,6 @@ namespace
return ret;
}
void translateDocument(const QString &locale, QString &data)
{
const QRegularExpression regex("QBT_TR\\((([^\\)]|\\)(?!QBT_TR))+)\\)QBT_TR(\\[CONTEXT=([a-zA-Z_][a-zA-Z0-9_]*)\\])");
const QRegularExpression mnemonic("\\(?&([a-zA-Z]?\\))?");
const bool isTranslationNeeded = !locale.startsWith("en")
|| locale.startsWith("en_AU") || locale.startsWith("en_GB");
int i = 0;
bool found = true;
while (i < data.size() && found) {
QRegularExpressionMatch regexMatch;
i = data.indexOf(regex, i, &regexMatch);
if (i >= 0) {
const QString word = regexMatch.captured(1);
const QString context = regexMatch.captured(4);
QString translation = isTranslationNeeded
? qApp->translate(context.toUtf8().constData(), word.toUtf8().constData(), nullptr, 1)
: word;
// Remove keyboard shortcuts
translation.remove(mnemonic);
// Use HTML code for quotes to prevent issues with JS
translation.replace('\'', "&#39;");
translation.replace('\"', "&#34;");
data.replace(i, regexMatch.capturedLength(), translation);
i += translation.length();
}
else {
found = false; // no more translatable strings
}
data.replace(QLatin1String("${LANG}"), locale.left(2));
data.replace(QLatin1String("${VERSION}"), QBT_VERSION);
}
}
inline QUrl urlFromHostHeader(const QString &hostHeader)
{
if (!hostHeader.contains(QLatin1String("://")))
@ -234,6 +193,43 @@ void WebApplication::sendWebUIFile()
sendFile(localPath);
}
void WebApplication::translateDocument(QString &data)
{
const QRegularExpression regex("QBT_TR\\((([^\\)]|\\)(?!QBT_TR))+)\\)QBT_TR\\[CONTEXT=([a-zA-Z_][a-zA-Z0-9_]*)\\]");
const bool isTranslationNeeded = !m_currentLocale.startsWith("en")
|| m_currentLocale.startsWith("en_AU") || m_currentLocale.startsWith("en_GB")
|| !m_translator.isEmpty();
int i = 0;
bool found = true;
while (i < data.size() && found) {
QRegularExpressionMatch regexMatch;
i = data.indexOf(regex, i, &regexMatch);
if (i >= 0) {
const QString word = regexMatch.captured(1);
const QString context = regexMatch.captured(3);
QString translation = isTranslationNeeded
? m_translator.translate(context.toUtf8().constData(), word.toUtf8().constData(), nullptr, 1)
: word;
// Use HTML code for quotes to prevent issues with JS
translation.replace('\'', "&#39;");
translation.replace('\"', "&#34;");
data.replace(i, regexMatch.capturedLength(), translation);
i += translation.length();
}
else {
found = false; // no more translatable strings
}
data.replace(QLatin1String("${LANG}"), m_currentLocale.left(2));
data.replace(QLatin1String("${VERSION}"), QBT_VERSION);
}
}
WebSession *WebApplication::session()
{
return m_currentSession;
@ -429,6 +425,14 @@ void WebApplication::configure()
if (m_currentLocale != newLocale) {
m_currentLocale = newLocale;
m_translatedFiles.clear();
if (m_translator.load(m_rootFolder + QLatin1String("/translations/webui_") + m_currentLocale)) {
LogMsg(tr("WebUI translation for selected locale (%1) is successfully loaded.")
.arg(m_currentLocale));
}
else {
LogMsg(tr("Couldn't load WebUI translation for selected locale (%1). Falling back to default (en).")
.arg(m_currentLocale), Log::WARNING);
}
}
m_isLocalAuthEnabled = pref->isWebUiLocalAuthEnabled();
@ -490,7 +494,7 @@ void WebApplication::sendFile(const QString &path)
// Translate the file
if (isTranslatable) {
QString dataStr {data};
translateDocument(m_currentLocale, dataStr);
translateDocument(dataStr);
data = dataStr.toUtf8();
m_translatedFiles[path] = {data, lastModified}; // caching translated file

View file

@ -34,6 +34,7 @@
#include <QObject>
#include <QRegularExpression>
#include <QSet>
#include <QTranslator>
#include "api/isessionmanager.h"
#include "base/http/irequesthandler.h"
@ -109,6 +110,8 @@ private:
void sendFile(const QString &path);
void sendWebUIFile();
void translateDocument(QString &data);
// Session management
QString generateSid() const;
void sessionInitialize();
@ -142,6 +145,7 @@ private:
};
QMap<QString, TranslatedFile> m_translatedFiles;
QString m_currentLocale;
QTranslator m_translator;
bool m_isLocalAuthEnabled;
bool m_isAuthSubnetWhitelistEnabled;

View file

@ -10,7 +10,6 @@ HEADERS += \
$$PWD/api/torrentscontroller.h \
$$PWD/api/transfercontroller.h \
$$PWD/api/serialize/serialize_torrent.h \
$$PWD/extra_translations.h \
$$PWD/webapplication.h \
$$PWD/webui.h
@ -29,3 +28,25 @@ SOURCES += \
$$PWD/webui.cpp
RESOURCES += $$PWD/www/webui.qrc
# WebUI Translation
isEmpty(QMAKE_LRELEASE) {
win32: QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease.exe
else: QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
unix {
equals(QT_MAJOR_VERSION, 5) {
!exists($$QMAKE_LRELEASE): QMAKE_LRELEASE = lrelease-qt5
}
}
else {
!exists($$QMAKE_LRELEASE): QMAKE_LRELEASE = lrelease
}
}
WEBUI_TRANSLATIONS = $$files(www/translations/webui_*.ts)
WEBUI_TRANSLATIONS_NOEXT = $$replace(WEBUI_TRANSLATIONS, ".ts", "")
message("Building WebUI translations...")
for(L, WEBUI_TRANSLATIONS_NOEXT) {
message("Processing $${L}")
system("$$QMAKE_LRELEASE -silent $${L}.ts -qm $${L}.qm")
!exists("$${L}.qm"): error("Building WebUI translations failed, cannot continue!")
}

View file

@ -37,22 +37,22 @@
<div id="desktopNavbar">
<ul>
<li>
<a class="returnFalse">QBT_TR(&File)QBT_TR[CONTEXT=MainWindow]</a>
<a class="returnFalse">QBT_TR(File)QBT_TR[CONTEXT=MainWindow]</a>
<ul>
<li><a id="uploadLink"><img class="MyMenuIcon" alt="QBT_TR(&Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/list-add.svg" width="16" height="16"/>QBT_TR(&Add Torrent File...)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="downloadLink"><img class="MyMenuIcon" alt="QBT_TR(Add Torrent &Link...)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/insert-link.svg" width="16" height="16"/>QBT_TR(Add Torrent &Link...)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="uploadLink"><img class="MyMenuIcon" alt="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/list-add.svg" width="16" height="16"/>QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="downloadLink"><img class="MyMenuIcon" alt="QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/insert-link.svg" width="16" height="16"/>QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id="logoutLink"><img class="MyMenuIcon" alt="QBT_TR(Logout)QBT_TR[CONTEXT=HttpServer]" src="images/qbt-theme/system-log-out.svg" width="16" height="16"/>QBT_TR(Logout)QBT_TR[CONTEXT=HttpServer]</a></li>
<li><a id="shutdownLink"><img class="MyMenuIcon" alt="QBT_TR(Exit qBittorrent)QBT_TR[CONTEXT=HttpServer]" src="images/qbt-theme/application-exit.svg" width="16" height="16"/>QBT_TR(Exit qBittorrent)QBT_TR[CONTEXT=HttpServer]</a></li>
</ul>
</li>
<li>
<a class="returnFalse">QBT_TR(&Edit)QBT_TR[CONTEXT=MainWindow]</a>
<a class="returnFalse">QBT_TR(Edit)QBT_TR[CONTEXT=MainWindow]</a>
<ul>
<li><a id="resumeAllLink"><img class="MyMenuIcon" alt="QBT_TR(R&esume All)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/media-playback-start.svg" width="16" height="16"/>QBT_TR(R&esume All)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="pauseAllLink"><img class="MyMenuIcon" alt="QBT_TR(P&ause All)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/media-playback-pause.svg" width="16" height="16"/>QBT_TR(P&ause All)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id="resumeLink"><img class="MyMenuIcon" alt="QBT_TR(&Resume)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/media-playback-start.svg" width="16" height="16"/>QBT_TR(&Resume)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="pauseLink"><img class="MyMenuIcon" src="images/qbt-theme/media-playback-pause.svg" alt="QBT_TR(&Pause)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(&Pause)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id="deleteLink"><img class="MyMenuIcon" src="images/qbt-theme/list-remove.svg" alt="QBT_TR(&Delete)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(&Delete)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="resumeAllLink"><img class="MyMenuIcon" alt="QBT_TR(Resume All)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/media-playback-start.svg" width="16" height="16"/>QBT_TR(Resume All)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="pauseAllLink"><img class="MyMenuIcon" alt="QBT_TR(Pause All)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/media-playback-pause.svg" width="16" height="16"/>QBT_TR(Pause All)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id="resumeLink"><img class="MyMenuIcon" alt="QBT_TR(Resume)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/media-playback-start.svg" width="16" height="16"/>QBT_TR(Resume)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="pauseLink"><img class="MyMenuIcon" src="images/qbt-theme/media-playback-pause.svg" alt="QBT_TR(Pause)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Pause)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id="deleteLink"><img class="MyMenuIcon" src="images/qbt-theme/list-remove.svg" alt="QBT_TR(Delete)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Delete)QBT_TR[CONTEXT=MainWindow]</a></li>
<li id="topPrioItem" class="divider"><a id="topPrioLink"><img class="MyMenuIcon" src="images/qbt-theme/go-top.svg" alt="QBT_TR(Top Priority)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Top Priority)QBT_TR[CONTEXT=MainWindow]</a></li>
<li id="increasePrioItem"><a id="increasePrioLink"><img class="MyMenuIcon" src="images/qbt-theme/go-up.svg" alt="QBT_TR(Increase Priority)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Increase Priority)QBT_TR[CONTEXT=MainWindow]</a></li>
<li id="decreasePrioItem"><a id="decreasePrioLink"><img class="MyMenuIcon" src="images/qbt-theme/go-down.svg" alt="QBT_TR(Decrease Priority)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Decrease Priority)QBT_TR[CONTEXT=MainWindow]</a></li>
@ -61,34 +61,34 @@
</ul>
</li>
<li>
<a class="returnFalse">QBT_TR(&View)QBT_TR[CONTEXT=MainWindow]</a>
<a class="returnFalse">QBT_TR(View)QBT_TR[CONTEXT=MainWindow]</a>
<ul>
<li><a id="showTopToolbarLink"><img class="MyMenuIcon" src="images/qbt-theme/checked.svg" alt="QBT_TR(&Top Toolbar)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(&Top Toolbar)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="showStatusBarLink"><img class="MyMenuIcon" src="images/qbt-theme/checked.svg" alt="QBT_TR(Status &Bar)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Status &Bar)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="speedInBrowserTitleBarLink"><img class="MyMenuIcon" src="images/qbt-theme/checked.svg" alt="QBT_TR(S&peed in Title Bar)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(S&peed in Title Bar)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id=StatisticsLink><img class="MyMenuIcon" src="images/qbt-theme/view-statistics.svg" alt="QBT_TR(&Statistics)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(&Statistics)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="showTopToolbarLink"><img class="MyMenuIcon" src="images/qbt-theme/checked.svg" alt="QBT_TR(Top Toolbar)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Top Toolbar)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="showStatusBarLink"><img class="MyMenuIcon" src="images/qbt-theme/checked.svg" alt="QBT_TR(Status Bar)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Status Bar)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="speedInBrowserTitleBarLink"><img class="MyMenuIcon" src="images/qbt-theme/checked.svg" alt="QBT_TR(Speed in Title Bar)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Speed in Title Bar)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id=StatisticsLink><img class="MyMenuIcon" src="images/qbt-theme/view-statistics.svg" alt="QBT_TR(Statistics)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Statistics)QBT_TR[CONTEXT=MainWindow]</a></li>
</ul>
</li>
<li>
<a class="returnFalse">QBT_TR(&Tools)QBT_TR[CONTEXT=MainWindow]</a>
<a class="returnFalse">QBT_TR(Tools)QBT_TR[CONTEXT=MainWindow]</a>
<ul>
<li><a id="preferencesLink"><img class="MyMenuIcon" src="images/qbt-theme/configure.svg" alt="QBT_TR(&Options...)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(&Options...)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="preferencesLink"><img class="MyMenuIcon" src="images/qbt-theme/configure.svg" alt="QBT_TR(Options...)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Options...)QBT_TR[CONTEXT=MainWindow]</a></li>
</ul>
</li>
<li>
<a class="returnFalse">QBT_TR(&Help)QBT_TR[CONTEXT=MainWindow]</a>
<a class="returnFalse">QBT_TR(Help)QBT_TR[CONTEXT=MainWindow]</a>
<ul>
<li><a id="docsLink" target="_blank" href="http://wiki.qbittorrent.org/"><img class="MyMenuIcon" src="images/qbt-theme/help-contents.svg" alt="QBT_TR(&Documentation)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(&Documentation)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id="bugLink" target="_blank" href="https://www.qbittorrent.org/donate"><img class="MyMenuIcon" src="images/qbt-theme/wallet-open.svg" alt="QBT_TR(Do&nate!)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Do&nate!)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="aboutLink"><img class="MyMenuIcon" src="images/qbt-theme/help-about.svg" alt="QBT_TR(&About)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(&About)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="docsLink" target="_blank" href="http://wiki.qbittorrent.org/"><img class="MyMenuIcon" src="images/qbt-theme/help-contents.svg" alt="QBT_TR(Documentation)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Documentation)QBT_TR[CONTEXT=MainWindow]</a></li>
<li class="divider"><a id="bugLink" target="_blank" href="https://www.qbittorrent.org/donate"><img class="MyMenuIcon" src="images/qbt-theme/wallet-open.svg" alt="QBT_TR(Donate!)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(Donate!)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="aboutLink"><img class="MyMenuIcon" src="images/qbt-theme/help-about.svg" alt="QBT_TR(About)QBT_TR[CONTEXT=MainWindow]" width="16" height="16"/>QBT_TR(About)QBT_TR[CONTEXT=MainWindow]</a></li>
</ul>
</li>
</ul>
</div>
<div id="mochaToolbar">
&nbsp;&nbsp;
<a id="downloadButton"><img class="mochaToolButton" title="QBT_TR(Add Torrent &Link...)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/insert-link.svg" alt="QBT_TR(Add Torrent &Link...)QBT_TR[CONTEXT=MainWindow]" width="24" height="24"/></a>
<a id="uploadButton"><img class="mochaToolButton" title="QBT_TR(&Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/list-add.svg" alt="QBT_TR(&Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" width="24" height="24"/></a>
<a id="downloadButton"><img class="mochaToolButton" title="QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/insert-link.svg" alt="QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow]" width="24" height="24"/></a>
<a id="uploadButton"><img class="mochaToolButton" title="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" src="images/qbt-theme/list-add.svg" alt="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" width="24" height="24"/></a>
<a id="deleteButton" class="divider"><img class="mochaToolButton" title="QBT_TR(Delete)QBT_TR[CONTEXT=TransferListWidget]" src="images/qbt-theme/list-remove.svg" alt="QBT_TR(Delete)QBT_TR[CONTEXT=TransferListWidget]" width="24" height="24"/></a>
<a id="resumeButton" class="divider"><img class="mochaToolButton" title="QBT_TR(Resume)QBT_TR[CONTEXT=TransferListWidget]" src="images/qbt-theme/media-playback-start.svg" alt="QBT_TR(Resume)QBT_TR[CONTEXT=TransferListWidget]" width="24" height="24"/></a>
<a id="pauseButton"><img class="mochaToolButton" title="QBT_TR(Pause)QBT_TR[CONTEXT=TransferListWidget]" src="images/qbt-theme/media-playback-pause.svg" alt="QBT_TR(Pause)QBT_TR[CONTEXT=TransferListWidget]" width="24" height="24"/></a>

View file

@ -51,7 +51,7 @@
<fieldset class="settings">
<legend><input type="checkbox" id="mail_notification_checkbox" onclick="updateMailNotification();" />
<label for="mail_notification_checkbox">QBT_TR(Email notification &upon download completion)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="mail_notification_checkbox">QBT_TR(Email notification upon download completion)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<div class="formRow">
<label for="dest_email_txt" class="leftLabelMedium">QBT_TR(To:)QBT_TR[CONTEXT=OptionsDialog]</label><input type="text" id="dest_email_txt" />
</div>
@ -74,7 +74,7 @@
<fieldset class="settings">
<legend><input type="checkbox" id="autorun_checkbox" onclick="updateAutoRun();" />
<label for="autorun_checkbox">QBT_TR(Run e&xternal program on torrent completion)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="autorun_checkbox">QBT_TR(Run external program on torrent completion)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<input type="text" id="autorunProg_txt" style="width: 400px;" /><br/>
<div style="font-style: italic;">QBT_TR(Supported parameters (case sensitive):)QBT_TR[CONTEXT=OptionsDialog]
<ul>
@ -192,7 +192,7 @@
<fieldset class="settings">
<legend><input type="checkbox" id="ipfilter_enabled_checkbox" onclick="updateFilterSettings();" />
<label for="ipfilter_enabled_checkbox">QBT_TR(IP Fi&ltering)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="ipfilter_enabled_checkbox">QBT_TR(IP Filtering)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="ipfilter_text">QBT_TR(Filter path (.dat, .p2p, .p2b):)QBT_TR[CONTEXT=OptionsDialog]</label>
<input type="text" id="ipfilter_text" /><br/>
<input type="checkbox" id="ipfilter_trackers_checkbox" />
@ -248,7 +248,7 @@
<fieldset class="settings">
<legend><input type="checkbox" id="limit_sheduling_checkbox" onclick="updateSchedulingEnabled();" />
<label for="limit_sheduling_checkbox">QBT_TR(Schedule &the use of alternative rate limits)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="limit_sheduling_checkbox">QBT_TR(Schedule the use of alternative rate limits)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
QBT_TR(From:)QBT_TR[CONTEXT=OptionsDialog]
<input type="text" id="schedule_from_hour" style="width: 1.5em;" />:<input type="text" id="schedule_from_min" style="width: 1.5em;" /> QBT_TR(To:)QBT_TR[CONTEXT=OptionsDialog]
<input type="text" id="schedule_to_hour" style="width: 1.5em;" />:<input type="text" id="schedule_to_min" style="width: 1.5em;" />
@ -299,7 +299,7 @@
<fieldset class="settings">
<legend><input type="checkbox" id="queueing_checkbox" onclick="updateQueueingSystem();" />
<label for="queueing_checkbox">QBT_TR(&Torrent Queueing)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="queueing_checkbox">QBT_TR(Torrent Queueing)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<div class="formRow">
<label for="max_active_dl_value" style="margin-left: 20px;" class="leftLabelLarge">QBT_TR(Maximum active downloads:)QBT_TR[CONTEXT=OptionsDialog]</label>
<input type="text" id="max_active_dl_value" style="width: 4em;" />
@ -354,7 +354,7 @@
<fieldset class="settings">
<legend><input type="checkbox" id="add_trackers_checkbox" onclick="updateAddTrackersEnabled();" />
<label for="add_trackers_checkbox">QBT_TR(A&utomatically add these trackers to new downloads:)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="add_trackers_checkbox">QBT_TR(Automatically add these trackers to new downloads:)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<textarea id="add_trackers_textarea" rows="5" cols="70"></textarea>
</fieldset>
</div>
@ -426,7 +426,7 @@
<label for="webui_upnp_checkbox">QBT_TR(Use UPnP / NAT-PMP to forward the port from my router)QBT_TR[CONTEXT=OptionsDialog]</label><br/>
<fieldset class="settings">
<legend><input type="checkbox" id="use_https_checkbox" onclick="updateHttpsSettings();" />
<label for="use_https_checkbox">QBT_TR(&Use HTTPS instead of HTTP)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="use_https_checkbox">QBT_TR(Use HTTPS instead of HTTP)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<div class="formRow">
<label class="leftLabelSmall" for="ssl_key_textarea">QBT_TR(Key:)QBT_TR[CONTEXT=OptionsDialog]</label>
<textarea id="ssl_key_textarea" rows="5" cols="70"></textarea>
@ -471,7 +471,7 @@
<fieldset class="settings">
<legend><input type="checkbox" id="use_dyndns_checkbox" onclick="updateDynDnsSettings();" />
<label for="use_dyndns_checkbox">QBT_TR(Upda&te my dynamic domain name)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<label for="use_dyndns_checkbox">QBT_TR(Update my dynamic domain name)QBT_TR[CONTEXT=OptionsDialog]</label></legend>
<select id="dyndns_select">
<option value="0">DynDNS</option>
<option value="1">NO-IP</option>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -45,5 +45,55 @@
<file>public/css/login.css</file>
<file>public/login.html</file>
<file>public/scripts/lib/mootools-1.2-core-yc.js</file>
<file>translations/webui_ar.qm</file>
<file>translations/webui_be.qm</file>
<file>translations/webui_bg.qm</file>
<file>translations/webui_ca.qm</file>
<file>translations/webui_cs.qm</file>
<file>translations/webui_da.qm</file>
<file>translations/webui_de.qm</file>
<file>translations/webui_el.qm</file>
<file>translations/webui_en.qm</file>
<file>translations/webui_en_AU.qm</file>
<file>translations/webui_en_GB.qm</file>
<file>translations/webui_eo.qm</file>
<file>translations/webui_es.qm</file>
<file>translations/webui_eu.qm</file>
<file>translations/webui_fi.qm</file>
<file>translations/webui_fr.qm</file>
<file>translations/webui_gl.qm</file>
<file>translations/webui_he.qm</file>
<file>translations/webui_hi_IN.qm</file>
<file>translations/webui_hr.qm</file>
<file>translations/webui_hu.qm</file>
<file>translations/webui_hy.qm</file>
<file>translations/webui_id.qm</file>
<file>translations/webui_is.qm</file>
<file>translations/webui_it.qm</file>
<file>translations/webui_ja.qm</file>
<file>translations/webui_ka.qm</file>
<file>translations/webui_ko.qm</file>
<file>translations/webui_lt.qm</file>
<file>translations/webui_lv_LV.qm</file>
<file>translations/webui_ms_MY.qm</file>
<file>translations/webui_nb.qm</file>
<file>translations/webui_nl.qm</file>
<file>translations/webui_oc.qm</file>
<file>translations/webui_pl.qm</file>
<file>translations/webui_pt_BR.qm</file>
<file>translations/webui_pt_PT.qm</file>
<file>translations/webui_ro.qm</file>
<file>translations/webui_ru.qm</file>
<file>translations/webui_sk.qm</file>
<file>translations/webui_sl.qm</file>
<file>translations/webui_sr.qm</file>
<file>translations/webui_sv.qm</file>
<file>translations/webui_tr.qm</file>
<file>translations/webui_uk.qm</file>
<file>translations/webui_uz@Latn.qm</file>
<file>translations/webui_vi.qm</file>
<file>translations/webui_zh.qm</file>
<file>translations/webui_zh_HK.qm</file>
<file>translations/webui_zh_TW.qm</file>
</qresource>
</RCC>