summaryrefslogtreecommitdiff
path: root/src/corefx/System.Globalization.Native
diff options
context:
space:
mode:
Diffstat (limited to 'src/corefx/System.Globalization.Native')
-rw-r--r--src/corefx/System.Globalization.Native/locale.cpp39
-rw-r--r--src/corefx/System.Globalization.Native/locale.hpp9
-rw-r--r--src/corefx/System.Globalization.Native/localeStringData.cpp4
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);