From: David Shea dshea@redhat.com
Requires contexts for GUI strings that contain keyboard accelerators and single-character TUI strings. Also require a comment for the single-character TUI strings. --- tests/Makefile.am | 3 ++ tests/gettext/contexts.py | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100755 tests/gettext/contexts.py
diff --git a/tests/Makefile.am b/tests/Makefile.am index b742e6e..22626ff 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,10 +42,12 @@ dist_check_SCRIPTS = $(srcdir)/glade/*.py \ pylint/runpylint.py \ cppcheck/runcppcheck.sh \ testenv.sh \ + $(srcdir)/gettext/*.py \ gettext/click.py \ gettext/gettext_warnings.sh \ gettext/gettext_potfiles.py \ gettext/style_guide.py \ + gettext/contexts.py \ storage/run_storage_tests.py \ install/run_install_test.sh \ $(srcdir)/kickstart_tests/*.ks \ @@ -65,6 +67,7 @@ TESTS = nosetests.sh \ gettext/gettext_warnings.sh \ gettext/gettext_potfiles.py \ gettext/style_guide.py \ + gettext/contexts.py \ storage/run_storage_tests.py \ glade/run_glade_tests.sh \ kickstart_tests/run_kickstart_tests.sh diff --git a/tests/gettext/contexts.py b/tests/gettext/contexts.py new file mode 100755 index 0000000..62470da --- /dev/null +++ b/tests/gettext/contexts.py @@ -0,0 +1,88 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2015 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +# Author: David Shea dshea@redhat.com + +import os, sys, re + +def list_occurrences(occurrences): + # Return polib's occurrences list [('file1', line1), ('file2', line2), ...] + # as a space-separated list of file1:line1 etc. + return " ".join("%s:%s" % (o[0], o[1]) for o in occurrences) + +def is_accelerated(message): + # True if there is a _ anywhere outside of a format parameter name + if "_" not in message.msgid: + return False + + if "python-format" in message.flags: + # Assume this is a %-formatted string, strip out everything from % + # to the end of a word, or at least to the end of the identifier + # we're trying to ignore + if "_" not in re.sub('%[()_a-zA-Z0-9]*', '', message.msgid): + return False + + return True + +# Use polib to parse anaconda.pot +try: + import polib +except ImportError: + print("You need to install the python-polib package to read anaconda.pot") + # This return code tells the automake test driver that the test setup failed + sys.exit(99) + +if "top_srcdir" not in os.environ: + sys.stderr.write("$top_srcdir must be defined in the test environment\n") + sys.exit(99) + +if "top_builddir" not in os.environ: + sys.stderr.write("$top_srcdir must be defined in the test environment\n") + sys.exit(99) + +# Update the .pot file with the latest strings +if os.system('make -C %s anaconda.pot-update' % (os.environ['top_builddir'] + "/po")) != 0: + sys.stderr.write("Unable to update anaconda.pot") + sys.exit(1) + +# Parse anaconda.pot +pofile = polib.pofile(os.environ['top_srcdir'] + "/po/anaconda.pot") + +success = True + +# There are two cases that require contexts: GUI strings with keyboard accelerators, +# and single-character TUI strings (e.g. c for continue) + +# First, the GUI strings with accelerators +for msg in (p for p in pofile if is_accelerated(p)): + if not msg.msgctxt: + print("Keyboard accelerator missing context at %s" % list_occurrences(msg.occurrences)) + success = False + +# Next, the abbreviations. These strings also require a comment to explain what +# they are abbreviating. +for msg in (p for p in pofile if len(p.msgid) == 1): + if not msg.msgctxt: + print("Abbreviation %s is missing context at %s" % + (msg.msgid, list_occurrences(msg.occurrences))) + success = False + + if not msg.comment: + print("Abbreviation %s is missing a comment at %s" % + (msg.msgid, list_occurrences(msg.occurrences))) + +sys.exit(0 if success else 1)
From: David Shea dshea@redhat.com
--- pyanaconda/ui/gui/spokes/custom.py | 8 ++++---- pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 0dd8a21..e15ba39 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -2169,7 +2169,7 @@ def on_container_changed(self, combo): return
device_type = self._get_current_device_type() - container_type_name = get_container_type(device_type).name.lower() + container_type_name = _(get_container_type(device_type).name).lower() new_text = _(NEW_CONTAINER_TEXT) % {"container_type": container_type_name} create_new_container = container_name == new_text if create_new_container: @@ -2447,7 +2447,7 @@ def _populate_container(self, device=None): container_size_policy = container.size_policy
container_type = get_container_type(device_type) - self._containerLabel.set_text(container_type.label.title()) + self._containerLabel.set_text(_(container_type.label).title()) self._containerLabel.set_use_underline(True) self._containerStore.clear() if device_type == DEVICE_TYPE_BTRFS: @@ -2474,8 +2474,8 @@ def _populate_container(self, device=None): self._containerStore.append(self._container_store_row(default_container_name)) self._containerCombo.set_active(len(self._containerStore) - 1)
- self._containerStore.append(self._container_store_row(_(NEW_CONTAINER_TEXT) % {"container_type": container_type.name.lower()})) - self._containerCombo.set_tooltip_text(_(CONTAINER_TOOLTIP) % {"container_type": container_type.name.lower()}) + self._containerStore.append(self._container_store_row(_(NEW_CONTAINER_TEXT) % {"container_type": _(container_type.name).lower()})) + self._containerCombo.set_tooltip_text(_(CONTAINER_TOOLTIP) % {"container_type": _(container_type.name).lower()}) if default_container_name is None: self._containerCombo.set_active(len(self._containerStore) - 1)
diff --git a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py index 2c363cf..aba056d 100644 --- a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py +++ b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py @@ -306,7 +306,7 @@ def containerRaidLevelsSupported(device_type): return set()
def get_container_type(device_type): - return CONTAINER_TYPES.get(device_type, ContainerType(_("container"), _("container"))) + return CONTAINER_TYPES.get(device_type, ContainerType(N_("container"), N_("container")))
class AddDialog(GUIObject): builderObjects = ["addDialog", "mountPointStore", "mountPointCompletion", "mountPointEntryBuffer"] @@ -494,10 +494,10 @@ def __init__(self, *args, **kwargs):
# set up the dialog labels with device-type-specific text container_type = get_container_type(self.device_type) - title_text = _(CONTAINER_DIALOG_TITLE) % {"container_type": container_type.name.upper()} + title_text = _(CONTAINER_DIALOG_TITLE) % {"container_type": _(container_type.name).upper()} self._title_label.set_text(title_text)
- dialog_text = _(CONTAINER_DIALOG_TEXT) % {"container_type": container_type.name.lower()} + dialog_text = _(CONTAINER_DIALOG_TEXT) % {"container_type": _(container_type.name).lower()} self._dialog_label.set_text(dialog_text)
# populate the dialog widgets
From: David Shea dshea@redhat.com
--- pyanaconda/errors.py | 5 +++-- pyanaconda/ui/gui/__init__.py | 7 ++++--- pyanaconda/ui/gui/main.glade | 2 +- pyanaconda/ui/gui/spokes/custom.glade | 11 +++++------ pyanaconda/ui/gui/spokes/custom.py | 7 ++++--- pyanaconda/ui/gui/spokes/datetime_spoke.glade | 2 +- pyanaconda/ui/gui/spokes/lib/accordion.py | 7 ++++--- .../ui/gui/spokes/lib/custom_storage_helpers.py | 10 +++++----- pyanaconda/ui/gui/spokes/storage.glade | 8 ++++---- pyanaconda/ui/gui/spokes/storage.py | 3 ++- pyanaconda/ui/tui/spokes/askvnc.py | 5 +++-- widgets/src/SpokeWindow.c | 2 +- widgets/src/StandaloneWindow.c | 19 +++++++++++-------- widgets/src/intl.h | 2 ++ 14 files changed, 50 insertions(+), 40 deletions(-)
diff --git a/pyanaconda/errors.py b/pyanaconda/errors.py index fb478e3..6cea303 100644 --- a/pyanaconda/errors.py +++ b/pyanaconda/errors.py @@ -18,7 +18,7 @@ # # Author(s): Chris Lumens clumens@redhat.com
-from pyanaconda.i18n import _ +from pyanaconda.i18n import _, C_
__all__ = ["ERROR_RAISE", "ERROR_CONTINUE", "ERROR_RETRY", "InvalidImageSizeError", "MissingImageError", "MediaUnmountError", @@ -150,7 +150,8 @@ def _storageResetHandler(self, exn): "storage scan. If you do not fix it you will have to exit " "the installer.") % {"errortxt": escape_markup(exn.message)}) details = _(exn.suggestion) - buttons = (_("_Exit Installer"), _("_Retry")) + buttons = (C_("GUI|Storage Detailed Error Dialog", "_Exit Installer"), + C_("GUI|Storage Detailed Error Dialog", "_Retry")) if self.ui.showDetailedError(message, details, buttons=buttons): return ERROR_RETRY else: diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py index fa90219..daab8dc 100644 --- a/pyanaconda/ui/gui/__init__.py +++ b/pyanaconda/ui/gui/__init__.py @@ -34,7 +34,7 @@
from gi.repository import Gdk, Gtk, AnacondaWidgets, Keybinder, GdkPixbuf, GLib, GObject
-from pyanaconda.i18n import _ +from pyanaconda.i18n import _, C_ from pyanaconda.constants import IPMI_ABORTED from pyanaconda import product, iutil from pyanaconda import threads @@ -763,7 +763,7 @@ def showError(self, message): @gtk_action_wait def showDetailedError(self, message, details, buttons=None): from pyanaconda.ui.gui.spokes.lib.detailederror import DetailedErrorDialog - buttons = buttons or [_("_Quit")] + buttons = buttons or [C_("GUI|Detailed Error Dialog", "_Quit")] dlg = DetailedErrorDialog(None, buttons=buttons, label=message)
with self.mainWindow.enlightbox(dlg.window): @@ -779,7 +779,8 @@ def showYesNoQuestion(self, message): buttons=Gtk.ButtonsType.NONE, message_format=message) dlg.set_decorated(False) - dlg.add_buttons(_("_No"), 0, _("_Yes"), 1) + dlg.add_buttons(C_("GUI|Yes No Dialog", "_No"), 0, + C_("GUI|Yes No Dialog", "_Yes"), 1) dlg.set_default_response(1)
with self.mainWindow.enlightbox(dlg): diff --git a/pyanaconda/ui/gui/main.glade b/pyanaconda/ui/gui/main.glade index 3d3e2e6..4f465b1 100644 --- a/pyanaconda/ui/gui/main.glade +++ b/pyanaconda/ui/gui/main.glade @@ -21,7 +21,7 @@ <property name="layout_style">end</property> <child> <object class="GtkButton" id="exitButton"> - <property name="label" translatable="yes">_Exit Installer</property> + <property name="label" translatable="yes" context="GUI|Error Dialog">_Exit Installer</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> diff --git a/pyanaconda/ui/gui/spokes/custom.glade b/pyanaconda/ui/gui/spokes/custom.glade index 0b5988d..2de2172 100644 --- a/pyanaconda/ui/gui/spokes/custom.glade +++ b/pyanaconda/ui/gui/spokes/custom.glade @@ -355,7 +355,7 @@ <property name="can_focus">False</property> <property name="halign">start</property> <property name="xalign">0</property> - <property name="label" translatable="yes">Mount _Point:</property> + <property name="label" translatable="yes" context="GUI|Custom Partitioning|Configure|Devices">Mount _Point:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">mountPointEntry</property> <attributes> @@ -402,7 +402,7 @@ <property name="can_focus">False</property> <property name="halign">start</property> <property name="xalign">0</property> - <property name="label" translatable="yes">_Desired Capacity:</property> + <property name="label" translatable="yes" context="GUI|Custom Partitioning|Configure|Devices">_Desired Capacity:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">sizeEntry</property> <attributes> @@ -452,8 +452,7 @@ <object class="GtkLabel" id="labelLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">_Label:</property> + <property name="label" translatable="yes" context="GUI|Custom Partitioning|Configure|Devices">_Label:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">labelEntry</property> <attributes> @@ -561,7 +560,7 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="xalign">0</property> - <property name="label" translatable="yes">_Name:</property> + <property name="label" translatable="yes" context="GUI|Custom Partitioning|Configure|Devices">_Name:</property> <property name="use_underline">True</property> <property name="mnemonic_widget">nameEntry</property> <attributes> @@ -941,7 +940,7 @@ <property name="spacing">6</property> <child> <object class="GtkButton" id="applyButton"> - <property name="label" translatable="yes">_Update Settings</property> + <property name="label" translatable="yes" context="GUI|Custom Partitioning|Configure|Devices">_Update Settings</property> <property name="visible">True</property> <property name="sensitive">False</property> <property name="can_focus">True</property> diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index e15ba39..c6e940d 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -39,7 +39,7 @@
from pykickstart.constants import CLEARPART_TYPE_NONE
-from pyanaconda.i18n import _, N_, CP_ +from pyanaconda.i18n import _, N_, CP_, C_ from pyanaconda.product import productName, productVersion, translated_new_install_name from pyanaconda.threads import AnacondaThread, threadMgr from pyanaconda.constants import THREAD_EXECUTE_STORAGE, THREAD_STORAGE, THREAD_CUSTOM_STORAGE_INIT @@ -2447,7 +2447,7 @@ def _populate_container(self, device=None): container_size_policy = container.size_policy
container_type = get_container_type(device_type) - self._containerLabel.set_text(_(container_type.label).title()) + self._containerLabel.set_text(C_("GUI|Custom Partitioning|Configure|Devices", container_type.label).title()) self._containerLabel.set_use_underline(True) self._containerStore.clear() if device_type == DEVICE_TYPE_BTRFS: @@ -2596,7 +2596,8 @@ def on_reset_clicked(self, *args): buttons=Gtk.ButtonsType.NONE, message_format=msg) dlg.set_decorated(False) - dlg.add_buttons(_("_Reset selections"), 0, _("_Preserve current selections"), 1) + dlg.add_buttons(C_("GUI|Custom Partitioning|Reset Dialog", "_Reset selections"), 0, + C_("GUI|Custom Partitioning|Reset Dialog", "_Preserve current selections"), 1) dlg.set_default_response(1)
with self.main_window.enlightbox(dlg): diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.glade b/pyanaconda/ui/gui/spokes/datetime_spoke.glade index fd5a5ec..9179640 100644 --- a/pyanaconda/ui/gui/spokes/datetime_spoke.glade +++ b/pyanaconda/ui/gui/spokes/datetime_spoke.glade @@ -596,7 +596,7 @@ <object class="GtkLabel" id="colonLabel"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes" comments="TRANSLATORS: This is the separator between hours and minutes, like in HH:MM">:</property> + <property name="label" translatable="yes" context="GUI|Date and Time" comments="TRANSLATORS: This is the separator between hours and minutes, like in HH:MM">:</property> <attributes> <attribute name="scale" value="2"/> </attributes> diff --git a/pyanaconda/ui/gui/spokes/lib/accordion.py b/pyanaconda/ui/gui/spokes/lib/accordion.py index d65abb3..ca5a90d 100644 --- a/pyanaconda/ui/gui/spokes/lib/accordion.py +++ b/pyanaconda/ui/gui/spokes/lib/accordion.py @@ -22,7 +22,7 @@
from blivet.devicefactory import is_supported_device_type
-from pyanaconda.i18n import _ +from pyanaconda.i18n import _, C_ from pyanaconda.product import productName, productVersion from pyanaconda.ui.gui.utils import escape_markup, really_hide, really_show from pyanaconda.constants import DEFAULT_AUTOPART_TYPE @@ -294,7 +294,8 @@ def __init__(self, title, createClickedCB, autopartTypeChangedCB, partitionsToRe dot = Gtk.Label(label="•", xalign=0.5, yalign=0.4, hexpand=False) self._createBox.attach(dot, 0, 1, 1, 1)
- self._createNewButton = Gtk.LinkButton(uri="", label=_("_Click here to create them automatically.")) + self._createNewButton = Gtk.LinkButton(uri="", + label=C_("GUI|Custom Partitioning|Autopart Page", "_Click here to create them automatically.")) label = self._createNewButton.get_children()[0] label.set_alignment(0, 0.5) label.set_hexpand(True) @@ -332,7 +333,7 @@ def __init__(self, title, createClickedCB, autopartTypeChangedCB, partitionsToRe xalign=0, yalign=0.5, hexpand=True, wrap=True) self._createBox.attach(label, 1, 3, 1, 1)
- label = Gtk.Label(label=_("_New mount points will use the following partitioning scheme:"), + label = Gtk.Label(label=C_("GUI|Custom Partitioning|Autopart Page", "_New mount points will use the following partitioning scheme:"), xalign=0, yalign=0.5, wrap=True, use_underline=True) self._createBox.attach(label, 0, 4, 2, 1) label.set_mnemonic_widget(combo) diff --git a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py index aba056d..8f3b6d6 100644 --- a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py +++ b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py @@ -41,7 +41,7 @@ from pyanaconda.ui.gui import GUIObject from pyanaconda.ui.gui.helpers import GUIDialogInputCheckHandler from pyanaconda.ui.gui.utils import fancy_set_sensitive, really_hide, really_show -from pyanaconda.i18n import _, N_, C_ +from pyanaconda.i18n import _, N_, C_, CN_
from blivet.size import Size from blivet.platform import platform @@ -70,9 +70,9 @@
ContainerType = namedtuple("ContainerType", ["name", "label"])
-CONTAINER_TYPES = {DEVICE_TYPE_LVM: ContainerType(N_("Volume Group"), N_("_Volume Group:")), - DEVICE_TYPE_LVM_THINP: ContainerType(N_("Volume Group"), N_("_Volume Group:")), - DEVICE_TYPE_BTRFS: ContainerType(N_("Volume"), N_("_Volume:"))} +CONTAINER_TYPES = {DEVICE_TYPE_LVM: ContainerType(N_("Volume Group"), CN_("GUI|Custom Partitioning|Configure|Devices", "_Volume Group:")), + DEVICE_TYPE_LVM_THINP: ContainerType(N_("Volume Group"), CN_("GUI|Custom Partitioning|Configure|Devices", "_Volume Group:")), + DEVICE_TYPE_BTRFS: ContainerType(N_("Volume"), CN_("GUI|Custom Partitioning|Configure|Devices", "_Volume:"))}
# These cannot be specified as mountpoints system_mountpoints = ["/dev", "/proc", "/run", "/sys"] @@ -306,7 +306,7 @@ def containerRaidLevelsSupported(device_type): return set()
def get_container_type(device_type): - return CONTAINER_TYPES.get(device_type, ContainerType(N_("container"), N_("container"))) + return CONTAINER_TYPES.get(device_type, ContainerType(N_("container"), CN_("GUI|Custom Partitioning|Configure|Devices", "container")))
class AddDialog(GUIObject): builderObjects = ["addDialog", "mountPointStore", "mountPointCompletion", "mountPointEntryBuffer"] diff --git a/pyanaconda/ui/gui/spokes/storage.glade b/pyanaconda/ui/gui/spokes/storage.glade index 0acdd3a..8bff202 100644 --- a/pyanaconda/ui/gui/spokes/storage.glade +++ b/pyanaconda/ui/gui/spokes/storage.glade @@ -820,7 +820,7 @@ </child> <child> <object class="GtkRadioButton" id="autopartRadioButton"> - <property name="label" translatable="yes">A_utomatically configure partitioning.</property> + <property name="label" translatable="yes" context="GUI|Storage">A_utomatically configure partitioning.</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> @@ -836,7 +836,7 @@ </child> <child> <object class="GtkRadioButton" id="customRadioButton"> - <property name="label" translatable="yes">_I will configure partitioning.</property> + <property name="label" translatable="yes" context="GUI|Storage">_I will configure partitioning.</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> @@ -868,7 +868,7 @@ <object class="GtkLabel" id="label13"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">_Encrypt my data.</property> + <property name="label" translatable="yes" context="GUI|Storage">_Encrypt my data.</property> <property name="use_underline">True</property> </object> </child> @@ -904,7 +904,7 @@ </child> <child> <object class="GtkCheckButton" id="reclaimCheckbox"> - <property name="label" translatable="yes">I would like to _make additional space available.</property> + <property name="label" translatable="yes" context="GUI|Storage">I would like to _make additional space available.</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> diff --git a/pyanaconda/ui/gui/spokes/storage.py b/pyanaconda/ui/gui/spokes/storage.py index 0f2b384..7bc4296 100644 --- a/pyanaconda/ui/gui/spokes/storage.py +++ b/pyanaconda/ui/gui/spokes/storage.py @@ -1003,7 +1003,8 @@ def on_info_bar_clicked(self, *args): "configuration. These are not fatal, but you may wish to make " "changes to your storage layout.")
- dialog = DetailedErrorDialog(self.data, buttons=[_("_OK")], label=label) + dialog = DetailedErrorDialog(self.data, + buttons=[C_("GUI|Storage|Warning Dialog", "_OK")], label=label) with self.main_window.enlightbox(dialog.window): warnings = "\n".join(self.warnings) dialog.refresh(warnings) diff --git a/pyanaconda/ui/tui/spokes/askvnc.py b/pyanaconda/ui/tui/spokes/askvnc.py index 45dda66..2d4121c 100644 --- a/pyanaconda/ui/tui/spokes/askvnc.py +++ b/pyanaconda/ui/tui/spokes/askvnc.py @@ -24,7 +24,7 @@ from pyanaconda.ui.tui.tuiobject import YesNoDialog from pyanaconda.constants import USEVNC, USETEXT, IPMI_ABORTED from pyanaconda.constants_text import INPUT_PROCESSED -from pyanaconda.i18n import N_, _ +from pyanaconda.i18n import N_, _, C_ from pyanaconda.ui.communication import hubQ from pyanaconda.ui.tui import exception_msg_handler from pyanaconda.iutil import execWithRedirect @@ -103,7 +103,8 @@ def input(self, args, key): except ValueError: pass
- if key.lower() == _('q'): + # TRANSLATORS: 'q' to quit + if key.lower() == C_('TUI|Spoke Navigation', 'q'): d = YesNoDialog(self.app, _(self.app.quit_message)) self.app.switch_screen_modal(d) if d.answer: diff --git a/widgets/src/SpokeWindow.c b/widgets/src/SpokeWindow.c index f213177..029f536 100644 --- a/widgets/src/SpokeWindow.c +++ b/widgets/src/SpokeWindow.c @@ -45,7 +45,7 @@ * space. This is where widgets will be added and the user will do things. */
-#define DEFAULT_BUTTON_LABEL _("_Done") +#define DEFAULT_BUTTON_LABEL C_("GUI|Spoke Navigation", "_Done")
enum { SIGNAL_BUTTON_CLICKED, diff --git a/widgets/src/StandaloneWindow.c b/widgets/src/StandaloneWindow.c index c952a1f..30e73e5 100644 --- a/widgets/src/StandaloneWindow.c +++ b/widgets/src/StandaloneWindow.c @@ -48,8 +48,11 @@ * space. This is where widgets will be added and the user will do things. */
-#define QUIT_TEXT N_("_Quit") -#define CONTINUE_TEXT N_("_Continue") +#define BUTTON_CONTEXT "GUI|Standalone Navigation" + +/* The context needs to be written out (no macros) for the CN_ lines so that gettext can see it */ +#define QUIT_TEXT CN_("GUI|Standalone Navigation", "_Quit") +#define CONTINUE_TEXT CN_("GUI|Standalone Navigation", "_Continue")
struct _AnacondaStandaloneWindowPrivate { GtkWidget *button_box; @@ -142,13 +145,13 @@ static void anaconda_standalone_window_init(AnacondaStandaloneWindow *win) { AnacondaStandaloneWindowPrivate);
/* Create the buttons. */ - win->priv->quit_button = gtk_button_new_with_mnemonic(_(QUIT_TEXT)); + win->priv->quit_button = gtk_button_new_with_mnemonic(C_(BUTTON_CONTEXT, QUIT_TEXT)); atk = gtk_widget_get_accessible(win->priv->quit_button); - atk_object_set_name(atk, _(QUIT_TEXT)); + atk_object_set_name(atk, C_(BUTTON_CONTEXT, QUIT_TEXT));
- win->priv->continue_button = gtk_button_new_with_mnemonic(_(CONTINUE_TEXT)); + win->priv->continue_button = gtk_button_new_with_mnemonic(C_(BUTTON_CONTEXT, CONTINUE_TEXT)); atk = gtk_widget_get_accessible(win->priv->continue_button); - atk_object_set_name(atk, _(CONTINUE_TEXT)); + atk_object_set_name(atk, C_(BUTTON_CONTEXT, CONTINUE_TEXT));
/* Set the Continue button to the blue 'suggested-action' style class */ context = gtk_widget_get_style_context(win->priv->continue_button); @@ -186,6 +189,6 @@ static void anaconda_standalone_window_init(AnacondaStandaloneWindow *win) { void anaconda_standalone_window_retranslate(AnacondaStandaloneWindow *win) { anaconda_base_window_retranslate(ANACONDA_BASE_WINDOW(win));
- gtk_button_set_label(GTK_BUTTON(win->priv->quit_button), _(QUIT_TEXT)); - gtk_button_set_label(GTK_BUTTON(win->priv->continue_button), _(CONTINUE_TEXT)); + gtk_button_set_label(GTK_BUTTON(win->priv->quit_button), C_(BUTTON_CONTEXT, QUIT_TEXT)); + gtk_button_set_label(GTK_BUTTON(win->priv->continue_button), C_(BUTTON_CONTEXT, CONTINUE_TEXT)); } diff --git a/widgets/src/intl.h b/widgets/src/intl.h index f73ce7a..533313a 100644 --- a/widgets/src/intl.h +++ b/widgets/src/intl.h @@ -25,6 +25,8 @@
#define _(x) dgettext("anaconda", x) #define N_(String) String +#define C_(Context, String) dpgettext("anaconda", Context, String) +#define CN_(Context, String) String
#ifdef ENABLE_NLS #define P_(String) g_dgettext("anaconda-properties",String)
In reply to line 48 of widgets/src/SpokeWindow.c:
I think we don't need the extra space before ``C_``
Added label: ACK.
Looks good to me too other than the nitpick above.
Closed.
Unspaced and pushed.
anaconda-patches@lists.fedorahosted.org