2 * "$Id: language.c 7558 2008-05-12 23:46:44Z mike $"
4 * I18N/language support for CUPS.
6 * Copyright 2007-2010 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * _cupsAppleLanguage() - Get the Apple language identifier associated
21 * _cupsEncodingName() - Return the character encoding name string
22 * for the given encoding enumeration.
23 * cupsLangDefault() - Return the default language.
24 * cupsLangEncoding() - Return the character encoding (us-ascii, etc.)
25 * for the given language.
26 * cupsLangFlush() - Flush all language data out of the cache.
27 * cupsLangFree() - Free language data.
28 * cupsLangGet() - Get a language.
29 * _cupsLangString() - Get a message string.
30 * _cupsMessageFree() - Free a messages array.
31 * _cupsMessageLoad() - Load a .po file into a messages array.
32 * _cupsMessageLookup() - Lookup a message string.
33 * appleLangDefault() - Get the default locale string.
34 * cups_cache_lookup() - Lookup a language in the cache...
35 * cups_message_compare() - Compare two messages.
36 * cups_unquote() - Unquote characters in strings...
40 * Include necessary headers...
43 #include "cups-private.h"
44 #ifdef HAVE_LANGINFO_H
45 # include <langinfo.h>
46 #endif /* HAVE_LANGINFO_H */
52 #ifdef HAVE_COREFOUNDATION_H
53 # include <CoreFoundation/CoreFoundation.h>
54 #endif /* HAVE_COREFOUNDATION_H */
62 static pthread_mutex_t lang_mutex
= PTHREAD_MUTEX_INITIALIZER
;
63 /* Mutex to control access to cache */
64 #endif /* HAVE_PTHREAD_H */
65 static cups_lang_t
*lang_cache
= NULL
;
66 /* Language string cache */
67 static const char * const lang_encodings
[] =
68 { /* Encoding strings */
69 "us-ascii", "iso-8859-1",
70 "iso-8859-2", "iso-8859-3",
71 "iso-8859-4", "iso-8859-5",
72 "iso-8859-6", "iso-8859-7",
73 "iso-8859-8", "iso-8859-9",
74 "iso-8859-10", "utf-8",
75 "iso-8859-13", "iso-8859-14",
76 "iso-8859-15", "windows-874",
77 "windows-1250", "windows-1251",
78 "windows-1252", "windows-1253",
79 "windows-1254", "windows-1255",
80 "windows-1256", "windows-1257",
81 "windows-1258", "koi8-r",
82 "koi8-u", "iso-8859-11",
83 "iso-8859-16", "mac-roman",
100 "unknown", "unknown",
101 "windows-932", "windows-936",
102 "windows-949", "windows-950",
103 "windows-1361", "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 "unknown", "unknown",
122 "unknown", "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",
141 const char * const language
; /* Language ID */
142 const char * const locale
; /* Locale ID */
143 } _apple_language_locale_t
;
145 static const _apple_language_locale_t apple_language_locale
[] =
146 { /* Locale to language ID LUT */
149 { "zh-Hans" , "zh_CN" },
150 { "zh-Hant" , "zh_TW" }
152 #endif /* __APPLE__ */
160 static const char *appleLangDefault(void);
161 #endif /* __APPLE__ */
162 static cups_lang_t
*cups_cache_lookup(const char *name
,
163 cups_encoding_t encoding
);
164 static int cups_message_compare(_cups_message_t
*m1
,
165 _cups_message_t
*m2
);
166 static void cups_unquote(char *d
, const char *s
);
171 * _cupsAppleLanguage() - Get the Apple language identifier associated
175 const char * /* O - Language ID */
176 _cupsAppleLanguage(const char *locale
, /* I - Locale ID */
177 char *language
,/* I - Language ID buffer */
178 size_t langsize
) /* I - Size of language ID buffer */
180 int i
; /* Looping var */
181 CFStringRef localeid
, /* CF locale identifier */
182 langid
; /* CF language identifier */
186 * Copy the locale name and convert, as needed, to the Apple-specific
187 * locale identifier...
190 switch (strlen(locale
))
197 strlcpy(language
, "en", langsize
);
201 strlcpy(language
, locale
, langsize
);
205 strlcpy(language
, locale
, langsize
);
207 if (language
[2] == '-')
210 * Convert ll-cc to ll_CC...
214 language
[3] = toupper(language
[3] & 255);
215 language
[4] = toupper(language
[4] & 255);
221 i
< (int)(sizeof(apple_language_locale
) /
222 sizeof(apple_language_locale
[0]));
224 if (!strcmp(locale
, apple_language_locale
[i
].locale
))
226 strlcpy(language
, apple_language_locale
[i
].language
, sizeof(language
));
231 * Attempt to map the locale ID to a language ID...
234 if ((localeid
= CFStringCreateWithCString(kCFAllocatorDefault
, language
,
235 kCFStringEncodingASCII
)) != NULL
)
237 if ((langid
= CFLocaleCreateCanonicalLanguageIdentifierFromString(
238 kCFAllocatorDefault
, localeid
)) != NULL
)
240 CFStringGetCString(langid
, language
, langsize
, kCFStringEncodingASCII
);
248 * Return what we got...
253 #endif /* __APPLE__ */
257 * '_cupsEncodingName()' - Return the character encoding name string
258 * for the given encoding enumeration.
261 const char * /* O - Character encoding */
263 cups_encoding_t encoding
) /* I - Encoding value */
266 encoding
>= (sizeof(lang_encodings
) / sizeof(const char *)))
267 return (lang_encodings
[0]);
269 return (lang_encodings
[encoding
]);
274 * 'cupsLangDefault()' - Return the default language.
277 cups_lang_t
* /* O - Language data */
278 cupsLangDefault(void)
280 return (cupsLangGet(NULL
));
285 * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.)
286 * for the given language.
289 const char * /* O - Character encoding */
290 cupsLangEncoding(cups_lang_t
*lang
) /* I - Language data */
293 return ((char*)lang_encodings
[0]);
295 return ((char*)lang_encodings
[lang
->encoding
]);
300 * 'cupsLangFlush()' - Flush all language data out of the cache.
306 cups_lang_t
*lang
, /* Current language */
307 *next
; /* Next language */
311 * Free all languages in the cache...
314 #ifdef HAVE_PTHREAD_H
315 pthread_mutex_lock(&lang_mutex
);
316 #endif /* HAVE_PTHREAD_H */
318 for (lang
= lang_cache
; lang
!= NULL
; lang
= next
)
321 * Free all messages...
324 _cupsMessageFree(lang
->strings
);
327 * Then free the language structure itself...
336 #ifdef HAVE_PTHREAD_H
337 pthread_mutex_unlock(&lang_mutex
);
338 #endif /* HAVE_PTHREAD_H */
343 * 'cupsLangFree()' - Free language data.
345 * This does not actually free anything; use @link cupsLangFlush@ for that.
349 cupsLangFree(cups_lang_t
*lang
) /* I - Language to free */
351 #ifdef HAVE_PTHREAD_H
352 pthread_mutex_lock(&lang_mutex
);
353 #endif /* HAVE_PTHREAD_H */
355 if (lang
!= NULL
&& lang
->used
> 0)
358 #ifdef HAVE_PTHREAD_H
359 pthread_mutex_unlock(&lang_mutex
);
360 #endif /* HAVE_PTHREAD_H */
365 * 'cupsLangGet()' - Get a language.
368 cups_lang_t
* /* O - Language data */
369 cupsLangGet(const char *language
) /* I - Language or locale */
371 int i
; /* Looping var */
373 char locale
[255]; /* Copy of locale name */
374 #endif /* !__APPLE__ */
375 char langname
[16], /* Requested language name */
376 country
[16], /* Country code */
377 charset
[16], /* Character set */
378 *csptr
, /* Pointer to CODESET string */
379 *ptr
, /* Pointer into language/charset */
380 real
[48], /* Real language name */
381 filename
[1024]; /* Filename for language locale file */
382 cups_encoding_t encoding
; /* Encoding to use */
383 cups_lang_t
*lang
; /* Current language... */
384 _cups_globals_t
*cg
= _cupsGlobals();
385 /* Pointer to library globals */
386 static const char * const locale_encodings
[] =
387 { /* Locale charset names */
388 "ASCII", "ISO88591", "ISO88592", "ISO88593",
389 "ISO88594", "ISO88595", "ISO88596", "ISO88597",
390 "ISO88598", "ISO88599", "ISO885910", "UTF8",
391 "ISO885913", "ISO885914", "ISO885915", "CP874",
392 "CP1250", "CP1251", "CP1252", "CP1253",
393 "CP1254", "CP1255", "CP1256", "CP1257",
394 "CP1258", "KOI8R", "KOI8U", "ISO885911",
395 "ISO885916", "MACROMAN", "", "",
406 "CP932", "CP936", "CP949", "CP950",
407 "CP1361", "", "", "",
424 "EUCCN", "EUCJP", "EUCKR", "EUCTW",
429 DEBUG_printf(("2cupsLangGet(language=\"%s\")", language
));
433 * Set the character set to UTF-8...
436 strcpy(charset
, "UTF8");
439 * Apple's setlocale doesn't give us the user's localization
440 * preference so we have to look it up this way...
445 if (!getenv("SOFTWARE") || (language
= getenv("LANG")) == NULL
)
446 language
= appleLangDefault();
448 DEBUG_printf(("4cupsLangGet: language=\"%s\"", language
));
453 * Set the charset to "unknown"...
459 * Use setlocale() to determine the currently set locale, and then
460 * fallback to environment variables to avoid setting the locale,
461 * since setlocale() is not thread-safe!
467 * First see if the locale has been set; if it is still "C" or
468 * "POSIX", use the environment to get the default...
472 ptr
= setlocale(LC_MESSAGES
, NULL
);
474 ptr
= setlocale(LC_ALL
, NULL
);
475 # endif /* LC_MESSAGES */
477 DEBUG_printf(("4cupsLangGet: current locale is \"%s\"", ptr
));
479 if (!ptr
|| !strcmp(ptr
, "C") || !strcmp(ptr
, "POSIX"))
482 * Get the character set from the LC_CTYPE locale setting...
485 if ((ptr
= getenv("LC_CTYPE")) == NULL
)
486 if ((ptr
= getenv("LC_ALL")) == NULL
)
487 if ((ptr
= getenv("LANG")) == NULL
)
490 if ((csptr
= strchr(ptr
, '.')) != NULL
)
493 * Extract the character set from the environment...
496 for (ptr
= charset
, csptr
++; *csptr
; csptr
++)
497 if (ptr
< (charset
+ sizeof(charset
) - 1) && isalnum(*csptr
& 255))
504 * Get the locale for messages from the LC_MESSAGES locale setting...
507 if ((ptr
= getenv("LC_MESSAGES")) == NULL
)
508 if ((ptr
= getenv("LC_ALL")) == NULL
)
509 if ((ptr
= getenv("LANG")) == NULL
)
515 strlcpy(locale
, ptr
, sizeof(locale
));
519 * CUPS STR #2575: Map "nb" to "no" for back-compatibility...
522 if (!strncmp(locale
, "nb", 2))
525 DEBUG_printf(("4cupsLangGet: new language value is \"%s\"", language
));
528 #endif /* __APPLE__ */
531 * If "language" is NULL at this point, then chances are we are using
532 * a language that is not installed for the base OS.
538 * Switch to the POSIX ("C") locale...
546 * On systems that support the nl_langinfo(CODESET) call, use
547 * this value as the character set...
550 if (!charset
[0] && (csptr
= nl_langinfo(CODESET
)) != NULL
)
553 * Copy all of the letters and numbers in the CODESET string...
556 for (ptr
= charset
; *csptr
; csptr
++)
557 if (isalnum(*csptr
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
562 DEBUG_printf(("4cupsLangGet: charset set to \"%s\" via "
563 "nl_langinfo(CODESET)...", charset
));
568 * If we don't have a character set by now, default to UTF-8...
572 strcpy(charset
, "UTF8");
575 * Parse the language string passed in to a locale string. "C" is the
576 * standard POSIX locale and is copied unchanged. Otherwise the
577 * language string is converted from ll-cc[.charset] (language-country)
578 * to ll_CC[.CHARSET] to match the file naming convention used by all
579 * POSIX-compliant operating systems. Invalid language names are mapped
580 * to the POSIX locale.
585 if (language
== NULL
|| !language
[0] ||
586 !strcmp(language
, "POSIX"))
587 strcpy(langname
, "C");
591 * Copy the parts of the locale string over safely...
594 for (ptr
= langname
; *language
; language
++)
595 if (*language
== '_' || *language
== '-' || *language
== '.')
597 else if (ptr
< (langname
+ sizeof(langname
) - 1))
598 *ptr
++ = tolower(*language
& 255);
602 if (*language
== '_' || *language
== '-')
605 * Copy the country code...
608 for (language
++, ptr
= country
; *language
; language
++)
609 if (*language
== '.')
611 else if (ptr
< (country
+ sizeof(country
) - 1))
612 *ptr
++ = toupper(*language
& 255);
617 if (*language
== '.' && !charset
[0])
620 * Copy the encoding...
623 for (language
++, ptr
= charset
; *language
; language
++)
624 if (isalnum(*language
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
625 *ptr
++ = toupper(*language
& 255);
631 * Force a POSIX locale for an invalid language name...
634 if (strlen(langname
) != 2)
636 strcpy(langname
, "C");
642 DEBUG_printf(("4cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"",
643 langname
, country
, charset
));
646 * Figure out the desired encoding...
649 encoding
= CUPS_AUTO_ENCODING
;
654 i
< (int)(sizeof(locale_encodings
) / sizeof(locale_encodings
[0]));
656 if (!strcasecmp(charset
, locale_encodings
[i
]))
658 encoding
= (cups_encoding_t
)i
;
662 if (encoding
== CUPS_AUTO_ENCODING
)
665 * Map alternate names for various character sets...
668 if (!strcasecmp(charset
, "iso-2022-jp") ||
669 !strcasecmp(charset
, "sjis"))
670 encoding
= CUPS_WINDOWS_932
;
671 else if (!strcasecmp(charset
, "iso-2022-cn"))
672 encoding
= CUPS_WINDOWS_936
;
673 else if (!strcasecmp(charset
, "iso-2022-kr"))
674 encoding
= CUPS_WINDOWS_949
;
675 else if (!strcasecmp(charset
, "big5"))
676 encoding
= CUPS_WINDOWS_950
;
680 DEBUG_printf(("4cupsLangGet: encoding=%d(%s)", encoding
,
681 encoding
== CUPS_AUTO_ENCODING
? "auto" :
682 lang_encodings
[encoding
]));
685 * See if we already have this language/country loaded...
690 snprintf(real
, sizeof(real
), "%s_%s", langname
, country
);
692 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s.po", cg
->localedir
,
697 strcpy(real
, langname
);
698 filename
[0] = '\0'; /* anti-compiler-warning-code */
701 #ifdef HAVE_PTHREAD_H
702 pthread_mutex_lock(&lang_mutex
);
703 #endif /* HAVE_PTHREAD_H */
705 if ((lang
= cups_cache_lookup(real
, encoding
)) != NULL
)
707 #ifdef HAVE_PTHREAD_H
708 pthread_mutex_unlock(&lang_mutex
);
709 #endif /* HAVE_PTHREAD_H */
711 DEBUG_printf(("3cupsLangGet: Using cached copy of \"%s\"...", real
));
716 if (!country
[0] || access(filename
, 0))
719 * Country localization not available, look for generic localization...
722 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s.po", cg
->localedir
,
725 if (access(filename
, 0))
728 * No generic localization, so use POSIX...
731 DEBUG_printf(("4cupsLangGet: access(\"%s\", 0): %s", filename
,
734 snprintf(filename
, sizeof(filename
), "%s/C/cups_C.po", cg
->localedir
);
739 * See if there is a free language available; if so, use that
743 for (lang
= lang_cache
; lang
!= NULL
; lang
= lang
->next
)
750 * Allocate memory for the language and add it to the cache.
753 if ((lang
= calloc(sizeof(cups_lang_t
), 1)) == NULL
)
755 #ifdef HAVE_PTHREAD_H
756 pthread_mutex_unlock(&lang_mutex
);
757 #endif /* HAVE_PTHREAD_H */
762 lang
->next
= lang_cache
;
768 * Free all old strings as needed...
771 _cupsMessageFree(lang
->strings
);
775 * Then assign the language and encoding fields...
779 strlcpy(lang
->language
, real
, sizeof(lang
->language
));
781 if (encoding
!= CUPS_AUTO_ENCODING
)
782 lang
->encoding
= encoding
;
784 lang
->encoding
= CUPS_UTF8
;
787 * Read the strings from the file...
790 lang
->strings
= _cupsMessageLoad(filename
, 1);
796 #ifdef HAVE_PTHREAD_H
797 pthread_mutex_unlock(&lang_mutex
);
798 #endif /* HAVE_PTHREAD_H */
805 * '_cupsLangString()' - Get a message string.
807 * The returned string is UTF-8 encoded; use cupsUTF8ToCharset() to
808 * convert the string to the language encoding.
811 const char * /* O - Localized message */
812 _cupsLangString(cups_lang_t
*lang
, /* I - Language */
813 const char *message
) /* I - Message */
816 * Range check input...
819 if (!lang
|| !message
)
822 #ifdef HAVE_PTHREAD_H
824 const char *s
; /* Localized message */
826 pthread_mutex_lock(&lang_mutex
);
828 s
= _cupsMessageLookup(lang
->strings
, message
);
830 pthread_mutex_unlock(&lang_mutex
);
835 return (_cupsMessageLookup(lang
->strings
, message
));
836 #endif /* HAVE_PTHREAD_H */
841 * '_cupsMessageFree()' - Free a messages array.
845 _cupsMessageFree(cups_array_t
*a
) /* I - Message array */
847 _cups_message_t
*m
; /* Current message */
850 for (m
= (_cups_message_t
*)cupsArrayFirst(a
);
852 m
= (_cups_message_t
*)cupsArrayNext(a
))
855 * Remove the message from the array, then free the message and strings.
858 cupsArrayRemove(a
, m
);
878 * '_cupsMessageLoad()' - Load a .po file into a messages array.
881 cups_array_t
* /* O - New message array */
882 _cupsMessageLoad(const char *filename
, /* I - Message catalog to load */
883 int unquote
) /* I - Unescape \foo in strings */
885 cups_file_t
*fp
; /* Message file */
886 cups_array_t
*a
; /* Message array */
887 _cups_message_t
*m
; /* Current message */
888 char s
[4096], /* String buffer */
889 *ptr
, /* Pointer into buffer */
890 *temp
; /* New string */
891 int length
; /* Length of combined strings */
894 DEBUG_printf(("4_cupsMessageLoad(filename=\"%s\")", filename
));
897 * Create an array to hold the messages...
900 if ((a
= cupsArrayNew((cups_array_func_t
)cups_message_compare
, NULL
)) == NULL
)
902 DEBUG_puts("5_cupsMessageLoad: Unable to allocate array!");
907 * Open the message catalog file...
910 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
912 DEBUG_printf(("5_cupsMessageLoad: Unable to open file: %s",
918 * Read messages from the catalog file until EOF...
920 * The format is the GNU gettext .po format, which is fairly simple:
923 * msgstr "localized text"
925 * The ID and localized text can span multiple lines using the form:
930 * "localized text spanning "
936 while (cupsFileGets(fp
, s
, sizeof(s
)) != NULL
)
939 * Skip blank and comment lines...
942 if (s
[0] == '#' || !s
[0])
946 * Strip the trailing quote...
949 if ((ptr
= strrchr(s
, '\"')) == NULL
)
955 * Find start of value...
958 if ((ptr
= strchr(s
, '\"')) == NULL
)
964 * Unquote the text...
968 cups_unquote(ptr
, ptr
);
971 * Create or add to a message...
974 if (!strncmp(s
, "msgid", 5))
977 * Add previous message as needed...
984 * Create a new message with the given msgid string...
987 if ((m
= (_cups_message_t
*)calloc(1, sizeof(_cups_message_t
))) == NULL
)
993 if ((m
->id
= strdup(ptr
)) == NULL
)
1000 else if (s
[0] == '\"' && m
)
1003 * Append to current string...
1006 length
= (int)strlen(m
->str
? m
->str
: m
->id
);
1008 if ((temp
= realloc(m
->str
? m
->str
: m
->id
,
1009 length
+ strlen(ptr
) + 1)) == NULL
)
1018 * Copy the new portion to the end of the msgstr string - safe
1019 * to use strcpy because the buffer is allocated to the correct
1025 strcpy(m
->str
+ length
, ptr
);
1030 * Copy the new portion to the end of the msgid string - safe
1031 * to use strcpy because the buffer is allocated to the correct
1037 strcpy(m
->id
+ length
, ptr
);
1040 else if (!strncmp(s
, "msgstr", 6) && m
)
1046 if ((m
->str
= strdup(ptr
)) == NULL
)
1055 * Add the last message string to the array as needed...
1062 * Close the message catalog file and return the new array...
1067 DEBUG_printf(("5_cupsMessageLoad: Returning %d messages...",
1068 cupsArrayCount(a
)));
1075 * '_cupsMessageLookup()' - Lookup a message string.
1078 const char * /* O - Localized message */
1079 _cupsMessageLookup(cups_array_t
*a
, /* I - Message array */
1080 const char *m
) /* I - Message */
1082 _cups_message_t key
, /* Search key */
1083 *match
; /* Matching message */
1087 * Lookup the message string; if it doesn't exist in the catalog,
1088 * then return the message that was passed to us...
1092 match
= (_cups_message_t
*)cupsArrayFind(a
, &key
);
1094 if (match
&& match
->str
)
1095 return (match
->str
);
1103 * 'appleLangDefault()' - Get the default locale string.
1106 static const char * /* O - Locale string */
1107 appleLangDefault(void)
1109 int i
; /* Looping var */
1110 CFBundleRef bundle
; /* Main bundle (if any) */
1111 CFArrayRef bundleList
; /* List of localizations in bundle */
1112 CFPropertyListRef localizationList
;
1113 /* List of localization data */
1114 CFStringRef languageName
; /* Current name */
1115 CFStringRef localeName
; /* Canonical from of name */
1116 char *lang
; /* LANG environment variable */
1117 _cups_globals_t
*cg
= _cupsGlobals();
1118 /* Pointer to library globals */
1121 DEBUG_puts("2appleLangDefault()");
1124 * Only do the lookup and translation the first time.
1127 if (!cg
->language
[0])
1129 if (getenv("SOFTWARE") != NULL
&& (lang
= getenv("LANG")) != NULL
)
1131 strlcpy(cg
->language
, lang
, sizeof(cg
->language
));
1132 return (cg
->language
);
1134 else if ((bundle
= CFBundleGetMainBundle()) != NULL
&&
1135 (bundleList
= CFBundleCopyBundleLocalizations(bundle
)) != NULL
)
1138 CFBundleCopyPreferredLocalizationsFromArray(bundleList
);
1140 CFRelease(bundleList
);
1144 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
1145 kCFPreferencesCurrentApplication
);
1147 if (localizationList
)
1149 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
1150 CFArrayGetCount(localizationList
) > 0)
1152 languageName
= CFArrayGetValueAtIndex(localizationList
, 0);
1155 CFGetTypeID(languageName
) == CFStringGetTypeID())
1157 localeName
= CFLocaleCreateCanonicalLocaleIdentifierFromString(
1158 kCFAllocatorDefault
, languageName
);
1162 CFStringGetCString(localeName
, cg
->language
, sizeof(cg
->language
),
1163 kCFStringEncodingASCII
);
1164 CFRelease(localeName
);
1166 DEBUG_printf(("9appleLangDefault: cg->language=\"%s\"",
1170 * Map new language identifiers to locales...
1174 i
< (int)(sizeof(apple_language_locale
) /
1175 sizeof(apple_language_locale
[0]));
1178 if (!strcmp(cg
->language
, apple_language_locale
[i
].language
))
1180 DEBUG_printf(("9appleLangDefault: mapping \"%s\" to \"%s\"...",
1181 cg
->language
, apple_language_locale
[i
].locale
));
1182 strlcpy(cg
->language
, apple_language_locale
[i
].locale
,
1183 sizeof(cg
->language
));
1189 * Convert language subtag into region subtag...
1192 if (cg
->language
[2] == '-')
1193 cg
->language
[2] = '_';
1195 if (!strchr(cg
->language
, '.'))
1196 strlcat(cg
->language
, ".UTF-8", sizeof(cg
->language
));
1201 CFRelease(localizationList
);
1205 * If we didn't find the language, default to en_US...
1208 if (!cg
->language
[0])
1209 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
1213 * Return the cached locale...
1216 return (cg
->language
);
1218 #endif /* __APPLE__ */
1222 * 'cups_cache_lookup()' - Lookup a language in the cache...
1225 static cups_lang_t
* /* O - Language data or NULL */
1226 cups_cache_lookup(const char *name
,/* I - Name of locale */
1227 cups_encoding_t encoding
)
1228 /* I - Encoding of locale */
1230 cups_lang_t
*lang
; /* Current language */
1233 DEBUG_printf(("7cups_cache_lookup(name=\"%s\", encoding=%d(%s))", name
,
1234 encoding
, encoding
== CUPS_AUTO_ENCODING
? "auto" :
1235 lang_encodings
[encoding
]));
1238 * Loop through the cache and return a match if found...
1241 for (lang
= lang_cache
; lang
!= NULL
; lang
= lang
->next
)
1243 DEBUG_printf(("9cups_cache_lookup: lang=%p, language=\"%s\", "
1244 "encoding=%d(%s)", lang
, lang
->language
, lang
->encoding
,
1245 lang_encodings
[lang
->encoding
]));
1247 if (!strcmp(lang
->language
, name
) &&
1248 (encoding
== CUPS_AUTO_ENCODING
|| encoding
== lang
->encoding
))
1252 DEBUG_puts("8cups_cache_lookup: returning match!");
1258 DEBUG_puts("8cups_cache_lookup: returning NULL!");
1265 * 'cups_message_compare()' - Compare two messages.
1268 static int /* O - Result of comparison */
1269 cups_message_compare(
1270 _cups_message_t
*m1
, /* I - First message */
1271 _cups_message_t
*m2
) /* I - Second message */
1273 return (strcmp(m1
->id
, m2
->id
));
1278 * 'cups_unquote()' - Unquote characters in strings...
1282 cups_unquote(char *d
, /* O - Unquoted string */
1283 const char *s
) /* I - Original string */
1296 *d
= *d
* 8 + *s
- '0';
1325 * End of "$Id: language.c 7558 2008-05-12 23:46:44Z mike $".