if (localeName != NULL)
{
- int32_t len = u_strlen(localeName);
- u_UCharsToChars(localeName, localeNameTemp, len + 1);
+ // use UnicodeString.extract instead of u_UCharsToChars; u_UCharsToChars considers '@' a variant and stops
+ UnicodeString str(localeName, -1, ULOC_FULLNAME_CAPACITY);
+ str.extract(0, str.length(), localeNameTemp);
}
Locale loc;
return U_ZERO_ERROR;
}
-void FixupLocaleName(UChar* value, int32_t valueLength)
+int FixupLocaleName(UChar* value, int32_t valueLength)
{
- for (int i = 0; i < valueLength; i++)
+ int i = 0;
+ for (; i < valueLength; i++)
{
if (value[i] == (UChar)'\0')
{
value[i] = (UChar)'-';
}
}
-}
+ return i;
+}
extern "C" int32_t GetLocaleName(const UChar* localeName, UChar* value, int32_t valueLength)
{
return UErrorCodeToBool(status);
}
+
+extern "C" int32_t GetDefaultLocaleName(UChar* value, int32_t valueLength)
+{
+ Locale locale = GetLocale(NULL);
+ if (locale.isBogus())
+ {
+ // ICU should be able to get default locale
+ return UErrorCodeToBool(U_INTERNAL_PROGRAM_ERROR);
+ }
+
+ UErrorCode status = u_charsToUChars_safe(locale.getBaseName(), value, valueLength);
+ if (U_SUCCESS(status))
+ {
+ int localeNameLen = FixupLocaleName(value, valueLength);
+
+ // if collation is present, return that to managed side
+ char collationValueTemp[ULOC_KEYWORDS_CAPACITY];
+ if (locale.getKeywordValue("collation", collationValueTemp, ULOC_KEYWORDS_CAPACITY, status) > 0)
+ {
+ // copy the collation; managed uses a "_" to represent collation (not "@collation=")
+ status = u_charsToUChars_safe("_", &value[localeNameLen], valueLength - localeNameLen);
+ if (U_SUCCESS(status))
+ {
+ status = u_charsToUChars_safe(collationValueTemp, &value[localeNameLen + 1], valueLength - localeNameLen - 1);
+ }
+ }
+ }
+
+ return UErrorCodeToBool(status);
+}
+
{
internal partial class CultureData
{
- // Win32 constants
- const string LOCALE_NAME_SYSTEM_DEFAULT = @"!x-sys-default-locale";
-
// ICU constants
const int ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY = 100; // max size of keyword or value
const int ICU_ULOC_FULLNAME_CAPACITY = 157; // max size of locale name
Contract.Assert(this.sRealName != null);
string alternateSortName = string.Empty;
- string realNameBuffer = null;
- int index;
+ string realNameBuffer = this.sRealName;
- bool useSystemDefault = (this.sRealName == LOCALE_NAME_SYSTEM_DEFAULT);
- if (!useSystemDefault) //ICU uses null to obtain the default (system) locale
+ // Basic validation
+ if (realNameBuffer.Contains("@"))
{
- realNameBuffer = this.sRealName;
-
- // Basic validation
- if (realNameBuffer.Contains("@"))
- {
- return false; // don't allow ICU variants to come in directly
- }
+ return false; // don't allow ICU variants to come in directly
+ }
- // Replace _ (alternate sort) with @collation= for ICU
- index = realNameBuffer.IndexOf('_');
- if (index > 0)
+ // Replace _ (alternate sort) with @collation= for ICU
+ int index = realNameBuffer.IndexOf('_');
+ if (index > 0)
+ {
+ if (index >= (realNameBuffer.Length - 1) // must have characters after _
+ || realNameBuffer.Substring(index + 1).Contains("_")) // only one _ allowed
{
- if (index >= (realNameBuffer.Length - 1) // must have characters after _
- || realNameBuffer.Substring(index + 1).Contains("_")) // only one _ allowed
- {
- return false; // fail
- }
- alternateSortName = realNameBuffer.Substring(index + 1);
- realNameBuffer = realNameBuffer.Substring(0, index) + ICU_COLLATION_KEYWORD + alternateSortName;
+ return false; // fail
}
+ alternateSortName = realNameBuffer.Substring(index + 1);
+ realNameBuffer = realNameBuffer.Substring(0, index) + ICU_COLLATION_KEYWORD + alternateSortName;
}
// Get the locale name from ICU
- StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_FULLNAME_CAPACITY);
- if (!Interop.GlobalizationInterop.GetLocaleName(realNameBuffer, sb, sb.Capacity))
+ if (!GetLocaleName(realNameBuffer, out this.sWindowsName))
{
- StringBuilderCache.Release(sb);
return false; // fail
}
- // Success - use the locale name returned which may be different than realNameBuffer (casing)
- this.sWindowsName = StringBuilderCache.GetStringAndRelease(sb); // the name passed to subsequent ICU calls
-
// Replace the ICU collation keyword with an _
- index = realNameBuffer.IndexOf(ICU_COLLATION_KEYWORD, StringComparison.Ordinal);
+ index = this.sWindowsName.IndexOf(ICU_COLLATION_KEYWORD, StringComparison.Ordinal);
if (index >= 0)
{
this.sName = this.sWindowsName.Substring(0, index) + "_" + alternateSortName;
{
this.sName = this.sWindowsName;
}
-
this.sRealName = this.sName;
this.sSpecificCulture = this.sRealName; // we don't attempt to find a non-neutral locale if a neutral is passed in (unlike win32)
this.iLanguage = this.ILANGUAGE;
if (this.iLanguage == 0)
{
- if (useSystemDefault)
- {
- this.iLanguage = LOCALE_CUSTOM_DEFAULT;
- }
- else
- {
- this.iLanguage = LOCALE_CUSTOM_UNSPECIFIED;
- }
+ this.iLanguage = LOCALE_CUSTOM_UNSPECIFIED;
}
this.bNeutral = (this.SISO3166CTRYNAME.Length == 0);
this.sName = this.sWindowsName.Substring(0, index);
}
}
+ return true;
+ }
+ internal static bool GetLocaleName(string localeName, out string windowsName)
+ {
+ // Get the locale name from ICU
+ StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_FULLNAME_CAPACITY);
+ if (!Interop.GlobalizationInterop.GetLocaleName(localeName, sb, sb.Capacity))
+ {
+ StringBuilderCache.Release(sb);
+ windowsName = null;
+ return false; // fail
+ }
+
+ // Success - use the locale name returned which may be different than realNameBuffer (casing)
+ windowsName = StringBuilderCache.GetStringAndRelease(sb); // the name passed to subsequent ICU calls
+ return true;
+ }
+
+ internal static bool GetDefaultLocaleName(out string windowsName)
+ {
+ // Get the default (system) locale name from ICU
+ StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_FULLNAME_CAPACITY);
+ if (!Interop.GlobalizationInterop.GetDefaultLocaleName(sb, sb.Capacity))
+ {
+ StringBuilderCache.Release(sb);
+ windowsName = null;
+ return false; // fail
+ }
+
+ // Success - use the locale name returned which may be different than realNameBuffer (casing)
+ windowsName = StringBuilderCache.GetStringAndRelease(sb); // the name passed to subsequent ICU calls
return true;
}
-
+
private string GetLocaleInfo(LocaleStringData type)
{
Contract.Assert(this.sWindowsName != null, "[CultureData.GetLocaleInfo] Expected this.sWindowsName to be populated already");
private static CultureInfo GetUserDefaultCulture()
{
- return new CultureInfo(LOCALE_NAME_SYSTEM_DEFAULT);
+ return CultureInfo.GetUserDefaultCulture();
}
}
}
{
public partial class CultureInfo : IFormatProvider
{
- /// <summary>
- /// Gets the default user culture from WinRT, if available.
- /// </summary>
- /// <remarks>
- /// This method may return null, if there is no default user culture or if WinRT isn't available.
- /// </remarks>
private static CultureInfo GetUserDefaultCultureCacheOverride()
{
- // TODO: Implement this fully.
- return null;
+ return null; // ICU doesn't provide a user override
}
- private static CultureInfo GetUserDefaultCulture()
+ internal static CultureInfo GetUserDefaultCulture()
{
- // TODO: Implement this fully.
- return CultureInfo.InvariantCulture;
+ CultureInfo cultureInfo = null;
+ string localeName;
+ if (CultureData.GetDefaultLocaleName(out localeName))
+ {
+ cultureInfo = GetCultureByName(localeName, true);
+ cultureInfo.m_isReadOnly = true;
+ }
+ else
+ {
+ cultureInfo = CultureInfo.InvariantCulture;
+ }
+
+ return cultureInfo;
}
}
-}
\ No newline at end of file
+}