mirror of
https://github.com/Carve/qbittorrent-webui-cjratliff.com.git
synced 2024-11-12 01:40:48 +01:00
Updated screenshot
This commit is contained in:
parent
9493fd2827
commit
fbef073a1c
Binary file not shown.
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 472 KiB |
181
tstool.py
181
tstool.py
@ -1,181 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# TSTool - script for update qBittorrent WebUI translation files
|
|
||||||
# Copyright (C) 2018 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.
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import copy
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
|
|
||||||
accepted_exts = [".js", ".html", ".css"]
|
|
||||||
|
|
||||||
no_obsolete = False
|
|
||||||
www_folder = "."
|
|
||||||
ts_folder = os.path.join(www_folder, "translations")
|
|
||||||
|
|
||||||
def parseSource(filename, sources):
|
|
||||||
print("Parsing %s..." % (os.path.normpath(filename)))
|
|
||||||
with open(filename, encoding = 'utf-8', mode = 'r') as file:
|
|
||||||
regex = re.compile(
|
|
||||||
r"QBT_TR\((([^\)]|\)(?!QBT_TR))+)\)QBT_TR\[CONTEXT=([a-zA-Z_][a-zA-Z0-9_]*)\]")
|
|
||||||
for match in regex.finditer(file.read()):
|
|
||||||
string = match.group(1)
|
|
||||||
context = match.group(3)
|
|
||||||
|
|
||||||
if context not in sources:
|
|
||||||
sources[context] = set()
|
|
||||||
sources[context].add(string)
|
|
||||||
|
|
||||||
def processTranslation(filename, sources):
|
|
||||||
print('Processing %s...' % (os.path.normpath(filename)))
|
|
||||||
|
|
||||||
try:
|
|
||||||
tree = ET.ElementTree(file = filename)
|
|
||||||
except Exception:
|
|
||||||
print('\tFailed to parse %s!' % (os.path.normpath(filename)))
|
|
||||||
return
|
|
||||||
|
|
||||||
root = tree.getroot()
|
|
||||||
for context in root.findall('context'):
|
|
||||||
context_name = context.find('name').text
|
|
||||||
has_context = context_name in sources
|
|
||||||
if not has_context and no_obsolete:
|
|
||||||
root.remove(context)
|
|
||||||
continue
|
|
||||||
|
|
||||||
for message in context.findall('message'):
|
|
||||||
for location in message.findall('location'):
|
|
||||||
message.remove(location)
|
|
||||||
|
|
||||||
source = message.find('source').text
|
|
||||||
translation = message.find('translation')
|
|
||||||
if has_context and source in sources[context_name]:
|
|
||||||
sources[context_name].remove(source)
|
|
||||||
|
|
||||||
trtype = translation.attrib.get('type')
|
|
||||||
if (trtype == 'obsolete') or (trtype == 'vanished'):
|
|
||||||
del translation.attrib['type'] # i.e. finished
|
|
||||||
else:
|
|
||||||
if no_obsolete or (translation.attrib.get('type', '') == 'unfinished'):
|
|
||||||
context.remove(message)
|
|
||||||
else:
|
|
||||||
translation.attrib['type'] = 'vanished'
|
|
||||||
|
|
||||||
if not has_context:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# add new messages for current context
|
|
||||||
for source in sources[context_name]:
|
|
||||||
message = ET.SubElement(context, 'message')
|
|
||||||
ET.SubElement(message, 'source').text = source
|
|
||||||
ET.SubElement(message, 'translation', {'type': 'unfinished'})
|
|
||||||
del sources[context_name]
|
|
||||||
|
|
||||||
# add messages for new contexts
|
|
||||||
for context_name in sources:
|
|
||||||
context = ET.SubElement(root, 'context')
|
|
||||||
ET.SubElement(context, 'name').text = context_name
|
|
||||||
|
|
||||||
for source in sources[context_name]:
|
|
||||||
message = ET.SubElement(context, 'message')
|
|
||||||
ET.SubElement(message, 'source').text = source
|
|
||||||
ET.SubElement(message, 'translation', {'type': 'unfinished'})
|
|
||||||
|
|
||||||
# prettify output xml
|
|
||||||
indent = ' ' * 4
|
|
||||||
root.text = '\n'
|
|
||||||
for context in root.findall('./context'):
|
|
||||||
context.text = '\n' + indent
|
|
||||||
context.tail = '\n'
|
|
||||||
context.find('./name').tail = '\n' + indent
|
|
||||||
messages = context.findall('./message')
|
|
||||||
if len(messages) == 0: continue
|
|
||||||
|
|
||||||
for message in messages:
|
|
||||||
message.text = '\n' + (indent * 2)
|
|
||||||
message.tail = '\n' + indent
|
|
||||||
elems = message.findall('./')
|
|
||||||
if len(elems) == 0: continue
|
|
||||||
|
|
||||||
for elem in elems:
|
|
||||||
elem.tail = '\n' + (indent * 2)
|
|
||||||
elems[-1:][0].tail = '\n' + indent
|
|
||||||
messages[-1:][0].tail = '\n'
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(filename, mode = 'wb') as file:
|
|
||||||
file.write(b'<?xml version="1.0" encoding="utf-8"?>\n'
|
|
||||||
b'<!DOCTYPE TS>\n')
|
|
||||||
tree.write(file, encoding = 'utf-8')
|
|
||||||
except Exception:
|
|
||||||
print('\tFailed to write %s!' % (os.path.normpath(filename)))
|
|
||||||
|
|
||||||
argp = argparse.ArgumentParser(
|
|
||||||
prog = 'tstool.py', description = 'Update qBittorrent WebUI translation files.')
|
|
||||||
argp.add_argument('--no-obsolete', dest = 'no_obsolete', action = 'store_true',
|
|
||||||
default = no_obsolete,
|
|
||||||
help = 'remove obsolete messages (default: mark them as obsolete)')
|
|
||||||
argp.add_argument('--www-folder', dest = 'www_folder', action = 'store',
|
|
||||||
default = www_folder,
|
|
||||||
help = 'folder with WebUI source files (default: "%s")' % (www_folder))
|
|
||||||
argp.add_argument('--ts-folder', dest = 'ts_folder', action = 'store',
|
|
||||||
default = ts_folder,
|
|
||||||
help = 'folder with WebUI translation files (default: "%s")' % (ts_folder))
|
|
||||||
|
|
||||||
args = argp.parse_args()
|
|
||||||
no_obsolete = args.no_obsolete
|
|
||||||
www_folder = args.www_folder
|
|
||||||
ts_folder = args.ts_folder
|
|
||||||
|
|
||||||
print("Processing source files...")
|
|
||||||
nfiles = 0
|
|
||||||
source_ts = {}
|
|
||||||
for root, dirs, files in os.walk(www_folder):
|
|
||||||
for file in files:
|
|
||||||
if os.path.splitext(file)[-1] in accepted_exts:
|
|
||||||
parseSource(os.path.join(root, file), source_ts)
|
|
||||||
nfiles += 1
|
|
||||||
|
|
||||||
if nfiles == 0:
|
|
||||||
print("No source files found!")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
nstrings = sum(len(sublist) for sublist in source_ts)
|
|
||||||
print("Found %d strings within %d contexts." % (nstrings, len(source_ts)))
|
|
||||||
print("")
|
|
||||||
|
|
||||||
print("Processing translation files...")
|
|
||||||
for entry in os.scandir(ts_folder):
|
|
||||||
if (entry.is_file() and entry.name.startswith('webui_')
|
|
||||||
and entry.name.endswith(".ts")):
|
|
||||||
processTranslation(entry.path, copy.deepcopy(source_ts))
|
|
||||||
|
|
||||||
print("Done!")
|
|
Loading…
Reference in New Issue
Block a user