2 * "$Id: language.c 5243 2006-03-08 02:29:48Z 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 */
269 char locale
[255]; /* Copy of locale name */
270 #endif /* !__APPLE__ */
271 char langname
[16], /* Requested language name */
272 country
[16], /* Country code */
273 charset
[16], /* Character set */
274 *csptr
, /* Pointer to CODESET string */
275 *ptr
, /* Pointer into language/charset */
276 real
[48], /* Real language name */
277 filename
[1024]; /* Filename for language locale file */
278 cups_encoding_t encoding
; /* Encoding to use */
279 cups_lang_t
*lang
; /* Current language... */
280 _cups_globals_t
*cg
= _cupsGlobals();
281 /* Pointer to library globals */
282 static const char * const locale_encodings
[] =
283 { /* Locale charset names */
284 "ASCII", "ISO88591", "ISO88592", "ISO88593",
285 "ISO88594", "ISO88595", "ISO88596", "ISO88597",
286 "ISO88598", "ISO88599", "ISO885910", "UTF8",
287 "ISO885913", "ISO885914", "ISO885915", "CP874",
288 "CP1250", "CP1251", "CP1252", "CP1253",
289 "CP1254", "CP1255", "CP1256", "CP1257",
290 "CP1258", "KOI8R", "KOI8U", "ISO885911",
291 "ISO885916", "MACROMAN", "", "",
302 "CP932", "CP936", "CP949", "CP950",
303 "CP1361", "", "", "",
320 "EUCCN", "EUCJP", "EUCKR", "EUCTW"
324 DEBUG_printf(("cupsLangGet(language=\"%s\")\n", language
? language
: "(null)"));
328 * Set the character set to UTF-8...
331 strcpy(charset
, "UTF8");
334 * Apple's setlocale doesn't give us the user's localization
335 * preference so we have to look it up this way...
339 language
= appleLangDefault();
343 * Set the charset to "unknown"...
349 * Use setlocale() to determine the currently set locale, and then
350 * fallback to environment variables to avoid setting the locale,
351 * since setlocale() is not thread-safe!
357 * First see if the locale has been set; if it is still "C" or
358 * "POSIX", use the environment to get the default...
362 ptr
= setlocale(LC_MESSAGES
, NULL
);
364 ptr
= setlocale(LC_ALL
, NULL
);
365 # endif /* LC_MESSAGES */
367 DEBUG_printf(("cupsLangGet: current locale is \"%s\"\n",
368 ptr
? ptr
: "(null)"));
370 if (!ptr
|| !strcmp(ptr
, "C") || !strcmp(ptr
, "POSIX"))
373 * Get the character set from the LC_CTYPE locale setting...
376 if ((ptr
= getenv("LC_CTYPE")) == NULL
)
377 if ((ptr
= getenv("LC_ALL")) == NULL
)
378 if ((ptr
= getenv("LANG")) == NULL
)
381 if ((csptr
= strchr(ptr
, '.')) != NULL
)
384 * Extract the character set from the environment...
387 for (ptr
= charset
, csptr
++; *csptr
; csptr
++)
388 if (ptr
< (charset
+ sizeof(charset
) - 1) && isalnum(*csptr
& 255))
396 * Default to UTF-8...
399 strcpy(charset
, "UTF8");
403 * Get the locale for messages from the LC_MESSAGES locale setting...
406 if ((ptr
= getenv("LC_MESSAGES")) == NULL
)
407 if ((ptr
= getenv("LC_ALL")) == NULL
)
408 if ((ptr
= getenv("LANG")) == NULL
)
414 strlcpy(locale
, ptr
, sizeof(locale
));
417 DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n",
418 language
? language
: "(null)"));
421 #endif /* __APPLE__ */
424 * If "language" is NULL at this point, then chances are we are using
425 * a language that is not installed for the base OS.
431 * Switch to the POSIX ("C") locale...
439 * On systems that support the nl_langinfo(CODESET) call, use
440 * this value as the character set...
443 if (!charset
[0] && (csptr
= nl_langinfo(CODESET
)) != NULL
)
446 * Copy all of the letters and numbers in the CODESET string...
449 for (ptr
= charset
; *csptr
; csptr
++)
450 if (isalnum(*csptr
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
455 DEBUG_printf(("cupsLangGet: charset set to \"%s\" via nl_langinfo(CODESET)...\n",
461 * Parse the language string passed in to a locale string. "C" is the
462 * standard POSIX locale and is copied unchanged. Otherwise the
463 * language string is converted from ll-cc[.charset] (language-country)
464 * to ll_CC[.CHARSET] to match the file naming convention used by all
465 * POSIX-compliant operating systems. Invalid language names are mapped
466 * to the POSIX locale.
471 if (language
== NULL
|| !language
[0] ||
472 !strcmp(language
, "POSIX"))
473 strcpy(langname
, "C");
477 * Copy the parts of the locale string over safely...
480 for (ptr
= langname
; *language
; language
++)
481 if (*language
== '_' || *language
== '-' || *language
== '.')
483 else if (ptr
< (langname
+ sizeof(langname
) - 1))
484 *ptr
++ = tolower(*language
& 255);
488 if (*language
== '_' || *language
== '-')
491 * Copy the country code...
494 for (language
++, ptr
= country
; *language
; language
++)
495 if (*language
== '.')
497 else if (ptr
< (country
+ sizeof(country
) - 1))
498 *ptr
++ = toupper(*language
& 255);
503 if (*language
== '.' && !charset
[0])
506 * Copy the encoding...
509 for (language
++, ptr
= charset
; *language
; language
++)
510 if (isalnum(*language
& 255) && ptr
< (charset
+ sizeof(charset
) - 1))
511 *ptr
++ = toupper(*language
& 255);
517 * Force a POSIX locale for an invalid language name...
520 if (strlen(langname
) != 2)
522 strcpy(langname
, "C");
528 DEBUG_printf(("cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"\n",
529 langname
, country
, charset
));
532 * Figure out the desired encoding...
535 encoding
= CUPS_AUTO_ENCODING
;
540 i
< (int)(sizeof(locale_encodings
) / sizeof(locale_encodings
[0]));
542 if (!strcasecmp(charset
, locale_encodings
[i
]))
544 encoding
= (cups_encoding_t
)i
;
549 DEBUG_printf(("cupsLangGet: encoding=%d(%s)\n", encoding
,
550 encoding
== CUPS_AUTO_ENCODING
? "auto" :
551 lang_encodings
[encoding
]));
554 * See if we already have this language/country loaded...
559 snprintf(real
, sizeof(real
), "%s_%s", langname
, country
);
561 if ((lang
= cups_cache_lookup(real
, encoding
)) != NULL
)
564 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s.po", cg
->localedir
,
568 filename
[0] = '\0'; /* anti-compiler-warning-code */
570 if (!country
[0] || access(filename
, 0))
573 * Country localization not available, look for generic localization...
576 if ((lang
= cups_cache_lookup(langname
, encoding
)) != NULL
)
579 snprintf(filename
, sizeof(filename
), "%s/%s/cups_%s.po", cg
->localedir
,
582 if (access(filename
, 0))
585 * No generic localization, so use POSIX...
588 DEBUG_printf(("access(\"%s\", 0): %s\n", filename
, strerror(errno
)));
591 snprintf(filename
, sizeof(filename
), "%s/C/cups_C.po", cg
->localedir
);
594 strcpy(real
, langname
);
598 * See if there is a free language available; if so, use that
602 for (lang
= cg
->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
609 * Allocate memory for the language and add it to the cache.
612 if ((lang
= calloc(sizeof(cups_lang_t
), 1)) == NULL
)
615 lang
->next
= cg
->lang_cache
;
616 cg
->lang_cache
= lang
;
621 * Free all old strings as needed...
624 _cupsMessageFree(lang
->strings
);
628 * Then assign the language and encoding fields...
632 strlcpy(lang
->language
, real
, sizeof(lang
->language
));
634 if (encoding
!= CUPS_AUTO_ENCODING
)
635 lang
->encoding
= encoding
;
637 lang
->encoding
= CUPS_UTF8
;
640 * Read the strings from the file...
643 lang
->strings
= _cupsMessageLoad(filename
);
654 * '_cupsLangString()' - Get a message string.
656 * The returned string is UTF-8 encoded; use cupsUTF8ToCharset() to
657 * convert the string to the language encoding.
660 const char * /* O - Localized message */
661 _cupsLangString(cups_lang_t
*lang
, /* I - Language */
662 const char *message
) /* I - Message */
665 * Range check input...
668 if (!lang
|| !message
)
671 return (_cupsMessageLookup(lang
->strings
, message
));
676 * '_cupsMessageFree()' - Free a messages array.
680 _cupsMessageFree(cups_array_t
*a
) /* I - Message array */
682 _cups_message_t
*m
; /* Current message */
685 for (m
= (_cups_message_t
*)cupsArrayFirst(a
);
687 m
= (_cups_message_t
*)cupsArrayNext(a
))
690 * Remove the message from the array, then free the message and strings.
693 cupsArrayRemove(a
, m
);
713 * '_cupsMessageLoad()' - Load a .po file into a messages array.
716 cups_array_t
* /* O - New message array */
717 _cupsMessageLoad(const char *filename
) /* I - Message catalog to load */
719 cups_file_t
*fp
; /* Message file */
720 cups_array_t
*a
; /* Message array */
721 _cups_message_t
*m
; /* Current message */
722 char s
[4096], /* String buffer */
723 *ptr
, /* Pointer into buffer */
724 *temp
; /* New string */
725 int length
; /* Length of combined strings */
728 DEBUG_printf(("_cupsMessageLoad(filename=\"%s\")\n", filename
));
731 * Create an array to hold the messages...
734 if ((a
= cupsArrayNew((cups_array_func_t
)cups_message_compare
, NULL
)) == NULL
)
738 * Open the message catalog file...
741 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
745 * Read messages from the catalog file until EOF...
747 * The format is the GNU gettext .po format, which is fairly simple:
750 * msgstr "localized text"
752 * The ID and localized text can span multiple lines using the form:
757 * "localized text spanning "
763 while (cupsFileGets(fp
, s
, sizeof(s
)) != NULL
)
766 * Skip blank and comment lines...
769 if (s
[0] == '#' || !s
[0])
773 * Strip the trailing quote...
776 if ((ptr
= strrchr(s
, '\"')) == NULL
)
782 * Find start of value...
785 if ((ptr
= strchr(s
, '\"')) == NULL
)
791 * Unquote the text...
794 cups_unquote(ptr
, ptr
);
797 * Create or add to a message...
800 if (!strncmp(s
, "msgid", 5))
803 * Add previous message as needed...
810 * Create a new message with the given msgid string...
813 if ((m
= (_cups_message_t
*)calloc(1, sizeof(_cups_message_t
))) == NULL
)
821 else if (s
[0] == '\"' && m
)
824 * Append to current string...
827 length
= strlen(m
->str
? m
->str
: m
->id
);
829 if ((temp
= realloc(m
->str
? m
->str
: m
->id
,
830 length
+ strlen(ptr
) + 1)) == NULL
)
839 * Copy the new portion to the end of the msgstr string - safe
840 * to use strcpy because the buffer is allocated to the correct
846 strcpy(m
->str
+ length
, ptr
);
851 * Copy the new portion to the end of the msgid string - safe
852 * to use strcpy because the buffer is allocated to the correct
858 strcpy(m
->id
+ length
, ptr
);
861 else if (!strncmp(s
, "msgstr", 6) && m
)
867 m
->str
= strdup(ptr
);
872 * Add the last message string to the array as needed...
879 * Close the message catalog file and return the new array...
889 * '_cupsMessageLookup()' - Lookup a message string.
892 const char * /* O - Localized message */
893 _cupsMessageLookup(cups_array_t
*a
, /* I - Message array */
894 const char *m
) /* I - Message */
896 _cups_message_t key
, /* Search key */
897 *match
; /* Matching message */
901 * Lookup the message string; if it doesn't exist in the catalog,
902 * then return the message that was passed to us...
906 match
= (_cups_message_t
*)cupsArrayFind(a
, &key
);
908 if (match
&& match
->str
)
917 * Code & data to translate OSX's language names to their ISO 639-1 locale.
919 * The first version uses the new CoreFoundation API added in 10.3 (Panther),
920 * the second is for 10.2 (Jaguar).
923 # ifdef HAVE_CF_LOCALE_ID
925 * 'appleLangDefault()' - Get the default locale string.
928 static const char * /* O - Locale string */
929 appleLangDefault(void)
931 CFPropertyListRef localizationList
;
932 /* List of localization data */
933 CFStringRef languageName
; /* Current name */
934 CFStringRef localeName
; /* Canonical from of name */
935 _cups_globals_t
*cg
= _cupsGlobals();
936 /* Pointer to library globals */
940 * Only do the lookup and translation the first time.
943 if (!cg
->language
[0])
946 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
947 kCFPreferencesCurrentApplication
);
949 if (localizationList
!= NULL
)
951 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
952 CFArrayGetCount(localizationList
) > 0)
954 languageName
= CFArrayGetValueAtIndex(localizationList
, 0);
956 if (languageName
!= NULL
&&
957 CFGetTypeID(languageName
) == CFStringGetTypeID())
959 localeName
= CFLocaleCreateCanonicalLocaleIdentifierFromString(
960 kCFAllocatorDefault
, languageName
);
962 if (localeName
!= NULL
)
964 CFStringGetCString(localeName
, cg
->language
, sizeof(cg
->language
),
965 kCFStringEncodingASCII
);
966 CFRelease(localeName
);
968 if (!strcmp(cg
->language
, "en"))
969 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
970 else if (strchr(cg
->language
, '.') == NULL
)
971 strlcat(cg
->language
, ".UTF-8", sizeof(cg
->language
));
976 CFRelease(localizationList
);
980 * If we didn't find the language, default to en_US...
983 if (!cg
->language
[0])
984 strlcpy(cg
->language
, "en_US.UTF-8", sizeof(cg
->language
));
988 * Return the cached locale...
991 return (cg
->language
);
995 * Code & data to translate OSX 10.2's language names to their ISO 639-1
1001 const char * const name
; /* Language name */
1002 const char * const locale
; /* Locale name */
1003 } _apple_name_locale_t
;
1005 static const _apple_name_locale_t apple_name_locale
[] =
1007 { "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" },
1008 { "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" },
1009 { "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" },
1010 { "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" },
1011 { "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" },
1012 { "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" },
1013 { "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" },
1014 { "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" },
1015 { "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" },
1016 { "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1017 { "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" },
1018 { "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" },
1019 { "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" },
1020 { "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" },
1021 { "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" },
1022 { "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" },
1023 { "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" },
1024 { "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" },
1025 { "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" },
1026 { "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" },
1027 { "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" },
1028 { "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" },
1029 { "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" },
1030 { "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" },
1031 { "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" },
1032 { "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" },
1033 { "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" },
1034 { "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" },
1035 { "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" },
1036 { "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" },
1037 { "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" },
1038 { "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" },
1039 { "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" },
1040 { "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" },
1041 { "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" },
1042 { "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" },
1043 { "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" },
1044 { "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" },
1045 { "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" },
1046 { "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" },
1047 { "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" },
1048 { "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" },
1049 { "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" },
1050 { "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" },
1051 { "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" },
1052 { "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" },
1053 { "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" },
1054 { "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" },
1055 { "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" },
1056 { "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" },
1057 { "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" },
1058 { "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" },
1059 { "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" },
1060 { "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" },
1061 { "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" },
1062 { "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" },
1063 { "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" },
1064 { "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" },
1065 { "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" }
1070 * 'appleLangDefault()' - Get the default locale string.
1073 static const char * /* O - Locale string */
1074 appleLangDefault(void)
1076 int i
; /* Looping var */
1077 CFPropertyListRef localizationList
;
1078 /* List of localization data */
1079 CFStringRef localizationName
;
1081 char buff
[256]; /* Temporary buffer */
1082 _cups_globals_t
*cg
= _cupsGlobals();
1083 /* Pointer to library globals */
1087 * Only do the lookup and translation the first time.
1090 if (cg
->language
== NULL
)
1093 CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
1094 kCFPreferencesCurrentApplication
);
1096 if (localizationList
!= NULL
)
1098 if (CFGetTypeID(localizationList
) == CFArrayGetTypeID() &&
1099 CFArrayGetCount(localizationList
) > 0)
1101 localizationName
= CFArrayGetValueAtIndex(localizationList
, 0);
1103 if (localizationName
!= NULL
&&
1104 CFGetTypeID(localizationName
) == CFStringGetTypeID())
1106 CFIndex length
= CFStringGetLength(localizationName
);
1108 if (length
<= sizeof(buff
) &&
1109 CFStringGetCString(localizationName
, buff
, sizeof(buff
),
1110 kCFStringEncodingASCII
))
1112 buff
[sizeof(buff
) - 1] = '\0';
1115 i
< sizeof(apple_name_locale
) / sizeof(apple_name_locale
[0]);
1118 if (!strcasecmp(buff
, apple_name_locale
[i
].name
))
1120 cg
->language
= apple_name_locale
[i
].locale
;
1128 CFRelease(localizationList
);
1132 * If we didn't find the language, default to en_US...
1135 if (cg
->language
== NULL
)
1136 cg
->language
= apple_name_locale
[0].locale
;
1140 * Return the cached locale...
1143 return (cg
->language
);
1145 # endif /* HAVE_CF_LOCALE_ID */
1146 #endif /* __APPLE__ */
1150 * 'cups_cache_lookup()' - Lookup a language in the cache...
1153 static cups_lang_t
* /* O - Language data or NULL */
1154 cups_cache_lookup(const char *name
,/* I - Name of locale */
1155 cups_encoding_t encoding
)
1156 /* I - Encoding of locale */
1158 cups_lang_t
*lang
; /* Current language */
1161 DEBUG_printf(("cups_cache_lookup(name=\"%s\", encoding=%d(%s))\n", name
,
1162 encoding
, encoding
== CUPS_AUTO_ENCODING
? "auto" :
1163 lang_encodings
[encoding
]));
1166 * Loop through the cache and return a match if found...
1169 for (lang
= _cupsGlobals()->lang_cache
; lang
!= NULL
; lang
= lang
->next
)
1171 DEBUG_printf(("cups_cache_lookup: lang=%p, language=\"%s\", encoding=%d(%s)\n",
1172 lang
, lang
->language
, lang
->encoding
,
1173 lang_encodings
[lang
->encoding
]));
1175 if (!strcmp(lang
->language
, name
) &&
1176 (encoding
== CUPS_AUTO_ENCODING
|| encoding
== lang
->encoding
))
1180 DEBUG_puts("cups_cache_lookup: returning match!");
1186 DEBUG_puts("cups_cache_lookup: returning NULL!");
1193 * 'cups_message_compare()' - Compare two messages.
1196 static int /* O - Result of comparison */
1197 cups_message_compare(
1198 _cups_message_t
*m1
, /* I - First message */
1199 _cups_message_t
*m2
) /* I - Second message */
1201 return (strcmp(m1
->id
, m2
->id
));
1206 * 'cups_unquote()' - Unquote characters in strings...
1210 cups_unquote(char *d
, /* O - Unquoted string */
1211 const char *s
) /* I - Original string */
1224 *d
= *d
* 8 + *s
- '0';
1251 * End of "$Id: language.c 5243 2006-03-08 02:29:48Z mike $".