[rhel7-branch][PATCH] Make layout and switching options description translated (#1015209)
Vratislav Podzimek
vpodzime at redhat.com
Wed Jan 8 16:22:17 UTC 2014
We have the translations of layout and switching options available we just need
to use them in the GUI.
(ported and squashed commits from the master branch)
Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
---
pyanaconda/iutil.py | 21 +++++
pyanaconda/keyboard.py | 160 ++++++++++++-----------------------
pyanaconda/localization.py | 27 +-----
pyanaconda/ui/gui/spokes/keyboard.py | 18 ++--
4 files changed, 87 insertions(+), 139 deletions(-)
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 7e6496f..fcacb94 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -722,3 +722,24 @@ def is_unsupported_hw():
if status:
log.debug("Installing on Unsupported Hardware")
return status
+
+def upcase_first_letter(text):
+ """
+ Helper function that upcases the first letter of the string. Python's
+ standard string.capitalize() not only upcases the first letter but also
+ lowercases all the others. string.title() capitalizes all words in the
+ string.
+
+ :type text: either a str or unicode object
+ :return: the given text with the first letter upcased
+ :rtype: str or unicode (depends on the input)
+
+ """
+
+ if not text:
+ # cannot change anything
+ return text
+ elif len(text) == 1:
+ return text.upper()
+ else:
+ return text[0].upper() + text[1:]
diff --git a/pyanaconda/keyboard.py b/pyanaconda/keyboard.py
index c8e1924..46c1a4d 100755
--- a/pyanaconda/keyboard.py
+++ b/pyanaconda/keyboard.py
@@ -36,6 +36,10 @@ import types
import os
import re
import shutil
+import ctypes
+import gettext
+
+from collections import namedtuple
from pyanaconda import iutil
from pyanaconda import flags
@@ -59,6 +63,12 @@ LAYOUT_VARIANT_RE = re.compile(r'^\s*(\w+)\s*' # layout plus
r'(?:(?:\(\s*([-\w]+)\s*\))' # variant in parentheses
r'|(?:$))\s*') # or nothing
+# namedtuple for information about a keyboard layout (its language and description)
+LayoutInfo = namedtuple("LayoutInfo", ["lang", "desc"])
+
+Xkb_ = lambda x: gettext.ldgettext("xkeyboard-config", x)
+iso_ = lambda x: gettext.ldgettext("iso_639", x)
+
class KeyboardConfigError(Exception):
"""Exception class for keyboard configuration related problems"""
@@ -351,28 +361,10 @@ def item_str(s):
elif type(s) == types.ListType:
# XXX: this is the wrong case that should be fixed (rhbz#920595)
i = s.index(0)
- s = "".join(chr(char) for char in s[:i] if char in xrange(256))
+ s = "".join(chr(ctypes.c_uint8(char).value) for char in s[:i])
return s.decode("utf-8") #there are some non-ascii layout descriptions
-class _Layout(object):
- """Internal class representing a single layout variant"""
-
- def __init__(self, name, desc):
- self.name = name
- self.desc = desc
-
- def __str__(self):
- return '%s (%s)' % (self.name, self.desc)
-
- def __eq__(self, obj):
- return isinstance(obj, self.__class__) and \
- self.name == obj.name
-
- @property
- def description(self):
- return self.desc
-
class XklWrapperError(KeyboardConfigError):
"""Exception class for reporting libxklavier-related problems"""
@@ -436,16 +428,8 @@ class XklWrapper(object):
self.configreg = Xkl.ConfigRegistry.get_instance(self._engine)
self.configreg.load(False)
- self._language_keyboard_variants = dict()
- self._country_keyboard_variants = dict()
- self._switching_options = list()
-
- #we want to display layouts as 'language (description)'
- self.name_to_show_str = dict()
-
- #we want to display layout switching options as e.g. "Alt + Shift" not
- #as "grp:alt_shift_toggle"
- self.switch_to_show_str = dict()
+ self._layout_infos = dict()
+ self._switch_opt_infos = dict()
#this might take quite a long time
self.configreg.foreach_language(self._get_language_variants, None)
@@ -464,14 +448,9 @@ class XklWrapper(object):
#if this layout has already been added for some other language,
#do not add it again (would result in duplicates in our lists)
- if name not in self.name_to_show_str:
- if lang and not description.startswith(lang):
- self.name_to_show_str[name] = "%s (%s)" % (lang.encode("utf-8"),
- description.encode("utf-8"))
- else:
- self.name_to_show_str[name] = "%s" % description.encode("utf-8")
-
- self._variants_list.append(_Layout(name, description))
+ if name not in self._layout_infos:
+ self._layout_infos[name] = LayoutInfo(lang.encode("utf-8"),
+ description.encode("utf-8"))
def _get_country_variant(self, c_reg, item, subitem, country):
if subitem:
@@ -482,109 +461,76 @@ class XklWrapper(object):
description = item_str(item.description)
# if the layout was not added with any language, add it with a country
- if name not in self.name_to_show_str:
- if country:
- self.name_to_show_str[name] = "%s (%s)" % (country.encode("utf-8"),
- description.encode("utf-8"))
- else:
- self.name_to_show_str[name] = "%s" % description.encode("utf-8")
-
- self._variants_list.append(_Layout(name, description))
+ if name not in self._layout_infos:
+ self._layout_infos[name] = LayoutInfo(country.encode("utf-8"),
+ description.encode("utf-8"))
def _get_language_variants(self, c_reg, item, user_data=None):
- #helper "global" variable
- self._variants_list = list()
lang_name, lang_desc = item_str(item.name), item_str(item.description)
c_reg.foreach_language_variant(lang_name, self._get_lang_variant, lang_desc)
- self._language_keyboard_variants[lang_desc] = self._variants_list
-
def _get_country_variants(self, c_reg, item, user_data=None):
- #helper "global" variable
- self._variants_list = list()
country_name, country_desc = item_str(item.name), item_str(item.description)
c_reg.foreach_country_variant(country_name, self._get_country_variant,
country_desc)
- self._country_keyboard_variants[country_name] = self._variants_list
-
def _get_switch_option(self, c_reg, item, user_data=None):
"""Helper function storing layout switching options in foreach cycle"""
desc = item_str(item.description)
name = item_str(item.name)
- self._switching_options.append(name)
- self.switch_to_show_str[name] = desc.encode("utf-8")
+ self._switch_opt_infos[name] = desc.encode("utf-8")
+
def get_available_layouts(self):
"""A generator yielding layouts (no need to store them as a bunch)"""
- return self.name_to_show_str.iterkeys()
+ return self._layout_infos.iterkeys()
def get_switching_options(self):
"""Method returning list of available layout switching options"""
- return self._switching_options
-
- def get_default_language_layout(self, language):
- """Get the default layout for a given language."""
-
- layouts = self.get_language_layouts(language)
- if layouts:
- #first layout (should exist for every language)
- return layouts[0].name
- else:
- return None
-
- def get_language_layouts(self, language):
- """Get layouts for a given language."""
-
- language_layouts = self._language_keyboard_variants.get(language, None)
-
- if language_layouts:
- return language_layouts
+ return self._switch_opt_infos.iterkeys()
- #else try some magic and if everything fails, return None
- for (lang, layouts) in self._language_keyboard_variants.iteritems():
- #XXX: some languages are returned in a weird form from the
- # libxklavier iterations (e.g. "Greek, Modern (1453-)")
- if lang.startswith(language):
- return layouts
-
- return None
-
- def get_default_lang_country_layout(self, language, country):
+ def get_layout_variant_description(self, layout_variant, with_lang=True):
"""
- Get default layout matching both language and country. If none such
- layout is found, get default layout for language. If no layout for
- the given language is found but there is layout for the given country,
- return the one for the country.
+ Get description of the given layout-variant.
+
+ :param layout_variant: layout-variant specification (e.g. 'cz (qwerty)')
+ :type layout_variant: str
+ :param with_lang: whether to include language of the layout-variant (if defined)
+ in the description or not
+ :type with_lang: bool
+ :return: description of the layout-variant specification (e.g. 'Czech (qwerty)')
+ :rtype: str
"""
- language_layouts = self.get_language_layouts(language)
- country_layouts = self._country_keyboard_variants.get(country, None)
- if not language_layouts and not country_layouts:
- return None
+ layout_info = self._layout_infos[layout_variant]
+ if with_lang and layout_info.lang:
+ # translate language and upcase its first letter, translate the
+ # layout-variant description
+ xlated_lang = iso_(layout_info.lang)
+ return "%s (%s)" % (iutil.upcase_first_letter(xlated_lang.decode("utf-8")),
+ Xkb_(layout_info.desc).decode("utf-8"))
+ else:
+ return layout_info.desc
- if not country_layouts:
- return language_layouts[0].name
+ def get_switch_opt_description(self, switch_opt):
+ """
+ Get description of the given layout switching option.
- if not language_layouts:
- return country_layouts[0].name
+ :param switch_opt: switching option name/ID (e.g. 'grp:alt_shift_toggle')
+ :type switch_opt: str
+ :return: description of the layout switching option (e.g. 'Alt + Shift')
+ :rtype: str
- matches_both = (layout for layout in language_layouts
- if layout in country_layouts)
+ """
- try:
- return matches_both.next().name
- except StopIteration:
- if country_layouts:
- return country_layouts[0].name
- else:
- return language_layouts[0].name
+ # translate the description of the switching option
+ return Xkb_(self._switch_opt_infos[switch_opt])
def activate_default_layout(self):
"""
@@ -598,7 +544,7 @@ class XklWrapper(object):
def is_valid_layout(self, layout):
"""Return if given layout is valid layout or not"""
- return layout in self.name_to_show_str
+ return layout in self._layout_infos
def add_layout(self, layout):
"""
diff --git a/pyanaconda/localization.py b/pyanaconda/localization.py
index 191e1a9..b13e047 100644
--- a/pyanaconda/localization.py
+++ b/pyanaconda/localization.py
@@ -26,6 +26,8 @@ import re
import langtable
import glob
+from pyanaconda.iutil import upcase_first_letter
+
import logging
log = logging.getLogger("anaconda")
@@ -47,27 +49,6 @@ class InvalidLocaleSpec(LocalizationConfigError):
pass
-def _upcase_first_letter(string):
- """
- Helper function that upcases the first letter of the string. Python's
- standard string.capitalize() not only upcases the first letter but also
- lowercases all the others. string.title() capitalizes all words in the
- string.
-
- :type string: either a str or unicode object
- :return: the given string with the first letter upcased
- :rtype: str or unicode (depends on the input)
-
- """
-
- if not string:
- # cannot change anything
- return string
- elif len(string) == 1:
- return string.upper()
- else:
- return string[0].upper() + string[1:]
-
def parse_langcode(langcode):
"""
For a given langcode (e.g. 'SR_RS.UTF-8 at latin') returns a dictionary
@@ -237,7 +218,7 @@ def get_english_name(locale):
scriptId=parts.get("script", ""),
languageIdQuery="en")
- return _upcase_first_letter(name)
+ return upcase_first_letter(name)
def get_native_name(locale):
"""
@@ -261,7 +242,7 @@ def get_native_name(locale):
languageIdQuery=parts["language"],
scriptIdQuery=parts.get("script", ""))
- return _upcase_first_letter(name)
+ return upcase_first_letter(name)
def get_available_translations(localedir=None):
"""
diff --git a/pyanaconda/ui/gui/spokes/keyboard.py b/pyanaconda/ui/gui/spokes/keyboard.py
index 7ba4cdf..3b76a50 100644
--- a/pyanaconda/ui/gui/spokes/keyboard.py
+++ b/pyanaconda/ui/gui/spokes/keyboard.py
@@ -40,11 +40,11 @@ __all__ = ["KeyboardSpoke"]
LAYOUT_SWITCHING_INFO = N_("%s to switch layouts.")
def _show_layout(column, renderer, model, itr, wrapper):
- value = wrapper.name_to_show_str[model[itr][0]]
+ value = wrapper.get_layout_variant_description(model[itr][0])
renderer.set_property("text", value)
def _show_description(column, renderer, model, itr, wrapper):
- value = wrapper.switch_to_show_str[model[itr][0]]
+ value = wrapper.get_switch_opt_description(model[itr][0])
if model[itr][1]:
value = "<b>%s</b>" % value
renderer.set_property("markup", value)
@@ -61,7 +61,7 @@ class AddLayoutDialog(GUIObject):
def matches_entry(self, model, itr, user_data=None):
value = model[itr][0]
- value = self._xkl_wrapper.name_to_show_str[value]
+ value = self._xkl_wrapper.get_layout_variant_description(value)
entry_text = self._entry.get_text()
if entry_text is not None:
entry_text = entry_text.lower()
@@ -87,8 +87,8 @@ class AddLayoutDialog(GUIObject):
value1 = model[itr1][0]
value2 = model[itr2][0]
- show_str1 = self._xkl_wrapper.name_to_show_str[value1]
- show_str2 = self._xkl_wrapper.name_to_show_str[value2]
+ show_str1 = self._xkl_wrapper.get_layout_variant_description(value1)
+ show_str2 = self._xkl_wrapper.get_layout_variant_description(value2)
if show_str1 < show_str2:
return -1
@@ -223,8 +223,8 @@ class ConfigureSwitchingDialog(GUIObject):
value1 = model[itr1][0]
value2 = model[itr2][0]
- show_str1 = self._xkl_wrapper.switch_to_show_str[value1]
- show_str2 = self._xkl_wrapper.switch_to_show_str[value2]
+ show_str1 = self._xkl_wrapper.get_switch_opt_description(value1)
+ show_str2 = self._xkl_wrapper.get_switch_opt_description(value2)
if show_str1 < show_str2:
return -1
@@ -285,7 +285,7 @@ class KeyboardSpoke(NormalSpoke):
@property
def status(self):
# We don't need to check that self._store is empty, because that isn't allowed.
- descriptions = (self._xkl_wrapper.name_to_show_str[row[0]]
+ descriptions = (self._xkl_wrapper.get_layout_variant_description(row[0])
for row in self._store)
return ", ".join(descriptions)
@@ -374,7 +374,7 @@ class KeyboardSpoke(NormalSpoke):
def _refresh_switching_info(self):
if self.data.keyboard.switch_options:
first_option = self.data.keyboard.switch_options[0]
- desc = self._xkl_wrapper.switch_to_show_str[first_option]
+ desc = self._xkl_wrapper.get_switch_opt_description(first_option)
self._layoutSwitchLabel.set_text(_(LAYOUT_SWITCHING_INFO) % desc)
else:
--
1.8.4.2
More information about the anaconda-patches
mailing list