From e5d850b3deeda3ba0a5cd634d20305637eaded47 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 8 Aug 2024 21:30:24 +0100 Subject: [PATCH] Use gettext for translations in .policy files Fixes https://github.com/polkit-org/polkit/issues/35 --- src/polkitbackend/polkitbackendactionpool.c | 49 +++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/polkitbackend/polkitbackendactionpool.c b/src/polkitbackend/polkitbackendactionpool.c index 24ade4bd..9f0dd17d 100644 --- a/src/polkitbackend/polkitbackendactionpool.c +++ b/src/polkitbackend/polkitbackendactionpool.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -43,7 +45,9 @@ typedef struct gchar *vendor_url; gchar *icon_name; gchar *description; + gchar *description_domain; gchar *message; + gchar *message_domain; PolkitImplicitAuthorization implicit_authorization_any; PolkitImplicitAuthorization implicit_authorization_inactive; @@ -64,7 +68,9 @@ parsed_action_free (ParsedAction *action) g_free (action->vendor_url); g_free (action->icon_name); g_free (action->description); + g_free (action->description_domain); g_free (action->message); + g_free (action->message_domain); g_hash_table_unref (action->localized_description); g_hash_table_unref (action->localized_message); @@ -84,6 +90,7 @@ static void ensure_all_files (PolkitBackendActionPool *pool); static const gchar *_localize (GHashTable *translations, const gchar *untranslated, + const gchar *domain, const gchar *lang); typedef struct @@ -380,9 +387,11 @@ polkit_backend_action_pool_get_action (PolkitBackendActionPool *pool, description = _localize (parsed_action->localized_description, parsed_action->description, + parsed_action->description_domain, locale); message = _localize (parsed_action->localized_message, parsed_action->message, + parsed_action->message_domain, locale); ret = polkit_action_description_new (action_id, @@ -598,11 +607,16 @@ typedef struct { GHashTable *policy_messages; char *policy_description_nolang; + char *policy_description_domain; char *policy_message_nolang; + char *policy_message_domain; /* the value of xml:lang for the thing we're reading in _cdata() */ char *elem_lang; + /* the value of gettext-domain for the thing we're reading in _cdata() */ + char *elem_domain; + char *annotate_key; GHashTable *annotations; @@ -624,8 +638,12 @@ pd_unref_action_data (ParserData *pd) g_free (pd->policy_description_nolang); pd->policy_description_nolang = NULL; + g_free (pd->policy_description_domain); + pd->policy_description_domain = NULL; g_free (pd->policy_message_nolang); pd->policy_message_nolang = NULL; + g_free (pd->policy_message_domain); + pd->policy_message_domain = NULL; if (pd->policy_descriptions != NULL) { g_hash_table_unref (pd->policy_descriptions); @@ -645,6 +663,8 @@ pd_unref_action_data (ParserData *pd) } g_free (pd->elem_lang); pd->elem_lang = NULL; + g_free (pd->elem_domain); + pd->elem_domain = NULL; } static void @@ -732,6 +752,10 @@ _start (void *data, const char *el, const char **attr) { pd->elem_lang = g_strdup (attr[1]); } + if (num_attr == 2 && strcmp (attr[0], "gettext-domain") == 0) + { + pd->elem_domain = g_strdup (attr[1]); + } state = STATE_IN_ACTION_DESCRIPTION; } else if (strcmp (el, "message") == 0) @@ -740,6 +764,10 @@ _start (void *data, const char *el, const char **attr) { pd->elem_lang = g_strdup (attr[1]); } + if (num_attr == 2 && strcmp (attr[0], "gettext-domain") == 0) + { + pd->elem_domain = g_strdup (attr[1]); + } state = STATE_IN_ACTION_MESSAGE; } else if (strcmp (el, "vendor") == 0 && num_attr == 0) @@ -842,6 +870,7 @@ _cdata (void *data, const char *s, int len) { g_free (pd->policy_description_nolang); pd->policy_description_nolang = str; + pd->policy_description_domain = g_strdup (pd->elem_domain); str = NULL; } else @@ -858,6 +887,7 @@ _cdata (void *data, const char *s, int len) { g_free (pd->policy_message_nolang); pd->policy_message_nolang = str; + pd->policy_message_domain = g_strdup (pd->elem_domain); str = NULL; } else @@ -955,6 +985,8 @@ _end (void *data, const char *el) g_free (pd->elem_lang); pd->elem_lang = NULL; + g_free (pd->elem_domain); + pd->elem_domain = NULL; switch (pd->state) { @@ -985,7 +1017,9 @@ _end (void *data, const char *el) action->vendor_url = g_strdup (vendor_url); action->icon_name = g_strdup (icon_name); action->description = g_strdup (pd->policy_description_nolang); + action->description_domain = g_strdup (pd->policy_description_domain); action->message = g_strdup (pd->policy_message_nolang); + action->message_domain = g_strdup (pd->policy_message_domain); action->localized_description = pd->policy_descriptions; action->localized_message = pd->policy_messages; @@ -1088,6 +1122,7 @@ process_policy_file (PolkitBackendActionPool *pool, * _localize: * @translations: a mapping from xml:lang to the value, e.g. 'da' -> 'Smadre', 'en_CA' -> 'Punch, Aye!' * @untranslated: the untranslated value, e.g. 'Punch' + * @domain: the gettext domain for this string. May be NULL. * @lang: the locale we're interested in, e.g. 'da_DK', 'da', 'en_CA', 'en_US'; basically just $LANG * with the encoding cut off. Maybe be NULL. * @@ -1098,6 +1133,7 @@ process_policy_file (PolkitBackendActionPool *pool, static const gchar * _localize (GHashTable *translations, const gchar *untranslated, + const gchar *domain, const gchar *lang) { const gchar *result; @@ -1110,6 +1146,19 @@ _localize (GHashTable *translations, goto out; } + if (domain != NULL) + { + gchar *old_locale; + + old_locale = g_strdup (setlocale (LC_ALL, NULL)); + setlocale (LC_ALL, lang); + result = dgettext (domain, untranslated); + setlocale (LC_ALL, old_locale); + g_free (old_locale); + + goto out; + } + /* first see if we have the translation */ result = (const char *) g_hash_table_lookup (translations, (void *) lang); if (result != NULL)