Merge branch 'backcancel'

Closes #234
This commit is contained in:
Dimitri John Ledkov 2017-09-18 17:32:15 +01:00
commit d3ca507cac
No known key found for this signature in database
GPG Key ID: CAC2D8B9CD2CA5F9
34 changed files with 1361 additions and 145 deletions

View File

@ -19,6 +19,7 @@ import sys
import logging
import signal
from subiquitycore.i18n import *
from subiquitycore.log import setup_logger
from subiquitycore import __version__ as VERSION
from subiquitycore.core import ApplicationError

3
debian/control vendored
View File

@ -6,9 +6,11 @@ Build-Depends: bzr,
debhelper (>= 9),
dh-python,
dh-systemd,
iso-codes,
git,
python3,
python3-setuptools,
python3-distutils-extra,
python3-yaml,
python3-attr
Standards-Version: 3.9.5
@ -23,6 +25,7 @@ Depends: curtin,
python3,
python3-attr,
subiquitycore,
iso-codes,
${misc:Depends},
${python3:Depends}
Description: Ubuntu Server Installer

View File

@ -1 +0,0 @@
installer usr/share/subiquity/

View File

@ -1 +1,2 @@
usr/share/subiquity/subiquitycore
usr/share/locale

19
po/POTFILES.in Normal file
View File

@ -0,0 +1,19 @@
[encoding: UTF-8]
subiquity/controllers/filesystem.py
subiquity/controllers/identity.py
subiquity/controllers/installpath.py
subiquity/controllers/installprogress.py
subiquity/controllers/welcome.py
subiquitycore/controllers/network.py
subiquitycore/ui/buttons.py
subiquitycore/ui/interactive.py
subiquitycore/ui/views/network_configure_interface.py
subiquitycore/ui/views/network_configure_manual_interface.py
subiquitycore/ui/views/network.py
subiquity/models/installpath.py
subiquity/ui/mount.py
subiquity/ui/views/filesystem/filesystem.py
subiquity/ui/views/filesystem/guided.py
subiquity/ui/views/identity.py
subiquity/ui/views/installprogress.py
subiquity/ui/views/welcome.py

558
po/en_US.po Normal file
View File

