VirtualBox

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

最後變更 在這個檔案從64588是 45170,由 vboxsync 提交於 12 年 前

Additions/linux: lightdm-greeter to OSE

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette