2 * "$Id: language.c 5238 2006-03-07 04:41:42Z 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 * appleLangDefault() - Get the default locale string.
42 * cups_cache_lookup() - Lookup a language in the cache...
43 * cups_message_compare() - Compare two messages.
44 * cups_unquote() - Unquote characters in strings...
48 * Include necessary headers...
55 #ifdef HAVE_LANGINFO_H
56 # include <langinfo.h>
57 #endif /* HAVE_LANGINFO_H */
63 #ifdef HAVE_COREFOUNDATION_H
64 # include <CoreFoundation/CoreFoundation.h>
65 #endif /* HAVE_COREFOUNDATION_H */
73 static const char *appleLangDefault(void);
74 #endif /* __APPLE__ */
75 static cups_lang_t
*cups_cache_lookup(const char *name
,
76 cups_encoding_t encoding
);
77 static int cups_message_compare(_cups_message_t
*m1
,
79 static void cups_unquote(char *d
, const char *s
);
86 static const char * const lang_encodings
[] =
87 { /* Encoding strings */
88 "us-ascii", "iso-8859-1",
89 "iso-8859-2", "iso-8859-3",
90 "iso-8859-4", "iso-8859-5",
91 "iso-8859-6", "iso-8859-7",
92 "iso-8859-8", "iso-8859-9",
93 "iso-8859-10", "utf-8",
94 "iso-8859-13", "iso-8859-14",
95 "iso-8859-15", "windows-874",
96 "windows-1250", "windows-1251",
97 "windows-1252", "windows-1253",
98 "windows-1254", "windows-1255",
99 "windows-1256", "windows-1257",
100 "windows-1258", "koi8-r",
101 "koi8-u", "iso-8859-11",
102 "iso-8859-16", "mac-roman",
103 "unknown", "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 "windows-932", "windows-936",
121 "windows-949", "windows-950",
122 "windows-1361", "unknown",
123 "unknown", "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",
158 * '_cupsEncodingName()' - Return the character encoding name string
159 * for the given encoding enumeration.
162 const char * /* O - Character encoding */
164 cups_encoding_t encoding
) /* I - Encoding value */
167 encoding
>= (sizeof(lang_encodings
) / sizeof(const char *)))
168 return (lang_encodings
[0]);
170 return (lang_encodings
[encoding
]);
175 * 'cupsLangDefault()' - Return the default language.
178 cups_lang_t
* /* O - Language data */
179 cupsLangDefault(void)
181 return (cupsLangGet(NULL
));
186 * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.)
187 * for the given language.
190 const char * /* O - Character encoding */
191 cupsLangEncoding(cups_lang_t
*lang
) /* I - Language data */
194 return ((char*)lang_encodings
[0]);
196 return ((char*)lang_encodings
[lang
->encoding
]);
201 * 'cupsLangFlush()' - Flush all language data out of the cache.
207 _cupsLangFlush(_cupsGlobals());
212 * '_cupsLangFlush()' - Flush all language data out of the cache.
216 _cupsLangFlush(_cups_globals_t
*cg
) /* I - Global data */
218 cups_lang_t
*lang
, /* Current language */
219 *next
; /* Next language */
223 * Free all languages in the cache...
226 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= next
)
229 * Free all messages...
232 _cupsMessageFree(lang
->strings
);
235 * Then free the language structure itself...
242 cg
->lang_cache
= NULL
;
247 * 'cupsLangFree()' - Free language data.
249 * This does not actually free anything; use cupsLangFlush() for that.
253 cupsLangFree(cups_lang_t
*lang
) /* I - Language to free */
255 if (lang
!= NULL
&& lang
->used
> 0)
261 * 'cupsLangGet()' - Get a language.
264 cups_lang_t
* /* O - Language data */
265 cupsLangGet(const char *language
) /* I - Language or locale */
267 int i
; /* Looping var */
268 char locale
[255], /* Copy of locale name */
269 langname
[16], /* Requested language name */
270 country
[16], /* Country code */
271 charset
[16], /* Character set */
272 *csptr
, /* Pointer to CODESET string */
273 *ptr
, /* Pointer into language/charset */
274 real
[48], /* Real language name */
275 filename
[1024]; /* Filename for language locale file */
276 cups_encoding_t encoding
; /* Encoding to use */
277 cups_lang_t
*lang
; /* Current language... */
278 _cups_globals_t
*cg
= _cupsGlobals();
279 /* Pointer to library globals */
280 static const char * const locale_encodings
[] =
281 { /* Locale charset names */
282 "ASCII", "ISO88591", "ISO88592", "ISO88593",
283 "ISO88594", "ISO88595", "ISO88596", "ISO88597",
284 "ISO88598", "ISO88599", "ISO885910", "UTF8",
285 "ISO885913", "ISO885914", "ISO885915", "CP874",
286 "CP1250", "CP1251", "CP1252", "CP1253",
287 "CP1254", "CP1255", "CP1256", "CP1257",
288 "CP1258", "KOI8R", "KOI8U", "ISO885911",
289 "ISO885916", "MACROMAN", "", "",
300 "CP932", "CP936", "CP949", "CP950",
301 "CP1361", "", "", "",
318 "EUCCN", "EUCJP", "EUCKR", "EUCTW"
322 DEBUG_printf(("cupsLangGet(language=\"%s\")\n", language
? language
: "(null)"));
326 * Set the character set to UTF-8...
329 strcpy(charset
, "UTF8");
332 * Apple's setlocale doesn't give us the user's localization
333 * preference so we have to look it up this way...
337 language
= appleLangDefault();
341 * Set the charset to "unknown"...
347 * Use setlocale() to determine the currently set locale, and then
348 * fallback to environment variables to avoid setting the locale,
349 * since setlocale() is not thread-safe!
355 * First see if the locale has been set; if it is still "C" or
356 * "POSIX", use the environment to get the default...
360 ptr
= setlocale(LC_MESSAGES
, NULL
);
362 ptr
= setlocale(LC_ALL
, NULL
);
363 # endif /* LC_MESSAGES */
365 DEBUG_printf(("cupsLangGet: current locale is \"%s\"\n",
366 ptr
? ptr
: "(null)"));
368 if (!ptr
|| !strcmp(ptr
, "C") || !strcmp(ptr
, "POSIX"))
371 * Get the character set from the LC_CTYPE locale setting...
374 if ((ptr
= getenv("LC_CTYPE")) == NULL
)
375 if ((ptr
= getenv("LC_ALL")) == NULL
)
376 if ((ptr
= getenv("LANG")) == NULL
)
379 if ((csptr
= strchr(ptr
, '.')) != NULL
)
382 * Extract the character set from the environment...
385 for (ptr
= charset
, csptr
++; *csptr
; csptr
++)
386 if (ptr
< (charset
+ sizeof(charset
) - 1) && isalnum(*csptr
& 255))
394 * Default to UTF-8...
397 strcpy(charset
, "UTF8");
401 * Get the locale for messages from the LC_MESSAGES locale setting...
404 if ((ptr
= getenv("LC_MESSAGES")) == NULL
)
405 if ((ptr
= getenv("LC_ALL")) == NULL
)
406 if ((ptr
= getenv("LANG")) == NULL
)
412 strlcpy(locale
, ptr
, sizeof(locale
));
415 DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n",
416 language
? language
: "(null)"));
419 #endif /* __APPLE__ */
422 * If "language" is NULL at this point, then chances are we are using
423 * a language that is not installed for the base OS.
429 * Switch to the POSIX ("C") locale...
437 * On systems that support the nl_langinfo(CODESET) call, use
438 * this value as the character set...
441 if (!charset
[0] && (csptr
= nl_langinfo(CODESET
)) != NULL
)
444 * Copy all of the letters and numbers in the CODESET string...
447 for (ptr
= charset
; *csptr
; csptr
++)
448 if (isalnum(*csptr
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
453 DEBUG_printf(("cupsLangGet: charset set to \"%s\" via nl_langinfo(CODESET)...\n",
459 * Parse the language string passed in to a locale string. "C" is the
460 * standard POSIX locale and is copied unchanged. Otherwise the
461 * language string is converted from ll-cc[.charset] (language-country)
462 * to ll_CC[.CHARSET] to match the file naming convention used by all
463 * POSIX-compliant operating systems. Invalid language names are mapped
464 * to the POSIX locale.
469 if (language
== NULL
|| !language
[0] ||
470 !strcmp(language
, "POSIX"))
471 strcpy(langname
, "C");
475 * Copy the parts of the locale string over safely...
478 for (ptr
= langname
; *language
; language
++)
479 if (*language
== '_' || *language
== '-' || *language
== '.')
481 else if (ptr
< (langname
+ sizeof(langname
) - 1))
482 *ptr
++ = tolower(*language
& 255);
486 if (*language
== '_' || *language
== '-')
489 * Copy the country code...
492 for (language
++, ptr
= country
; *language
; language
++)
493 if (*language
== '.')
495 else if (ptr
< (country
+ sizeof(country
) - 1))
496 *ptr
++ = toupper(*language
& 255);
501 if (*language
== '.' && !charset
[0])
504 * Copy the encoding...
507 for (language
++, ptr
= charset
; *language
; language
++)
508 if (isalnum(*language
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
509 *ptr
++ = toupper(*language
& 255);
515 * Force a POSIX locale for an invalid language name...
518 if (strlen(langname
) != 2)
520 strcpy(langname
, "C");
526 DEBUG_printf(("cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"\n",
527 langname
, country
, charset
));
530 * Figure out the desired encoding...
533 encoding
= CUPS_AUTO_ENCODING
;
538 i
< (int)(sizeof(locale_encodings
) / sizeof(locale_encodings
[0]));
540 if (!strcasecmp(charset
, locale_encodings
[i
]))
542 encoding
= (cups_encoding_t
)i
;
547 DEBUG_printf(("cupsLangGet: encoding=%d(%s)\n", encoding
,
548 encoding
== CUPS_AUTO_ENCODING
? "auto" :
549 lang_encodings
[encoding
]));
552 * See if we already have this language/country loaded...
557 snprintf(real
, sizeof(real
), "%s_%s", langname
, country
);
559 if ((lang
= cups_cache_lookup(real
, encoding
)) != NULL
)
562 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s.po", cg
->localedir
,
566 filename
[0] = '\0'; /* anti-compiler-warning-code */
568 if (!country
[0] || access(filename
, 0))
571 * Country localization not available, look for generic localization...
574 if ((lang
= cups_cache_lookup(langname
, encoding
)) != NULL
)
577 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s.po", cg
->localedir
,
580 if (access(filename
, 0))
583 * No generic localization, so use POSIX...
586 DEBUG_printf(("access(\"%s\", 0): %s\n", filename
, strerror(errno
)));
589 snprintf(filename
, sizeof(filename
), "%s/C/cups_C.po", cg
->localedir
);
592 strcpy(real
, langname
);
596 * See if there is a free language available; if so, use that
600 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
607 * Allocate memory for the language and add it to the cache.
610 if ((lang
= calloc(sizeof(cups_lang_t
), 1)) == NULL
)
613 lang
->next
= cg
->lang_cache
;
614 cg
->lang_cache
= lang
;
619 * Free all old strings as needed...
622 _cupsMessageFree(lang
->strings
);
626 * Then assign the language and encoding fields...
630 strlcpy(lang
->language
, real
, sizeof(lang
->language
));
632 if (encoding
!= CUPS_AUTO_ENCODING
)
633 lang
->encoding
= encoding
;
635 lang
->encoding
= CUPS_UTF8
;
638 * Read the strings from the file...
641 lang
->strings
= _cupsMessageLoad(filename
);
652 * '_cupsLangString()' - Get a message string.
654 * The returned string is UTF-8 encoded; use cupsUTF8ToCharset() to
655 * convert the string to the language encoding.
658 const char * /* O - Localized message */
659 _cupsLangString(cups_lang_t
*lang
, /* I - Language */
660 const char *message
) /* I - Message */
663 * Range check input...
666 if (!lang
|| !message
)
669 return (_cupsMessageLookup(lang
->strings
, message
));
674 * '_cupsMessageFree()' - Free a messages array.
678 _cupsMessageFree(cups_array_t
*a
) /* I - Message array */
680 _cups_message_t
*m
; /* Current message */
683 for (m
= (_cups_message_t
*)cupsArrayFirst(a
);
685 m
= (_cups_message_t
*)cupsArrayNext(a
))
688 * Remove the message from the array, then free the message and strings.
691 cupsArrayRemove(a
, m
);
711 * '_cupsMessageLoad()' - Load a .po file into a messages array.
714 cups_array_t
* /* O - New message array */
715 _cupsMessageLoad(const char *filename
) /* I - Message catalog to load */
717 cups_file_t
*fp
; /* Message file */
718 cups_array_t
*a
; /* Message array */
719 _cups_message_t
*m
; /* Current message */
720 char s
[4096], /* String buffer */
721 *ptr
, /* Pointer into buffer */
722 *temp
; /* New string */
723 int length
; /* Length of combined strings */
726 DEBUG_printf(("_cupsMessageLoad(filename=\"%s\")\n", filename
));
729 * Create an array to hold the messages...
732 if ((a
= cupsArrayNew((cups_array_func_t
)cups_message_compare
, NULL
)) == NULL
)
736 * Open the message catalog file...
739 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
743 * Read messages from the catalog file until EOF...
745 * The format is the GNU gettext .po format, which is fairly simple:
748 * msgstr "localized text"
750 * The ID and localized text can span multiple lines using the form:
755 * "localized text spanning "
761 while (cupsFileGets(fp
, s
, sizeof(s
)) != NULL
)
764 * Skip blank and comment lines...
767 if (s
[0] == '#' || !s
[0])
771 * Strip the trailing quote...
774 if ((ptr
= strrchr(s
, '\"')) == NULL
)
780 * Find start of value...
783 if ((ptr
= strchr(s
, '\"')) == NULL
)
789 * Unquote the text...
792 cups_unquote(ptr
, ptr
);
795 * Create or add to a message...
798 if (!strncmp(s
, "msgid", 5))
801 * Add previous message as needed...
808 * Create a new message with the given msgid string...
811 if ((m
= (_cups_message_t
*)calloc(1, sizeof(_cups_message_t
))) == NULL
)
819 else if (s
[0] == '\"' && m
)
822 * Append to current string...
825 length
= strlen(m
->str
? m
->str
: m
->id
);
827 if ((temp
= realloc(m
->str
? m
->str
: m
->id
,
828 length
+ strlen(ptr
) + 1)) == NULL
)
837 * Copy the new portion to the end of the msgstr string - safe
838 * to use strcpy because the buffer is allocated to the correct
844 strcpy(m
->str
+ length
, ptr
);
849 * Copy the new portion to the end of the msgid string - safe
850 * to use strcpy because the buffer is allocated to the correct
856 strcpy(m
->id
+ length
, ptr
);
859 else if (!strncmp(s
, "msgstr", 6) && m
)
865 m
->str
= strdup(ptr
);
870 * Add the last message string to the array as needed...
877 * Close the message catalog file and return the new array...
887 * '_cupsMessageLookup()' - Lookup a message string.
890 const char * /* O - Localized message */
891 _cupsMessageLookup(cups_array_t
*a
, /* I - Message array */
892 const char *m
) /* I - Message */
894 _cups_message_t key
, /* Search key */
895 *match
; /* Matching message */
899 * Lookup the message string; if it doesn't exist in the catalog,
900 * then return the message that was passed to us...
904 match
= (_cups_message_t
*)cupsArrayFind(a
, &key
);
906 if (match
&& match
->str
)
915 * Code & data to translate OSX's language names to their ISO 639-1 locale.
917 * The first version uses the new CoreFoundation API added in 10.3 (Panther),
918 * the second is for 10.2 (Jaguar).
921 # ifdef HAVE_CF_LOCALE_ID
923 * 'appleLangDefault()' - Get the default locale string.
926 static const char * /* O - Locale string */
927 appleLangDefault(void)
929 CFPropertyListRef localizationList
;
930 /* List of localization data */
931 CFStringRef languageName
; /* Current name */
932 CFStringRef localeName
; /* Canonical from of name */
933 _cups_globals_t
*cg
= _cupsGlobals();
934 /* Pointer to library globals */
938 * Only do the lookup and translation the first time.
941 if (!cg
->language
[0])
944 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
945 kCFPreferencesCurrentApplication
);
947 if (localizationList
!= NULL
)
949 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
950 CFArrayGetCount(localizationList
) > 0)
952 languageName
= CFArrayGetValueAtIndex(localizationList
, 0);
954 if (languageName
!= NULL
&&
955 CFGetTypeID(languageName
) == CFStringGetTypeID())
957 localeName
= CFLocaleCreateCanonicalLocaleIdentifierFromString(
958 kCFAllocatorDefault
, languageName
);
960 if (localeName
!= NULL
)
962 CFStringGetCString(localeName
, cg
->language
, sizeof(cg
->language
),
963 kCFStringEncodingASCII
);
964 CFRelease(localeName
);
966 if (!strcmp(cg
->language
, "en"))
967 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
968 else if (strchr(cg
->language
, '.') == NULL
)
969 strlcat(cg
->language
, ".UTF-8", sizeof(cg
->language
));
974 CFRelease(localizationList
);
978 * If we didn't find the language, default to en_US...
981 if (!cg
->language
[0])
982 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
986 * Return the cached locale...
989 return (cg
->language
);
993 * Code & data to translate OSX 10.2's language names to their ISO 639-1
999 const char * const name
; /* Language name */
1000 const char * const locale
; /* Locale name */
1001 } _apple_name_locale_t
;
1003 static const _apple_name_locale_t apple_name_locale
[] =
1005 { "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" },
1006 { "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" },
1007 { "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" },
1008 { "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" },
1009 { "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" },
1010 { "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" },
1011 { "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" },
1012 { "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" },
1013 { "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" },
1014 { "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1015 { "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" },
1016 { "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" },
1017 { "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" },
1018 { "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" },
1019 { "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" },
1020 { "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" },
1021 { "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1022 { "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" },
1023 { "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" },
1024 { "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" },
1025 { "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" },
1026 { "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" },
1027 { "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" },
1028 { "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" },
1029 { "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" },
1030 { "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" },
1031 { "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" },
1032 { "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" },
1033 { "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" },
1034 { "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" },
1035 { "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" },
1036 { "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" },
1037 { "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" },
1038 { "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" },
1039 { "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" },
1040 { "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" },
1041 { "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" },
1042 { "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" },
1043 { "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" },
1044 { "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" },
1045 { "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" },
1046 { "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" },
1047 { "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" },
1048 { "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" },
1049 { "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" },
1050 { "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" },
1051 { "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" },
1052 { "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" },
1053 { "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" },
1054 { "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" },
1055 { "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" },
1056 { "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" },
1057 { "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" },
1058 { "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" },
1059 { "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" },
1060 { "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" },
1061 { "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" },
1062 { "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" },
1063 { "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" }
1068 * 'appleLangDefault()' - Get the default locale string.
1071 static const char * /* O - Locale string */
1072 appleLangDefault(void)
1074 int i
; /* Looping var */
1075 CFPropertyListRef localizationList
;
1076 /* List of localization data */
1077 CFStringRef localizationName
;
1079 char buff
[256]; /* Temporary buffer */
1080 _cups_globals_t
*cg
= _cupsGlobals();
1081 /* Pointer to library globals */
1085 * Only do the lookup and translation the first time.
1088 if (cg
->language
== NULL
)
1091 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
1092 kCFPreferencesCurrentApplication
);
1094 if (localizationList
!= NULL
)
1096 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
1097 CFArrayGetCount(localizationList
) > 0)
1099 localizationName
= CFArrayGetValueAtIndex(localizationList
, 0);
1101 if (localizationName
!= NULL
&&
1102 CFGetTypeID(localizationName
) == CFStringGetTypeID())
1104 CFIndex length
= CFStringGetLength(localizationName
);
1106 if (length
<= sizeof(buff
) &&
1107 CFStringGetCString(localizationName
, buff
, sizeof(buff
),
1108 kCFStringEncodingASCII
))
1110 buff
[sizeof(buff
) - 1] = '\0';
1113 i
< sizeof(apple_name_locale
) / sizeof(apple_name_locale
[0]);
1116 if (!strcasecmp(buff
, apple_name_locale
[i
].name
))
1118 cg
->language
= apple_name_locale
[i
].locale
;
1126 CFRelease(localizationList
);
1130 * If we didn't find the language, default to en_US...
1133 if (cg
->language
== NULL
)
1134 cg
->language
= apple_name_locale
[0].locale
;
1138 * Return the cached locale...
1141 return (cg
->language
);
1143 # endif /* HAVE_CF_LOCALE_ID */
1144 #endif /* __APPLE__ */
1148 * 'cups_cache_lookup()' - Lookup a language in the cache...
1151 static cups_lang_t
* /* O - Language data or NULL */
1152 cups_cache_lookup(const char *name
,/* I - Name of locale */
1153 cups_encoding_t encoding
)
1154 /* I - Encoding of locale */
1156 cups_lang_t
*lang
; /* Current language */
1159 DEBUG_printf(("cups_cache_lookup(name=\"%s\", encoding=%d(%s))\n", name
,
1160 encoding
, encoding
== CUPS_AUTO_ENCODING
? "auto" :
1161 lang_encodings
[encoding
]));
1164 * Loop through the cache and return a match if found...
1167 for (lang
= _cupsGlobals()->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
1169 DEBUG_printf(("cups_cache_lookup: lang=%p, language=\"%s\", encoding=%d(%s)\n",
1170 lang
, lang
->language
, lang
->encoding
,
1171 lang_encodings
[lang
->encoding
]));
1173 if (!strcmp(lang
->language
, name
) &&
1174 (encoding
== CUPS_AUTO_ENCODING
|| encoding
== lang
->encoding
))
1178 DEBUG_puts("cups_cache_lookup: returning match!");
1184 DEBUG_puts("cups_cache_lookup: returning NULL!");
1191 * 'cups_message_compare()' - Compare two messages.
1194 static int /* O - Result of comparison */
1195 cups_message_compare(
1196 _cups_message_t
*m1
, /* I - First message */
1197 _cups_message_t
*m2
) /* I - Second message */
1199 return (strcmp(m1
->id
, m2
->id
));
1204 * 'cups_unquote()' - Unquote characters in strings...
1208 cups_unquote(char *d
, /* O - Unquoted string */
1209 const char *s
) /* I - Original string */
1222 *d
= *d
* 8 + *s
- '0';
1249 * End of "$Id: language.c 5238 2006-03-07 04:41:42Z mike $".