diff options
Diffstat (limited to 'src/corefx/System.Globalization.Native')
-rw-r--r-- | src/corefx/System.Globalization.Native/locale.cpp | 39 | ||||
-rw-r--r-- | src/corefx/System.Globalization.Native/locale.hpp | 9 | ||||
-rw-r--r-- | src/corefx/System.Globalization.Native/localeStringData.cpp | 4 |
3 files changed, 49 insertions, 3 deletions
diff --git a/src/corefx/System.Globalization.Native/locale.cpp b/src/corefx/System.Globalization.Native/locale.cpp index 3b5c860270..1cb564a45a 100644 --- a/src/corefx/System.Globalization.Native/locale.cpp +++ b/src/corefx/System.Globalization.Native/locale.cpp @@ -6,6 +6,8 @@ #include <assert.h> #include <stdint.h> #include <string.h> +#include <stdlib.h> +#include <locale.h> #include "locale.hpp" @@ -110,6 +112,41 @@ int32_t FixupLocaleName(UChar* value, int32_t valueLength) return i; } +bool IsEnvVarSet(const char* name) +{ + const char* value = getenv(name); + + return (value != nullptr) && (strcmp("", value) != 0); +} + +// The behavior of uloc_getDefault() on POSIX systems is to query +// setlocale(LC_MESSAGES) and use that value, unless it is C or +// POSIX. In that case it tries to read LC_ALL, LC_MESSAGES and LANG +// and then falls back to en_US_POSIX if none of them are set. +// +// en_US_POSIX is a weird locale since the collation rules treat 'a' +// and 'A' as different letters even when ignoring case. Furthermore +// it's common for LC_ALL, LC_MESSAGES and LANG to be unset when +// running under Docker. +// +// We'd rather default to invariant in this case. If any of these +// are set, we'll just call into ICU and let it do whatever +// normalization it would do. +const char* DetectDefaultLocaleName() +{ + char* loc = setlocale(LC_MESSAGES, nullptr); + + if (loc != nullptr && (strcmp("C", loc) == 0 || strcmp("POSIX", loc) == 0)) + { + if (!IsEnvVarSet("LC_ALL") && !IsEnvVarSet("LC_MESSAGES") && !IsEnvVarSet("LANG")) + { + return ""; + } + } + + return uloc_getDefault(); +} + extern "C" int32_t GlobalizationNative_GetLocaleName(const UChar* localeName, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; @@ -135,7 +172,7 @@ extern "C" int32_t GlobalizationNative_GetDefaultLocaleName(UChar* value, int32_ char localeNameBuffer[ULOC_FULLNAME_CAPACITY]; UErrorCode status = U_ZERO_ERROR; - const char* defaultLocale = uloc_getDefault(); + const char* defaultLocale = DetectDefaultLocaleName(); uloc_getBaseName(defaultLocale, localeNameBuffer, ULOC_FULLNAME_CAPACITY, &status); diff --git a/src/corefx/System.Globalization.Native/locale.hpp b/src/corefx/System.Globalization.Native/locale.hpp index ed87d86af0..4845859960 100644 --- a/src/corefx/System.Globalization.Native/locale.hpp +++ b/src/corefx/System.Globalization.Native/locale.hpp @@ -41,3 +41,12 @@ Replace underscores with hyphens to interop with existing .NET code. Returns the length of the string. */ int FixupLocaleName(UChar* value, int32_t valueLength); + +/* +Function: +DetectDefaultLocaleName + +Detect the default locale for the machine, defaulting to Invaraint if +we can't compute one (different from uloc_getDefault()) would do. +*/ +const char* DetectDefaultLocaleName(); diff --git a/src/corefx/System.Globalization.Native/localeStringData.cpp b/src/corefx/System.Globalization.Native/localeStringData.cpp index 6adb38f9ac..927da67095 100644 --- a/src/corefx/System.Globalization.Native/localeStringData.cpp +++ b/src/corefx/System.Globalization.Native/localeStringData.cpp @@ -179,7 +179,7 @@ extern "C" int32_t GlobalizationNative_GetLocaleInfoString( switch (localeStringData) { case LocalizedDisplayName: - uloc_getDisplayName(locale, uloc_getDefault(), value, valueLength, &status); + uloc_getDisplayName(locale, DetectDefaultLocaleName(), value, valueLength, &status); break; case EnglishDisplayName: uloc_getDisplayName(locale, ULOC_ENGLISH, value, valueLength, &status); @@ -188,7 +188,7 @@ extern "C" int32_t GlobalizationNative_GetLocaleInfoString( uloc_getDisplayName(locale, locale, value, valueLength, &status); break; case LocalizedLanguageName: - uloc_getDisplayLanguage(locale, uloc_getDefault(), value, valueLength, &status); + uloc_getDisplayLanguage(locale, DetectDefaultLocaleName(), value, valueLength, &status); break; case EnglishLanguageName: uloc_getDisplayLanguage(locale, ULOC_ENGLISH, value, valueLength, &status); |