diff --git a/lib/logitech_receiver/i18n.py b/lib/logitech_receiver/i18n.py
index 5c6ca195..43210364 100644
--- a/lib/logitech_receiver/i18n.py
+++ b/lib/logitech_receiver/i18n.py
@@ -38,7 +38,7 @@ _DUMMY = (
_("empty"), _("critical"), _("low"), _("good"), _("full"),
# battery charging statuses
- _("discharging"), _("recharging"), _("almost full"), _("full"),
+ _("discharging"), _("recharging"), _("almost full"), _("charged"),
_("slow recharge"), _("invalid battery"), _("thermal error"),
# pairing errors
diff --git a/lib/logitech_receiver/notifications.py b/lib/logitech_receiver/notifications.py
index 7a0d2664..4e4aa4db 100644
--- a/lib/logitech_receiver/notifications.py
+++ b/lib/logitech_receiver/notifications.py
@@ -64,7 +64,7 @@ def _process_receiver_notification(receiver, status, n):
# pairing lock notification
if n.sub_id == 0x4A:
status.lock_open = bool(n.address & 0x01)
- reason = _("pairing lock is ") + (_("open") if status.lock_open else _("closed"))
+ reason = (_("pairing lock is open") if status.lock_open else _("pairing lock is closed"))
if _log.isEnabledFor(_INFO):
_log.info("%s: %s", receiver, reason)
diff --git a/lib/logitech_receiver/status.py b/lib/logitech_receiver/status.py
index 4fb59113..e55381f6 100644
--- a/lib/logitech_receiver/status.py
+++ b/lib/logitech_receiver/status.py
@@ -27,6 +27,7 @@ del getLogger
from .i18n import _
+from gettext import ngettext
from .common import NamedInts as _NamedInts, NamedInt as _NamedInt
from . import hidpp10 as _hidpp10
from . import hidpp20 as _hidpp20
@@ -96,8 +97,7 @@ class ReceiverStatus(dict):
def __str__(self):
count = len(self._receiver)
return (_("No paired devices.") if count == 0 else
- _("1 paired device.") if count == 1 else
- (str(count) + _(" paired devices.")))
+ ngettext("%(count)s paired device.", "%(count)s paired devices.", count) % { 'count': count })
__unicode__ = __str__
def changed(self, alert=ALERT.NOTIFICATION, reason=None):
@@ -146,9 +146,9 @@ class DeviceStatus(dict):
battery_level = self.get(KEYS.BATTERY_LEVEL)
if battery_level is not None:
if isinstance(battery_level, _NamedInt):
- yield _("Battery") + ': ' + _(str(battery_level))
+ yield _("Battery: %(level)s") % { 'level': _(str(battery_level)) }
else:
- yield _("Battery") + ': ' + ('%d%%' % battery_level)
+ yield _("Battery: %(percent)d%%") % { 'percent': battery_level }
battery_status = self.get(KEYS.BATTERY_STATUS)
if battery_status is not None:
@@ -159,7 +159,7 @@ class DeviceStatus(dict):
light_level = self.get(KEYS.LIGHT_LEVEL)
if light_level is not None:
if comma: yield ', '
- yield _("Lighting") + (': %d ' % light_level) + _("lux")
+ yield _("Lighting: %(level)s lux") % { 'level': light_level }
return ''.join(i for i in _items())
@@ -200,9 +200,9 @@ class DeviceStatus(dict):
# only show the notification once
alert = ALERT.NOTIFICATION | ALERT.ATTENTION
if isinstance(level, _NamedInt):
- reason = '%s: %s (%s)' % (_("Battery"), _(str(level)), _(str(status)))
+ reason = _("Battery: %(level)s (%(status)s)") % { 'level': _(level), 'status': _(status) }
else:
- reason = '%s: %d%% (%s)' % (_("Battery"), level, _(str(status)))
+ reason = _("Battery: %(percent)d%% (%(status)s)") % { 'percent': level, 'status': _(status) }
if changed or reason:
# update the leds on the device, if any
diff --git a/lib/solaar/ui/pair_window.py b/lib/solaar/ui/pair_window.py
index aaed4cd8..62958b8e 100644
--- a/lib/solaar/ui/pair_window.py
+++ b/lib/solaar/ui/pair_window.py
@@ -152,7 +152,7 @@ def _pairing_succeeded(assistant, receiver, device):
page = _create_page(assistant, Gtk.AssistantPageType.SUMMARY)
- header = Gtk.Label(_("Found a new device") + ':')
+ header = Gtk.Label(_("Found a new device:"))
header.set_alignment(0.5, 0)
page.pack_start(header, False, False, 0)
@@ -194,7 +194,7 @@ def create(receiver):
assert receiver.kind is None
assistant = Gtk.Assistant()
- assistant.set_title(receiver.name + ': ' + _("pair new device"))
+ assistant.set_title(_('%(receiver_name)s: pair new device') % { 'receiver_name': receiver.name })
assistant.set_icon_name('list-add')
assistant.set_size_request(400, 240)
diff --git a/lib/solaar/ui/window.py b/lib/solaar/ui/window.py
index 5facfd82..6e27e095 100644
--- a/lib/solaar/ui/window.py
+++ b/lib/solaar/ui/window.py
@@ -29,6 +29,7 @@ from gi.repository.GObject import TYPE_PYOBJECT
from solaar import NAME
from solaar.i18n import _
+from gettext import ngettext
# from solaar import __version__ as VERSION
from solaar.ui import async as _ui_async
from logitech_receiver import hidpp10 as _hidpp10
@@ -61,23 +62,6 @@ _TREE_SEPATATOR = (None, 0, False, None, None, None, None, None)
assert len(_TREE_SEPATATOR) == len(_COLUMN_TYPES)
assert len(_COLUMN_TYPES) == len(_COLUMN)
-_TOOLTIP_LINK_SECURE = _("The wireless link between this device and its receiver is encrypted.")
-_TOOLTIP_LINK_INSECURE = _("The wireless link between this device and its receiver is not encrypted.\n"
- "\n"
- "For pointing devices (mice, trackballs, trackpads), this is a minor security issue.\n"
- "\n"
- "It is, however, a major security issue for text-input devices (keyboards, numpads),\n"
- "because typed text can be sniffed inconspicuously by 3rd parties within range.")
-
-_UNIFYING_RECEIVER_TEXT = (
- _("No device paired") + '.\n\n' + _("Up to %d devices can be paired to this receiver") + '.',
- '%d ' + _("paired devices") + '\n\n' + _("Up to %d devices can be paired to this receiver") + '.',
- )
-_NANO_RECEIVER_TEXT = (
- _("No device paired") + '.\n\n ',
- ' \n\n' + _("Only one device can be paired to this receiver") + '.',
- )
-
#
# create UI layout
#
@@ -525,9 +509,9 @@ def _update_details(button):
yield (_("Index"), device.number)
yield (_("Wireless PID"), device.wpid)
hid_version = device.protocol
- yield (_("Protocol"), 'HID++ %1.1f' % hid_version if hid_version else 'unknown')
+ yield (_("Protocol"), 'HID++ %1.1f' % hid_version if hid_version else _('Unknown'))
if read_all and device.polling_rate:
- yield (_("Polling rate"), '%d ms (%dHz)' % (device.polling_rate, 1000 // device.polling_rate))
+ yield (_("Polling rate"), _('%(rate)d ms (%(rate_hz)dHz)') % { 'rate': device.polling_rate, 'rate_hz': 1000 // device.polling_rate })
if read_all or not device.online:
yield (_("Serial"), device.serial)
@@ -578,16 +562,15 @@ def _update_receiver_panel(receiver, panel, buttons, full=False):
assert receiver
devices_count = len(receiver)
- if receiver.max_devices > 1:
- if devices_count == 0:
- panel._count.set_markup(_UNIFYING_RECEIVER_TEXT[0] % receiver.max_devices)
- else:
- panel._count.set_markup(_UNIFYING_RECEIVER_TEXT[1] % (devices_count, receiver.max_devices))
- else:
- if devices_count == 0:
- panel._count.set_markup(_NANO_RECEIVER_TEXT[0])
- else:
- panel._count.set_markup(_NANO_RECEIVER_TEXT[1])
+
+ paired_text = _('No device paired.') if devices_count == 0 else ngettext('%(count)s paired device.', '%(count)s paired devices.', devices_count) % { 'count': devices_count }
+
+ if(receiver.max_devices > 0):
+ paired_text += '\n\n%s' % ngettext('Up to %(max_count)s device can be paired to this receiver.', 'Up to %(max_count)s devices can be paired to this receiver.', receiver.max_devices) % { 'max_count': receiver.max_devices }
+ elif(devices_count > 0):
+ paired_text += '\n\n%s' % _('Only one device can be paired to this receiver.')
+
+ panel._count.set_markup(paired_text)
is_pairing = receiver.status.lock_open
if is_pairing:
@@ -635,7 +618,7 @@ def _update_device_panel(device, panel, buttons, full=False):
if isinstance(battery_level, _NamedInt):
text = _(str(battery_level))
else:
- text = '%d%%' % battery_level
+ text = _("%(battery_percent)d%%") % { 'battery_percent': battery_level }
if is_online:
if charging:
text += ' (%s)' % _("charging")
@@ -649,11 +632,16 @@ def _update_device_panel(device, panel, buttons, full=False):
if not_secure:
panel._secure._text.set_text(_("not encrypted"))
panel._secure._icon.set_from_icon_name('security-low', _INFO_ICON_SIZE)
- panel._secure.set_tooltip_text(_TOOLTIP_LINK_INSECURE)
+ panel._secure.set_tooltip_text(_("The wireless link between this device and its receiver is not encrypted.\n"
+ "\n"
+ "For pointing devices (mice, trackballs, trackpads), this is a minor security issue.\n"
+ "\n"
+ "It is, however, a major security issue for text-input devices (keyboards, numpads),\n"
+ "because typed text can be sniffed inconspicuously by 3rd parties within range."))
else:
panel._secure._text.set_text(_("encrypted"))
panel._secure._icon.set_from_icon_name('security-high', _INFO_ICON_SIZE)
- panel._secure.set_tooltip_text(_TOOLTIP_LINK_SECURE)
+ panel._secure.set_tooltip_text(_("The wireless link between this device and its receiver is encrypted."))
panel._secure._icon.set_visible(True)
else:
panel._secure._text.set_markup('%s' % _("offline"))
@@ -666,7 +654,7 @@ def _update_device_panel(device, panel, buttons, full=False):
panel._lux.set_visible(False)
else:
panel._lux._icon.set_from_icon_name(_icons.lux(light_level), _INFO_ICON_SIZE)
- panel._lux._text.set_text('%d %s' % (light_level, _("lux")))
+ panel._lux._text.set_text(_("%(light_level)d lux") % { 'light_level': light_level })
panel._lux.set_visible(True)
else:
panel._lux.set_visible(False)
@@ -813,9 +801,9 @@ def update(device, need_popup=False):
_model.set_value(item, _COLUMN.STATUS_ICON, _CAN_SET_ROW_NONE)
else:
if isinstance(battery_level, _NamedInt):
- status_text = str(battery_level)
+ status_text = _("%(battery_level)s") % { 'battery_level': _(str(battery_level)) }
else:
- status_text = '%d%%' % battery_level
+ status_text = _("%(battery_percent)d%%") % { 'battery_percent': battery_level }
_model.set_value(item, _COLUMN.STATUS_TEXT, status_text)
charging = device.status.get(_K.BATTERY_CHARGING)