@ -0,0 +1,558 @@
# English translation for subiquity
# Copyright (C) 2017 Canonical Ltd, and Rosetta Contributors 2017
# This file is distributed under the same license as the subiquity package.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: subiquity\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-15 18:29+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../subiquity/controllers/filesystem.py:67
#: ../subiquity/controllers/filesystem.py:74
#: ../subiquity/controllers/filesystem.py:81
msgid "Filesystem setup"
msgstr ""
#: ../subiquity/controllers/filesystem.py:68
msgid "Choose guided or manual partitioning"
msgstr ""
#: ../subiquity/controllers/filesystem.py:75
msgid "Select available disks to format and mount"
msgstr ""
#: ../subiquity/controllers/filesystem.py:82
msgid "Choose the installation target"
msgstr ""
#: ../subiquity/controllers/filesystem.py:96
msgid "Filesystem error"
msgstr ""
#: ../subiquity/controllers/filesystem.py:97
msgid "Error while installing Ubuntu"
msgstr ""
#: ../subiquity/controllers/filesystem.py:98
msgid "Failed to obtain write permissions to /tmp"
msgstr ""
#: ../subiquity/controllers/filesystem.py:140
msgid "Partition, format, and mount {}"
msgstr ""
#: ../subiquity/controllers/filesystem.py:141
msgid "Partition the disk, or format the entire device without partitions"
msgstr ""
#: ../subiquity/controllers/filesystem.py:151
msgid "Select whole disk, or partition, to format and mount."
msgstr ""
#: ../subiquity/controllers/filesystem.py:158
msgid "Edit partition details format and mount."
msgstr ""
#: ../subiquity/controllers/filesystem.py:265
msgid "Create Logical Volume Group (\"LVM2\") disk"
msgstr ""
#: ../subiquity/controllers/filesystem.py:266
#: ../subiquity/controllers/filesystem.py:276
#: ../subiquity/controllers/filesystem.py:289
msgid "ENTER on a disk will show detailed information for that disk"
msgstr ""
#: ../subiquity/controllers/filesystem.py:268
msgid ""
"Use SPACE to select disks to form your LVM2 volume group, and then specify "
"the Volume Group name. "
msgstr ""
#: ../subiquity/controllers/filesystem.py:275
msgid "Create software RAID (\"MD\") disk"
msgstr ""
#: ../subiquity/controllers/filesystem.py:278
msgid ""
"Use SPACE to select disks to form your RAID array, and then specify the RAID "
"parameters. Multiple-disk arrays work best when all the disks in an array "
"are the same size and speed."
msgstr ""
#: ../subiquity/controllers/filesystem.py:288
msgid "Create hierarchical storage (\"bcache\") disk"
msgstr ""
#: ../subiquity/controllers/filesystem.py:291
msgid ""
"Use SPACE to select a cache disk and a backing disk to form your bcache "
"device."
msgstr ""
#: ../subiquity/controllers/filesystem.py:306
msgid "Format and/or mount {}"
msgstr ""
#: ../subiquity/controllers/filesystem.py:307
msgid "Format or mount whole disk."
msgstr ""
#: ../subiquity/controllers/filesystem.py:316
msgid "Mount partition {} of {}"
msgstr ""
#: ../subiquity/controllers/filesystem.py:317
msgid "Mount partition."
msgstr ""
#: ../subiquity/controllers/filesystem.py:319
msgid "Format and mount partition {} of {}"
msgstr ""
#: ../subiquity/controllers/filesystem.py:320
msgid "Format and mount partition."
msgstr ""
#: ../subiquity/controllers/filesystem.py:385
msgid "Select next or previous disks with n and p"
msgstr ""
#: ../subiquity/controllers/identity.py:36
msgid "Profile setup"
msgstr ""
#: ../subiquity/controllers/identity.py:37
msgid ""
"Enter the username and password (or ssh identity) you will use to log in to "
"the system."
msgstr ""
#: ../subiquity/controllers/installpath.py:45
msgid ""
"Welcome to Ubuntu! The world's favorite platform for clouds, clusters, and "
"amazing internet things. This is the installer for Ubuntu on servers and "
"internet devices."
msgstr ""
#: ../subiquity/controllers/installpath.py:49
msgid "Use UP, DOWN arrow keys, and ENTER, to navigate options"
msgstr ""
#: ../subiquity/controllers/installprogress.py:74
msgid "An error occurred during installation"
msgstr ""
#: ../subiquity/controllers/installprogress.py:75
msgid "Please report this error in Launchpad"
msgstr ""
#: ../subiquity/controllers/installprogress.py:76
msgid "An error has occurred."
msgstr ""
#: ../subiquity/controllers/installprogress.py:137
#: ../subiquity/controllers/installprogress.py:228
msgid "Running postinstall step"
msgstr ""
#: ../subiquity/controllers/installprogress.py:165
msgid "Installation complete!"
msgstr ""
#: ../subiquity/controllers/installprogress.py:167
msgid "Finished install!"
msgstr ""
#: ../subiquity/controllers/installprogress.py:215
msgid "Installing system"
msgstr ""
#: ../subiquity/controllers/installprogress.py:216
msgid "Please wait for the installation to finish."
msgstr ""
#: ../subiquity/controllers/installprogress.py:217
msgid "Thank you for using Ubuntu!"
msgstr ""
#: ../subiquity/controllers/installprogress.py:226
msgid "Running install step"
msgstr ""
#: ../subiquity/controllers/welcome.py:31
msgid "Please choose your preferred language"
msgstr ""
#: ../subiquity/controllers/welcome.py:32
msgid "Use UP, DOWN and ENTER keys to select your language."
msgstr ""
#: ../subiquitycore/controllers/network.py:347
msgid "Network connections"
msgstr ""
#: ../subiquitycore/controllers/network.py:348
msgid ""
"Configure at least one interface this server can use to talk to other "
"machines, and which preferably provides sufficient access for updates."
msgstr ""
#: ../subiquitycore/controllers/network.py:351
msgid "Select an interface to configure it or select Done to continue"
msgstr ""
#: ../subiquitycore/ui/buttons.py:37
msgid "Start"
msgstr ""
#: ../subiquitycore/ui/buttons.py:38
msgid "Save"
msgstr ""
#: ../subiquitycore/ui/buttons.py:39
msgid "Finish"
msgstr ""
#: ../subiquitycore/ui/buttons.py:40
msgid "OK"
msgstr ""
#: ../subiquitycore/ui/buttons.py:41
msgid "Confirm"
msgstr ""
#: ../subiquitycore/ui/buttons.py:42
msgid "Done"
msgstr ""
#: ../subiquitycore/ui/buttons.py:43
#: ../subiquity/ui/views/filesystem/filesystem.py:60
msgid "Continue"
msgstr ""
#: ../subiquitycore/ui/buttons.py:45
msgid "Reset"
msgstr ""
#: ../subiquitycore/ui/buttons.py:47
msgid "Cancel"
msgstr ""
#: ../subiquitycore/ui/buttons.py:48
msgid "Back"
msgstr ""
#: ../subiquitycore/ui/interactive.py:114
msgid "Yes"
msgstr ""
#: ../subiquitycore/ui/interactive.py:114
#: ../subiquity/ui/views/filesystem/filesystem.py:59
msgid "No"
msgstr ""
#: ../subiquitycore/ui/interactive.py:121
msgid "Close"
msgstr ""
#: ../subiquitycore/ui/interactive.py:122
msgid "Help"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:66
msgid "Use a static IPv4 configuration"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:69
msgid "Use DHCPv4 on this interface"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:72
#: ../subiquitycore/ui/views/network_configure_interface.py:91
msgid "Do not use"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:85
msgid "Use a static IPv6 configuration"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:88
msgid "Use DHCPv6 on this interface"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:102
msgid "Configure WIFI settings"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:67
msgid "Subnet:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:68
msgid "Address:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:69
msgid "Gateway:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:70
msgid "Name servers:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:70
msgid "IP addresses, comma separated"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:71
msgid "Search domains:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:71
msgid "Domains, comma separated"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:122
#, python-format
msgid "CIDR e.g. %s"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:158
msgid "Set this as default gateway"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:161
msgid "This will be your default gateway"
msgstr ""
#: ../subiquitycore/ui/views/network.py:51
msgid "Applying network config"
msgstr ""
#: ../subiquitycore/ui/views/network.py:65
#, python-format
msgid "Associated to '%s', will associate to '%s'"
msgstr ""
#: ../subiquitycore/ui/views/network.py:67
#, python-format
msgid "Associated to '%s'"
msgstr ""
#: ../subiquitycore/ui/views/network.py:69
#, python-format
msgid "No access point configured, but associated to '%s'"
msgstr ""
#: ../subiquitycore/ui/views/network.py:72
#, python-format
msgid "Will associate to '%s'"
msgstr ""
#: ../subiquitycore/ui/views/network.py:74
msgid "No access point configured"
msgstr ""
#: ../subiquitycore/ui/views/network.py:94
#, python-format
msgid "Will use DHCP for IPv%s, currently has address%%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:95
#, python-format
msgid "Will use DHCP for IPv%s"
msgstr ""
#: ../subiquitycore/ui/views/network.py:98
#, python-format
msgid "Using static address%%s for IPv%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:99
#, python-format
msgid "Will use static address%%s for IPv%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:101
#, python-format
msgid "Currently has address%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:104
#, python-format
msgid "Has no IPv%s configuration, currently has address%%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:106
#, python-format
msgid "IPv%s is not configured"
msgstr ""
#: ../subiquitycore/ui/views/network.py:165
msgid "Not connected"
msgstr ""
#: ../subiquitycore/ui/views/network.py:204
#, python-format
msgid " IPv4 default route %s."
msgstr ""
#: ../subiquity/models/installpath.py:31
msgid "Install Ubuntu"
msgstr ""
#: ../subiquity/ui/mount.py:53
msgid "other"
msgstr ""
#: ../subiquity/ui/mount.py:55
msgid "leave unmounted"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:47
msgid ""
"\n"
"Selecting Continue below will result of the loss of data on the disks "
"selected to be formatted.\n"
"\n"
"Are you sure you want to continue?\n"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:63
msgid "Confirm destructive action"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:80
msgid "FILE SYSTEM SUMMARY"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:84
msgid "AVAILABLE DEVICES"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:208
msgid "ADD/EDIT PARTITIONS"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:211
msgid "ADD FIRST PARTITION"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:214
msgid "EDIT PARTITIONS"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:222
msgid "No disks available."
msgstr ""
#: ../subiquity/ui/views/filesystem/guided.py:33
msgid ""
"The installer can guide you through partitioning a disk or, if you prefer, "
"you can do it manually. If you choose guided partitioning you will still "
"have a chance to review and modify the results."
msgstr ""
#: ../subiquity/ui/views/filesystem/guided.py:42
msgid "Guided"
msgstr ""
#: ../subiquity/ui/views/filesystem/guided.py:43
msgid "Manual"
msgstr ""
#: ../subiquity/ui/views/filesystem/guided.py:78
msgid "Choose the disk to install to:"
msgstr ""
#: ../subiquity/ui/views/identity.py:49
msgid "Your name:"
msgstr ""
#: ../subiquity/ui/views/identity.py:51
msgid "Your server's name:"
msgstr ""
#: ../subiquity/ui/views/identity.py:52
msgid "The name it uses when it talks to other computers."
msgstr ""
#: ../subiquity/ui/views/identity.py:53
msgid "Pick a username:"
msgstr ""
#: ../subiquity/ui/views/identity.py:54
msgid "Choose a password:"
msgstr ""
#: ../subiquity/ui/views/identity.py:55
msgid "Confirm your password:"
msgstr ""
#: ../subiquity/ui/views/identity.py:57
msgid "Import SSH identity:"
msgstr ""
#: ../subiquity/ui/views/identity.py:58
msgid ""
"Input your SSH user id from Ubuntu SSO (sso:email), Launchpad (lp:username) "
"or Github (gh:username)."
msgstr ""
#: ../subiquity/ui/views/identity.py:63
msgid "Real name must not be empty."
msgstr ""
#: ../subiquity/ui/views/identity.py:65
msgid "Realname too long, must be < "
msgstr ""
#: ../subiquity/ui/views/identity.py:69
msgid "Server name must not be empty"
msgstr ""
#: ../subiquity/ui/views/identity.py:72
msgid "Server name too long, must be < "
msgstr ""
#: ../subiquity/ui/views/identity.py:76
msgid "Username missing"
msgstr ""
#: ../subiquity/ui/views/identity.py:79
msgid "Username too long, must be < "
msgstr ""
#: ../subiquity/ui/views/identity.py:85
msgid "Password must be set"
msgstr ""
#: ../subiquity/ui/views/identity.py:89
msgid "Passwords do not match"
msgstr ""
#: ../subiquity/ui/views/identity.py:94
msgid "SSH id too long, must be < "
msgstr ""
#: ../subiquity/ui/views/installprogress.py:65
msgid "Reboot Now"
msgstr ""
#: ../subiquity/ui/views/installprogress.py:68
msgid "Quit Installer"
msgstr ""
#: ../subiquity/ui/views/welcome.py:40
msgid "(More language choices will appear in time)"
msgstr ""

558
po/ru.po Normal file
View File

