From 96e15488ec6eabd13089fbc4f4354db9d41a2100 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Wed, 18 Aug 2010 16:26:15 +1000 Subject: [PATCH] Use gettext for translations in .policy files --- src/polkitbackend/polkitbackendactionpool.c | 204 ++++++-------------- src/polkitbackend/polkitbackendactionpool.h | 6 +- .../polkitbackendinteractiveauthority.c | 37 +++-- 3 files changed, 81 insertions(+), 166 deletions(-) diff --git a/src/polkitbackend/polkitbackendactionpool.c b/src/polkitbackend/polkitbackendactionpool.c index 30e9540..2e3ac3a 100644 --- a/src/polkitbackend/polkitbackendactionpool.c +++ b/src/polkitbackend/polkitbackendactionpool.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -45,16 +46,14 @@ typedef struct gchar *vendor_url; gchar *icon_name; gchar *description; + gchar *description_gettext_domain; gchar *message; + gchar *message_gettext_domain; PolkitImplicitAuthorization implicit_authorization_any; PolkitImplicitAuthorization implicit_authorization_inactive; PolkitImplicitAuthorization implicit_authorization_active; - /* each of these map from the locale identifer (e.g. da_DK) to the localized value */ - GHashTable *localized_description; - GHashTable *localized_message; - /* this maps from annotation key (string) to annotation value (also a string) */ GHashTable *annotations; } ParsedAction; @@ -67,10 +66,9 @@ parsed_action_free (ParsedAction *action) g_free (action->vendor_url); g_free (action->icon_name); g_free (action->description); + g_free (action->description_gettext_domain); g_free (action->message); - - g_hash_table_unref (action->localized_description); - g_hash_table_unref (action->localized_message); + g_free (action->message_gettext_domain); g_hash_table_unref (action->annotations); g_free (action); @@ -85,10 +83,6 @@ static void ensure_file (PolkitBackendActionPool *pool, static void ensure_all_files (PolkitBackendActionPool *pool); -static const gchar *_localize (GHashTable *translations, - const gchar *untranslated, - const gchar *lang); - typedef struct { /* directory with .policy files, e.g. /usr/share/polkit-1/actions */ @@ -351,7 +345,6 @@ polkit_backend_action_pool_new (GFile *directory) * polkit_backend_action_pool_get_action: * @pool: A #PolkitBackendActionPool. * @action_id: A PolicyKit action identifier. - * @locale: The locale to get descriptions for or %NULL for system locale. * * Gets a #PolkitActionDescription object describing the action with identifier @action_id. * @@ -360,8 +353,7 @@ polkit_backend_action_pool_new (GFile *directory) **/ PolkitActionDescription * polkit_backend_action_pool_get_action (PolkitBackendActionPool *pool, - const gchar *action_id, - const gchar *locale) + const gchar *action_id) { PolkitBackendActionPoolPrivate *priv; PolkitActionDescription *ret; @@ -385,12 +377,8 @@ polkit_backend_action_pool_get_action (PolkitBackendActionPool *pool, goto out; } - description = _localize (parsed_action->localized_description, - parsed_action->description, - locale); - message = _localize (parsed_action->localized_message, - parsed_action->message, - locale); + description = dgettext (parsed_action->description_gettext_domain, parsed_action->description); + message = dgettext (parsed_action->message_gettext_domain, parsed_action->message); ret = polkit_action_description_new (action_id, description, @@ -410,7 +398,6 @@ polkit_backend_action_pool_get_action (PolkitBackendActionPool *pool, /** * polkit_backend_action_pool_get_all_actions: * @pool: A #PolkitBackendActionPool. - * @locale: The locale to get descriptions for or %NULL for system locale. * * Gets all registered PolicyKit action descriptions from @pool with strings for @locale. * @@ -419,8 +406,7 @@ polkit_backend_action_pool_get_action (PolkitBackendActionPool *pool, * been unreffed with g_object_unref(). **/ GList * -polkit_backend_action_pool_get_all_actions (PolkitBackendActionPool *pool, - const gchar *locale) +polkit_backend_action_pool_get_all_actions (PolkitBackendActionPool *pool) { GList *ret; PolkitBackendActionPoolPrivate *priv; @@ -441,8 +427,7 @@ polkit_backend_action_pool_get_all_actions (PolkitBackendActionPool *pool, PolkitActionDescription *action_desc; action_desc = polkit_backend_action_pool_get_action (pool, - action_id, - locale); + action_id); if (action_desc != NULL) ret = g_list_prepend (ret, action_desc); @@ -569,7 +554,9 @@ enum { STATE_IN_POLICY_ICON_NAME, STATE_IN_ACTION, STATE_IN_ACTION_DESCRIPTION, + STATE_IN_OBSOLETE_ACTION_DESCRIPTION, STATE_IN_ACTION_MESSAGE, + STATE_IN_OBSOLETE_ACTION_MESSAGE, STATE_IN_ACTION_VENDOR, STATE_IN_ACTION_VENDOR_URL, STATE_IN_ACTION_ICON_NAME, @@ -601,14 +588,10 @@ typedef struct { PolkitImplicitAuthorization implicit_authorization_inactive; PolkitImplicitAuthorization implicit_authorization_active; - GHashTable *policy_descriptions; - GHashTable *policy_messages; - - char *policy_description_nolang; - char *policy_message_nolang; - - /* the value of xml:lang for the thing we're reading in _cdata() */ - char *elem_lang; + char *policy_description; + char *description_gettext_domain; + char *policy_message; + char *message_gettext_domain; char *annotate_key; GHashTable *annotations; @@ -629,20 +612,14 @@ pd_unref_action_data (ParserData *pd) g_free (pd->icon_name); pd->icon_name = NULL; - g_free (pd->policy_description_nolang); - pd->policy_description_nolang = NULL; - g_free (pd->policy_message_nolang); - pd->policy_message_nolang = NULL; - if (pd->policy_descriptions != NULL) - { - g_hash_table_unref (pd->policy_descriptions); - pd->policy_descriptions = NULL; - } - if (pd->policy_messages != NULL) - { - g_hash_table_unref (pd->policy_messages); - pd->policy_messages = NULL; - } + g_free (pd->policy_description); + pd->policy_description = NULL; + g_free (pd->description_gettext_domain); + pd->description_gettext_domain = NULL; + g_free (pd->policy_message); + pd->policy_message = NULL; + g_free (pd->message_gettext_domain); + pd->message_gettext_domain = NULL; g_free (pd->annotate_key); pd->annotate_key = NULL; if (pd->annotations != NULL) @@ -650,8 +627,6 @@ pd_unref_action_data (ParserData *pd) g_hash_table_unref (pd->annotations); pd->annotations = NULL; } - g_free (pd->elem_lang); - pd->elem_lang = NULL; } static void @@ -700,14 +675,6 @@ _start (void *data, const char *el, const char **attr) pd_unref_action_data (pd); pd->action_id = g_strdup (attr[1]); - pd->policy_descriptions = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); - pd->policy_messages = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); pd->annotations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); /* initialize defaults */ pd->implicit_authorization_any = POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED; @@ -735,19 +702,37 @@ _start (void *data, const char *el, const char **attr) } else if (strcmp (el, "description") == 0) { + if (num_attr == 2 && strcmp (attr[0], "gettext-domain") == 0) + { + pd->description_gettext_domain = g_strdup (attr[1]); + } + + /* Ignore old form of translations */ if (num_attr == 2 && strcmp (attr[0], "xml:lang") == 0) { - pd->elem_lang = g_strdup (attr[1]); + state = STATE_IN_OBSOLETE_ACTION_DESCRIPTION; + } + else + { + state = STATE_IN_ACTION_DESCRIPTION; } - state = STATE_IN_ACTION_DESCRIPTION; } else if (strcmp (el, "message") == 0) { + if (num_attr == 2 && strcmp (attr[0], "gettext-domain") == 0) + { + pd->message_gettext_domain = g_strdup (attr[1]); + } + + /* Ignore old form of translations */ if (num_attr == 2 && strcmp (attr[0], "xml:lang") == 0) { - pd->elem_lang = g_strdup (attr[1]); + state = STATE_IN_OBSOLETE_ACTION_MESSAGE; + } + else + { + state = STATE_IN_ACTION_MESSAGE; } - state = STATE_IN_ACTION_MESSAGE; } else if (strcmp (el, "vendor") == 0 && num_attr == 0) { @@ -845,35 +830,15 @@ _cdata (void *data, const char *s, int len) switch (pd->state) { case STATE_IN_ACTION_DESCRIPTION: - if (pd->elem_lang == NULL) - { - g_free (pd->policy_description_nolang); - pd->policy_description_nolang = str; - str = NULL; - } - else - { - g_hash_table_insert (pd->policy_descriptions, - g_strdup (pd->elem_lang), - str); - str = NULL; - } + g_free (pd->policy_description); + pd->policy_description = str; + str = NULL; break; case STATE_IN_ACTION_MESSAGE: - if (pd->elem_lang == NULL) - { - g_free (pd->policy_message_nolang); - pd->policy_message_nolang = str; - str = NULL; - } - else - { - g_hash_table_insert (pd->policy_messages, - g_strdup (pd->elem_lang), - str); - str = NULL; - } + g_free (pd->policy_message); + pd->policy_message = str; + str = NULL; break; case STATE_IN_POLICY_VENDOR: @@ -960,9 +925,6 @@ _end (void *data, const char *el) { ParserData *pd = data; - g_free (pd->elem_lang); - pd->elem_lang = NULL; - switch (pd->state) { case STATE_IN_ACTION: @@ -992,11 +954,11 @@ _end (void *data, const char *el) action->vendor_name = g_strdup (vendor); action->vendor_url = g_strdup (vendor_url); action->icon_name = g_strdup (icon_name); - action->description = g_strdup (pd->policy_description_nolang); - action->message = g_strdup (pd->policy_message_nolang); + action->description = g_strdup (pd->policy_description); + action->description_gettext_domain = g_strdup (pd->description_gettext_domain); + action->message = g_strdup (pd->policy_message); + action->message_gettext_domain = g_strdup (pd->message_gettext_domain); - action->localized_description = pd->policy_descriptions; - action->localized_message = pd->policy_messages; action->annotations = pd->annotations; action->implicit_authorization_any = pd->implicit_authorization_any; @@ -1007,8 +969,6 @@ _end (void *data, const char *el) /* we steal these hash tables */ pd->annotations = NULL; - pd->policy_descriptions = NULL; - pd->policy_messages = NULL; break; } @@ -1093,55 +1053,3 @@ error: pd_unref_data (&pd); return FALSE; } - -/** - * _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' - * @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. - * - * Pick the correct translation to use. - * - * Returns: the localized string to use - */ -static const gchar * -_localize (GHashTable *translations, - const gchar *untranslated, - const gchar *lang) -{ - const gchar *result; - gchar lang2[256]; - guint n; - - if (lang == NULL) - { - result = untranslated; - goto out; - } - - /* first see if we have the translation */ - result = (const char *) g_hash_table_lookup (translations, (void *) lang); - if (result != NULL) - goto out; - - /* we could have a translation for 'da' but lang=='da_DK'; cut off the last part and try again */ - strncpy (lang2, lang, sizeof (lang2)); - for (n = 0; lang2[n] != '\0'; n++) - { - if (lang2[n] == '_') - { - lang2[n] = '\0'; - break; - } - } - result = (const char *) g_hash_table_lookup (translations, (void *) lang2); - if (result != NULL) - goto out; - - /* fall back to untranslated */ - result = untranslated; - -out: - return result; -} diff --git a/src/polkitbackend/polkitbackendactionpool.h b/src/polkitbackend/polkitbackendactionpool.h index e992eea..9d99cf5 100644 --- a/src/polkitbackend/polkitbackendactionpool.h +++ b/src/polkitbackend/polkitbackendactionpool.h @@ -65,12 +65,10 @@ struct _PolkitBackendActionPoolClass GType polkit_backend_action_pool_get_type (void) G_GNUC_CONST; PolkitBackendActionPool *polkit_backend_action_pool_new (GFile *directory); -GList *polkit_backend_action_pool_get_all_actions (PolkitBackendActionPool *pool, - const gchar *locale); +GList *polkit_backend_action_pool_get_all_actions (PolkitBackendActionPool *pool); PolkitActionDescription *polkit_backend_action_pool_get_action (PolkitBackendActionPool *pool, - const gchar *action_id, - const gchar *locale); + const gchar *action_id); G_END_DECLS diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c index 31e60df..cba3a4a 100644 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c @@ -402,7 +402,7 @@ polkit_backend_interactive_authority_class_init (PolkitBackendInteractiveAuthori static GList * polkit_backend_interactive_authority_enumerate_actions (PolkitBackendAuthority *authority, PolkitSubject *caller, - const gchar *interactivee, + const gchar *locale, GError **error) { PolkitBackendInteractiveAuthority *interactive_authority; @@ -412,7 +412,18 @@ polkit_backend_interactive_authority_enumerate_actions (PolkitBackendAuthority interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority); priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority); - actions = polkit_backend_action_pool_get_all_actions (priv->action_pool, interactivee); + /* Set LANG and locale so gettext() + friends work when running the code in the extensions */ + if (setlocale (LC_ALL, locale) == NULL) + { + g_printerr ("Invalid locale '%s'\n", locale); + } + g_setenv ("LANG", locale, TRUE); + + actions = polkit_backend_action_pool_get_all_actions (priv->action_pool); + + /* Back to C! */ + setlocale (LC_ALL, "C"); + g_setenv ("LANG", "C", TRUE); return actions; } @@ -985,8 +996,7 @@ check_authorization_sync (PolkitBackendAuthority *authority, /* get the action description */ action_desc = polkit_backend_action_pool_get_action (priv->action_pool, - action_id, - NULL); + action_id); if (action_desc == NULL) { @@ -1728,12 +1738,6 @@ get_localized_data_for_challenge (PolkitBackendInteractiveAuthority *authority, *out_localized_icon_name = NULL; *out_localized_details = NULL; - action_desc = polkit_backend_action_pool_get_action (priv->action_pool, - action_id, - locale); - if (action_desc == NULL) - goto out; - /* Set LANG and locale so gettext() + friends work when running the code in the extensions */ if (setlocale (LC_ALL, locale) == NULL) { @@ -1741,6 +1745,11 @@ get_localized_data_for_challenge (PolkitBackendInteractiveAuthority *authority, } g_setenv ("LANG", locale, TRUE); + action_desc = polkit_backend_action_pool_get_action (priv->action_pool, + action_id); + if (action_desc == NULL) + goto out; + /* call into extension points to get localized auth dialog data - the list is sorted by priority */ action_lookup_list = get_action_lookup_list (); for (l = action_lookup_list; l != NULL; l = l->next) @@ -1769,10 +1778,6 @@ get_localized_data_for_challenge (PolkitBackendInteractiveAuthority *authority, action_desc); } - /* Back to C! */ - setlocale (LC_ALL, "C"); - g_setenv ("LANG", "C", TRUE); - /* fall back to action description */ if (message == NULL) { @@ -1784,6 +1789,10 @@ get_localized_data_for_challenge (PolkitBackendInteractiveAuthority *authority, } out: + /* Back to C! */ + setlocale (LC_ALL, "C"); + g_setenv ("LANG", "C", TRUE); + if (message == NULL) message = g_strdup (""); if (icon_name == NULL) -- 1.7.1