2 * "$Id: language.c 5109 2006-02-15 20:11:10Z 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...
57 #ifdef HAVE_LANGINFO_H
58 # include <langinfo.h>
59 #endif /* HAVE_LANGINFO_H */
65 #ifdef HAVE_COREFOUNDATION_H
66 # include <CoreFoundation/CoreFoundation.h>
67 #endif /* HAVE_COREFOUNDATION_H */
75 static const char *appleLangDefault(void);
76 #endif /* __APPLE__ */
77 static cups_lang_t
*cups_cache_lookup(const char *name
,
78 cups_encoding_t encoding
);
79 static int cups_message_compare(_cups_message_t
*m1
,
81 static void cups_unquote(char *d
, const char *s
);
88 static const char * const lang_encodings
[] =
89 { /* Encoding strings */
90 "us-ascii", "iso-8859-1",
91 "iso-8859-2", "iso-8859-3",
92 "iso-8859-4", "iso-8859-5",
93 "iso-8859-6", "iso-8859-7",
94 "iso-8859-8", "iso-8859-9",
95 "iso-8859-10", "utf-8",
96 "iso-8859-13", "iso-8859-14",
97 "iso-8859-15", "windows-874",
98 "windows-1250", "windows-1251",
99 "windows-1252", "windows-1253",
100 "windows-1254", "windows-1255",
101 "windows-1256", "windows-1257",
102 "windows-1258", "koi8-r",
103 "koi8-u", "iso-8859-11",
104 "iso-8859-16", "mac-roman",
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 "windows-932", "windows-936",
123 "windows-949", "windows-950",
124 "windows-1361", "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",
153 "unknown", "unknown",
160 * '_cupsEncodingName()' - Return the character encoding name string
161 * for the given encoding enumeration.
164 const char * /* O - Character encoding */
166 cups_encoding_t encoding
) /* I - Encoding value */
169 encoding
>= (sizeof(lang_encodings
) / sizeof(const char *)))
170 return (lang_encodings
[0]);
172 return (lang_encodings
[encoding
]);
177 * 'cupsLangDefault()' - Return the default language.
180 cups_lang_t
* /* O - Language data */
181 cupsLangDefault(void)
183 return (cupsLangGet(NULL
));
188 * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.)
189 * for the given language.
192 const char * /* O - Character encoding */
193 cupsLangEncoding(cups_lang_t
*lang
) /* I - Language data */
196 return ((char*)lang_encodings
[0]);
198 return ((char*)lang_encodings
[lang
->encoding
]);
203 * 'cupsLangFlush()' - Flush all language data out of the cache.
209 _cupsLangFlush(_cupsGlobals());
214 * '_cupsLangFlush()' - Flush all language data out of the cache.
218 _cupsLangFlush(_cups_globals_t
*cg
) /* I - Global data */
220 cups_lang_t
*lang
, /* Current language */
221 *next
; /* Next language */
225 * Free all languages in the cache...
228 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= next
)
231 * Free all messages...
234 _cupsMessageFree(lang
->strings
);
237 * Then free the language structure itself...
244 cg
->lang_cache
= NULL
;
249 * 'cupsLangFree()' - Free language data.
251 * This does not actually free anything; use cupsLangFlush() for that.
255 cupsLangFree(cups_lang_t
*lang
) /* I - Language to free */
257 if (lang
!= NULL
&& lang
->used
> 0)
263 * 'cupsLangGet()' - Get a language.
266 cups_lang_t
* /* O - Language data */
267 cupsLangGet(const char *language
) /* I - Language or locale */
269 int i
; /* Looping var */
270 char locale
[255], /* Copy of locale name */
271 langname
[16], /* Requested language name */
272 country
[16], /* Country code */
273 charset
[16], /* Character set */
275 *csptr
, /* Pointer to CODESET string */
277 *ptr
, /* Pointer into language/charset */
278 real
[48], /* Real language name */
279 filename
[1024]; /* Filename for language locale file */
280 cups_encoding_t encoding
; /* Encoding to use */
281 cups_lang_t
*lang
; /* Current language... */
282 char *oldlocale
; /* Old locale name */
283 _cups_globals_t
*cg
= _cupsGlobals();
284 /* Pointer to library globals */
285 static const char * const locale_encodings
[] =
286 { /* Locale charset names */
287 "ASCII", "ISO88591", "ISO88592", "ISO88593",
288 "ISO88594", "ISO88595", "ISO88596", "ISO88597",
289 "ISO88598", "ISO88599", "ISO885910", "UTF8",
290 "ISO885913", "ISO885914", "ISO885915", "CP874",
291 "CP1250", "CP1251", "CP1252", "CP1253",
292 "CP1254", "CP1255", "CP1256", "CP1257",
293 "CP1258", "KOI8R", "KOI8U", "ISO885911",
294 "ISO885916", "MACROMAN", "", "",
305 "CP932", "CP936", "CP949", "CP950",
306 "CP1361", "", "", "",
323 "EUCCN", "EUCJP", "EUCKR", "EUCTW"
327 DEBUG_printf(("cupsLangGet(language=\"%s\")\n", language
? language
: "(null)"));
331 * Apple's setlocale doesn't give us the user's localization
332 * preference so we have to look it up this way...
335 if (language
== NULL
)
336 language
= appleLangDefault();
338 if (language
== NULL
)
341 * First see if the locale has been set; if it is still "C" or
342 * "POSIX", set the locale to the default...
346 ptr
= setlocale(LC_MESSAGES
, NULL
);
348 ptr
= setlocale(LC_ALL
, NULL
);
349 # endif /* LC_MESSAGES */
351 DEBUG_printf(("cupsLangGet: current locale is \"%s\"\n",
352 ptr
? ptr
: "(null)"));
354 if (!ptr
|| !strcmp(ptr
, "C") || !strcmp(ptr
, "POSIX"))
357 ptr
= setlocale(LC_MESSAGES
, "");
358 setlocale(LC_CTYPE
, "");
361 ptr
= setlocale(LC_ALL
, "");
362 # endif /* LC_MESSAGES */
366 strlcpy(locale
, ptr
, sizeof(locale
));
369 DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n",
370 language
? language
: "(null)"));
373 #endif /* __APPLE__ */
376 * If "language" is NULL at this point, then chances are we are using
377 * a language that is not installed for the base OS.
383 * Switch to the value of the "LANG" environment variable, and if
384 * that is NULL as well, use "C".
387 if ((language
= getenv("LANG")) == NULL
)
392 * Set the charset to "unknown"...
399 * On systems that support the nl_langinfo(CODESET) call, use
400 * this value as the character set...
403 if ((csptr
= nl_langinfo(CODESET
)) != NULL
)
406 * Copy all of the letters and numbers in the CODESET string...
409 for (ptr
= charset
; *csptr
; csptr
++)
410 if (isalnum(*csptr
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
415 DEBUG_printf(("cupsLangGet: charset set to \"%s\" via nl_langinfo(CODESET)...\n",
421 * Set the locale back to POSIX while we do string ops, since
422 * apparently some buggy C libraries break ctype() for non-I18N
426 #if defined(__APPLE__)
427 /* The ctype bug isn't in Apple's libc */
428 (void)locale
; /* anti-compiler-warning-code */
429 (void)oldlocale
; /* anti-compiler-warning-code */
430 #elif !defined(LC_CTYPE)
431 oldlocale
= _cupsSaveLocale(LC_ALL
, "C");
433 oldlocale
= _cupsSaveLocale(LC_CTYPE
, "C");
434 #endif /* __APPLE__ */
437 * Parse the language string passed in to a locale string. "C" is the
438 * standard POSIX locale and is copied unchanged. Otherwise the
439 * language string is converted from ll-cc[.charset] (language-country)
440 * to ll_CC[.CHARSET] to match the file naming convention used by all
441 * POSIX-compliant operating systems. Invalid language names are mapped
442 * to the POSIX locale.
447 if (language
== NULL
|| !language
[0] ||
448 !strcmp(language
, "POSIX"))
449 strcpy(langname
, "C");
453 * Copy the parts of the locale string over safely...
456 for (ptr
= langname
; *language
; language
++)
457 if (*language
== '_' || *language
== '-' || *language
== '.')
459 else if (ptr
< (langname
+ sizeof(langname
) - 1))
460 *ptr
++ = tolower(*language
& 255);
464 if (*language
== '_' || *language
== '-')
467 * Copy the country code...
470 for (language
++, ptr
= country
; *language
; language
++)
471 if (*language
== '.')
473 else if (ptr
< (country
+ sizeof(country
) - 1))
474 *ptr
++ = toupper(*language
& 255);
479 if (*language
== '.' && !charset
[0])
482 * Copy the encoding...
485 for (language
++, ptr
= charset
; *language
; language
++)
486 if (isalnum(*language
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
487 *ptr
++ = toupper(*language
& 255);
493 * Force a POSIX locale for an invalid language name...
496 if (strlen(langname
) != 2)
498 strcpy(langname
, "C");
505 * Restore the locale...
508 #if defined(__APPLE__)
509 /* The ctype bug isn't in Apple's libc */
510 #elif !defined(LC_CTYPE)
511 _cupsRestoreLocale(LC_ALL
, oldlocale
);
513 _cupsRestoreLocale(LC_CTYPE
, oldlocale
);
514 #endif /* __APPLE__ */
516 DEBUG_printf(("cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"\n",
517 langname
, country
, charset
));
520 * Figure out the desired encoding...
523 encoding
= CUPS_AUTO_ENCODING
;
528 i
< (int)(sizeof(locale_encodings
) / sizeof(locale_encodings
[0]));
530 if (!strcasecmp(charset
, locale_encodings
[i
]))
532 encoding
= (cups_encoding_t
)i
;
537 DEBUG_printf(("cupsLangGet: encoding=%d(%s)\n", encoding
,
538 encoding
== CUPS_AUTO_ENCODING
? "auto" :
539 lang_encodings
[encoding
]));
542 * See if we already have this language/country loaded...
547 snprintf(real
, sizeof(real
), "%s_%s", langname
, country
);
549 if ((lang
= cups_cache_lookup(real
, encoding
)) != NULL
)
552 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s.po", cg
->localedir
,
556 filename
[0] = '\0'; /* anti-compiler-warning-code */
558 if (!country
[0] || access(filename
, 0))
561 * Country localization not available, look for generic localization...
564 if ((lang
= cups_cache_lookup(langname
, encoding
)) != NULL
)
567 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s.po", cg
->localedir
,
570 if (access(filename
, 0))
573 * No generic localization, so use POSIX...
576 DEBUG_printf(("access(\"%s\", 0): %s\n", filename
, strerror(errno
)));
579 snprintf(filename
, sizeof(filename
), "%s/C/cups_C.po", cg
->localedir
);
582 strcpy(real
, langname
);
586 * See if there is a free language available; if so, use that
590 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
597 * Allocate memory for the language and add it to the cache.
600 if ((lang
= calloc(sizeof(cups_lang_t
), 1)) == NULL
)
603 lang
->next
= cg
->lang_cache
;
604 cg
->lang_cache
= lang
;
609 * Free all old strings as needed...
612 _cupsMessageFree(lang
->strings
);
616 * Then assign the language and encoding fields...
620 strlcpy(lang
->language
, real
, sizeof(lang
->language
));
622 if (encoding
!= CUPS_AUTO_ENCODING
)
623 lang
->encoding
= encoding
;
625 lang
->encoding
= CUPS_UTF8
;
628 * Read the strings from the file...
631 lang
->strings
= _cupsMessageLoad(filename
);
642 * '_cupsLangString()' - Get a message string.
644 * The returned string is UTF-8 encoded; use cupsUTF8ToCharset() to
645 * convert the string to the language encoding.
648 const char * /* O - Localized message */
649 _cupsLangString(cups_lang_t
*lang
, /* I - Language */
650 const char *message
) /* I - Message */
653 * Range check input...
656 if (!lang
|| !message
)
659 return (_cupsMessageLookup(lang
->strings
, message
));
664 * '_cupsMessageFree()' - Free a messages array.
668 _cupsMessageFree(cups_array_t
*a
) /* I - Message array */
670 _cups_message_t
*m
; /* Current message */
673 for (m
= (_cups_message_t
*)cupsArrayFirst(a
);
675 m
= (_cups_message_t
*)cupsArrayNext(a
))
678 * Remove the message from the array, then free the message and strings.
681 cupsArrayRemove(a
, m
);
701 * '_cupsMessageLoad()' - Load a .po file into a messages array.
704 cups_array_t
* /* O - New message array */
705 _cupsMessageLoad(const char *filename
) /* I - Message catalog to load */
707 cups_file_t
*fp
; /* Message file */
708 cups_array_t
*a
; /* Message array */
709 _cups_message_t
*m
; /* Current message */
710 char s
[4096], /* String buffer */
711 *ptr
, /* Pointer into buffer */
712 *temp
; /* New string */
713 int length
; /* Length of combined strings */
716 DEBUG_printf(("_cupsMessageLoad(filename=\"%s\")\n", filename
));
719 * Create an array to hold the messages...
722 if ((a
= cupsArrayNew((cups_array_func_t
)cups_message_compare
, NULL
)) == NULL
)
726 * Open the message catalog file...
729 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
733 * Read messages from the catalog file until EOF...
735 * The format is the GNU gettext .po format, which is fairly simple:
738 * msgstr "localized text"
740 * The ID and localized text can span multiple lines using the form:
745 * "localized text spanning "
751 while (cupsFileGets(fp
, s
, sizeof(s
)) != NULL
)
754 * Skip blank and comment lines...
757 if (s
[0] == '#' || !s
[0])
761 * Strip the trailing quote...
764 if ((ptr
= strrchr(s
, '\"')) == NULL
)
770 * Find start of value...
773 if ((ptr
= strchr(s
, '\"')) == NULL
)
779 * Unquote the text...
782 cups_unquote(ptr
, ptr
);
785 * Create or add to a message...
788 if (!strncmp(s
, "msgid", 5))
791 * Add previous message as needed...
798 * Create a new message with the given msgid string...
801 if ((m
= (_cups_message_t
*)calloc(1, sizeof(_cups_message_t
))) == NULL
)
809 else if (s
[0] == '\"' && m
)
812 * Append to current string...
815 length
= strlen(m
->str
? m
->str
: m
->id
);
817 if ((temp
= realloc(m
->str
? m
->str
: m
->id
,
818 length
+ strlen(ptr
) + 1)) == NULL
)
827 * Copy the new portion to the end of the msgstr string - safe
828 * to use strcpy because the buffer is allocated to the correct
834 strcpy(m
->str
+ length
, ptr
);
839 * Copy the new portion to the end of the msgid string - safe
840 * to use strcpy because the buffer is allocated to the correct
846 strcpy(m
->id
+ length
, ptr
);
849 else if (!strncmp(s
, "msgstr", 6) && m
)
855 m
->str
= strdup(ptr
);
860 * Add the last message string to the array as needed...
867 * Close the message catalog file and return the new array...
877 * '_cupsMessageLookup()' - Lookup a message string.
880 const char * /* O - Localized message */
881 _cupsMessageLookup(cups_array_t
*a
, /* I - Message array */
882 const char *m
) /* I - Message */
884 _cups_message_t key
, /* Search key */
885 *match
; /* Matching message */
889 * Lookup the message string; if it doesn't exist in the catalog,
890 * then return the message that was passed to us...
894 match
= (_cups_message_t
*)cupsArrayFind(a
, &key
);
896 if (match
&& match
->str
)
904 * '_cupsRestoreLocale()' - Restore the original locale...
908 _cupsRestoreLocale(int category
, /* I - Category */
909 char *oldlocale
) /* I - Old locale or NULL */
911 DEBUG_printf(("_cupsRestoreLocale(category=%d, oldlocale=\"%s\")\n",
912 category
, oldlocale
));
917 * Reset the locale and free the locale string...
920 setlocale(category
, oldlocale
);
927 * '_cupsSaveLocale()' - Set the locale and save a copy of the old locale...
930 char * /* O - Old locale or NULL */
931 _cupsSaveLocale(int category
, /* I - Category */
932 const char *locale
) /* I - New locale or NULL */
934 char *oldlocale
; /* Old locale */
937 DEBUG_printf(("_cupsSaveLocale(category=%d, locale=\"%s\")\n",
941 * Get the old locale and copy it...
944 if ((oldlocale
= setlocale(category
, NULL
)) != NULL
)
945 oldlocale
= strdup(oldlocale
);
947 DEBUG_printf((" oldlocale=\"%s\"\n", oldlocale
? oldlocale
: "(null)"));
950 * Set the new locale...
953 setlocale(category
, locale
);
956 * Return a copy of the old locale...
965 * Code & data to translate OSX's language names to their ISO 639-1 locale.
967 * The first version uses the new CoreFoundation API added in 10.3 (Panther),
968 * the second is for 10.2 (Jaguar).
971 # ifdef HAVE_CF_LOCALE_ID
973 * 'appleLangDefault()' - Get the default locale string.
976 static const char * /* O - Locale string */
977 appleLangDefault(void)
979 CFPropertyListRef localizationList
;
980 /* List of localization data */
981 CFStringRef languageName
; /* Current name */
982 CFStringRef localeName
; /* Canonical from of name */
983 _cups_globals_t
*cg
= _cupsGlobals();
984 /* Pointer to library globals */
988 * Only do the lookup and translation the first time.
991 if (!cg
->language
[0])
994 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
995 kCFPreferencesCurrentApplication
);
997 if (localizationList
!= NULL
)
999 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
1000 CFArrayGetCount(localizationList
) > 0)
1002 languageName
= CFArrayGetValueAtIndex(localizationList
, 0);
1004 if (languageName
!= NULL
&&
1005 CFGetTypeID(languageName
) == CFStringGetTypeID())
1007 localeName
= CFLocaleCreateCanonicalLocaleIdentifierFromString(
1008 kCFAllocatorDefault
, languageName
);
1010 if (localeName
!= NULL
)
1012 CFStringGetCString(localeName
, cg
->language
, sizeof(cg
->language
),
1013 kCFStringEncodingASCII
);
1014 CFRelease(localeName
);
1016 if (!strcmp(cg
->language
, "en"))
1017 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
1018 else if (strchr(cg
->language
, '.') == NULL
)
1019 strlcat(cg
->language
, ".UTF-8", sizeof(cg
->language
));
1024 CFRelease(localizationList
);
1028 * If we didn't find the language, default to en_US...
1031 if (!cg
->language
[0])
1032 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
1036 * Return the cached locale...
1039 return (cg
->language
);
1043 * Code & data to translate OSX 10.2's language names to their ISO 639-1
1049 const char * const name
; /* Language name */
1050 const char * const locale
; /* Locale name */
1051 } _apple_name_locale_t
;
1053 static const _apple_name_locale_t apple_name_locale
[] =
1055 { "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" },
1056 { "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" },
1057 { "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" },
1058 { "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" },
1059 { "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" },
1060 { "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" },
1061 { "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" },
1062 { "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" },
1063 { "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" },
1064 { "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1065 { "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" },
1066 { "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" },
1067 { "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" },
1068 { "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" },
1069 { "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" },
1070 { "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" },
1071 { "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1072 { "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" },
1073 { "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" },
1074 { "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" },
1075 { "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" },
1076 { "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" },
1077 { "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" },
1078 { "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" },
1079 { "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" },
1080 { "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" },
1081 { "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" },
1082 { "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" },
1083 { "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" },
1084 { "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" },
1085 { "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" },
1086 { "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" },
1087 { "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" },
1088 { "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" },
1089 { "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" },
1090 { "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" },
1091 { "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" },
1092 { "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" },
1093 { "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" },
1094 { "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" },
1095 { "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" },
1096 { "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" },
1097 { "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" },
1098 { "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" },
1099 { "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" },
1100 { "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" },
1101 { "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" },
1102 { "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" },
1103 { "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" },
1104 { "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" },
1105 { "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" },
1106 { "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" },
1107 { "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" },
1108 { "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" },
1109 { "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" },
1110 { "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" },
1111 { "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" },
1112 { "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" },
1113 { "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" }
1118 * 'appleLangDefault()' - Get the default locale string.
1121 static const char * /* O - Locale string */
1122 appleLangDefault(void)
1124 int i
; /* Looping var */
1125 CFPropertyListRef localizationList
;
1126 /* List of localization data */
1127 CFStringRef localizationName
;
1129 char buff
[256]; /* Temporary buffer */
1130 _cups_globals_t
*cg
= _cupsGlobals();
1131 /* Pointer to library globals */
1135 * Only do the lookup and translation the first time.
1138 if (cg
->language
== NULL
)
1141 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
1142 kCFPreferencesCurrentApplication
);
1144 if (localizationList
!= NULL
)
1146 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
1147 CFArrayGetCount(localizationList
) > 0)
1149 localizationName
= CFArrayGetValueAtIndex(localizationList
, 0);
1151 if (localizationName
!= NULL
&&
1152 CFGetTypeID(localizationName
) == CFStringGetTypeID())
1154 CFIndex length
= CFStringGetLength(localizationName
);
1156 if (length
<= sizeof(buff
) &&
1157 CFStringGetCString(localizationName
, buff
, sizeof(buff
),
1158 kCFStringEncodingASCII
))
1160 buff
[sizeof(buff
) - 1] = '\0';
1163 i
< sizeof(apple_name_locale
) / sizeof(apple_name_locale
[0]);
1166 if (!strcasecmp(buff
, apple_name_locale
[i
].name
))
1168 cg
->language
= apple_name_locale
[i
].locale
;
1176 CFRelease(localizationList
);
1180 * If we didn't find the language, default to en_US...
1183 if (cg
->language
== NULL
)
1184 cg
->language
= apple_name_locale
[0].locale
;
1188 * Return the cached locale...
1191 return (cg
->language
);
1193 # endif /* HAVE_CF_LOCALE_ID */
1194 #endif /* __APPLE__ */
1198 * 'cups_cache_lookup()' - Lookup a language in the cache...
1201 static cups_lang_t
* /* O - Language data or NULL */
1202 cups_cache_lookup(const char *name
,/* I - Name of locale */
1203 cups_encoding_t encoding
)
1204 /* I - Encoding of locale */
1206 cups_lang_t
*lang
; /* Current language */
1209 DEBUG_printf(("cups_cache_lookup(name=\"%s\", encoding=%d(%s))\n", name
,
1210 encoding
, encoding
== CUPS_AUTO_ENCODING
? "auto" :
1211 lang_encodings
[encoding
]));
1214 * Loop through the cache and return a match if found...
1217 for (lang
= _cupsGlobals()->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
1219 DEBUG_printf(("cups_cache_lookup: lang=%p, language=\"%s\", encoding=%d(%s)\n",
1220 lang
, lang
->language
, lang
->encoding
,
1221 lang_encodings
[lang
->encoding
]));
1223 if (!strcmp(lang
->language
, name
) &&
1224 (encoding
== CUPS_AUTO_ENCODING
|| encoding
== lang
->encoding
))
1228 DEBUG_puts("cups_cache_lookup: returning match!");
1234 DEBUG_puts("cups_cache_lookup: returning NULL!");
1241 * 'cups_message_compare()' - Compare two messages.
1244 static int /* O - Result of comparison */
1245 cups_message_compare(
1246 _cups_message_t
*m1
, /* I - First message */
1247 _cups_message_t
*m2
) /* I - Second message */
1249 return (strcmp(m1
->id
, m2
->id
));
1254 * 'cups_unquote()' - Unquote characters in strings...
1258 cups_unquote(char *d
, /* O - Unquoted string */
1259 const char *s
) /* I - Original string */
1272 *d
= *d
* 8 + *s
- '0';
1299 * End of "$Id: language.c 5109 2006-02-15 20:11:10Z mike $".