@ -0,0 +1,558 @@
# Russian translation for subiquity
# Copyright (C) 2017 Canonical Ltd, and Rosetta Contributors 2017
# This file is distributed under the same license as the subiquity package.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: subiquity\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-15 18:41+0100\n"
"PO-Revision-Date: 2017-09-04 14:44+0100\n"
"Last-Translator: Dimitri Ledkov <xnox@ubuntu.com>\n"
"Language-Team: Russian <ru@li.org>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../subiquity/controllers/filesystem.py:67
#: ../subiquity/controllers/filesystem.py:74
#: ../subiquity/controllers/filesystem.py:81
msgid "Filesystem setup"
msgstr ""
#: ../subiquity/controllers/filesystem.py:68
msgid "Choose guided or manual partitioning"
msgstr ""
#: ../subiquity/controllers/filesystem.py:75
msgid "Select available disks to format and mount"
msgstr ""
#: ../subiquity/controllers/filesystem.py:82
msgid "Choose the installation target"
msgstr ""
#: ../subiquity/controllers/filesystem.py:96
msgid "Filesystem error"
msgstr ""
#: ../subiquity/controllers/filesystem.py:97
msgid "Error while installing Ubuntu"
msgstr ""
#: ../subiquity/controllers/filesystem.py:98
msgid "Failed to obtain write permissions to /tmp"
msgstr ""
#: ../subiquity/controllers/filesystem.py:140
msgid "Partition, format, and mount {}"
msgstr ""
#: ../subiquity/controllers/filesystem.py:141
msgid "Partition the disk, or format the entire device without partitions"
msgstr ""
#: ../subiquity/controllers/filesystem.py:151
msgid "Select whole disk, or partition, to format and mount."
msgstr ""
#: ../subiquity/controllers/filesystem.py:158
msgid "Edit partition details format and mount."
msgstr ""
#: ../subiquity/controllers/filesystem.py:265
msgid "Create Logical Volume Group (\"LVM2\") disk"
msgstr ""
#: ../subiquity/controllers/filesystem.py:266
#: ../subiquity/controllers/filesystem.py:276
#: ../subiquity/controllers/filesystem.py:289
msgid "ENTER on a disk will show detailed information for that disk"
msgstr ""
#: ../subiquity/controllers/filesystem.py:268
msgid ""
"Use SPACE to select disks to form your LVM2 volume group, and then specify "
"the Volume Group name. "
msgstr ""
#: ../subiquity/controllers/filesystem.py:275
msgid "Create software RAID (\"MD\") disk"
msgstr ""
#: ../subiquity/controllers/filesystem.py:278
msgid ""
"Use SPACE to select disks to form your RAID array, and then specify the RAID "
"parameters. Multiple-disk arrays work best when all the disks in an array "
"are the same size and speed."
msgstr ""
#: ../subiquity/controllers/filesystem.py:288
msgid "Create hierarchical storage (\"bcache\") disk"
msgstr ""
#: ../subiquity/controllers/filesystem.py:291
msgid ""
"Use SPACE to select a cache disk and a backing disk to form your bcache "
"device."
msgstr ""
#: ../subiquity/controllers/filesystem.py:306
msgid "Format and/or mount {}"
msgstr ""
#: ../subiquity/controllers/filesystem.py:307
msgid "Format or mount whole disk."
msgstr ""
#: ../subiquity/controllers/filesystem.py:316
msgid "Mount partition {} of {}"
msgstr ""
#: ../subiquity/controllers/filesystem.py:317
msgid "Mount partition."
msgstr ""
#: ../subiquity/controllers/filesystem.py:319
msgid "Format and mount partition {} of {}"
msgstr ""
#: ../subiquity/controllers/filesystem.py:320
msgid "Format and mount partition."
msgstr ""
#: ../subiquity/controllers/filesystem.py:385
msgid "Select next or previous disks with n and p"
msgstr ""
#: ../subiquity/controllers/identity.py:36
msgid "Profile setup"
msgstr ""
#: ../subiquity/controllers/identity.py:37
msgid ""
"Enter the username and password (or ssh identity) you will use to log in to "
"the system."
msgstr ""
#: ../subiquity/controllers/installpath.py:45
msgid ""
"Welcome to Ubuntu! The world's favorite platform for clouds, clusters, and "
"amazing internet things. This is the installer for Ubuntu on servers and "
"internet devices."
msgstr ""
#: ../subiquity/controllers/installpath.py:49
msgid "Use UP, DOWN arrow keys, and ENTER, to navigate options"
msgstr ""
#: ../subiquity/controllers/installprogress.py:74
msgid "An error occurred during installation"
msgstr ""
#: ../subiquity/controllers/installprogress.py:75
msgid "Please report this error in Launchpad"
msgstr ""
#: ../subiquity/controllers/installprogress.py:76
msgid "An error has occurred."
msgstr ""
#: ../subiquity/controllers/installprogress.py:137
#: ../subiquity/controllers/installprogress.py:228
msgid "Running postinstall step"
msgstr ""
#: ../subiquity/controllers/installprogress.py:165
msgid "Installation complete!"
msgstr ""
#: ../subiquity/controllers/installprogress.py:167
msgid "Finished install!"
msgstr ""
#: ../subiquity/controllers/installprogress.py:215
msgid "Installing system"
msgstr ""
#: ../subiquity/controllers/installprogress.py:216
msgid "Please wait for the installation to finish."
msgstr ""
#: ../subiquity/controllers/installprogress.py:217
msgid "Thank you for using Ubuntu!"
msgstr ""
#: ../subiquity/controllers/installprogress.py:226
msgid "Running install step"
msgstr ""
#: ../subiquity/controllers/welcome.py:31
msgid "Please choose your preferred language"
msgstr "Выберите предпочитаемый язык"
#: ../subiquity/controllers/welcome.py:32
msgid "Use UP, DOWN and ENTER keys to select your language."
msgstr ""
#: ../subiquitycore/controllers/network.py:347
msgid "Network connections"
msgstr ""
#: ../subiquitycore/controllers/network.py:348
msgid ""
"Configure at least one interface this server can use to talk to other "
"machines, and which preferably provides sufficient access for updates."
msgstr ""
#: ../subiquitycore/controllers/network.py:351
msgid "Select an interface to configure it or select Done to continue"
msgstr ""
#: ../subiquitycore/ui/buttons.py:37
msgid "Start"
msgstr ""
#: ../subiquitycore/ui/buttons.py:38
msgid "Save"
msgstr ""
#: ../subiquitycore/ui/buttons.py:39
msgid "Finish"
msgstr ""
#: ../subiquitycore/ui/buttons.py:40
msgid "OK"
msgstr ""
#: ../subiquitycore/ui/buttons.py:41
msgid "Confirm"
msgstr ""
#: ../subiquitycore/ui/buttons.py:42
msgid "Done"
msgstr ""
#: ../subiquitycore/ui/buttons.py:43
#: ../subiquity/ui/views/filesystem/filesystem.py:60
msgid "Continue"
msgstr "Продолжить"
#: ../subiquitycore/ui/buttons.py:45
msgid "Reset"
msgstr ""
#: ../subiquitycore/ui/buttons.py:47
msgid "Cancel"
msgstr "Отменить"
#: ../subiquitycore/ui/buttons.py:48
msgid "Back"
msgstr ""
#: ../subiquitycore/ui/interactive.py:114
msgid "Yes"
msgstr ""
#: ../subiquitycore/ui/interactive.py:114
#: ../subiquity/ui/views/filesystem/filesystem.py:59
msgid "No"
msgstr ""
#: ../subiquitycore/ui/interactive.py:121
msgid "Close"
msgstr ""
#: ../subiquitycore/ui/interactive.py:122
msgid "Help"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:66
msgid "Use a static IPv4 configuration"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:69
msgid "Use DHCPv4 on this interface"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:72
#: ../subiquitycore/ui/views/network_configure_interface.py:91
msgid "Do not use"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:85
msgid "Use a static IPv6 configuration"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:88
msgid "Use DHCPv6 on this interface"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_interface.py:102
msgid "Configure WIFI settings"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:67
msgid "Subnet:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:68
msgid "Address:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:69
msgid "Gateway:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:70
msgid "Name servers:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:70
msgid "IP addresses, comma separated"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:71
msgid "Search domains:"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:71
msgid "Domains, comma separated"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:122
#, python-format
msgid "CIDR e.g. %s"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:158
msgid "Set this as default gateway"
msgstr ""
#: ../subiquitycore/ui/views/network_configure_manual_interface.py:161
msgid "This will be your default gateway"
msgstr ""
#: ../subiquitycore/ui/views/network.py:51
msgid "Applying network config"
msgstr ""
#: ../subiquitycore/ui/views/network.py:65
#, python-format
msgid "Associated to '%s', will associate to '%s'"
msgstr ""
#: ../subiquitycore/ui/views/network.py:67
#, python-format
msgid "Associated to '%s'"
msgstr ""
#: ../subiquitycore/ui/views/network.py:69
#, python-format
msgid "No access point configured, but associated to '%s'"
msgstr ""
#: ../subiquitycore/ui/views/network.py:72
#, python-format
msgid "Will associate to '%s'"
msgstr ""
#: ../subiquitycore/ui/views/network.py:74
msgid "No access point configured"
msgstr ""
#: ../subiquitycore/ui/views/network.py:94
#, python-format
msgid "Will use DHCP for IPv%s, currently has address%%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:95
#, python-format
msgid "Will use DHCP for IPv%s"
msgstr ""
#: ../subiquitycore/ui/views/network.py:98
#, python-format
msgid "Using static address%%s for IPv%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:99
#, python-format
msgid "Will use static address%%s for IPv%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:101
#, python-format
msgid "Currently has address%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:104
#, python-format
msgid "Has no IPv%s configuration, currently has address%%s:"
msgstr ""
#: ../subiquitycore/ui/views/network.py:106
#, python-format
msgid "IPv%s is not configured"
msgstr ""
#: ../subiquitycore/ui/views/network.py:165
msgid "Not connected"
msgstr ""
#: ../subiquitycore/ui/views/network.py:204
#, python-format
msgid " IPv4 default route %s."
msgstr ""
#: ../subiquity/models/installpath.py:31
msgid "Install Ubuntu"
msgstr ""
#: ../subiquity/ui/mount.py:53
msgid "other"
msgstr "другое"
#: ../subiquity/ui/mount.py:55
msgid "leave unmounted"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:47
msgid ""
"\n"
"Selecting Continue below will result of the loss of data on the disks "
"selected to be formatted.\n"
"\n"
"Are you sure you want to continue?\n"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:63
msgid "Confirm destructive action"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:80
msgid "FILE SYSTEM SUMMARY"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:84
msgid "AVAILABLE DEVICES"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:208
msgid "ADD/EDIT PARTITIONS"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:211
msgid "ADD FIRST PARTITION"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:214
msgid "EDIT PARTITIONS"
msgstr ""
#: ../subiquity/ui/views/filesystem/filesystem.py:222
msgid "No disks available."
msgstr ""
#: ../subiquity/ui/views/filesystem/guided.py:33
msgid ""
"The installer can guide you through partitioning a disk or, if you prefer, "
"you can do it manually. If you choose guided partitioning you will still "
"have a chance to review and modify the results."
msgstr ""
#: ../subiquity/ui/views/filesystem/guided.py:42
msgid "Guided"
msgstr ""
#: ../subiquity/ui/views/filesystem/guided.py:43
msgid "Manual"
msgstr ""
#: ../subiquity/ui/views/filesystem/guided.py:78
msgid "Choose the disk to install to:"
msgstr ""
#: ../subiquity/ui/views/identity.py:49
msgid "Your name:"
msgstr ""
#: ../subiquity/ui/views/identity.py:51
msgid "Your server's name:"
msgstr ""
#: ../subiquity/ui/views/identity.py:52
msgid "The name it uses when it talks to other computers."
msgstr ""
#: ../subiquity/ui/views/identity.py:53
msgid "Pick a username:"
msgstr ""
#: ../subiquity/ui/views/identity.py:54
msgid "Choose a password:"
msgstr ""
#: ../subiquity/ui/views/identity.py:55
msgid "Confirm your password:"
msgstr ""
#: ../subiquity/ui/views/identity.py:57
msgid "Import SSH identity:"
msgstr ""
#: ../subiquity/ui/views/identity.py:58
msgid ""
"Input your SSH user id from Ubuntu SSO (sso:email), Launchpad (lp:username) "
"or Github (gh:username)."
msgstr ""
#: ../subiquity/ui/views/identity.py:63
msgid "Real name must not be empty."
msgstr ""
#: ../subiquity/ui/views/identity.py:65
msgid "Realname too long, must be < "
msgstr ""
#: ../subiquity/ui/views/identity.py:69
msgid "Server name must not be empty"
msgstr ""
#: ../subiquity/ui/views/identity.py:72
msgid "Server name too long, must be < "
msgstr ""
#: ../subiquity/ui/views/identity.py:76
msgid "Username missing"
msgstr ""
#: ../subiquity/ui/views/identity.py:79
msgid "Username too long, must be < "
msgstr ""
#: ../subiquity/ui/views/identity.py:85
msgid "Password must be set"
msgstr ""
#: ../subiquity/ui/views/identity.py:89
msgid "Passwords do not match"
msgstr ""
#: ../subiquity/ui/views/identity.py:94
msgid "SSH id too long, must be < "
msgstr ""
#: ../subiquity/ui/views/installprogress.py:65
msgid "Reboot Now"
msgstr ""
#: ../subiquity/ui/views/installprogress.py:68
msgid "Quit Installer"
msgstr ""
#: ../subiquity/ui/views/welcome.py:40
msgid "(More language choices will appear in time)"
msgstr ""

