Merge pull request #318 from CanonicalLtd/mwhudson/i18n-updates

updates to make subiquity more translatable
This commit is contained in:
Michael Hudson-Doyle 2018-04-19 12:34:12 +12:00 committed by GitHub
commit 47b5acab92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 47 additions and 40 deletions

View File

@ -14,6 +14,7 @@ subiquitycore/ui/views/network_configure_interface.py
subiquitycore/ui/views/network_configure_manual_interface.py subiquitycore/ui/views/network_configure_manual_interface.py
subiquitycore/ui/views/network_configure_wlan_interface.py subiquitycore/ui/views/network_configure_wlan_interface.py
subiquitycore/ui/views/network.py subiquitycore/ui/views/network.py
subiquity/models/filesystem.py
subiquity/models/installpath.py subiquity/models/installpath.py
subiquity/ui/mount.py subiquity/ui/mount.py
subiquity/ui/views/filesystem/disk_info.py subiquity/ui/views/filesystem/disk_info.py

View File

@ -45,11 +45,11 @@ class KeyboardController(BaseController):
def default(self): def default(self):
if self.model.current_lang is None: if self.model.current_lang is None:
self.model.load_language('C') self.model.load_language('C')
title = "Keyboard configuration" title = _("Keyboard configuration")
if self.opts.run_on_serial: if self.opts.run_on_serial:
excerpt = 'Please select the layout of the keyboard directly attached to the system, if any.' excerpt = _('Please select the layout of the keyboard directly attached to the system, if any.')
else: else:
excerpt = 'Please select your keyboard layout below, or select "Identify keyboard" to detect your layout automatically.' excerpt = _('Please select your keyboard layout below, or select "Identify keyboard" to detect your layout automatically.')
footer = _("Use UP, DOWN and ENTER keys to select your keyboard.") footer = _("Use UP, DOWN and ENTER keys to select your keyboard.")
self.ui.set_header(title, excerpt) self.ui.set_header(title, excerpt)
self.ui.set_footer(footer) self.ui.set_footer(footer)

View File

@ -161,7 +161,7 @@ class Disk:
return align_down(self._info.size) - (2<<20) # The first and last megabyte of the disk are not usable. return align_down(self._info.size) - (2<<20) # The first and last megabyte of the disk are not usable.
def desc(self): def desc(self):
return "local disk" return _("local disk")
@property @property
def label(self): def label(self):
@ -199,7 +199,7 @@ class Partition:
return self._fs return self._fs
def desc(self): def desc(self):
return "partition of {}".format(self.device.desc()) return _("partition of {}").format(self.device.desc())
@property @property
def available(self): def available(self):

View File

