2 * "$Id: language.c 4922 2006-01-12 22:05:06Z 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 * cupsLangFree() - Free language data.
35 * cupsLangGet() - Get a language.
36 * _cupsLangString() - Get a message string.
37 * _cupsMessageFree() - Free a messages array.
38 * _cupsMessageLoad() - Load a .po file into a messages array.
39 * _cupsMessageLookup() - Lookup a message string.
40 * _cupsRestoreLocale() - Restore the original locale...
41 * _cupsSaveLocale() - Set the locale and save a copy of the old locale...
42 * appleLangDefault() - Get the default locale string.
43 * cups_cache_lookup() - Lookup a language in the cache...
44 * cups_message_compare() - Compare two messages.
45 * cups_unquote() - Unquote characters in strings...
49 * Include necessary headers...
55 #ifdef HAVE_LANGINFO_H
56 # include <langinfo.h>
57 #endif /* HAVE_LANGINFO_H */
70 # include <CoreFoundation/CoreFoundation.h>
71 static const char *appleLangDefault(void);
72 #endif /* __APPLE__ */
73 static cups_lang_t
*cups_cache_lookup(const char *name
,
74 cups_encoding_t encoding
);
75 static int cups_message_compare(_cups_message_t
*m1
,
77 static void cups_unquote(char *d
, const char *s
);
84 static const char * const lang_encodings
[] =
85 { /* Encoding strings */
86 "us-ascii", "iso-8859-1",
87 "iso-8859-2", "iso-8859-3",
88 "iso-8859-4", "iso-8859-5",
89 "iso-8859-6", "iso-8859-7",
90 "iso-8859-8", "iso-8859-9",
91 "iso-8859-10", "utf-8",
92 "iso-8859-13", "iso-8859-14",
93 "iso-8859-15", "windows-874",
94 "windows-1250", "windows-1251",
95 "windows-1252", "windows-1253",
96 "windows-1254", "windows-1255",
97 "windows-1256", "windows-1257",
98 "windows-1258", "koi8-r",
99 "koi8-u", "iso-8859-11",
100 "iso-8859-16", "unknown",
101 "unknown", "unknown",
102 "unknown", "unknown",
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 "windows-932", "windows-936",
119 "windows-949", "windows-950",
120 "windows-1361", "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",
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",
156 * '_cupsEncodingName()' - Return the character encoding name string
157 * for the given encoding enumeration.
160 const char * /* O - Character encoding */
162 cups_encoding_t encoding
) /* I - Encoding value */
165 encoding
>= (sizeof(lang_encodings
) / sizeof(const char *)))
166 return (lang_encodings
[0]);
168 return (lang_encodings
[encoding
]);
173 * 'cupsLangDefault()' - Return the default language.
176 cups_lang_t
* /* O - Language data */
177 cupsLangDefault(void)
179 return (cupsLangGet(NULL
));
184 * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.)
185 * for the given language.
188 const char * /* O - Character encoding */
189 cupsLangEncoding(cups_lang_t
*lang
) /* I - Language data */
192 return ((char*)lang_encodings
[0]);
194 return ((char*)lang_encodings
[lang
->encoding
]);
199 * 'cupsLangFlush()' - Flush all language data out of the cache.
205 cups_lang_t
*lang
, /* Current language */
206 *next
; /* Next language */
207 _cups_globals_t
*cg
= _cupsGlobals(); /* Pointer to library globals */
211 * Free all languages in the cache...
214 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= next
)
217 * Free all messages...
220 _cupsMessageFree(lang
->strings
);
223 * Then free the language structure itself...
230 cg
->lang_cache
= NULL
;
235 * 'cupsLangFree()' - Free language data.
237 * This does not actually free anything; use cupsLangFlush() for that.
241 cupsLangFree(cups_lang_t
*lang
) /* I - Language to free */
243 if (lang
!= NULL
&& lang
->used
> 0)
249 * 'cupsLangGet()' - Get a language.
252 cups_lang_t
* /* O - Language data */
253 cupsLangGet(const char *language
) /* I - Language or locale */
255 int i
; /* Looping var */
256 char locale
[255], /* Copy of locale name */
257 langname
[16], /* Requested language name */
258 country
[16], /* Country code */
259 charset
[16], /* Character set */
261 *csptr
, /* Pointer to CODESET string */
263 *ptr
, /* Pointer into language/charset */
264 real
[48], /* Real language name */
265 filename
[1024]; /* Filename for language locale file */
266 cups_encoding_t encoding
; /* Encoding to use */
267 cups_lang_t
*lang
; /* Current language... */
268 char *oldlocale
; /* Old locale name */
269 _cups_globals_t
*cg
= _cupsGlobals();
270 /* Pointer to library globals */
271 static const char * const locale_encodings
[] =
272 { /* Locale charset names */
273 "ASCII", "ISO88591", "ISO88592", "ISO88593",
274 "ISO88594", "ISO88595", "ISO88596", "ISO88597",
275 "ISO88598", "ISO88599", "ISO885910", "UTF8",
276 "ISO885913", "ISO885914", "ISO885915", "CP874",
277 "CP1250", "CP1251", "CP1252", "CP1253",
278 "CP1254", "CP1255", "CP1256", "CP1257",
279 "CP1258", "KOI8R", "KOI8U", "ISO885911",
280 "ISO885916", "", "", "",
291 "CP932", "CP936", "CP949", "CP950",
292 "CP1361", "", "", "",
309 "EUCCN", "EUCJP", "EUCKR", "EUCTW"
313 DEBUG_printf(("cupsLangGet(language=\"%s\")\n", language
? language
: "(null)"));
317 * Apple's setlocale doesn't give us the user's localization
318 * preference so we have to look it up this way...
321 if (language
== NULL
)
322 language
= appleLangDefault();
324 if (language
== NULL
)
327 * First see if the locale has been set; if it is still "C" or
328 * "POSIX", set the locale to the default...
332 ptr
= setlocale(LC_MESSAGES
, NULL
);
334 ptr
= setlocale(LC_ALL
, NULL
);
335 # endif /* LC_MESSAGES */
337 DEBUG_printf(("cupsLangGet: current locale is \"%s\"\n",
338 ptr
? ptr
: "(null)"));
340 if (!ptr
|| !strcmp(ptr
, "C") || !strcmp(ptr
, "POSIX"))
343 ptr
= setlocale(LC_MESSAGES
, "");
344 setlocale(LC_CTYPE
, "");
347 ptr
= setlocale(LC_ALL
, "");
348 # endif /* LC_MESSAGES */
352 strlcpy(locale
, ptr
, sizeof(locale
));
355 DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n",
356 language
? language
: "(null)"));
359 #endif /* __APPLE__ */
362 * If "language" is NULL at this point, then chances are we are using
363 * a language that is not installed for the base OS.
369 * Switch to the value of the "LANG" environment variable, and if
370 * that is NULL as well, use "C".
373 if ((language
= getenv("LANG")) == NULL
)
378 * Set the charset to "unknown"...
385 * On systems that support the nl_langinfo(CODESET) call, use
386 * this value as the character set...
389 if ((csptr
= nl_langinfo(CODESET
)) != NULL
)
392 * Copy all of the letters and numbers in the CODESET string...
395 for (ptr
= charset
; *csptr
; csptr
++)
396 if (isalnum(*csptr
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
401 DEBUG_printf(("cupsLangGet: charset set to \"%s\" via nl_langinfo(CODESET)...\n",
407 * Set the locale back to POSIX while we do string ops, since
408 * apparently some buggy C libraries break ctype() for non-I18N
412 #if defined(__APPLE__)
413 /* The ctype bug isn't in Apple's libc */
414 (void)locale
; /* anti-compiler-warning-code */
415 (void)oldlocale
; /* anti-compiler-warning-code */
416 #elif !defined(LC_CTYPE)
417 oldlocale
= _cupsSaveLocale(LC_ALL
, "C");
419 oldlocale
= _cupsSaveLocale(LC_CTYPE
, "C");
420 #endif /* __APPLE__ */
423 * Parse the language string passed in to a locale string. "C" is the
424 * standard POSIX locale and is copied unchanged. Otherwise the
425 * language string is converted from ll-cc[.charset] (language-country)
426 * to ll_CC[.CHARSET] to match the file naming convention used by all
427 * POSIX-compliant operating systems. Invalid language names are mapped
428 * to the POSIX locale.
433 if (language
== NULL
|| !language
[0] ||
434 !strcmp(language
, "POSIX"))
435 strcpy(langname
, "C");
439 * Copy the parts of the locale string over safely...
442 for (ptr
= langname
; *language
; language
++)
443 if (*language
== '_' || *language
== '-' || *language
== '.')
445 else if (ptr
< (langname
+ sizeof(langname
) - 1))
446 *ptr
++ = tolower(*language
& 255);
450 if (*language
== '_' || *language
== '-')
453 * Copy the country code...
456 for (language
++, ptr
= country
; *language
; language
++)
457 if (*language
== '.')
459 else if (ptr
< (country
+ sizeof(country
) - 1))
460 *ptr
++ = toupper(*language
& 255);
465 if (*language
== '.' && !charset
[0])
468 * Copy the encoding...
471 for (language
++, ptr
= charset
; *language
; language
++)
472 if (isalnum(*language
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
473 *ptr
++ = toupper(*language
& 255);
479 * Force a POSIX locale for an invalid language name...
482 if (strlen(langname
) != 2)
484 strcpy(langname
, "C");
491 * Restore the locale...
494 #if defined(__APPLE__)
495 /* The ctype bug isn't in Apple's libc */
496 #elif !defined(LC_CTYPE)
497 _cupsRestoreLocale(LC_ALL
, oldlocale
);
499 _cupsRestoreLocale(LC_CTYPE
, oldlocale
);
500 #endif /* __APPLE__ */
502 DEBUG_printf(("cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"\n",
503 langname
, country
, charset
));
506 * Figure out the desired encoding...
509 encoding
= CUPS_AUTO_ENCODING
;
513 for (i
= 0; i
< (int)(sizeof(locale_encodings
) / sizeof(locale_encodings
[0])); i
++)
514 if (!strcasecmp(charset
, locale_encodings
[i
]))
516 encoding
= (cups_encoding_t
)i
;
521 DEBUG_printf(("cupsLangGet: encoding=%d(%s)\n", encoding
,
522 encoding
== CUPS_AUTO_ENCODING
? "auto" :
523 lang_encodings
[encoding
]));
526 * See if we already have this language/country loaded...
529 snprintf(real
, sizeof(real
), "%s_%s", langname
, country
);
531 if ((lang
= cups_cache_lookup(real
, encoding
)) != NULL
)
534 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s", cg
->localedir
,
537 if (!country
[0] || access(filename
, 0))
540 * Country localization not available, look for generic localization...
543 if ((lang
= cups_cache_lookup(langname
, encoding
)) != NULL
)
546 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s", cg
->localedir
,
549 if (access(filename
, 0))
552 * No generic localization, so use POSIX...
556 snprintf(filename
, sizeof(filename
), "%s/C/cups_C", cg
->localedir
);
559 strcpy(real
, langname
);
563 * See if there is a free language available; if so, use that
567 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
574 * Allocate memory for the language and add it to the cache.
577 if ((lang
= calloc(sizeof(cups_lang_t
), 1)) == NULL
)
580 lang
->next
= cg
->lang_cache
;
581 cg
->lang_cache
= lang
;
585 * Free all old strings as needed...
588 _cupsMessageFree(lang
->strings
);
591 * Then assign the language and encoding fields...
595 strlcpy(lang
->language
, real
, sizeof(lang
->language
));
597 if (encoding
!= CUPS_AUTO_ENCODING
)
598 lang
->encoding
= encoding
;
600 lang
->encoding
= CUPS_UTF8
;
603 * Read the strings from the file...
606 lang
->strings
= _cupsMessageLoad(filename
);
617 * '_cupsLangString()' - Get a message string.
619 * The returned string is UTF-8 encoded; use cupsUTF8ToCharset() to
620 * convert the string to the language encoding.
623 const char * /* O - Localized message */
624 _cupsLangString(cups_lang_t
*lang
, /* I - Language */
625 const char *message
) /* I - Message */
628 * Range check input...
631 if (!lang
|| !message
)
634 return (_cupsMessageLookup(lang
->strings
, message
));
639 * '_cupsMessageFree()' - Free a messages array.
643 _cupsMessageFree(cups_array_t
*a
) /* I - Message array */
645 _cups_message_t
*m
; /* Current message */
648 for (m
= (_cups_message_t
*)cupsArrayFirst(a
);
650 m
= (_cups_message_t
*)cupsArrayNext(a
))
653 * Remove the message from the array, then free the message and strings.
656 cupsArrayRemove(a
, m
);
676 * '_cupsMessageLoad()' - Load a .po file into a messages array.
679 cups_array_t
* /* O - New message array */
680 _cupsMessageLoad(const char *filename
) /* I - Message catalog to load */
682 cups_file_t
*fp
; /* Message file */
683 cups_array_t
*a
; /* Message array */
684 _cups_message_t
*m
; /* Current message */
685 char s
[4096], /* String buffer */
686 *ptr
, /* Pointer into buffer */
687 *temp
; /* New string */
688 int length
; /* Length of combined strings */
692 * Create an array to hold the messages...
695 if ((a
= cupsArrayNew((cups_array_func_t
)cups_message_compare
, NULL
)) == NULL
)
699 * Open the message catalog file...
702 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
706 * Read messages from the catalog file until EOF...
708 * The format is the GNU gettext .po format, which is fairly simple:
711 * msgstr "localized text"
713 * The localized text can span multiple lines using the form:
715 * msgid "some long text"
716 * msgstr "localized text spanning "
722 while (cupsFileGets(fp
, s
, sizeof(s
)) != NULL
)
725 * Skip blank and comment lines...
728 if (s
[0] == '#' || !s
[0])
732 * Strip the trailing quote...
735 if ((ptr
= strrchr(s
, '\"')) == NULL
)
741 * Find start of value...
744 if ((ptr
= strchr(s
, '\"')) == NULL
)
750 * Unquote the text...
753 cups_unquote(ptr
, ptr
);
756 * Create or add to a message...
759 if (!strncmp(s
, "msgid", 5))
761 if ((m
= (_cups_message_t
*)calloc(1, sizeof(_cups_message_t
))) == NULL
)
770 else if ((s
[0] == '\"' || !strncmp(s
, "msgstr", 6)) && m
)
775 * Append the string...
778 length
= strlen(m
->str
);
780 if ((temp
= realloc(m
->str
, length
+ strlen(ptr
) + 1)) == NULL
)
789 * Copy the new portion at the end - safe because the buffer is
790 * allocated to the correct size...
793 strcpy(m
->str
+ length
, ptr
);
801 m
->str
= strdup(ptr
);
807 * Close the message catalog file and return the new array...
817 * '_cupsMessageLookup()' - Lookup a message string.
820 const char * /* O - Localized message */
821 _cupsMessageLookup(cups_array_t
*a
, /* I - Message array */
822 const char *m
) /* I - Message */
824 _cups_message_t key
, /* Search key */
825 *match
; /* Matching message */
829 * Lookup the message string; if it doesn't exist in the catalog,
830 * then return the message that was passed to us...
834 match
= (_cups_message_t
*)cupsArrayFind(a
, &key
);
836 if (match
&& match
->str
)
844 * '_cupsRestoreLocale()' - Restore the original locale...
848 _cupsRestoreLocale(int category
, /* I - Category */
849 char *oldlocale
) /* I - Old locale or NULL */
851 DEBUG_printf(("_cupsRestoreLocale(category=%d, oldlocale=\"%s\")\n",
852 category
, oldlocale
));
857 * Reset the locale and free the locale string...
860 setlocale(category
, oldlocale
);
867 * '_cupsSaveLocale()' - Set the locale and save a copy of the old locale...
870 char * /* O - Old locale or NULL */
871 _cupsSaveLocale(int category
, /* I - Category */
872 const char *locale
) /* I - New locale or NULL */
874 char *oldlocale
; /* Old locale */
877 DEBUG_printf(("_cupsSaveLocale(category=%d, locale=\"%s\")\n",
881 * Get the old locale and copy it...
884 if ((oldlocale
= setlocale(category
, NULL
)) != NULL
)
885 oldlocale
= strdup(oldlocale
);
887 DEBUG_printf((" oldlocale=\"%s\"\n", oldlocale
? oldlocale
: "(null)"));
890 * Set the new locale...
893 setlocale(category
, locale
);
896 * Return a copy of the old locale...
905 * Code & data to translate OSX's language names to their ISO 639-1 locale.
907 * The first version uses the new CoreFoundation API added in 10.3 (Panther),
908 * the second is for 10.2 (Jaguar).
911 # ifdef HAVE_CF_LOCALE_ID
913 * 'appleLangDefault()' - Get the default locale string.
916 static const char * /* O - Locale string */
917 appleLangDefault(void)
919 CFPropertyListRef localizationList
;
920 /* List of localization data */
921 CFStringRef languageName
; /* Current name */
922 CFStringRef localeName
; /* Canonical from of name */
923 _cups_globals_t
*cg
= _cupsGlobals();
924 /* Pointer to library globals */
928 * Only do the lookup and translation the first time.
931 if (!cg
->language
[0])
934 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
935 kCFPreferencesCurrentApplication
);
937 if (localizationList
!= NULL
)
939 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
940 CFArrayGetCount(localizationList
) > 0)
942 languageName
= CFArrayGetValueAtIndex(localizationList
, 0);
944 if (languageName
!= NULL
&&
945 CFGetTypeID(languageName
) == CFStringGetTypeID())
947 localeName
= CFLocaleCreateCanonicalLocaleIdentifierFromString(
948 kCFAllocatorDefault
, languageName
);
950 if (localeName
!= NULL
)
952 CFStringGetCString(localeName
, cg
->language
, sizeof(cg
->language
),
953 kCFStringEncodingASCII
);
954 CFRelease(localeName
);
956 if (!strcmp(cg
->language
, "en"))
957 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
958 else if (strchr(cg
->language
, '.') == NULL
)
959 strlcat(cg
->language
, ".UTF-8", sizeof(cg
->language
));
964 CFRelease(localizationList
);
968 * If we didn't find the language, default to en_US...
971 if (!cg
->language
[0])
972 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
976 * Return the cached locale...
979 return (cg
->language
);
983 * Code & data to translate OSX 10.2's language names to their ISO 639-1
989 const char * const name
; /* Language name */
990 const char * const locale
; /* Locale name */
991 } _apple_name_locale_t
;
993 static const _apple_name_locale_t apple_name_locale
[] =
995 { "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" },
996 { "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" },
997 { "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" },
998 { "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" },
999 { "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" },
1000 { "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" },
1001 { "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" },
1002 { "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" },
1003 { "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" },
1004 { "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1005 { "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" },
1006 { "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" },
1007 { "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" },
1008 { "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" },
1009 { "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" },
1010 { "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" },
1011 { "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1012 { "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" },
1013 { "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" },
1014 { "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" },
1015 { "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" },
1016 { "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" },
1017 { "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" },
1018 { "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" },
1019 { "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" },
1020 { "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" },
1021 { "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" },
1022 { "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" },
1023 { "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" },
1024 { "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" },
1025 { "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" },
1026 { "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" },
1027 { "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" },
1028 { "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" },
1029 { "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" },
1030 { "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" },
1031 { "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" },
1032 { "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" },
1033 { "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" },
1034 { "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" },
1035 { "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" },
1036 { "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" },
1037 { "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" },
1038 { "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" },
1039 { "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" },
1040 { "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" },
1041 { "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" },
1042 { "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" },
1043 { "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" },
1044 { "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" },
1045 { "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" },
1046 { "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" },
1047 { "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" },
1048 { "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" },
1049 { "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" },
1050 { "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" },
1051 { "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" },
1052 { "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" },
1053 { "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" }
1058 * 'appleLangDefault()' - Get the default locale string.
1061 static const char * /* O - Locale string */
1062 appleLangDefault(void)
1064 int i
; /* Looping var */
1065 CFPropertyListRef localizationList
;
1066 /* List of localization data */
1067 CFStringRef localizationName
;
1069 char buff
[256]; /* Temporary buffer */
1070 _cups_globals_t
*cg
= _cupsGlobals();
1071 /* Pointer to library globals */
1075 * Only do the lookup and translation the first time.
1078 if (cg
->language
== NULL
)
1081 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
1082 kCFPreferencesCurrentApplication
);
1084 if (localizationList
!= NULL
)
1086 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
1087 CFArrayGetCount(localizationList
) > 0)
1089 localizationName
= CFArrayGetValueAtIndex(localizationList
, 0);
1091 if (localizationName
!= NULL
&&
1092 CFGetTypeID(localizationName
) == CFStringGetTypeID())
1094 CFIndex length
= CFStringGetLength(localizationName
);
1096 if (length
<= sizeof(buff
) &&
1097 CFStringGetCString(localizationName
, buff
, sizeof(buff
),
1098 kCFStringEncodingASCII
))
1100 buff
[sizeof(buff
) - 1] = '\0';
1103 i
< sizeof(apple_name_locale
) / sizeof(apple_name_locale
[0]);
1106 if (!strcasecmp(buff
, apple_name_locale
[i
].name
))
1108 cg
->language
= apple_name_locale
[i
].locale
;
1116 CFRelease(localizationList
);
1120 * If we didn't find the language, default to en_US...
1123 if (cg
->language
== NULL
)
1124 cg
->language
= apple_name_locale
[0].locale
;
1128 * Return the cached locale...
1131 return (cg
->language
);
1133 # endif /* HAVE_CF_LOCALE_ID */
1134 #endif /* __APPLE__ */
1138 * 'cups_cache_lookup()' - Lookup a language in the cache...
1141 static cups_lang_t
* /* O - Language data or NULL */
1142 cups_cache_lookup(const char *name
,/* I - Name of locale */
1143 cups_encoding_t encoding
)
1144 /* I - Encoding of locale */
1146 cups_lang_t
*lang
; /* Current language */
1149 DEBUG_printf(("cups_cache_lookup(name=\"%s\", encoding=%d(%s))\n", name
,
1150 encoding
, encoding
== CUPS_AUTO_ENCODING
? "auto" :
1151 lang_encodings
[encoding
]));
1154 * Loop through the cache and return a match if found...
1157 for (lang
= _cupsGlobals()->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
1159 DEBUG_printf(("cups_cache_lookup: lang=%p, language=\"%s\", encoding=%d(%s)\n",
1160 lang
, lang
->language
, lang
->encoding
,
1161 lang_encodings
[lang
->encoding
]));
1163 if (!strcmp(lang
->language
, name
) &&
1164 (encoding
== CUPS_AUTO_ENCODING
|| encoding
== lang
->encoding
))
1168 DEBUG_puts("cups_cache_lookup: returning match!");
1174 DEBUG_puts("cups_cache_lookup: returning NULL!");
1181 * 'cups_message_compare()' - Compare two messages.
1184 static int /* O - Result of comparison */
1185 cups_message_compare(
1186 _cups_message_t
*m1
, /* I - First message */
1187 _cups_message_t
*m2
) /* I - Second message */
1189 return (strcmp(m1
->id
, m2
->id
));
1194 * 'cups_unquote()' - Unquote characters in strings...
1198 cups_unquote(char *d
, /* O - Unquoted string */
1199 const char *s
) /* I - Original string */
1212 *d
= *d
* 8 + *s
- '0';
1239 * End of "$Id: language.c 4922 2006-01-12 22:05:06Z mike $".