2
setup.cfg Normal file
View File

@ -0,0 +1,2 @@
[build_i18n]
domain=subiquity

View File

@ -23,6 +23,8 @@ Ubuntu Server Installer
"""
from setuptools import setup, find_packages
from DistUtilsExtra.command import build_extra
from DistUtilsExtra.command import build_i18n
import os
import sys
@ -43,4 +45,6 @@ setup(name='subiquity',
url='https://github.com/CanonicalLtd/subiquity',
license="AGPLv3+",
packages=find_packages(exclude=["tests"]),
cmdclass={'build': build_extra.build_extra,
'build_i18n': build_i18n.build_i18n, },
data_files=[])

View File

@ -15,8 +15,8 @@ apps:
parts:
subiquity:
plugin: python
build-packages: [python-setuptools, pkg-config, lsb-release]
stage-packages: [curtin, lsb-release]
build-packages: [pkg-config, lsb-release, python3-distutils-extra]
stage-packages: [curtin, lsb-release, python3-distutils-extra, iso-codes]
python-packages:
- urwid
- pyyaml

View File

@ -64,22 +64,22 @@ class FilesystemController(BaseController):
if self.model.any_configuration_done():
self.manual()
else:
title = "Filesystem setup"
footer = ("Choose guided or manual partitioning")
title = _("Filesystem setup")
footer = (_("Choose guided or manual partitioning"))
self.ui.set_header(title)
self.ui.set_footer(footer, 30)
self.ui.set_body(GuidedFilesystemView(self.model, self))
def manual(self):
title = "Filesystem setup"
footer = ("Select available disks to format and mount")
title = _("Filesystem setup")
footer = (_("Select available disks to format and mount"))
self.ui.set_header(title)
self.ui.set_footer(footer, 30)
self.ui.set_body(FilesystemView(self.model, self))
def guided(self):
title = "Filesystem setup"
footer = ("Choose the installation target")
title = _("Filesystem setup")
footer = (_("Choose the installation target"))
self.ui.set_header(title)
self.ui.set_footer(footer, 30)
self.ui.set_body(GuidedDiskSelectionView(self.model, self))
@ -93,9 +93,9 @@ class FilesystemController(BaseController):
self.signal.emit_signal('prev-screen')
def filesystem_error(self, error_fname):
title = "Filesystem error"
footer = ("Error while installing Ubuntu")
error_msg = "Failed to obtain write permissions to /tmp"
title = _("Filesystem error")
footer = (_("Error while installing Ubuntu"))
error_msg = _("Failed to obtain write permissions to /tmp")
self.ui.set_header(title)
self.ui.set_footer(footer, 30)
self.ui.set_body(ErrorView(self.signal, error_msg))
@ -137,9 +137,9 @@ class FilesystemController(BaseController):
# Filesystem/Disk partition -----------------------------------------------
def partition_disk(self, disk):
log.debug("In disk partition view, using {} as the disk.".format(disk.serial))
title = ("Partition, format, and mount {}".format(disk.serial))
footer = ("Partition the disk, or format the entire device "
"without partitions")
title = (_("Partition, format, and mount {}").format(disk.serial))
footer = (_("Partition the disk, or format the entire device "
"without partitions"))
self.ui.set_header(title)
self.ui.set_footer(footer)
dp_view = DiskPartitionView(self.model, self, disk)
@ -148,14 +148,14 @@ class FilesystemController(BaseController):
def add_disk_partition(self, disk):
log.debug("Adding partition to {}".format(disk))
footer = ("Select whole disk, or partition, to format and mount.")
footer = _("Select whole disk, or partition, to format and mount.")
self.ui.set_footer(footer)
adp_view = PartitionView(self.model, self, disk)
self.ui.set_body(adp_view)
def edit_partition(self, disk, partition):
log.debug("Editing partition {}".format(partition))
footer = ("Edit partition details format and mount.")
footer = _("Edit partition details format and mount.")
self.ui.set_footer(footer)
adp_view = PartitionView(self.model, self, disk, partition)
self.ui.set_body(adp_view)
@ -303,8 +303,8 @@ class FilesystemController(BaseController):
def format_entire(self, disk):
log.debug("format_entire {}".format(disk.serial))
header = ("Format and/or mount {}".format(disk.serial))
footer = ("Format or mount whole disk.")
header = (_("Format and/or mount {}").format(disk.serial))
footer = _("Format or mount whole disk.")
self.ui.set_header(header)
self.ui.set_footer(footer)
afv_view = FormatEntireView(self.model, self, disk, lambda : self.partition_disk(disk))
@ -313,11 +313,11 @@ class FilesystemController(BaseController):
def format_mount_partition(self, partition):
log.debug("format_entire {}".format(partition))
if partition.fs() is not None:
header = ("Mount partition {} of {}".format(partition.number, partition.device.serial))
footer = ("Mount partition.")
header = (_("Mount partition {} of {}").format(partition.number, partition.device.serial))
footer = _("Mount partition.")
else:
header = ("Format and mount partition {} of {}".format(partition.number, partition.device.serial))
footer = ("Format and mount partition.")
header = (_("Format and mount partition {} of {}").format(partition.number, partition.device.serial))
footer = _("Format and mount partition.")
self.ui.set_header(header)
self.ui.set_footer(footer)
afv_view = FormatEntireView(self.model, self, partition, self.default)
@ -382,7 +382,7 @@ class FilesystemController(BaseController):
result = template.format(**dinfo)
log.debug('calling DiskInfoView()')
disk_info_view = DiskInfoView(self.model, self, disk, result)
footer = ('Select next or previous disks with n and p')
footer = _('Select next or previous disks with n and p')
self.ui.set_footer(footer, 30)
self.ui.set_body(disk_info_view)

View File

@ -33,8 +33,8 @@ class IdentityController(BaseController):
self.model = IdentityModel(self.opts)
def default(self):
title = "Profile setup"
excerpt = ("Enter the username and password (or ssh identity) you will use to log in to the system.")
title = _("Profile setup")
excerpt = _("Enter the username and password (or ssh identity) you will use to log in to the system.")
footer = ""
self.ui.set_header(title, excerpt)
self.ui.set_footer(footer, 40)

View File

@ -42,11 +42,11 @@ class InstallpathController(BaseController):
def installpath(self):
title = "Ubuntu %s"%(lsb_release.get_distro_information()['RELEASE'],)
excerpt = ("Welcome to Ubuntu! The world's favorite platform "
excerpt = _("Welcome to Ubuntu! The world's favorite platform "
"for clouds, clusters, and amazing internet things. "
"This is the installer for Ubuntu on servers and "
"internet devices.")
footer = ("Use UP, DOWN arrow keys, and ENTER, to "
footer = _("Use UP, DOWN arrow keys, and ENTER, to "
"navigate options")
self.ui.set_header(title, excerpt)

View File

@ -71,9 +71,9 @@ class InstallProgressController(BaseController):
def curtin_error(self):
log.debug('curtin_error')
title = ('An error occurred during installation')
self.ui.set_header(title, 'Please report this error in Launchpad')
self.ui.set_footer("An error has occurred.", 100)
title = _('An error occurred during installation')
self.ui.set_header(title, _('Please report this error in Launchpad'))
self.ui.set_footer(_("An error has occurred."), 100)
if self.progress_view is not None:
self.progress_view.set_status(('info_error', "An error has occurred"))
self.progress_view.show_complete()
@ -134,7 +134,7 @@ class InstallProgressController(BaseController):
self.install_state = InstallState.RUNNING_POSTINSTALL
if self.progress_view is not None:
self.progress_view.clear_log_tail()
self.progress_view.set_status("Running postinstall step")
self.progress_view.set_status(_("Running postinstall step"))
self.start_tail_proc()
if self.opts.dry_run:
log.debug("Installprogress: this is a dry-run")
@ -162,9 +162,9 @@ class InstallProgressController(BaseController):
return
log.debug('After curtin postinstall OK')
self.install_state = InstallState.DONE_POSTINSTALL
self.ui.set_header("Installation complete!", "")
self.ui.set_header(_("Installation complete!"), "")
self.ui.set_footer("", 100)
self.progress_view.set_status("Finished install!")
self.progress_view.set_status(_("Finished install!"))
self.progress_view.show_complete()
def update_log_tail(self):
@ -212,9 +212,9 @@ class InstallProgressController(BaseController):
def default(self):
log.debug('show_progress called')
title = ("Installing system")
excerpt = ("Please wait for the installation to finish.")
footer = ("Thank you for using Ubuntu!")
title = _("Installing system")
excerpt = _("Please wait for the installation to finish.")
footer = _("Thank you for using Ubuntu!")
self.ui.set_header(title, excerpt)
self.ui.set_footer(footer, 90)
self.progress_view = ProgressView(self.model, self)
@ -223,9 +223,9 @@ class InstallProgressController(BaseController):
self.ui.set_body(self.progress_view)
return
if self.install_state < InstallState.RUNNING_POSTINSTALL:
self.progress_view.set_status("Running install step")
self.progress_view.set_status(_("Running install step"))
else:
self.progress_view.set_status("Running postinstall step")
self.progress_view.set_status(_("Running postinstall step"))
self.ui.set_body(self.progress_view)
self.start_tail_proc()

View File

@ -27,9 +27,9 @@ class WelcomeController(BaseController):
self.model = WelcomeModel()
def default(self):
title = "Wilkommen! Bienvenue! Welcome! Zdrastvutie! Welkom!"
excerpt = "Please choose your preferred language"
footer = ("Use UP, DOWN and ENTER keys to select your language.")
title = "Willkommen! Bienvenue! Welcome! Добро пожаловать! Welkom!"
excerpt = _("Please choose your preferred language")
footer = _("Use UP, DOWN and ENTER keys to select your language.")
self.ui.set_header(title, excerpt)
self.ui.set_footer(footer)
view = WelcomeView(self.model, self)

View File

@ -26,14 +26,16 @@ class InstallpathModel(object):
('UI Text seen by user', <signal name>, <callback function string>)
"""
# TODO: Re-enable once available
install_paths = [
('Install Ubuntu', 'installpath:install-ubuntu'),
# ('Install MAAS Region Server', 'installpath:maas-region-server'),
# ('Install MAAS Cluster Server', 'installpath:maas-cluster-server'),
# ('Test installation media', 'installpath:test-media'),
# ('Test machine memory', 'installpath:test-memory')
]
def _refresh_install_paths(self):
# TODO: Re-enable once available
self.install_paths = [
(_('Install Ubuntu'), 'installpath:install-ubuntu'),
# ('Install MAAS Region Server', 'installpath:maas-region-server'),
# ('Install MAAS Cluster Server', 'installpath:maas-cluster-server'),
# ('Test installation media', 'installpath:test-media'),
# ('Test machine memory', 'installpath:test-memory')
]
def get_menu(self):
self._refresh_install_paths()
return self.install_paths

