summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2022-07-24 13:02:22 +0200
committerRay Strode <rstrode@redhat.com>2022-07-26 12:52:24 -0400
commitf49f6c46bbfcc3376cb498c9ab9bc91a1efde93a (patch)
treed74b84757abf7580811689ece395ed5ab7453479
parent07dadfd22e2e3fa6419eb3e931f08aff5c5467e6 (diff)
downloadaccountsservice-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.xml29
-rw-r--r--src/daemon.c80
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;