@ -55,7 +55,7 @@ class FilesystemConfirmation(Stretchy):
self.parent = parent self.parent = parent
self.controller = controller self.controller = controller
widgets = [ widgets = [
Text(confirmation_text), Text(_(confirmation_text)),
Text(""), Text(""),
button_pile([ button_pile([
cancel_btn(_("No"), on_press=self.cancel), cancel_btn(_("No"), on_press=self.cancel),
@ -120,25 +120,26 @@ class FilesystemView(BaseView):
def _build_filesystem_list(self): def _build_filesystem_list(self):
log.debug('FileSystemView: building part list') log.debug('FileSystemView: building part list')
cols = [] cols = []
longest_path = len("MOUNT POINT") mount_point_text = _("MOUNT POINT")
longest_path = len(mount_point_text)
for m in sorted(self.model._mounts, key=lambda m:m.path): for m in sorted(self.model._mounts, key=lambda m:m.path):
path = m.path path = m.path
longest_path = max(longest_path, len(path)) longest_path = max(longest_path, len(path))
for p, *_ in reversed(cols): for p, *dummy in reversed(cols):
if path.startswith(p): if path.startswith(p):
path = [('info_minor', p), path[len(p):]] path = [('info_minor', p), path[len(p):]]
break break
cols.append((m.path, path, humanize_size(m.device.volume.size), m.device.fstype, m.device.volume.desc())) cols.append((m.path, path, humanize_size(m.device.volume.size), m.device.fstype, m.device.volume.desc()))
for fs in self.model._filesystems: for fs in self.model._filesystems:
if fs.fstype == 'swap': if fs.fstype == 'swap':
cols.append((None, 'SWAP', humanize_size(fs.volume.size), fs.fstype, fs.volume.desc())) cols.append((None, _('SWAP'), humanize_size(fs.volume.size), fs.fstype, fs.volume.desc()))
if len(cols) == 0: if len(cols) == 0:
return Pile([Color.info_minor( return Pile([Color.info_minor(
Text("No disks or partitions mounted."))]) Text(_("No disks or partitions mounted.")))])
cols.insert(0, (None, "MOUNT POINT", "SIZE", "TYPE", "DEVICE TYPE")) cols.insert(0, (None, mount_point_text, _("SIZE"), _("TYPE"), _("DEVICE TYPE")))
pl = [] pl = []
for _, a, b, c, d in cols: for dummy, a, b, c, d in cols:
if b == "SIZE": if b == "SIZE":
b = Text(b, align='center') b = Text(b, align='center')
else: else:
@ -172,7 +173,7 @@ class FilesystemView(BaseView):
inputs.append(Columns([(40, col1)], 1)) inputs.append(Columns([(40, col1)], 1))
inputs = [] inputs = []
col3(Text("DEVICE"), Text("SIZE", align="center"), Text("TYPE")) col3(Text(_("DEVICE")), Text(_("SIZE"), align="center"), Text(_("TYPE")))
r.append(Pile(inputs)) r.append(Pile(inputs))
for disk in self.model.all_disks(): for disk in self.model.all_disks():
@ -183,7 +184,7 @@ class FilesystemView(BaseView):
col3(disk_label, size, typ) col3(disk_label, size, typ)
fs = disk.fs() fs = disk.fs()
if fs is not None: if fs is not None:
label = "entire device, " label = _("entire device, ")
fs_obj = self.model.fs_by_name[fs.fstype] fs_obj = self.model.fs_by_name[fs.fstype]
if fs.mount(): if fs.mount():
label += "%-*s"%(self.model.longest_fs_name+2, fs.fstype+',') + fs.mount().path label += "%-*s"%(self.model.longest_fs_name+2, fs.fstype+',') + fs.mount().path
@ -196,7 +197,7 @@ class FilesystemView(BaseView):
disk_btn = Color.info_minor(Text(" " + label)) disk_btn = Color.info_minor(Text(" " + label))
col1(disk_btn) col1(disk_btn)
for partition in disk.partitions(): for partition in disk.partitions():
label = "partition {}, ".format(partition._number) label = _("partition {}, ").format(partition._number)
fs = partition.fs() fs = partition.fs()
if fs is not None: if fs is not None:
if fs.mount(): if fs.mount():
@ -206,7 +207,7 @@ class FilesystemView(BaseView):
elif partition.flag == "bios_grub": elif partition.flag == "bios_grub":
label += "bios_grub" label += "bios_grub"
else: else:
label += "unformatted" label += _("unformatted")
size = Text("{:>9} ({}%)".format(humanize_size(partition.size), int(100*partition.size/disk.size))) size = Text("{:>9} ({}%)".format(humanize_size(partition.size), int(100*partition.size/disk.size)))
if partition.available: if partition.available:
part_btn = menu_btn(label=label, on_press=self.click_partition, user_arg=partition) part_btn = menu_btn(label=label, on_press=self.click_partition, user_arg=partition)

View File

@ -46,7 +46,7 @@ class GuidedFilesystemView(BaseView):
back = back_btn(_("Back"), on_press=self.cancel) back = back_btn(_("Back"), on_press=self.cancel)
lb = ListBox([ lb = ListBox([
Padding.center_70(Text("")), Padding.center_70(Text("")),
Padding.center_70(Text(text)), Padding.center_70(Text(_(text))),
Padding.center_70(Text("")), Padding.center_70(Text("")),
button_pile([guided, manual, back]), button_pile([guided, manual, back]),
]) ])
@ -67,7 +67,7 @@ class GuidedDiskSelectionView(BaseView):
def __init__(self, model, controller): def __init__(self, model, controller):
self.model = model self.model = model
self.controller = controller self.controller = controller
cancel = cancel_btn("Cancel", on_press=self.cancel) cancel = cancel_btn(_("Cancel"), on_press=self.cancel)
disks = [] disks = []
for disk in self.model.all_disks(): for disk in self.model.all_disks():
disk_btn = forward_btn( disk_btn = forward_btn(

View File

@ -48,7 +48,7 @@ class RealnameEditor(StringEditor, WantsToKnowFormField):
def valid_char(self, ch): def valid_char(self, ch):
if len(ch) == 1 and ch in ':,=': if len(ch) == 1 and ch in ':,=':
self.bff.in_error = True self.bff.in_error = True
self.bff.show_extra(("info_error", "The characters : , and = are not permitted in this field")) self.bff.show_extra(("info_error", _("The characters : , and = are not permitted in this field")))
return False return False
else: else:
return super().valid_char(ch) return super().valid_char(ch)
@ -56,7 +56,7 @@ class RealnameEditor(StringEditor, WantsToKnowFormField):
class UsernameEditor(StringEditor, WantsToKnowFormField): class UsernameEditor(StringEditor, WantsToKnowFormField):
def __init__(self): def __init__(self):
self.valid_char_pat = r'[-a-z0-9_]' self.valid_char_pat = r'[-a-z0-9_]'
self.error_invalid_char = "The only characters permitted in this field are a-z, 0-9, _ and -" self.error_invalid_char = _("The only characters permitted in this field are a-z, 0-9, _ and -")
super().__init__() super().__init__()
def valid_char(self, ch): def valid_char(self, ch):
@ -202,17 +202,17 @@ class IdentityView(BaseView):
def _check_password(self, sender, new_text): def _check_password(self, sender, new_text):
password = self.form.password.value password = self.form.password.value
if not password.startswith(new_text): if not password.startswith(new_text):
self.form.confirm_password.show_extra(("info_error", "Passwords do not match")) self.form.confirm_password.show_extra(("info_error", _("Passwords do not match")))
else: else:
self.form.confirm_password.show_extra('') self.form.confirm_password.show_extra('')
def _select_ssh_import_id(self, sender, val): def _select_ssh_import_id(self, sender, val):
iu = self.form.import_username iu = self.form.import_username
data = _ssh_import_data[val] data = _ssh_import_data[val]
iu.help = data['help'] iu.help = _(data['help'])
iu.caption = data['caption'] iu.caption = _(data['caption'])
iu.widget.valid_char_pat = data['valid_char'] iu.widget.valid_char_pat = data['valid_char']
iu.widget.error_invalid_char = data['error_invalid_char'] iu.widget.error_invalid_char = _(data['error_invalid_char'])
iu.enabled = val is not None iu.enabled = val is not None
if val is not None: if val is not None:
self.form_rows.body.focus += 2 self.form_rows.body.focus += 2

View File

@ -45,7 +45,7 @@ class ProgressView(BaseView):
self.event_listwalker = SimpleFocusListWalker([]) self.event_listwalker = SimpleFocusListWalker([])
self.event_listbox = ListBox(self.event_listwalker) self.event_listbox = ListBox(self.event_listwalker)
self.event_linebox = MyLineBox(self.event_listbox) self.event_linebox = MyLineBox(self.event_listbox)
self.event_buttons = button_pile([other_btn("View full log", on_press=self.view_log)]) self.event_buttons = button_pile([other_btn(_("View full log"), on_press=self.view_log)])
event_body = [ event_body = [
('pack', Text("")), ('pack', Text("")),
('weight', 1, Padding.center_79(self.event_linebox)), ('weight', 1, Padding.center_79(self.event_linebox)),

View File

@ -119,13 +119,16 @@ another layout or run the automated detection again.
model = self.keyboard_detector.keyboard_view.model model = self.keyboard_detector.keyboard_view.model
layout, variant = model.lookup(self.step.result) layout, variant = model.lookup(self.step.result)
var_desc = [] var_desc = []
layout_text = _("Layout")
var_text = _("Variant")
width = max(len(layout_text), len(var_text), 12)
if variant is not None: if variant is not None:
var_desc = [Text(_(" Variant: ") + variant)] var_desc = [Text("%*s: %s"%(width, var_text, variant))]
return Pile([ return Pile([
Text(self.preamble), Text(_(self.preamble)),
Text(_(" Layout: ") + layout), Text("%*s: %s"%(width, layout_text, layout)),
] + var_desc + [ ] + var_desc + [
Text(self.postamble), Text(_(self.postamble)),
button_pile([ok_btn(label=_("OK"), on_press=self.ok)]), button_pile([ok_btn(label=_("OK"), on_press=self.ok)]),
]) ])

View File

@ -420,25 +420,22 @@ class NetworkController(BaseController):
self.ui.set_body(NetworkBondInterfacesView(self.model, self)) self.ui.set_body(NetworkBondInterfacesView(self.model, self))
def network_configure_interface(self, iface): def network_configure_interface(self, iface):
self.ui.set_header("Network interface {}".format(iface)) self.ui.set_header(_("Network interface {}").format(iface))
self.ui.set_footer("") self.ui.set_footer("")
self.ui.set_body(NetworkConfigureInterfaceView(self.model, self, iface)) self.ui.set_body(NetworkConfigureInterfaceView(self.model, self, iface))
def network_configure_ipv4_interface(self, iface): def network_configure_ipv4_interface(self, iface):
self.ui.set_header("Network interface {} manual IPv4 " self.ui.set_header(_("Network interface {} manual IPv4 configuration").format(iface))
"configuration".format(iface))
self.ui.set_footer("") self.ui.set_footer("")
self.ui.set_body(NetworkConfigureIPv4InterfaceView(self.model, self, iface)) self.ui.set_body(NetworkConfigureIPv4InterfaceView(self.model, self, iface))
def network_configure_wlan_interface(self, iface): def network_configure_wlan_interface(self, iface):
self.ui.set_header("Network interface {} WIFI " self.ui.set_header(_("Network interface {} WIFI configuration").format(iface))
"configuration".format(iface))
self.ui.set_footer("") self.ui.set_footer("")
self.ui.set_body(NetworkConfigureWLANView(self.model, self, iface)) self.ui.set_body(NetworkConfigureWLANView(self.model, self, iface))
def network_configure_ipv6_interface(self, iface): def network_configure_ipv6_interface(self, iface):
self.ui.set_header("Network interface {} manual IPv6 " self.ui.set_header(_("Network interface {} manual IPv6 configuration").format(iface))
"configuration".format(iface))
self.ui.set_footer("") self.ui.set_footer("")
self.ui.set_body(NetworkConfigureIPv6InterfaceView(self.model, self, iface)) self.ui.set_body(NetworkConfigureIPv6InterfaceView(self.model, self, iface))

View File

@ -29,11 +29,16 @@ syslog.syslog('Final localedir is ' + localedir)
def switch_language(code='en_US'): def switch_language(code='en_US'):
if code != 'en_US' and 'FAKE_TRANSLATE' in os.environ: if code != 'en_US' and 'FAKE_TRANSLATE' in os.environ:
import builtins def my_gettext(message):
builtins.__dict__['_'] = lambda a: '_(%s)' % a return "_(%s)" % message
elif code: elif code:
translation = gettext.translation('subiquity', localedir=localedir, languages=[code]) translation = gettext.translation('subiquity', localedir=localedir, languages=[code])
translation.install() def my_gettext(message):
if not message:
return message
return translation.gettext(message)
import builtins
builtins.__dict__['_'] = my_gettext
switch_language() switch_language()

View File

@ -184,7 +184,7 @@ class BoundFormField(object):
if self._help is not None: if self._help is not None:
return self._help return self._help
elif self.field.help is not None: elif self.field.help is not None:
return self.field.help return _(self.field.help)
else: else:
return "" return ""