View File

@ -13,8 +13,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import gettext
import logging
from subiquitycore import i18n
log = logging.getLogger('subiquity.models.welcome')
@ -23,13 +24,26 @@ class WelcomeModel(object):
""" Model representing language selection
"""
supported_languages = [
('English', 'en_US'),
]
supported_languages = [('en_US', 'English'), ('ru_RU', 'Russian')]
selected_language = None
def get_languages(self):
return self.supported_languages
languages = []
for code, name in self.supported_languages:
label = name
native = name
if gettext.find('iso_639_3'):
cur_lang = gettext.translation('iso_639_3')
label = cur_lang.gettext(name).capitalize()
if gettext.find('iso_639_3', languages=[code]):
native_lang = gettext.translation('iso_639_3', languages=[code])
native = native_lang.gettext(name).capitalize()
languages.append((code, label, native))
return languages
def switch_language(self, code):
self.selected_language = code
i18n.switch_language(code)
def __repr__(self):
return "<Selected: {}>".format(self.selected_language)

View File

@ -50,9 +50,9 @@ class MountSelector(WidgetWrap):
opts.append(("%-*s (%s)"%(max_len, mnt, devpath), False))
if first_opt is None:
first_opt = len(opts)
opts.append(('other', True, OTHER))
opts.append((_('other'), True, OTHER))
opts.append(('---', False)),
opts.append(('leave unmounted', True, LEAVE_UNMOUNTED))
opts.append((_('leave unmounted'), True, LEAVE_UNMOUNTED))
self._selector = Selector(opts, first_opt)
connect_signal(self._selector, 'select', self._select_mount)
self._other = _MountEditor(edit_text='/')

View File

@ -28,6 +28,7 @@ from urwid import (
)
from subiquitycore.ui.buttons import (
back_btn,
cancel_btn,
danger_btn,
done_btn,
@ -44,12 +45,12 @@ from subiquity.models.filesystem import humanize_size
log = logging.getLogger('subiquity.ui.filesystem.filesystem')
confirmation_text = """\
confirmation_text = _("""\
Selecting Continue below will begin the installation process and \
result in the loss of data on the disks selected to be formatted.
Are you sure you want to continue?
"""
""")
class FilesystemConfirmationView(WidgetWrap):
def __init__(self, parent, controller):
@ -57,11 +58,11 @@ class FilesystemConfirmationView(WidgetWrap):
self.controller = controller
pile = Pile([
UrwidPadding(Text(confirmation_text), left=2, right=2),
Padding.fixed_15(cancel_btn(label="No", on_press=self.cancel)),
Padding.fixed_15(cancel_btn(label=_("No"), on_press=self.cancel)),
Padding.fixed_15(danger_btn(on_press=self.ok)),
Text(""),
])
lb = LineBox(pile, title="Confirm destructive action")
lb = LineBox(pile, title=_("Confirm destructive action"))
super().__init__(Padding.center_75(lb))
def ok(self, sender):
@ -78,11 +79,11 @@ class FilesystemView(BaseView):
self.controller = controller
self.items = []
self.body = [
Text("FILE SYSTEM SUMMARY"),
Text(_("FILE SYSTEM SUMMARY")),
Text(""),
Padding.push_4(self._build_filesystem_list()),
Text(""),
Text("AVAILABLE DEVICES"),
Text(_("AVAILABLE DEVICES")),
Text(""),
Padding.push_4(self._build_available_inputs()),
#self._build_menu(),
@ -144,12 +145,13 @@ class FilesystemView(BaseView):
buttons = []
# don't enable done botton if we can't install
# XXX should enable/disable button rather than having it appear/disappear I think
if self.model.can_install():
buttons.append(
done_btn(on_press=self.done))
buttons.append(reset_btn(on_press=self.reset))
buttons.append(cancel_btn(on_press=self.cancel))
buttons.append(back_btn(on_press=self.cancel))
return Pile(buttons)
@ -206,13 +208,13 @@ class FilesystemView(BaseView):
free = disk.free
percent = int(100*free/size)
if disk.available and disk.used > 0 and percent > 0:
label = "ADD/EDIT PARTITIONS"
label = _("ADD/EDIT PARTITIONS")
size = "{:>9} ({}%) free".format(humanize_size(free), percent)
elif disk.available and percent > 0:
label = "ADD FIRST PARTITION"
label = _("ADD FIRST PARTITION")
size = ""
else:
label = "EDIT PARTITIONS"
label = _("EDIT PARTITIONS")
size = ""
col2(
menu_btn(label=label, on_press=self.click_disk, user_arg=disk),
@ -220,7 +222,7 @@ class FilesystemView(BaseView):
if len(inputs) == 1:
return Pile([Color.info_minor(
Text("No disks available."))])
Text(_("No disks available.")))])
return Pile(inputs)

View File

@ -20,6 +20,7 @@ from urwid import (
from subiquitycore.ui.utils import Padding
from subiquitycore.ui.buttons import (
back_btn,
cancel_btn,
menu_btn,
ok_btn,
@ -30,24 +31,24 @@ from subiquitycore.view import BaseView
from subiquity.models.filesystem import humanize_size
text = """The installer can guide you through partitioning a disk or, if \
text = _("""The installer can guide you through partitioning a disk or, if \
you prefer, you can do it manually. If you choose guided partitioning you \
will still have a chance to review and modify the results."""
will still have a chance to review and modify the results.""")
class GuidedFilesystemView(BaseView):
def __init__(self, model, controller):
self.controller = controller
guided = ok_btn(label="Guided", on_press=self.guided)
manual = ok_btn(label="Manual", on_press=self.manual)
cancel = cancel_btn(on_press=self.cancel)
guided = ok_btn(label=_("Guided"), on_press=self.guided)
manual = ok_btn(label=_("Manual"), on_press=self.manual)
back = back_btn(on_press=self.cancel)
lb = ListBox([
Padding.center_70(Text(text)),
Padding.center_70(Text("")),
Padding.fixed_10(guided),
Padding.fixed_10(manual),
Padding.fixed_10(cancel),
Padding.fixed_10(back),
])
super().__init__(lb)
@ -75,7 +76,7 @@ class GuidedDiskSelectionView(BaseView):
on_press=self.choose_disk, user_arg=disk)
disks.append(disk_btn)
lb = ListBox([
Padding.center_70(Text("Choose the disk to install to:")),
Padding.center_70(Text(_("Choose the disk to install to:"))),
Padding.center_70(Text("")),
Padding.center_70(Pile(disks)),
Padding.center_70(Text("")),

View File

@ -107,6 +107,9 @@ class PartitionForm(Form):
class PartitionFormatView(BaseView):
form_cls = PartitionForm
def __init__(self, size, existing, initial, back):
mountpoint_to_devpath_mapping = self.model.get_mountpoint_to_devpath_mapping()
@ -119,7 +122,7 @@ class PartitionFormatView(BaseView):
initial['mount'] = mount.path
if mount.path in mountpoint_to_devpath_mapping:
del mountpoint_to_devpath_mapping[mount.path]
self.form = PartitionForm(mountpoint_to_devpath_mapping, size, initial)
self.form = self.form_cls(mountpoint_to_devpath_mapping, size, initial)
self.back = back
connect_signal(self.form, 'submit', self.done)
@ -151,13 +154,16 @@ class PartitionView(PartitionFormatView):
max_size = disk.free
if partition is None:
initial = {'partnum': disk.next_partnum}
label = _("Create")
else:
max_size += partition.size
initial = {
'partnum': partition.number,
'size': humanize_size(partition.size),
}
label = _("Save")
super().__init__(max_size, partition, initial, lambda : self.controller.partition_disk(disk))
self.form.buttons[0].set_label(label)
def make_body(self):
body = super().make_body()

View File

@ -46,52 +46,52 @@ PasswordField = simple_field(PasswordEditor)
class IdentityForm(Form):
realname = RealnameField("Your name:")
realname = RealnameField(_("Your name:"))
hostname = UsernameField(
"Your server's name:",
help="The name it uses when it talks to other computers.")
username = UsernameField("Pick a username:")
password = PasswordField("Choose a password:")
confirm_password = PasswordField("Confirm your password:")
_("Your server's name:"),
help=_("The name it uses when it talks to other computers."))
username = UsernameField(_("Pick a username:"))
password = PasswordField(_("Choose a password:"))
confirm_password = PasswordField(_("Confirm your password:"))
ssh_import_id = StringField(
"Import SSH identity:",
help=("Input your SSH user id from Ubuntu SSO (sso:email), "
"Launchpad (lp:username) or Github (gh:username)."))
_("Import SSH identity:"),
help=(_("Input your SSH user id from Ubuntu SSO (sso:email), "
"Launchpad (lp:username) or Github (gh:username).")))
def validate_realname(self):
if len(self.realname.value) < 1:
return "Real name must not be empty."
return _("Real name must not be empty.")
if len(self.realname.value) > REALNAME_MAXLEN:
return "Realname too long, must be < " + str(REALNAME_MAXLEN)
return _("Realname too long, must be < ") + str(REALNAME_MAXLEN)
def validate_hostname(self):
if len(self.hostname.value) < 1:
return "Server name must not be empty"
return _("Server name must not be empty")
if len(self.hostname.value) > HOSTNAME_MAXLEN:
return "Server name too long, must be < " + str(HOSTNAME_MAXLEN)
return _("Server name too long, must be < ") + str(HOSTNAME_MAXLEN)
def validate_username(self):
if len(self.username.value) < 1:
return "Username missing"
return _("Username missing")
if len(self.username.value) > USERNAME_MAXLEN:
return "Username too long, must be < " + str(USERNAME_MAXLEN)
return _("Username too long, must be < ") + str(USERNAME_MAXLEN)
def validate_password(self):
# XXX we should not require a password if an ssh identity is provided
# Form doesn't support form-wide validation yet though, oops.
if len(self.password.value) < 1:
return "Password must be set"
return _("Password must be set")
def validate_confirm_password(self):
if self.password.value != self.confirm_password.value:
return "Passwords do not match"
return _("Passwords do not match")
self.password.validate()
def validate_ssh_import_id(self):
if len(self.ssh_import_id.value) > SSH_IMPORT_MAXLEN:
return "SSH id too long, must be < " + str(SSH_IMPORT_MAXLEN)
return _("SSH id too long, must be < ") + str(SSH_IMPORT_MAXLEN)
class IdentityView(BaseView):

