Commit 829034f8 authored by Pino Toscano's avatar Pino Toscano
Browse files

usb: rework translations of USB classes & subclasses

The current translations for classes and subclasses come from a static
classes.i18n, which is supposed to be filled with strings from usb.ids.
However, this file has few issues:
- it has not been updated in a very long time, and half of its string
  do not exist anymore
- there is no indication of how it was created in the beginning, so
  keeping it up-to-date is a non-trivial job
- translations for classes and subclasses are mixed together

To improve the situation, introduce a script, i18n-from-usb-ids.py,
that can be used to update classes.i18n from a specified usb.ids file;
this way, it is much easier to keep these messages up-to-date regularly,
and the printed Date from usb.ids is an indication on the last time
classes.i18n was updated.

In addition, add different contexts for classes and subclasses: classes
follow the context previously introduced to translate the classes from
libusb.

As semi-related change: translate the class string only when reading it
from usb.ids, as we get translated strings from the mapping of the
libusb class.
parent ec46df3c
i18n("AT-commands");
i18n("ATM Networking");
i18n("Abstract (modem)");
i18n("Audio");
i18n("Bidirectional");
i18n("Boot Interface Subclass");
i18n("Bulk (Zip)");
i18n("CAPI 2.0");
i18n("CAPI Control");
i18n("CDC PUF");
i18n("Communications");
i18n("Control Device");
i18n("Control/Bulk");
i18n("Control/Bulk/Interrupt");
i18n("Data");
i18n("Direct Line");
i18n("Ethernet Networking");
i18n("Floppy");
i18n("HDLC");
i18n("Host Based Driver");
i18n("Hub");
i18n("Human Interface Devices");
i18n("I.430 ISDN BRI");
i18n("Interface");
i18n("Keyboard");
i18n("Mass Storage");
i18n("Mouse");
i18n("Multi-Channel");
i18n("No Subclass");
i18n("Non Streaming");
i18n("None");
i18n("Printer");
i18n("Q.921");
i18n("Q.921M");
i18n("Q.921TM");
i18n("Q.932 EuroISDN");
i18n("SCSI");
i18n("Streaming");
i18n("Telephone");
i18n("Transparent");
i18n("Unidirectional");
i18n("V.120 V.24 rate ISDN");
i18n("V.42bis");
i18n("Vendor Specific");
i18n("Vendor Specific Class");
i18n("Vendor Specific Protocol");
i18n("Vendor Specific Subclass");
i18n("Vendor specific");
// Generated from usb.ids with date '2021-03-31 20:34:09'
i18nc("USB device class", "(Defined at Interface level)");
i18nc("USB device class", "Application Specific Interface");
i18nc("USB device class", "Audio");
i18nc("USB device class", "CDC Data");
i18nc("USB device class", "Chip/SmartCard");
i18nc("USB device class", "Communications");
i18nc("USB device class", "Content Security");
i18nc("USB device class", "Diagnostic");
i18nc("USB device class", "Hub");
i18nc("USB device class", "Human Interface Device");
i18nc("USB device class", "Imaging");
i18nc("USB device class", "Mass Storage");
i18nc("USB device class", "Miscellaneous Device");
i18nc("USB device class", "Physical Interface Device");
i18nc("USB device class", "Printer");
i18nc("USB device class", "Vendor Specific Class");
i18nc("USB device class", "Video");
i18nc("USB device class", "Wireless");
i18nc("USB device class", "Xbox");
i18nc("USB device subclass", "?");
i18nc("USB device subclass", "ATM Networking");
i18nc("USB device subclass", "Abstract (modem)");
i18nc("USB device subclass", "Boot Interface Subclass");
i18nc("USB device subclass", "CAPI Control");
i18nc("USB device subclass", "Control Device");
i18nc("USB device subclass", "Controller");
i18nc("USB device subclass", "Device Firmware Update");
i18nc("USB device subclass", "Device Management");
i18nc("USB device subclass", "Direct Line");
i18nc("USB device subclass", "Ethernet Emulation");
i18nc("USB device subclass", "Ethernet Networking");
i18nc("USB device subclass", "Floppy (UFI)");
i18nc("USB device subclass", "IRDA Bridge");
i18nc("USB device subclass", "MIDI Streaming");
i18nc("USB device subclass", "Mobile Direct Line");
i18nc("USB device subclass", "Multi-Channel");
i18nc("USB device subclass", "No Subclass");
i18nc("USB device subclass", "OBEX");
i18nc("USB device subclass", "Printer");
i18nc("USB device subclass", "QIC-157");
i18nc("USB device subclass", "RBC (typically Flash)");
i18nc("USB device subclass", "Radio Frequency");
i18nc("USB device subclass", "Reprogrammable Diagnostics");
i18nc("USB device subclass", "SCSI");
i18nc("USB device subclass", "SFF-8020i, MMC-2 (ATAPI)");
i18nc("USB device subclass", "SFF-8070i");
i18nc("USB device subclass", "Still Image Capture");
i18nc("USB device subclass", "Streaming");
i18nc("USB device subclass", "Telephone");
i18nc("USB device subclass", "Test and Measurement");
i18nc("USB device subclass", "USB3 Vision");
i18nc("USB device subclass", "Undefined");
i18nc("USB device subclass", "Unused");
i18nc("USB device subclass", "Vendor Specific Subclass");
i18nc("USB device subclass", "Video Control");
i18nc("USB device subclass", "Video Interface Collection");
i18nc("USB device subclass", "Video Streaming");
i18nc("USB device subclass", "Wireless Handset Control");
i18nc("USB device subclass", "Wireless USB Wire Adapter");
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2021 Pino Toscano <pino@debian.org>
# SPDX-License-Identifier: GPL-2.0-or-later
import os
import re
import sys
from collections import namedtuple
UsbIds = namedtuple('UsbIds',
['classes', 'subclasses', 'protocols', 'date'])
def parse(fn):
classes = []
subclasses = []
protocols = []
date = None
class_re = re.compile("^C ([0-9a-fA-F]{2})\\s+(.+)$")
subclass_re = re.compile("^\t([0-9a-fA-F]{2})\\s+(.+)$")
protocol_re = re.compile("^\t\t([0-9a-fA-F]{2})\\s+(.+)$")
with open(fn, 'r', encoding='iso-8859-1') as f:
in_class = False
in_subclass = False
for line in f:
line = line.rstrip('\n')
line_len = len(line)
if line_len > 0 and line[0] == '#':
if line.startswith('# Date:'):
date = line.split(':', maxsplit=1)[1].strip()
continue
if line_len == 0 or (line[0].isalnum() and line[0] != 'C'):
in_class = False
in_subclass = False
continue
m = class_re.fullmatch(line)
if m:
classes.append(m[2].rstrip())
in_class = True
continue
if in_class:
m = subclass_re.fullmatch(line)
if m:
in_subclass = True
subclasses.append(m[2].rstrip())
continue
if in_class and in_subclass:
m = protocol_re.fullmatch(line)
if m:
protocols.append(m[2].rstrip())
continue
in_class = False
in_subclass = False
parsed = UsbIds(classes, subclasses, protocols, date)
return parsed
def output(strings, context):
for s in strings:
print('i18nc("{}", "{}");'.format(context, s))
if __name__ == '__main__':
if len(sys.argv) != 2:
print('Usage: {} /path/to/usb.ids'.format(sys.argv[0]),
file=sys.stderr)
sys.exit(1)
filename = sys.argv[1]
parsed = parse(filename)
classes = sorted(list(set(parsed.classes)))
subclasses = sorted(list(set(parsed.subclasses)))
if parsed.date:
date_str = parsed.date
else:
date_str = 'n/a'
print('// Generated from {} with date \'{}\''.format(
os.path.basename(filename), date_str))
output(classes, 'USB device class')
output(subclasses, 'USB device subclass')
......@@ -226,15 +226,18 @@ QString USBDevice::dump() {
QString c = QStringLiteral("<td>%1</td>").arg(_class);
QString cname = prettyLibusbClassName(_class);
if (cname.isEmpty())
if (cname.isEmpty()) {
cname = _db->cls(_class);
if (!cname.isEmpty())
cname = i18nc("USB device class", cname.toUtf8().constData());
}
if (!cname.isEmpty())
c += QStringLiteral("<td>(") + i18n(cname.toLatin1().constData()) +QStringLiteral(")</td>");
c += QStringLiteral("<td>(") + cname +QStringLiteral(")</td>");
r += i18n("<tr><td><i>Class</i></td>%1</tr>", c);
QString sc = QStringLiteral("<td>%1</td>").arg(_sub);
QString scname = _db->subclass(_class, _sub);
if (!scname.isEmpty())
sc += QStringLiteral("<td>(") + i18n(scname.toLatin1().constData()) +QStringLiteral(")</td>");
sc += QStringLiteral("<td>(") + i18nc("USB device subclass", scname.toLatin1().constData()) +QStringLiteral(")</td>");
r += i18n("<tr><td><i>Subclass</i></td>%1</tr>", sc);
QString pr = QStringLiteral("<td>%1</td>").arg(_prot);
QString prname = _db->protocol(_class, _sub, _prot);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment