2 * "$Id: language.c 4985 2006-01-25 21:57:18Z mike $"
4 * I18N/language support for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * _cupsEncodingName() - Return the character encoding name string
29 * for the given encoding enumeration.
30 * cupsLangDefault() - Return the default language.
31 * cupsLangEncoding() - Return the character encoding (us-ascii, etc.)
32 * for the given language.
33 * cupsLangFlush() - Flush all language data out of the cache.
34 * _cupsLangFlush() - Flush all language data out of the cache.
35 * cupsLangFree() - Free language data.
36 * cupsLangGet() - Get a language.
37 * _cupsLangString() - Get a message string.
38 * _cupsMessageFree() - Free a messages array.
39 * _cupsMessageLoad() - Load a .po file into a messages array.
40 * _cupsMessageLookup() - Lookup a message string.
41 * _cupsRestoreLocale() - Restore the original locale...
42 * _cupsSaveLocale() - Set the locale and save a copy of the old locale...
43 * appleLangDefault() - Get the default locale string.
44 * cups_cache_lookup() - Lookup a language in the cache...
45 * cups_message_compare() - Compare two messages.
46 * cups_unquote() - Unquote characters in strings...
50 * Include necessary headers...
56 #ifdef HAVE_LANGINFO_H
57 # include <langinfo.h>
58 #endif /* HAVE_LANGINFO_H */
64 #ifdef HAVE_COREFOUNDATION_H
65 # include <CoreFoundation/CoreFoundation.h>
66 #endif /* HAVE_COREFOUNDATION_H */
74 static const char *appleLangDefault(void);
75 #endif /* __APPLE__ */
76 static cups_lang_t
*cups_cache_lookup(const char *name
,
77 cups_encoding_t encoding
);
78 static int cups_message_compare(_cups_message_t
*m1
,
80 static void cups_unquote(char *d
, const char *s
);
87 static const char * const lang_encodings
[] =
88 { /* Encoding strings */
89 "us-ascii", "iso-8859-1",
90 "iso-8859-2", "iso-8859-3",
91 "iso-8859-4", "iso-8859-5",
92 "iso-8859-6", "iso-8859-7",
93 "iso-8859-8", "iso-8859-9",
94 "iso-8859-10", "utf-8",
95 "iso-8859-13", "iso-8859-14",
96 "iso-8859-15", "windows-874",
97 "windows-1250", "windows-1251",
98 "windows-1252", "windows-1253",
99 "windows-1254", "windows-1255",
100 "windows-1256", "windows-1257",
101 "windows-1258", "koi8-r",
102 "koi8-u", "iso-8859-11",
103 "iso-8859-16", "unknown",
104 "unknown", "unknown",
105 "unknown", "unknown",
106 "unknown", "unknown",
107 "unknown", "unknown",
108 "unknown", "unknown",
109 "unknown", "unknown",
110 "unknown", "unknown",
111 "unknown", "unknown",
112 "unknown", "unknown",
113 "unknown", "unknown",
114 "unknown", "unknown",
115 "unknown", "unknown",
116 "unknown", "unknown",
117 "unknown", "unknown",
118 "unknown", "unknown",
119 "unknown", "unknown",
120 "unknown", "unknown",
121 "windows-932", "windows-936",
122 "windows-949", "windows-950",
123 "windows-1361", "unknown",
124 "unknown", "unknown",
125 "unknown", "unknown",
126 "unknown", "unknown",
127 "unknown", "unknown",
128 "unknown", "unknown",
129 "unknown", "unknown",
130 "unknown", "unknown",
131 "unknown", "unknown",
132 "unknown", "unknown",
133 "unknown", "unknown",
134 "unknown", "unknown",
135 "unknown", "unknown",
136 "unknown", "unknown",
137 "unknown", "unknown",
138 "unknown", "unknown",
139 "unknown", "unknown",
140 "unknown", "unknown",
141 "unknown", "unknown",
142 "unknown", "unknown",
143 "unknown", "unknown",
144 "unknown", "unknown",
145 "unknown", "unknown",
146 "unknown", "unknown",
147 "unknown", "unknown",
148 "unknown", "unknown",
149 "unknown", "unknown",
150 "unknown", "unknown",
151 "unknown", "unknown",
152 "unknown", "unknown",
159 * '_cupsEncodingName()' - Return the character encoding name string
160 * for the given encoding enumeration.
163 const char * /* O - Character encoding */
165 cups_encoding_t encoding
) /* I - Encoding value */
168 encoding
>= (sizeof(lang_encodings
) / sizeof(const char *)))
169 return (lang_encodings
[0]);
171 return (lang_encodings
[encoding
]);
176 * 'cupsLangDefault()' - Return the default language.
179 cups_lang_t
* /* O - Language data */
180 cupsLangDefault(void)
182 return (cupsLangGet(NULL
));
187 * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.)
188 * for the given language.
191 const char * /* O - Character encoding */
192 cupsLangEncoding(cups_lang_t
*lang
) /* I - Language data */
195 return ((char*)lang_encodings
[0]);
197 return ((char*)lang_encodings
[lang
->encoding
]);
202 * 'cupsLangFlush()' - Flush all language data out of the cache.
208 _cupsLangFlush(_cupsGlobals());
213 * '_cupsLangFlush()' - Flush all language data out of the cache.
217 _cupsLangFlush(_cups_globals_t
*cg
) /* I - Global data */
219 cups_lang_t
*lang
, /* Current language */
220 *next
; /* Next language */
224 * Free all languages in the cache...
227 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= next
)
230 * Free all messages...
233 _cupsMessageFree(lang
->strings
);
236 * Then free the language structure itself...
243 cg
->lang_cache
= NULL
;
248 * 'cupsLangFree()' - Free language data.
250 * This does not actually free anything; use cupsLangFlush() for that.
254 cupsLangFree(cups_lang_t
*lang
) /* I - Language to free */
256 if (lang
!= NULL
&& lang
->used
> 0)
262 * 'cupsLangGet()' - Get a language.
265 cups_lang_t
* /* O - Language data */
266 cupsLangGet(const char *language
) /* I - Language or locale */
268 int i
; /* Looping var */
269 char locale
[255], /* Copy of locale name */
270 langname
[16], /* Requested language name */
271 country
[16], /* Country code */
272 charset
[16], /* Character set */
274 *csptr
, /* Pointer to CODESET string */
276 *ptr
, /* Pointer into language/charset */
277 real
[48], /* Real language name */
278 filename
[1024]; /* Filename for language locale file */
279 cups_encoding_t encoding
; /* Encoding to use */
280 cups_lang_t
*lang
; /* Current language... */
281 char *oldlocale
; /* Old locale name */
282 _cups_globals_t
*cg
= _cupsGlobals();
283 /* Pointer to library globals */
284 static const char * const locale_encodings
[] =
285 { /* Locale charset names */
286 "ASCII", "ISO88591", "ISO88592", "ISO88593",
287 "ISO88594", "ISO88595", "ISO88596", "ISO88597",
288 "ISO88598", "ISO88599", "ISO885910", "UTF8",
289 "ISO885913", "ISO885914", "ISO885915", "CP874",
290 "CP1250", "CP1251", "CP1252", "CP1253",
291 "CP1254", "CP1255", "CP1256", "CP1257",
292 "CP1258", "KOI8R", "KOI8U", "ISO885911",
293 "ISO885916", "", "", "",
304 "CP932", "CP936", "CP949", "CP950",
305 "CP1361", "", "", "",
322 "EUCCN", "EUCJP", "EUCKR", "EUCTW"
326 DEBUG_printf(("cupsLangGet(language=\"%s\")\n", language
? language
: "(null)"));
330 * Apple's setlocale doesn't give us the user's localization
331 * preference so we have to look it up this way...
334 if (language
== NULL
)
335 language
= appleLangDefault();
337 if (language
== NULL
)
340 * First see if the locale has been set; if it is still "C" or
341 * "POSIX", set the locale to the default...
345 ptr
= setlocale(LC_MESSAGES
, NULL
);
347 ptr
= setlocale(LC_ALL
, NULL
);
348 # endif /* LC_MESSAGES */
350 DEBUG_printf(("cupsLangGet: current locale is \"%s\"\n",
351 ptr
? ptr
: "(null)"));
353 if (!ptr
|| !strcmp(ptr
, "C") || !strcmp(ptr
, "POSIX"))
356 ptr
= setlocale(LC_MESSAGES
, "");
357 setlocale(LC_CTYPE
, "");
360 ptr
= setlocale(LC_ALL
, "");
361 # endif /* LC_MESSAGES */
365 strlcpy(locale
, ptr
, sizeof(locale
));
368 DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n",
369 language
? language
: "(null)"));
372 #endif /* __APPLE__ */
375 * If "language" is NULL at this point, then chances are we are using
376 * a language that is not installed for the base OS.
382 * Switch to the value of the "LANG" environment variable, and if
383 * that is NULL as well, use "C".
386 if ((language
= getenv("LANG")) == NULL
)
391 * Set the charset to "unknown"...
398 * On systems that support the nl_langinfo(CODESET) call, use
399 * this value as the character set...
402 if ((csptr
= nl_langinfo(CODESET
)) != NULL
)
405 * Copy all of the letters and numbers in the CODESET string...
408 for (ptr
= charset
; *csptr
; csptr
++)
409 if (isalnum(*csptr
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
414 DEBUG_printf(("cupsLangGet: charset set to \"%s\" via nl_langinfo(CODESET)...\n",
420 * Set the locale back to POSIX while we do string ops, since
421 * apparently some buggy C libraries break ctype() for non-I18N
425 #if defined(__APPLE__)
426 /* The ctype bug isn't in Apple's libc */
427 (void)locale
; /* anti-compiler-warning-code */
428 (void)oldlocale
; /* anti-compiler-warning-code */
429 #elif !defined(LC_CTYPE)
430 oldlocale
= _cupsSaveLocale(LC_ALL
, "C");
432 oldlocale
= _cupsSaveLocale(LC_CTYPE
, "C");
433 #endif /* __APPLE__ */
436 * Parse the language string passed in to a locale string. "C" is the
437 * standard POSIX locale and is copied unchanged. Otherwise the
438 * language string is converted from ll-cc[.charset] (language-country)
439 * to ll_CC[.CHARSET] to match the file naming convention used by all
440 * POSIX-compliant operating systems. Invalid language names are mapped
441 * to the POSIX locale.
446 if (language
== NULL
|| !language
[0] ||
447 !strcmp(language
, "POSIX"))
448 strcpy(langname
, "C");
452 * Copy the parts of the locale string over safely...
455 for (ptr
= langname
; *language
; language
++)
456 if (*language
== '_' || *language
== '-' || *language
== '.')
458 else if (ptr
< (langname
+ sizeof(langname
) - 1))
459 *ptr
++ = tolower(*language
& 255);
463 if (*language
== '_' || *language
== '-')
466 * Copy the country code...
469 for (language
++, ptr
= country
; *language
; language
++)
470 if (*language
== '.')
472 else if (ptr
< (country
+ sizeof(country
) - 1))
473 *ptr
++ = toupper(*language
& 255);
478 if (*language
== '.' && !charset
[0])
481 * Copy the encoding...
484 for (language
++, ptr
= charset
; *language
; language
++)
485 if (isalnum(*language
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
486 *ptr
++ = toupper(*language
& 255);
492 * Force a POSIX locale for an invalid language name...
495 if (strlen(langname
) != 2)
497 strcpy(langname
, "C");
504 * Restore the locale...
507 #if defined(__APPLE__)
508 /* The ctype bug isn't in Apple's libc */
509 #elif !defined(LC_CTYPE)
510 _cupsRestoreLocale(LC_ALL
, oldlocale
);
512 _cupsRestoreLocale(LC_CTYPE
, oldlocale
);
513 #endif /* __APPLE__ */
515 DEBUG_printf(("cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"\n",
516 langname
, country
, charset
));
519 * Figure out the desired encoding...
522 encoding
= CUPS_AUTO_ENCODING
;
526 for (i
= 0; i
< (int)(sizeof(locale_encodings
) / sizeof(locale_encodings
[0])); i
++)
527 if (!strcasecmp(charset
, locale_encodings
[i
]))
529 encoding
= (cups_encoding_t
)i
;
534 DEBUG_printf(("cupsLangGet: encoding=%d(%s)\n", encoding
,
535 encoding
== CUPS_AUTO_ENCODING
? "auto" :
536 lang_encodings
[encoding
]));
539 * See if we already have this language/country loaded...
542 snprintf(real
, sizeof(real
), "%s_%s", langname
, country
);
544 if ((lang
= cups_cache_lookup(real
, encoding
)) != NULL
)
547 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s", cg
->localedir
,
550 if (!country
[0] || access(filename
, 0))
553 * Country localization not available, look for generic localization...
556 if ((lang
= cups_cache_lookup(langname
, encoding
)) != NULL
)
559 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s", cg
->localedir
,
562 if (access(filename
, 0))
565 * No generic localization, so use POSIX...
569 snprintf(filename
, sizeof(filename
), "%s/C/cups_C", cg
->localedir
);
572 strcpy(real
, langname
);
576 * See if there is a free language available; if so, use that
580 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
587 * Allocate memory for the language and add it to the cache.
590 if ((lang
= calloc(sizeof(cups_lang_t
), 1)) == NULL
)
593 lang
->next
= cg
->lang_cache
;
594 cg
->lang_cache
= lang
;
598 * Free all old strings as needed...
601 _cupsMessageFree(lang
->strings
);
604 * Then assign the language and encoding fields...
608 strlcpy(lang
->language
, real
, sizeof(lang
->language
));
610 if (encoding
!= CUPS_AUTO_ENCODING
)
611 lang
->encoding
= encoding
;
613 lang
->encoding
= CUPS_UTF8
;
616 * Read the strings from the file...
619 lang
->strings
= _cupsMessageLoad(filename
);
630 * '_cupsLangString()' - Get a message string.
632 * The returned string is UTF-8 encoded; use cupsUTF8ToCharset() to
633 * convert the string to the language encoding.
636 const char * /* O - Localized message */
637 _cupsLangString(cups_lang_t
*lang
, /* I - Language */
638 const char *message
) /* I - Message */
641 * Range check input...
644 if (!lang
|| !message
)
647 return (_cupsMessageLookup(lang
->strings
, message
));
652 * '_cupsMessageFree()' - Free a messages array.
656 _cupsMessageFree(cups_array_t
*a
) /* I - Message array */
658 _cups_message_t
*m
; /* Current message */
661 for (m
= (_cups_message_t
*)cupsArrayFirst(a
);
663 m
= (_cups_message_t
*)cupsArrayNext(a
))
666 * Remove the message from the array, then free the message and strings.
669 cupsArrayRemove(a
, m
);
689 * '_cupsMessageLoad()' - Load a .po file into a messages array.
692 cups_array_t
* /* O - New message array */
693 _cupsMessageLoad(const char *filename
) /* I - Message catalog to load */
695 cups_file_t
*fp
; /* Message file */
696 cups_array_t
*a
; /* Message array */
697 _cups_message_t
*m
; /* Current message */
698 char s
[4096], /* String buffer */
699 *ptr
, /* Pointer into buffer */
700 *temp
; /* New string */
701 int length
; /* Length of combined strings */
705 * Create an array to hold the messages...
708 if ((a
= cupsArrayNew((cups_array_func_t
)cups_message_compare
, NULL
)) == NULL
)
712 * Open the message catalog file...
715 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
719 * Read messages from the catalog file until EOF...
721 * The format is the GNU gettext .po format, which is fairly simple:
724 * msgstr "localized text"
726 * The localized text can span multiple lines using the form:
728 * msgid "some long text"
729 * msgstr "localized text spanning "
735 while (cupsFileGets(fp
, s
, sizeof(s
)) != NULL
)
738 * Skip blank and comment lines...
741 if (s
[0] == '#' || !s
[0])
745 * Strip the trailing quote...
748 if ((ptr
= strrchr(s
, '\"')) == NULL
)
754 * Find start of value...
757 if ((ptr
= strchr(s
, '\"')) == NULL
)
763 * Unquote the text...
766 cups_unquote(ptr
, ptr
);
769 * Create or add to a message...
772 if (!strncmp(s
, "msgid", 5))
774 if ((m
= (_cups_message_t
*)calloc(1, sizeof(_cups_message_t
))) == NULL
)
783 else if ((s
[0] == '\"' || !strncmp(s
, "msgstr", 6)) && m
)
788 * Append the string...
791 length
= strlen(m
->str
);
793 if ((temp
= realloc(m
->str
, length
+ strlen(ptr
) + 1)) == NULL
)
802 * Copy the new portion at the end - safe because the buffer is
803 * allocated to the correct size...
806 strcpy(m
->str
+ length
, ptr
);
814 m
->str
= strdup(ptr
);
820 * Close the message catalog file and return the new array...
830 * '_cupsMessageLookup()' - Lookup a message string.
833 const char * /* O - Localized message */
834 _cupsMessageLookup(cups_array_t
*a
, /* I - Message array */
835 const char *m
) /* I - Message */
837 _cups_message_t key
, /* Search key */
838 *match
; /* Matching message */
842 * Lookup the message string; if it doesn't exist in the catalog,
843 * then return the message that was passed to us...
847 match
= (_cups_message_t
*)cupsArrayFind(a
, &key
);
849 if (match
&& match
->str
)
857 * '_cupsRestoreLocale()' - Restore the original locale...
861 _cupsRestoreLocale(int category
, /* I - Category */
862 char *oldlocale
) /* I - Old locale or NULL */
864 DEBUG_printf(("_cupsRestoreLocale(category=%d, oldlocale=\"%s\")\n",
865 category
, oldlocale
));
870 * Reset the locale and free the locale string...
873 setlocale(category
, oldlocale
);
880 * '_cupsSaveLocale()' - Set the locale and save a copy of the old locale...
883 char * /* O - Old locale or NULL */
884 _cupsSaveLocale(int category
, /* I - Category */
885 const char *locale
) /* I - New locale or NULL */
887 char *oldlocale
; /* Old locale */
890 DEBUG_printf(("_cupsSaveLocale(category=%d, locale=\"%s\")\n",
894 * Get the old locale and copy it...
897 if ((oldlocale
= setlocale(category
, NULL
)) != NULL
)
898 oldlocale
= strdup(oldlocale
);
900 DEBUG_printf((" oldlocale=\"%s\"\n", oldlocale
? oldlocale
: "(null)"));
903 * Set the new locale...
906 setlocale(category
, locale
);
909 * Return a copy of the old locale...
918 * Code & data to translate OSX's language names to their ISO 639-1 locale.
920 * The first version uses the new CoreFoundation API added in 10.3 (Panther),
921 * the second is for 10.2 (Jaguar).
924 # ifdef HAVE_CF_LOCALE_ID
926 * 'appleLangDefault()' - Get the default locale string.
929 static const char * /* O - Locale string */
930 appleLangDefault(void)
932 CFPropertyListRef localizationList
;
933 /* List of localization data */
934 CFStringRef languageName
; /* Current name */
935 CFStringRef localeName
; /* Canonical from of name */
936 _cups_globals_t
*cg
= _cupsGlobals();
937 /* Pointer to library globals */
941 * Only do the lookup and translation the first time.
944 if (!cg
->language
[0])
947 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
948 kCFPreferencesCurrentApplication
);
950 if (localizationList
!= NULL
)
952 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
953 CFArrayGetCount(localizationList
) > 0)
955 languageName
= CFArrayGetValueAtIndex(localizationList
, 0);
957 if (languageName
!= NULL
&&
958 CFGetTypeID(languageName
) == CFStringGetTypeID())
960 localeName
= CFLocaleCreateCanonicalLocaleIdentifierFromString(
961 kCFAllocatorDefault
, languageName
);
963 if (localeName
!= NULL
)
965 CFStringGetCString(localeName
, cg
->language
, sizeof(cg
->language
),
966 kCFStringEncodingASCII
);
967 CFRelease(localeName
);
969 if (!strcmp(cg
->language
, "en"))
970 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
971 else if (strchr(cg
->language
, '.') == NULL
)
972 strlcat(cg
->language
, ".UTF-8", sizeof(cg
->language
));
977 CFRelease(localizationList
);
981 * If we didn't find the language, default to en_US...
984 if (!cg
->language
[0])
985 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
989 * Return the cached locale...
992 return (cg
->language
);
996 * Code & data to translate OSX 10.2's language names to their ISO 639-1
1002 const char * const name
; /* Language name */
1003 const char * const locale
; /* Locale name */
1004 } _apple_name_locale_t
;
1006 static const _apple_name_locale_t apple_name_locale
[] =
1008 { "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" },
1009 { "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" },
1010 { "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" },
1011 { "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" },
1012 { "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" },
1013 { "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" },
1014 { "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" },
1015 { "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" },
1016 { "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" },
1017 { "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1018 { "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" },
1019 { "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" },
1020 { "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" },
1021 { "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" },
1022 { "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" },
1023 { "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" },
1024 { "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1025 { "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" },
1026 { "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" },
1027 { "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" },
1028 { "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" },
1029 { "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" },
1030 { "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" },
1031 { "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" },
1032 { "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" },
1033 { "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" },
1034 { "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" },
1035 { "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" },
1036 { "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" },
1037 { "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" },
1038 { "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" },
1039 { "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" },
1040 { "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" },
1041 { "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" },
1042 { "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" },
1043 { "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" },
1044 { "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" },
1045 { "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" },
1046 { "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" },
1047 { "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" },
1048 { "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" },
1049 { "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" },
1050 { "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" },
1051 { "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" },
1052 { "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" },
1053 { "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" },
1054 { "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" },
1055 { "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" },
1056 { "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" },
1057 { "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" },
1058 { "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" },
1059 { "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" },
1060 { "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" },
1061 { "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" },
1062 { "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" },
1063 { "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" },
1064 { "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" },
1065 { "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" },
1066 { "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" }
1071 * 'appleLangDefault()' - Get the default locale string.
1074 static const char * /* O - Locale string */
1075 appleLangDefault(void)
1077 int i
; /* Looping var */
1078 CFPropertyListRef localizationList
;
1079 /* List of localization data */
1080 CFStringRef localizationName
;
1082 char buff
[256]; /* Temporary buffer */
1083 _cups_globals_t
*cg
= _cupsGlobals();
1084 /* Pointer to library globals */
1088 * Only do the lookup and translation the first time.
1091 if (cg
->language
== NULL
)
1094 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
1095 kCFPreferencesCurrentApplication
);
1097 if (localizationList
!= NULL
)
1099 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
1100 CFArrayGetCount(localizationList
) > 0)
1102 localizationName
= CFArrayGetValueAtIndex(localizationList
, 0);
1104 if (localizationName
!= NULL
&&
1105 CFGetTypeID(localizationName
) == CFStringGetTypeID())
1107 CFIndex length
= CFStringGetLength(localizationName
);
1109 if (length
<= sizeof(buff
) &&
1110 CFStringGetCString(localizationName
, buff
, sizeof(buff
),
1111 kCFStringEncodingASCII
))
1113 buff
[sizeof(buff
) - 1] = '\0';
1116 i
< sizeof(apple_name_locale
) / sizeof(apple_name_locale
[0]);
1119 if (!strcasecmp(buff
, apple_name_locale
[i
].name
))
1121 cg
->language
= apple_name_locale
[i
].locale
;
1129 CFRelease(localizationList
);
1133 * If we didn't find the language, default to en_US...
1136 if (cg
->language
== NULL
)
1137 cg
->language
= apple_name_locale
[0].locale
;
1141 * Return the cached locale...
1144 return (cg
->language
);
1146 # endif /* HAVE_CF_LOCALE_ID */
1147 #endif /* __APPLE__ */
1151 * 'cups_cache_lookup()' - Lookup a language in the cache...
1154 static cups_lang_t
* /* O - Language data or NULL */
1155 cups_cache_lookup(const char *name
,/* I - Name of locale */
1156 cups_encoding_t encoding
)
1157 /* I - Encoding of locale */
1159 cups_lang_t
*lang
; /* Current language */
1162 DEBUG_printf(("cups_cache_lookup(name=\"%s\", encoding=%d(%s))\n", name
,
1163 encoding
, encoding
== CUPS_AUTO_ENCODING
? "auto" :
1164 lang_encodings
[encoding
]));
1167 * Loop through the cache and return a match if found...
1170 for (lang
= _cupsGlobals()->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
1172 DEBUG_printf(("cups_cache_lookup: lang=%p, language=\"%s\", encoding=%d(%s)\n",
1173 lang
, lang
->language
, lang
->encoding
,
1174 lang_encodings
[lang
->encoding
]));
1176 if (!strcmp(lang
->language
, name
) &&
1177 (encoding
== CUPS_AUTO_ENCODING
|| encoding
== lang
->encoding
))
1181 DEBUG_puts("cups_cache_lookup: returning match!");
1187 DEBUG_puts("cups_cache_lookup: returning NULL!");
1194 * 'cups_message_compare()' - Compare two messages.
1197 static int /* O - Result of comparison */
1198 cups_message_compare(
1199 _cups_message_t
*m1
, /* I - First message */
1200 _cups_message_t
*m2
) /* I - Second message */
1202 return (strcmp(m1
->id
, m2
->id
));
1207 * 'cups_unquote()' - Unquote characters in strings...
1211 cups_unquote(char *d
, /* O - Unquoted string */
1212 const char *s
) /* I - Original string */
1225 *d
= *d
* 8 + *s
- '0';
1252 * End of "$Id: language.c 4985 2006-01-25 21:57:18Z mike $".