View File

@ -22,8 +22,8 @@ import logging
from urwid import BoxAdapter
from subiquitycore.ui.lists import SimpleList
from subiquitycore.ui.buttons import menu_btn, cancel_btn
from subiquitycore.ui.utils import Padding, Color
from subiquitycore.ui.buttons import back_btn, menu_btn
from subiquitycore.ui.utils import Padding
from subiquitycore.ui.container import ListBox, Pile
from subiquitycore.view import BaseView
@ -44,7 +44,7 @@ class InstallpathView(BaseView):
def _build_buttons(self):
self.buttons = [
cancel_btn(on_press=self.cancel),
back_btn(on_press=self.cancel),
]
return Pile(self.buttons)

View File

@ -62,10 +62,10 @@ class ProgressView(BaseView):
def show_complete(self):
w = Padding.fixed_20(
ok_btn(label="Reboot Now", on_press=self.reboot))
ok_btn(label=_("Reboot Now"), on_press=self.reboot))
z = Padding.fixed_20(
cancel_btn(label="Quit Installer", on_press=self.quit))
cancel_btn(label=_("Quit Installer"), on_press=self.quit))
new_focus = len(self.pile.contents)
self.pile.contents.append((w, self.pile.options('pack')))

View File

@ -19,7 +19,7 @@ Welcome provides user with language selection
"""
import logging
from urwid import BoxAdapter, Text
from urwid import BoxAdapter, Text, connect_signal
from subiquitycore.ui.lists import SimpleList
from subiquitycore.ui.buttons import menu_btn
from subiquitycore.ui.container import ListBox
@ -37,16 +37,16 @@ class WelcomeView(BaseView):
super().__init__(ListBox([
Padding.center_50(self._build_model_inputs()),
Text(""),
Padding.center_79(Text("(More language choices will appear in time)"))]))
Padding.center_79(Text(_("(More language choices will appear in time)")))]))
def _build_model_inputs(self):
sl = []
for lang, code in self.model.get_languages():
sl.append(menu_btn(label=lang, on_press=self.confirm, user_arg=code))
for code, label, native in self.model.get_languages():
sl.append(menu_btn(label=native, on_press=self.confirm, user_arg=code))
return BoxAdapter(SimpleList(sl), height=len(sl))
def confirm(self, sender, code):
self.model.selected_language = code
self.model.switch_language(code)
log.debug('calling installpath')
self.controller.done()

View File

@ -344,11 +344,11 @@ class NetworkController(BaseController):
self.signal.emit_signal('prev-screen')
def default(self):
title = "Network connections"
excerpt = ("Configure at least one interface this server can use to talk to "
title = _("Network connections")
excerpt = _("Configure at least one interface this server can use to talk to "
"other machines, and which preferably provides sufficient access for "
"updates.")
footer = ("Select an interface to configure it or select Done to continue")
footer = _("Select an interface to configure it or select Done to continue")
self.ui.set_header(title, excerpt)
self.ui.set_footer(footer, 20)
self.ui.set_body(NetworkView(self.model, self))

40
subiquitycore/i18n.py Normal file
View File

@ -0,0 +1,40 @@
# Copyright 2017 Canonical, Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import gettext
import os
import syslog
syslog.syslog('i18n file is ' + __file__)
localedir = '/usr/share/locale'
if __file__.startswith('/snap/'):
localedir = os.path.realpath(__file__ + '/../../../../../share/locale')
build_mo = os.path.realpath(__file__ + '/../../build/mo/')
if os.path.isdir(build_mo):
localedir = build_mo
syslog.syslog('Final localedir is ' + localedir)
def switch_language(code='en_US'):
if code != 'en_US' and 'FAKE_TRANSLATE' in os.environ:
import builtins
builtins.__dict__['_'] = lambda a: '_(%s)' % a
elif code:
translation = gettext.translation('subiquity', localedir=localedir, languages=[code])
translation.install()
switch_language()
__all__ = ['switch_language']

View File

@ -22,7 +22,7 @@ def _stylized_button(left, right, stocklabel, style):
class StyleAttrMap(AttrMap):
def __init__(self, *args, **kwargs):
label = kwargs.pop('label', stocklabel)
label = kwargs.pop('label', _(stocklabel))
btn = Btn(label, *args, **kwargs)
super().__init__(btn, style + '_button', style + '_button focus')
return StyleAttrMap
@ -39,6 +39,7 @@ done_btn = stylized_button("Done", "save")
reset_btn = stylized_button("Reset", "reset")
back_btn = stylized_button("Back", "cancel")
cancel_btn = stylized_button("Cancel", "cancel")
close_btn = stylized_button("Close", "cancel")

View File

@ -258,10 +258,10 @@ class Form(object, metaclass=MetaForm):
signals = ['submit', 'cancel']
opts = {}
ok_label = _("Done")
def __init__(self, initial={}):
self.done_btn = Toggleable(done_btn(on_press=self._click_done))
self.done_btn = Toggleable(done_btn(label=self.ok_label, on_press=self._click_done))
self.cancel_btn = Toggleable(cancel_btn(on_press=self._click_cancel))
self.buttons = Pile([self.done_btn, self.cancel_btn])
self._fields = []

View File

@ -111,7 +111,7 @@ class YesNo(Selector):
""" Yes/No selector
"""
def __init__(self):
opts = ['Yes', 'No']
opts = [_('Yes'), _('No')]
super().__init__(opts)
@ -119,7 +119,7 @@ class _HelpDisplay(WidgetWrap):
def __init__(self, closer, help_text):
self._closer = closer
button = close_btn(on_press=lambda btn:self._closer())
super().__init__(LineBox(Pile([Text(help_text), Padding.fixed_10(button)]), title="Help"))
super().__init__(LineBox(Pile([Text(help_text), Padding.fixed_10(button)]), title=_("Help")))
class Help(WidgetWrap):

View File

@ -29,7 +29,7 @@ from urwid import (
WidgetWrap,
)
from subiquitycore.ui.buttons import cancel_btn, menu_btn, done_btn
from subiquitycore.ui.buttons import back_btn, cancel_btn, done_btn, menu_btn
from subiquitycore.ui.container import Columns, ListBox, Pile
from subiquitycore.ui.utils import Padding, Color
from subiquitycore.view import BaseView
@ -48,7 +48,7 @@ class ApplyingConfigWidget(WidgetWrap):
current=0, done=step_count)
box = LineBox(Pile([self.bar,
Padding.fixed_10(button)]),
title="Applying network config")
title=_("Applying network config"))
super().__init__(box)
def advance(self):
@ -62,16 +62,16 @@ def _build_wifi_info(dev):
if dev.actual_ssid is not None:
if dev.configured_ssid is not None:
if dev.actual_ssid != dev.configured_ssid:
r.append(Text("Associated to '%s', will associate to '%s'"%(dev.actual_ssid, dev.configured_ssid)))
r.append(Text(_("Associated to '%s', will associate to '%s'" % (dev.actual_ssid, dev.configured_ssid))))
else:
r.append(Text("Associated to '" + dev.actual_ssid + "'"))
r.append(Text(_("Associated to '%s'" % dev.actual_ssid)))
else:
r.append(Text("No access point configured, but associated to '%s'"%(dev.actual_ssid,)))
r.append(Text(_("No access point configured, but associated to '%s'" % dev.actual_ssid)))
else:
if dev.configured_ssid is not None:
r.append(Text("Will associate to '" + dev.configured_ssid + "'"))
r.append(Text(_("Will associate to '%s'" % dev.configured_ssid)))
else:
r.append(Text("No access point configured"))
r.append(Text(_("No access point configured")))
return r
def _format_address_list(label, addresses):
@ -91,19 +91,19 @@ def _build_gateway_ip_info_for_version(dev, version):
configured_ip_addresses = dev.configured_ip_addresses_for_version(version)
if dev.dhcp_for_version(version):
if dev.actual_ip_addresses:
return _format_address_list("Will use DHCP for IPv%s, currently has address%%s:"%(version,), actual_ip_addresses)
return [Text("Will use DHCP for IPv%s"%(version,))]
return _format_address_list(_("Will use DHCP for IPv%s, currently has address%%s:" % version), actual_ip_addresses)
return [Text(_("Will use DHCP for IPv%s" % version))]
elif configured_ip_addresses:
if sorted(actual_ip_addresses) == sorted(configured_ip_addresses):
return _format_address_list("Using static address%%s for IPv%s:"%(version,), actual_ip_addresses)
p = _format_address_list("Will use static address%%s for IPv%s:"%(version,), configured_ip_addresses)
return _format_address_list(_("Using static address%%s for IPv%s:" % version), actual_ip_addresses)
p = _format_address_list(_("Will use static address%%s for IPv%s:" % version), configured_ip_addresses)
if actual_ip_addresses:
p.extend(_format_address_list("Currently has address%s:", actual_ip_addresses))
p.extend(_format_address_list(_("Currently has address%s:"), actual_ip_addresses))
return p
elif actual_ip_addresses:
return _format_address_list("Has no IPv%s configuration, currently has address%%s:"%(version,), actual_ip_addresses)
return _format_address_list(_("Has no IPv%s configuration, currently has address%%s:" % version), actual_ip_addresses)
else:
return [Text("IPv%s is not configured"%(version,))]
return [Text(_("IPv%s is not configured" % version))]
class NetworkView(BaseView):
@ -132,11 +132,11 @@ class NetworkView(BaseView):
super().__init__(self.frame)
def _build_buttons(self):
cancel = cancel_btn(on_press=self.cancel)
back = back_btn(on_press=self.cancel)
done = done_btn(on_press=self.done)
self.default_focus = done
buttons = [done, cancel]
buttons = [done, back]
return Pile(buttons, focus_item=done)
def _build_model_inputs(self):
@ -162,7 +162,7 @@ class NetworkView(BaseView):
if dev.type == 'wlan':
col_2.extend(_build_wifi_info(dev))
if len(dev.actual_ip_addresses) == 0 and dev.type == 'eth' and not dev.is_connected:
col_2.append(Color.info_primary(Text("Not connected")))
col_2.append(Color.info_primary(Text(_("Not connected"))))
col_2.extend(_build_gateway_ip_info_for_version(dev, 4))
col_2.extend(_build_gateway_ip_info_for_version(dev, 6))
@ -170,8 +170,10 @@ class NetworkView(BaseView):
template = ''
if dev.hwaddr:
template += '{} '.format(dev.hwaddr)
## TODO is this to translate?
if dev.is_bond_slave:
template += '(Bonded) '
## TODO to check if this is affected by translations
if not dev.vendor.lower().startswith('unknown'):
vendor = textwrap.wrap(dev.vendor, 15)[0]
template += '{} '.format(vendor)
@ -199,7 +201,7 @@ class NetworkView(BaseView):
v4_route_source = "via " + self.model.default_v4_gateway
default_v4_route_w = Color.info_minor(
Text(" IPv4 default route " + v4_route_source + "."))
Text(_(" IPv4 default route %s." % v4_route_source)))
labels.append(default_v4_route_w)
if self.model.default_v6_gateway is not None:

View File

@ -63,11 +63,11 @@ class NetworkConfigureInterfaceView(BaseView):
button_padding = 70
buttons = [
menu_btn(label="Use a static IPv4 configuration",
menu_btn(label=_("Use a static IPv4 configuration"),
on_press=self.show_ipv4_configuration),
menu_btn(label="Use DHCPv4 on this interface",
menu_btn(label=_("Use DHCPv4 on this interface"),
on_press=self.enable_dhcp4),
menu_btn(label="Do not use",
menu_btn(label=_("Do not use"),
on_press=self.clear_ipv4),
]
@ -80,11 +80,11 @@ class NetworkConfigureInterfaceView(BaseView):
button_padding = 70
buttons = [
menu_btn(label="Use a static IPv6 configuration",
menu_btn(label=_("Use a static IPv6 configuration"),
on_press=self.show_ipv6_configuration),
menu_btn(label="Use DHCPv6 on this interface",
menu_btn(label=_("Use DHCPv6 on this interface"),
on_press=self.enable_dhcp6),
menu_btn(label="Do not use",
menu_btn(label=_("Do not use"),
on_press=self.clear_ipv6),
]
@ -95,7 +95,7 @@ class NetworkConfigureInterfaceView(BaseView):
def _build_wifi_config(self):
btn = menu_btn(label="Configure WIFI settings", on_press=self.show_wlan_configuration)
btn = menu_btn(label=_("Configure WIFI settings"), on_press=self.show_wlan_configuration)
return [Padding.left_70(btn)]
def _build_buttons(self):

View File

@ -64,11 +64,12 @@ class NetworkConfigForm(Form):
self.ip_address_cls = fam['address_cls']
self.ip_network_cls = fam['network_cls']
subnet = IPField("Subnet:", has_mask=True)
address = IPField("Address:")
gateway = IPField("Gateway:")
nameservers = StringField("Name servers:", help="IP addresses, comma separated")
searchdomains = StringField("Search domains:", help="Domains, comma separated")
ok_label = _("Save")
subnet = IPField(_("Subnet:"), has_mask=True)
address = IPField(_("Address:"))
gateway = IPField(_("Gateway:"))
nameservers = StringField(_("Name servers:"), help=_("IP addresses, comma separated"))
searchdomains = StringField(_("Search domains:"), help=_("Domains, comma separated"))
def clean_subnet(self, subnet):
log.debug("clean_subnet %r", subnet)
@ -119,7 +120,7 @@ class BaseNetworkConfigureManualView(BaseView):
connect_signal(self.form, 'submit', self.done)
connect_signal(self.form, 'cancel', self.cancel)
self.form.subnet.help = "CIDR e.g. %s"%(self.example_address,)
self.form.subnet.help = _("CIDR e.g. %s"%(self.example_address,))
configured_addresses = self.dev.configured_ip_addresses_for_version(self.ip_version)
if configured_addresses:
addr = ipaddress.ip_interface(configured_addresses[0])
@ -155,10 +156,10 @@ class BaseNetworkConfigureManualView(BaseView):
self.is_gateway = self.model.v4_gateway_dev == self.dev.name
if not self.is_gateway and len(devs) > 1:
btn = menu_btn(label="Set this as default gateway",
btn = menu_btn(label=_("Set this as default gateway"),
on_press=self.set_default_gateway)
else:
btn = Text("This will be your default gateway")
btn = Text(_("This will be your default gateway"))
return [btn]

View File

@ -35,6 +35,8 @@ class NetworkList(WidgetWrap):
class WLANForm(Form):
ok_label = _("Save")
ssid = StringField(caption="Network Name:")
psk = PasswordField(caption="Password:")