[anaconda][rhel7-branch][PATCH] Prevent incomplete translations from making the TUI unusable (#1235617)

David Shea dshea at redhat.com
Mon Jul 27 14:15:44 UTC 2015


On 07/24/2015 08:06 AM, Martin Kolman wrote:
> What happens is that we have the following translatable strings:
> - "Please make your choice from above ['q' to quit | 'c' to continue | 'r' to refresh]"
> - "q"
> - "c"
> - "r"
> All of these strings can be translated *separately* and in many partial
> translations *some of them are translated while some are not*.
>
> The end result is that we might be telling the user to press say "p"
> for "pokračovat" but me might actually expect "c" for continue,
> because the "c" string was not translated to "p".
>
> This affects both the Anaconda and Initial Setup TUIs and can make the
> UI totally unusable.
>
> The fix for this is to remove the keystrokes from the long  strings and replace
> them by string formatting operators & do the keystroke transformation separately:
>
> _("Please make your choice from above ['%s' to quit | '%s' to continue | '%s' to refresh]") % \
>   (_("q"), _("c"), _("r"))
>
> This makes sure that we will always ask the user to type the same
> keystroke that is actually displayed.
>
> Resolves: rhbz#1235617
> Signed-off-by: Martin Kolman <mkolman at redhat.com>
> ---
>   pyanaconda/ui/tui/hubs/__init__.py      | 6 ++++--
>   pyanaconda/ui/tui/hubs/summary.py       | 5 ++++-
>   pyanaconda/ui/tui/simpleline/base.py    | 4 +++-
>   pyanaconda/ui/tui/spokes/langsupport.py | 4 +++-
>   pyanaconda/ui/tui/spokes/time_spoke.py  | 3 ++-
>   pyanaconda/ui/tui/tuiobject.py          | 2 +-
>   6 files changed, 17 insertions(+), 7 deletions(-)
>
> diff --git a/pyanaconda/ui/tui/hubs/__init__.py b/pyanaconda/ui/tui/hubs/__init__.py
> index 82b49fe..69d7985 100644
> --- a/pyanaconda/ui/tui/hubs/__init__.py
> +++ b/pyanaconda/ui/tui/hubs/__init__.py
> @@ -129,7 +129,9 @@ class TUIHub(TUIObject, common.Hub):
>           """
>           if self._spoke_count == 1:
>               single_spoke_title = self._spokes.values()[0].title
> -            return _(u"  Please make your choice from [ '1' to enter the %s spoke | 'q' to quit |\n"
> -                     "  'c' to continue | 'r' to refresh]: ") % single_spoke_title
> +            # TRANSLATORS: 'q' to quit, 'c' to continue, 'r' to refresh
> +            return _(u"  Please make your choice from [ '1' to enter the %s spoke | '%s' to quit |\n"
> +                     "  '%s' to continue | '%s' to refresh]: ") % (single_spoke_title, _("q"), _("c"), _("r"))
> +

The translators comment is going to be associated with the "Please make 
your choice..." string instead of the three strings for the individual 
letters. It'll look kind of ugly, but each of _() calls for q, c, and r 
needs to go on its own line, with a TRANSLATORS comment above it.

Also, please use a context for all of the single letter translations. 
Similar to how its used to potentially give different translated 
keyboard accelerators to the same word in the GUI, it needs to be used 
in the TUI to avoid things like this that I just found:

#. TRANSLATORS: 'b' to begin installation
#. TRANSLATORS: 'b' to go back
#: pyanaconda/ui/tui/hubs/summary.py:93 
pyanaconda/ui/tui/hubs/summary.py:107
#: pyanaconda/ui/tui/spokes/langsupport.py:112
#: pyanaconda/ui/tui/spokes/langsupport.py:122
#: pyanaconda/ui/tui/spokes/time_spoke.py:135
msgid "b"
msgstr ""

Oops. I can probably add a test for that.

Anyway the context here should be "TUI|Spoke Navigation".

>           else:
>               return super(TUIHub, self).prompt(args)
> diff --git a/pyanaconda/ui/tui/hubs/summary.py b/pyanaconda/ui/tui/hubs/summary.py
> index 5d414ee..d6fdcaf 100644
> --- a/pyanaconda/ui/tui/hubs/summary.py
> +++ b/pyanaconda/ui/tui/hubs/summary.py
> @@ -87,7 +87,10 @@ class SummaryHub(TUIHub):
>   
>           # override the default prompt since we want to offer the 'b' to begin
>           # installation option here
> -        return _("  Please make your choice from above ['q' to quit | 'b' to begin installation |\n  'r' to refresh]: ")
> +
> +        # TRANSLATORS: 'q' to quit, 'b' to begin installation, 'r' to refresh
> +        return _("  Please make your choice from above ['%s' to quit | '%s' to begin installation |\n  '%s' to refresh]: ") % \
> +                (_("q"), _("b"), _("r"))
>   

Same thing with the comment and contexts. Master uses "TUI Spoke 
Navigation" for here as well, and it looks like it's missing on rhel7 
for the _('b') and _('c') translations also in this file.

>       def input(self, args, key):
>           """Handle user input. Numbers are used to show a spoke, the rest is passed
> diff --git a/pyanaconda/ui/tui/simpleline/base.py b/pyanaconda/ui/tui/simpleline/base.py
> index c4fe736..d75a893 100644
> --- a/pyanaconda/ui/tui/simpleline/base.py
> +++ b/pyanaconda/ui/tui/simpleline/base.py
> @@ -627,7 +627,9 @@ class UIScreen(object):
>                    to skip further input processing
>           :rtype: unicode|None
>           """
> -        return _(u"  Please make your choice from above ['q' to quit | 'c' to continue |\n  'r' to refresh]: ")
> +        # TRANSLATORS: 'q' to quit, "c" to continue, "r" to refresh
> +        return _(u"  Please make your choice from above ['%s' to quit | '%s' to continue |\n  '%s' to refresh]: ") % \
> +                (_("q"), _("c"), _("r"))

Same.
>   
>       @property
>       def app(self):
> diff --git a/pyanaconda/ui/tui/spokes/langsupport.py b/pyanaconda/ui/tui/spokes/langsupport.py
> index 0b1e836..0baf330 100644
> --- a/pyanaconda/ui/tui/spokes/langsupport.py
> +++ b/pyanaconda/ui/tui/spokes/langsupport.py
> @@ -117,7 +117,9 @@ class LangSpoke(FirstbootSpokeMixIn, NormalTUISpoke):
>   
>       def prompt(self, args=None):
>           """ Override default prompt with a custom prompt. """
> -        return _("Please select language support to install.\n[b to language list, c to continue, q to quit]: ")
> +        # TRANSLATORS: 'b' to go back, "c" to continue, "q" to quit
> +        return _("Please select language support to install.\n[%s to return to language list, %s to continue, %s to quit]: ") % \
> +                (_("b"), _("c"), _("q"))

Same, master has the context "TUI Spoke Navigation|Language Support"

>   
>       def apply(self):
>           """ Store the selected langsupport locales """
> diff --git a/pyanaconda/ui/tui/spokes/time_spoke.py b/pyanaconda/ui/tui/spokes/time_spoke.py
> index a6e59e3..a8dfdac 100644
> --- a/pyanaconda/ui/tui/spokes/time_spoke.py
> +++ b/pyanaconda/ui/tui/spokes/time_spoke.py
> @@ -131,7 +131,8 @@ class TimeZoneSpoke(FirstbootSpokeMixIn, NormalTUISpoke):
>               return INPUT_PROCESSED
>   
>       def prompt(self, args = None):
> -        return _("Please select the timezone.\nUse numbers or type names directly [b to region list, q to quit]: ")
> +        # TRANSLATORS: 'b' to go back, "q" to quit
> +        return _("Please select the timezone.\nUse numbers or type names directly [%s to region list, %s to quit]: ") % (_("b"), _("q"))

The actual use of "b" is not translated (also true on master), turns 
out. Same thing with comments and contexts.

>   
>       def apply(self):
>           self.data.timezone.timezone = self._selection
> diff --git a/pyanaconda/ui/tui/tuiobject.py b/pyanaconda/ui/tui/tuiobject.py
> index 9fbb726..58d3664 100644
> --- a/pyanaconda/ui/tui/tuiobject.py
> +++ b/pyanaconda/ui/tui/tuiobject.py
> @@ -128,7 +128,7 @@ class YesNoDialog(tui.UIScreen):
>           return True
>   
>       def prompt(self, args = None):
> -        return _("Please respond 'yes' or 'no': ")
> +        return _("Please respond '%s' or '%s': ") % (_("yes"), _("no"))

This needs to use named parameters (%(yes), %(no))

>   
>       def input(self, args, key):
>           if key == _("yes"):



More information about the anaconda-patches mailing list