/*
- * "$Id: language.c 6188 2007-01-10 16:23:06Z mike $"
+ * "$Id: language.c 6916 2007-09-05 21:14:08Z mike $"
*
* I18N/language support for the Common UNIX Printing System (CUPS).
*
+ * Copyright 2007-2008 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* This file is subject to the Apple OS-Developed Software exception.
*
* Contents:
*
+ * _cupsAppleLanguage() - Get the Apple language identifier associated
+ * with a locale ID.
* _cupsEncodingName() - Return the character encoding name string
* for the given encoding enumeration.
* cupsLangDefault() - Return the default language.
#endif /* HAVE_PTHREAD_H */
static cups_lang_t *lang_cache = NULL;
/* Language string cache */
-
-
-/*
- * Local functions...
- */
-
-#ifdef __APPLE__
-static const char *appleLangDefault(void);
-#endif /* __APPLE__ */
-static cups_lang_t *cups_cache_lookup(const char *name,
- cups_encoding_t encoding);
-static int cups_message_compare(_cups_message_t *m1,
- _cups_message_t *m2);
-static void cups_unquote(char *d, const char *s);
-
-
-/*
- * Local globals...
- */
-
static const char * const lang_encodings[] =
{ /* Encoding strings */
"us-ascii", "iso-8859-1",
"euc-kr", "euc-tw"
};
+#ifdef __APPLE__
+typedef struct
+{
+ const char * const language; /* Language ID */
+ const char * const locale; /* Locale ID */
+} _apple_language_locale_t;
+
+static const _apple_language_locale_t apple_language_locale[] =
+{ /* Locale to language ID LUT */
+ { "en" , "en_US" },
+ { "nb" , "no" },
+ { "zh-Hans" , "zh_CN" },
+ { "zh-Hant" , "zh_TW" }
+};
+#endif /* __APPLE__ */
+
+
+/*
+ * Local functions...
+ */
+
+#ifdef __APPLE__
+static const char *appleLangDefault(void);
+#endif /* __APPLE__ */
+static cups_lang_t *cups_cache_lookup(const char *name,
+ cups_encoding_t encoding);
+static int cups_message_compare(_cups_message_t *m1,
+ _cups_message_t *m2);
+static void cups_unquote(char *d, const char *s);
+
+
+#ifdef __APPLE__
+/*
+ * _cupsAppleLanguage() - Get the Apple language identifier associated
+ * with a locale ID.
+ */
+
+const char * /* O - Language ID */
+_cupsAppleLanguage(const char *locale, /* I - Locale ID */
+ char *language,/* I - Language ID buffer */
+ size_t langsize) /* I - Size of language ID buffer */
+{
+ int i; /* Looping var */
+ CFStringRef localeid, /* CF locale identifier */
+ langid; /* CF language identifier */
+
+
+ /*
+ * Copy the locale name and convert, as needed, to the Apple-specific
+ * locale identifier...
+ */
+
+ switch (strlen(locale))
+ {
+ default :
+ /*
+ * Invalid locale...
+ */
+
+ strlcpy(language, "en", langsize);
+ break;
+
+ case 2 :
+ strlcpy(language, locale, langsize);
+ break;
+
+ case 5 :
+ strlcpy(language, locale, langsize);
+
+ if (language[2] == '-')
+ {
+ /*
+ * Convert ll-cc to ll_CC...
+ */
+
+ language[2] = '_';
+ language[3] = toupper(language[3] & 255);
+ language[4] = toupper(language[4] & 255);
+ }
+ break;
+ }
+
+ for (i = 0;
+ i < (int)(sizeof(apple_language_locale) /
+ sizeof(apple_language_locale[0]));
+ i ++)
+ if (!strcmp(locale, apple_language_locale[i].locale))
+ {
+ strlcpy(language, apple_language_locale[i].language, sizeof(language));
+ break;
+ }
+
+ /*
+ * Attempt to map the locale ID to a language ID...
+ */
+
+ if ((localeid = CFStringCreateWithCString(kCFAllocatorDefault, language,
+ kCFStringEncodingASCII)) != NULL)
+ {
+ if ((langid = CFLocaleCreateCanonicalLanguageIdentifierFromString(
+ kCFAllocatorDefault, localeid)) != NULL)
+ {
+ CFStringGetCString(langid, language, langsize, kCFStringEncodingASCII);
+ CFRelease(langid);
+ }
+
+ CFRelease(localeid);
+ }
+
+ /*
+ * Return what we got...
+ */
+
+ return (language);
+}
+#endif /* __APPLE__ */
+
/*
* '_cupsEncodingName()' - Return the character encoding name string
/*
* 'cupsLangFree()' - Free language data.
*
- * This does not actually free anything; use cupsLangFlush() for that.
+ * This does not actually free anything; use @link cupsLangFlush@ for that.
*/
void
* preference so we have to look it up this way...
*/
- if (!language)
+ if (!language && (language = getenv("LANG")) == NULL)
language = appleLangDefault();
#else
strlcpy(locale, ptr, sizeof(locale));
language = locale;
- DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n",
- language ? language : "(null)"));
+ /*
+ * CUPS STR #2575: Map "nb" to "no" for back-compatibility...
+ */
+
+ if (!strncmp(locale, "nb", 2))
+ locale[1] = 'o';
+
+ DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n", language));
}
}
#endif /* __APPLE__ */
pthread_mutex_lock(&lang_mutex);
#endif /* HAVE_PTHREAD_H */
- if ((lang = cups_cache_lookup(langname, encoding)) != NULL)
+ if ((lang = cups_cache_lookup(real, encoding)) != NULL)
{
#ifdef HAVE_PTHREAD_H
pthread_mutex_unlock(&lang_mutex);
return (a);
}
- m->id = strdup(ptr);
+ if ((m->id = strdup(ptr)) == NULL)
+ {
+ free(m);
+ cupsFileClose(fp);
+ return (a);
+ }
}
else if (s[0] == '\"' && m)
{
* Set the string...
*/
- m->str = strdup(ptr);
+ if ((m->str = strdup(ptr)) == NULL)
+ {
+ cupsFileClose(fp);
+ return (a);
+ }
}
}
#ifdef __APPLE__
-/*
- * Code & data to translate OSX's language names to their ISO 639-1 locale.
- *
- * The first version uses the new CoreFoundation API added in 10.3 (Panther),
- * the second is for 10.2 (Jaguar).
- */
-
-# ifdef HAVE_CF_LOCALE_ID
/*
* 'appleLangDefault()' - Get the default locale string.
*/
static const char * /* O - Locale string */
appleLangDefault(void)
{
+ int i; /* Looping var */
+ CFBundleRef bundle; /* Main bundle (if any) */
+ CFArrayRef bundleList; /* List of localizations in bundle */
CFPropertyListRef localizationList;
/* List of localization data */
CFStringRef languageName; /* Current name */
if (!cg->language[0])
{
if ((lang = getenv("LANG")))
+ {
strlcpy(cg->language, lang, sizeof(cg->language));
- else
+ return (cg->language);
+ }
+ else if ((bundle = CFBundleGetMainBundle()) != NULL &&
+ (bundleList = CFBundleCopyBundleLocalizations(bundle)) != NULL)
{
localizationList =
- CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
- kCFPreferencesCurrentApplication);
-
- if (localizationList != NULL)
- {
- if (CFGetTypeID(localizationList) == CFArrayGetTypeID() &&
- CFArrayGetCount(localizationList) > 0)
- {
- languageName = CFArrayGetValueAtIndex(localizationList, 0);
-
- if (languageName != NULL &&
- CFGetTypeID(languageName) == CFStringGetTypeID())
- {
- localeName = CFLocaleCreateCanonicalLocaleIdentifierFromString(
- kCFAllocatorDefault, languageName);
-
- if (localeName != NULL)
- {
- CFStringGetCString(localeName, cg->language, sizeof(cg->language),
- kCFStringEncodingASCII);
- CFRelease(localeName);
-
- if (!strcmp(cg->language, "en"))
- strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language));
- else if (strchr(cg->language, '.') == NULL)
- strlcat(cg->language, ".UTF-8", sizeof(cg->language));
- }
- }
- }
+ CFBundleCopyPreferredLocalizationsFromArray(bundleList);
- CFRelease(localizationList);
- }
+ CFRelease(bundleList);
}
-
- /*
- * If we didn't find the language, default to en_US...
- */
-
- if (!cg->language[0])
- strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language));
- }
-
- /*
- * Return the cached locale...
- */
-
- return (cg->language);
-}
-# else
-/*
- * Code & data to translate OSX 10.2's language names to their ISO 639-1
- * locale.
- */
-
-typedef struct
-{
- const char * const name; /* Language name */
- const char * const locale; /* Locale name */
-} _apple_name_locale_t;
-
-static const _apple_name_locale_t apple_name_locale[] =
-{
- { "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" },
- { "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" },
- { "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" },
- { "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" },
- { "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" },
- { "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" },
- { "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" },
- { "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" },
- { "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" },
- { "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" },
- { "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" },
- { "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" },
- { "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" },
- { "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" },
- { "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" },
- { "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" },
- { "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" },
- { "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" },
- { "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" },
- { "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" },
- { "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" },
- { "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" },
- { "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" },
- { "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" },
- { "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" },
- { "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" },
- { "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" },
- { "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" },
- { "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" },
- { "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" },
- { "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" },
- { "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" },
- { "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" },
- { "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" },
- { "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" },
- { "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" },
- { "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" },
- { "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" },
- { "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" },
- { "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" },
- { "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" },
- { "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" },
- { "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" },
- { "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" },
- { "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" },
- { "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" },
- { "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" },
- { "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" },
- { "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" },
- { "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" },
- { "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" },
- { "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" },
- { "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" },
- { "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" },
- { "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" },
- { "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" },
- { "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" },
- { "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" },
- { "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" }
-};
-
-
-/*
- * 'appleLangDefault()' - Get the default locale string.
- */
-
-static const char * /* O - Locale string */
-appleLangDefault(void)
-{
- int i; /* Looping var */
- CFPropertyListRef localizationList;
- /* List of localization data */
- CFStringRef localizationName;
- /* Current name */
- char buff[256]; /* Temporary buffer */
- _cups_globals_t *cg = _cupsGlobals();
- /* Pointer to library globals */
- char *lang; /* LANG environment variable */
-
-
- /*
- * Only do the lookup and translation the first time.
- */
-
- if (!cg->language[0])
- {
- if ((lang = getenv("LANG")))
- strlcpy(cg->language, lang, sizeof(cg->language));
else
- {
localizationList =
- CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
- kCFPreferencesCurrentApplication);
+ CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
+ kCFPreferencesCurrentApplication);
- if (localizationList != NULL)
+ if (localizationList)
+ {
+ if (CFGetTypeID(localizationList) == CFArrayGetTypeID() &&
+ CFArrayGetCount(localizationList) > 0)
{
- if (CFGetTypeID(localizationList) == CFArrayGetTypeID() &&
- CFArrayGetCount(localizationList) > 0)
+ languageName = CFArrayGetValueAtIndex(localizationList, 0);
+
+ if (languageName &&
+ CFGetTypeID(languageName) == CFStringGetTypeID())
{
- localizationName = CFArrayGetValueAtIndex(localizationList, 0);
+ localeName = CFLocaleCreateCanonicalLocaleIdentifierFromString(
+ kCFAllocatorDefault, languageName);
- if (localizationName != NULL &&
- CFGetTypeID(localizationName) == CFStringGetTypeID())
+ if (localeName)
{
- CFIndex length = CFStringGetLength(localizationName);
+ CFStringGetCString(localeName, cg->language, sizeof(cg->language),
+ kCFStringEncodingASCII);
+ CFRelease(localeName);
- if (length <= sizeof(buff) &&
- CFStringGetCString(localizationName, buff, sizeof(buff),
- kCFStringEncodingASCII))
- {
- buff[sizeof(buff) - 1] = '\0';
+ DEBUG_printf(("appleLangDefault: cg->language=\"%s\"\n",
+ cg->language));
+
+ /*
+ * Map new language identifiers to locales...
+ */
- for (i = 0;
- i < sizeof(apple_name_locale) / sizeof(apple_name_locale[0]);
- i++)
+ for (i = 0;
+ i < (int)(sizeof(apple_language_locale) /
+ sizeof(apple_language_locale[0]));
+ i ++)
+ {
+ if (!strcmp(cg->language, apple_language_locale[i].language))
{
- if (!strcasecmp(buff, apple_name_locale[i].name))
- {
- strlcpy(cg->language, apple_name_locale[i].locale,
- sizeof(cg->language));
- break;
- }
+ DEBUG_printf(("appleLangDefault: mapping \"%s\" to \"%s\"...\n",
+ cg->language, apple_language_locale[i].locale));
+ strlcpy(cg->language, apple_language_locale[i].locale,
+ sizeof(cg->language));
+ break;
}
}
+
+ /*
+ * Convert language subtag into region subtag...
+ */
+
+ if (cg->language[2] == '-')
+ cg->language[2] = '_';
+
+ if (!strchr(cg->language, '.'))
+ strlcat(cg->language, ".UTF-8", sizeof(cg->language));
}
}
-
- CFRelease(localizationList);
}
+
+ CFRelease(localizationList);
}
/*
*/
if (!cg->language[0])
- strlcpy(cg->language, apple_name_locale[0].locale, sizeof(cg->language));
+ strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language));
}
/*
return (cg->language);
}
-# endif /* HAVE_CF_LOCALE_ID */
#endif /* __APPLE__ */
/*
- * End of "$Id: language.c 6188 2007-01-10 16:23:06Z mike $".
+ * End of "$Id: language.c 6916 2007-09-05 21:14:08Z mike $".
*/