VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/lightdm-greeter/liblightdm-gobject-1.5.0/language.c

Last change on this file was 69506, checked in by vboxsync, 7 years ago

More scm updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
Line 
1/*
2 * Copyright (C) 2010 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
4 *
5 * This library is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License as published by the Free
7 * Software Foundation; either version 2 or version 3 of the License.
8 * See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
9 */
10
11/*
12 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
13 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
14 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
15 * a choice of LGPL license versions is made available with the language indicating
16 * that LGPLv2 or any later version may be used, or where a choice of which version
17 * of the LGPL is applied is otherwise unspecified.
18 */
19
20#include <string.h>
21#include <locale.h>
22#include <langinfo.h>
23#include <stdio.h>
24#include <glib/gi18n.h>
25
26#include "lightdm/language.h"
27
28enum {
29 PROP_0,
30 PROP_CODE,
31 PROP_NAME,
32 PROP_TERRITORY
33};
34
35typedef struct
36{
37 gchar *code;
38 gchar *name;
39 gchar *territory;
40} LightDMLanguagePrivate;
41
42G_DEFINE_TYPE (LightDMLanguage, lightdm_language, G_TYPE_OBJECT);
43
44#define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_LANGUAGE, LightDMLanguagePrivate)
45
46static gboolean have_languages = FALSE;
47static GList *languages = NULL;
48
49static void
50update_languages (void)
51{
52 gchar *command = "locale -a";
53 gchar *stdout_text = NULL, *stderr_text = NULL;
54 gint exit_status;
55 gboolean result;
56 GError *error = NULL;
57
58 if (have_languages)
59 return;
60
61 result = g_spawn_command_line_sync (command, &stdout_text, &stderr_text, &exit_status, &error);
62 if (error)
63 {
64 g_warning ("Failed to run '%s': %s", command, error->message);
65 g_clear_error (&error);
66 }
67 else if (exit_status != 0)
68 g_warning ("Failed to get languages, '%s' returned %d", command, exit_status);
69 else if (result)
70 {
71 gchar **tokens;
72 int i;
73
74 tokens = g_strsplit_set (stdout_text, "\n\r", -1);
75 for (i = 0; tokens[i]; i++)
76 {
77 LightDMLanguage *language;
78 gchar *code;
79
80 code = g_strchug (tokens[i]);
81 if (code[0] == '\0')
82 continue;
83
84 /* Ignore the non-interesting languages */
85 if (strcmp (command, "locale -a") == 0 && !g_strrstr (code, ".utf8"))
86 continue;
87
88 language = g_object_new (LIGHTDM_TYPE_LANGUAGE, "code", code, NULL);
89 languages = g_list_append (languages, language);
90 }
91
92 g_strfreev (tokens);
93 }
94
95 g_free (stdout_text);
96 g_free (stderr_text);
97
98 have_languages = TRUE;
99}
100
101static gboolean
102is_utf8 (const gchar *code)
103{
104 return g_strrstr (code, ".utf8") || g_strrstr (code, ".UTF-8");
105}
106
107/* Get a valid locale name that can be passed to setlocale(), so we always can use nl_langinfo() to get language and country names. */
108static gchar *
109get_locale_name (const gchar *code)
110{
111 gchar *locale = NULL, *language;
112 char *at;
113 static gchar **avail_locales;
114 gint i;
115
116 if (is_utf8 (code))
117 return (gchar *) code;
118
119 if ((at = strchr (code, '@')))
120 language = g_strndup (code, at - code);
121 else
122 language = g_strdup (code);
123
124 if (!avail_locales)
125 {
126 gchar *locales;
127 GError *error = NULL;
128
129 if (g_spawn_command_line_sync ("locale -a", &locales, NULL, NULL, &error))
130 {
131 avail_locales = g_strsplit (g_strchomp (locales), "\n", -1);
132 g_free (locales);
133 }
134 else
135 {
136 g_warning ("Failed to run 'locale -a': %s", error->message);
137 g_clear_error (&error);
138 }
139 }
140
141 if (avail_locales)
142 {
143 for (i = 0; avail_locales[i]; i++)
144 {
145 gchar *loc = avail_locales[i];
146 if (!g_strrstr (loc, ".utf8"))
147 continue;
148 if (g_str_has_prefix (loc, language))
149 {
150 locale = g_strdup (loc);
151 break;
152 }
153 }
154 }
155
156 g_free (language);
157
158 return locale;
159}
160
161/**
162 * lightdm_get_language:
163 *
164 * Get the current language.
165 *
166 * Return value: (transfer none): The current language or #NULL if no language.
167 **/
168LightDMLanguage *
169lightdm_get_language (void)
170{
171 const gchar *lang;
172 GList *link;
173
174 lang = g_getenv ("LANG");
175 if (!lang)
176 return NULL;
177
178 for (link = lightdm_get_languages (); link; link = link->next)
179 {
180 LightDMLanguage *language = link->data;
181 if (lightdm_language_matches (language, lang))
182 return language;
183 }
184
185 return NULL;
186}
187
188/**
189 * lightdm_get_languages:
190 *
191 * Get a list of languages to present to the user.
192 *
193 * Return value: (element-type LightDMLanguage) (transfer none): A list of #LightDMLanguage that should be presented to the user.
194 **/
195GList *
196lightdm_get_languages (void)
197{
198 update_languages ();
199 return languages;
200}
201
202/**
203 * lightdm_language_get_code:
204 * @language: A #LightDMLanguage
205 *
206 * Get the code of a language.
207 *
208 * Return value: The code of the language
209 **/
210const gchar *
211lightdm_language_get_code (LightDMLanguage *language)
212{
213 g_return_val_if_fail (LIGHTDM_IS_LANGUAGE (language), NULL);
214 return GET_PRIVATE (language)->code;
215}
216
217/**
218 * lightdm_language_get_name:
219 * @language: A #LightDMLanguage
220 *
221 * Get the name of a language.
222 *
223 * Return value: The name of the language
224 **/
225const gchar *
226lightdm_language_get_name (LightDMLanguage *language)
227{
228 LightDMLanguagePrivate *priv;
229
230 g_return_val_if_fail (LIGHTDM_IS_LANGUAGE (language), NULL);
231
232 priv = GET_PRIVATE (language);
233
234 if (!priv->name)
235 {
236 gchar *locale = get_locale_name (priv->code);
237 if (locale)
238 {
239 gchar *current = setlocale (LC_ALL, NULL);
240 setlocale (LC_IDENTIFICATION, locale);
241 setlocale (LC_MESSAGES, "");
242
243 gchar *language_en = nl_langinfo (_NL_IDENTIFICATION_LANGUAGE);
244 if (language_en && strlen (language_en) > 0)
245 priv->name = g_strdup (dgettext ("iso_639_3", language_en));
246
247 setlocale (LC_ALL, current);
248 }
249 if (!priv->name)
250 {
251 gchar **tokens = g_strsplit_set (priv->code, "_.@", 2);
252 priv->name = g_strdup (tokens[0]);
253 g_strfreev (tokens);
254 }
255 }
256
257 return priv->name;
258}
259
260/**
261 * lightdm_language_get_territory:
262 * @language: A #LightDMLanguage
263 *
264 * Get the territory the language is used in.
265 *
266 * Return value: The territory the language is used in.
267 **/
268const gchar *
269lightdm_language_get_territory (LightDMLanguage *language)
270{
271 LightDMLanguagePrivate *priv;
272
273 g_return_val_if_fail (LIGHTDM_IS_LANGUAGE (language), NULL);
274
275 priv = GET_PRIVATE (language);
276
277 if (!priv->territory && strchr (priv->code, '_'))
278 {
279 gchar *locale = get_locale_name (priv->code);
280 if (locale)
281 {
282 gchar *current = setlocale (LC_ALL, NULL);
283 setlocale (LC_IDENTIFICATION, locale);
284 setlocale (LC_MESSAGES, "");
285
286 gchar *country_en = nl_langinfo (_NL_IDENTIFICATION_TERRITORY);
287 if (country_en && strlen (country_en) > 0 && g_strcmp0 (country_en, "ISO") != 0)
288 priv->territory = g_strdup (dgettext ("iso_3166", country_en));
289
290 setlocale (LC_ALL, current);
291 }
292 if (!priv->territory)
293 {
294 gchar **tokens = g_strsplit_set (priv->code, "_.@", 3);
295 priv->territory = g_strdup (tokens[1]);
296 g_strfreev (tokens);
297 }
298 }
299
300 return priv->territory;
301}
302
303/**
304 * lightdm_language_matches:
305 * @language: A #LightDMLanguage
306 * @code: A language code
307 *
308 * Check if a language code matches this language.
309 *
310 * Return value: #TRUE if the code matches this language.
311 **/
312gboolean
313lightdm_language_matches (LightDMLanguage *language, const gchar *code)
314{
315 LightDMLanguagePrivate *priv;
316
317 g_return_val_if_fail (LIGHTDM_IS_LANGUAGE (language), FALSE);
318 g_return_val_if_fail (code != NULL, FALSE);
319
320 priv = GET_PRIVATE (language);
321
322 /* Handle the fact the UTF-8 is specified both as '.utf8' and '.UTF-8' */
323 if (is_utf8 (priv->code) && is_utf8 (code))
324 {
325 /* Match the characters before the '.' */
326 int i;
327 for (i = 0; priv->code[i] && code[i] && priv->code[i] == code[i] && code[i] != '.' ; i++);
328 return priv->code[i] == '.' && code[i] == '.';
329 }
330
331 return g_str_equal (priv->code, code);
332}
333
334static void
335lightdm_language_init (LightDMLanguage *language)
336{
337}
338
339static void
340lightdm_language_set_property (GObject *object,
341 guint prop_id,
342 const GValue *value,
343 GParamSpec *pspec)
344{
345 LightDMLanguage *self = LIGHTDM_LANGUAGE (object);
346 LightDMLanguagePrivate *priv = GET_PRIVATE (self);
347
348 switch (prop_id) {
349 case PROP_CODE:
350 g_free (priv->name);
351 priv->code = g_strdup (g_value_get_string (value));
352 break;
353 default:
354 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
355 break;
356 }
357}
358
359static void
360lightdm_language_get_property (GObject *object,
361 guint prop_id,
362 GValue *value,
363 GParamSpec *pspec)
364{
365 LightDMLanguage *self;
366
367 self = LIGHTDM_LANGUAGE (object);
368
369 switch (prop_id) {
370 case PROP_CODE:
371 g_value_set_string (value, lightdm_language_get_code (self));
372 break;
373 case PROP_NAME:
374 g_value_set_string (value, lightdm_language_get_name (self));
375 break;
376 case PROP_TERRITORY:
377 g_value_set_string (value, lightdm_language_get_territory (self));
378 break;
379 default:
380 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
381 break;
382 }
383}
384
385static void
386lightdm_language_class_init (LightDMLanguageClass *klass)
387{
388 GObjectClass *object_class = G_OBJECT_CLASS (klass);
389
390 g_type_class_add_private (klass, sizeof (LightDMLanguagePrivate));
391
392 object_class->set_property = lightdm_language_set_property;
393 object_class->get_property = lightdm_language_get_property;
394
395 g_object_class_install_property (object_class,
396 PROP_CODE,
397 g_param_spec_string ("code",
398 "code",
399 "Language code",
400 NULL,
401 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
402 g_object_class_install_property (object_class,
403 PROP_NAME,
404 g_param_spec_string ("name",
405 "name",
406 "Name of the language",
407 NULL,
408 G_PARAM_READABLE));
409 g_object_class_install_property (object_class,
410 PROP_TERRITORY,
411 g_param_spec_string ("territory",
412 "territory",
413 "Territory the language is from",
414 NULL,
415 G_PARAM_READABLE));
416}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use