diff options
author | Bastien Nocera <hadess@hadess.net> | 2022-07-24 13:02:22 +0200 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2022-07-26 12:52:24 -0400 |
commit | f49f6c46bbfcc3376cb498c9ab9bc91a1efde93a (patch) | |
tree | d74b84757abf7580811689ece395ed5ab7453479 | |
parent | 07dadfd22e2e3fa6419eb3e931f08aff5c5467e6 (diff) | |
download | accountsservice-f49f6c46bbfcc3376cb498c9ab9bc91a1efde93a.tar.gz |
daemon: Add GetUsersLanguages() function
This will get an array of unique languages, formatted in XPG locale
format, as used by all the users of the system.
-rw-r--r-- | data/org.freedesktop.Accounts.xml | 29 | ||||
-rw-r--r-- | src/daemon.c | 80 |
2 files changed, 109 insertions, 0 deletions
diff --git a/data/org.freedesktop.Accounts.xml b/data/org.freedesktop.Accounts.xml index 4612c5d..64b44e2 100644 --- a/data/org.freedesktop.Accounts.xml +++ b/data/org.freedesktop.Accounts.xml @@ -187,6 +187,35 @@ </doc:doc> </method> + <method name="GetUsersLanguages"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <arg name="languages" direction="out" type="as"> + <doc:doc> + <doc:summary> + List users' preferred languages, as an array of locale specification like "de_DE.UTF-8". + </doc:summary> + </doc:doc> + </arg> + <doc:doc> + <doc:description> + <doc:para> + Lists all the languages set by all the users, sorted in order from most used to least used, + in XPG locale format. + </doc:para> + <doc:para> + Note that the languages are not parsed, and functional duplicates can occur (for instance, + en_GB and en_GB.UTF-8 may both end up in the list, even though they are the same). + </doc:para> + <doc:para> + The expectation is that package installers will use + this to know which languages users are interested in, so as + to install extra data, like translations, dictionaries, etc. + system-wide. + </doc:para> + </doc:description> + </doc:doc> + </method> + <signal name="UserAdded"> <arg name="user" type="o"> <doc:doc><doc:summary>Object path of the user that was added.</doc:summary></doc:doc> diff --git a/src/daemon.c b/src/daemon.c index 9e5b797..882bc26 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -22,6 +22,7 @@ #include "config.h" +#include <locale.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> @@ -1074,6 +1075,84 @@ daemon_list_cached_users (AccountsAccounts *accounts, return TRUE; } +static int +sort_languages (gconstpointer element_1, + gconstpointer element_2, + GHashTable *language_frequency_map) +{ + const char *language_1 = *(const char **) element_1; + const char *language_2 = *(const char **) element_2; + int count_1, count_2; + + count_1 = GPOINTER_TO_INT (g_hash_table_lookup (language_frequency_map, language_1)); + count_2 = GPOINTER_TO_INT (g_hash_table_lookup (language_frequency_map, language_2)); + + if (count_2 == count_1) { + return strcmp (language_1, language_2); + } + + return count_2 - count_1; +} + +static gboolean +daemon_get_users_languages (AccountsAccounts *accounts, + GDBusMethodInvocation *context) +{ + Daemon *daemon = (Daemon*)accounts; + DaemonPrivate *priv = daemon_get_instance_private (daemon); + g_autoptr(GHashTable) language_frequency_map = NULL; + GHashTableIter users_iter, language_frequency_map_iter; + gpointer key, value; + g_autoptr(GPtrArray) languages_array = NULL; + const char *system_locale; + + language_frequency_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + system_locale = setlocale (LC_MESSAGES, NULL); + + g_hash_table_insert (language_frequency_map, g_strdup (system_locale), 0); + + g_hash_table_iter_init (&users_iter, priv->users); + while (g_hash_table_iter_next (&users_iter, &key, &value)) { + const char *name = key; + User *user = value; + const char * const *languages = NULL; + guint i; + + if (user_get_system_account (user)) + continue; + + languages = accounts_user_get_languages (ACCOUNTS_USER (user)); + for (i = 0; languages != NULL && languages[i] != NULL; i++) { + int count; + const char *locale; + + if (languages[i][0] != '\0') + locale = languages[i]; + else + locale = system_locale; + + count = GPOINTER_TO_INT (g_hash_table_lookup (language_frequency_map, locale)); + count++; + + g_debug ("Adding lang '%s' for user %s to the list (count now %d)", locale, name, count); + + g_hash_table_insert (language_frequency_map, g_strdup (locale), GINT_TO_POINTER (count)); + } + } + + languages_array = g_ptr_array_new (); + g_hash_table_iter_init (&language_frequency_map_iter, language_frequency_map); + while (g_hash_table_iter_next (&language_frequency_map_iter, &key, &value)) { + g_ptr_array_add (languages_array, key); + } + g_ptr_array_sort_with_data (languages_array, (GCompareDataFunc) sort_languages, language_frequency_map); + g_ptr_array_add (languages_array, NULL); + + accounts_accounts_complete_get_users_languages (accounts, context, (const char * const *) languages_array->pdata); + return TRUE; +} + static const gchar * daemon_get_daemon_version (AccountsAccounts *object) { @@ -1706,6 +1785,7 @@ daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface) iface->handle_find_user_by_id = daemon_find_user_by_id; iface->handle_find_user_by_name = daemon_find_user_by_name; iface->handle_list_cached_users = daemon_list_cached_users; + iface->handle_get_users_languages = daemon_get_users_languages; iface->get_daemon_version = daemon_get_daemon_version; iface->handle_cache_user = daemon_cache_user; iface->handle_uncache_user = daemon_uncache_user; |