3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 ////////////////////////////////////////////////////////////////////////////
11 // Purpose: This class represents the software preferences of a particular
12 // culture or community. It includes information such as the
13 // language, writing system, and a calendar used by the culture
14 // as well as methods for common operations such as printing
15 // dates and sorting strings.
17 // Date: Microsoft 31, 1999
20 // !!!! NOTE WHEN CHANGING THIS CLASS !!!!
22 // If adding or removing members to this class, please update CultureInfoBaseObject
23 // in ndp/clr/src/vm/object.h. Note, the "actual" layout of the class may be
24 // different than the order in which members are declared. For instance, all
25 // reference types will come first in the class before value types (like ints, bools, etc)
26 // regardless of the order in which they are declared. The best way to see the
27 // actual order of the class is to do a !dumpobj on an instance of the managed
28 // object inside of the debugger.
30 ////////////////////////////////////////////////////////////////////////////
32 namespace System
.Globalization
{
34 using System
.Security
;
35 using System
.Threading
;
36 using System
.Collections
;
38 using System
.Runtime
.CompilerServices
;
39 using System
.Runtime
.InteropServices
;
40 using System
.Runtime
.Serialization
;
41 using System
.Runtime
.Versioning
;
42 using System
.Security
.Permissions
;
43 using System
.Reflection
;
44 using Microsoft
.Win32
;
45 using System
.Diagnostics
.Contracts
;
46 using System
.Resources
;
49 [System
.Runtime
.InteropServices
.ComVisible(true)]
50 public class CultureInfo
: ICloneable
, IFormatProvider
{
51 //--------------------------------------------------------------------//
52 // Internal Information //
53 //--------------------------------------------------------------------//
55 //--------------------------------------------------------------------//
56 // Data members to be serialized:
57 //--------------------------------------------------------------------//
59 // We use an RFC4646 type string to construct CultureInfo.
60 // This string is stored in m_name and is authoritative.
61 // We use the m_cultureData to get the data for our object
64 // WARNING: All member fields declared here must also be in ndp/clr/src/vm/object.h
65 // WARNING: They aren't really private because object.h can access them, but other C# stuff cannot
66 // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureInfoBaseObject
67 // WARNING: must be manually structured to match the true loaded class layout
69 internal bool m_isReadOnly
;
70 internal CompareInfo compareInfo
;
71 internal TextInfo textInfo
;
72 // Not serialized for now since we only build it privately for use in the CARIB (so rebuilding is OK)
74 [NonSerialized
]internal RegionInfo regionInfo
;
76 internal NumberFormatInfo numInfo
;
77 internal DateTimeFormatInfo dateTimeInfo
;
78 internal Calendar calendar
;
80 [OptionalField(VersionAdded
= 1)]
81 internal int m_dataItem
; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett)
82 [OptionalField(VersionAdded
= 1)]
83 internal int cultureID
= 0x007f; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett)
84 #endif // !FEATURE_CORECLR
86 // The CultureData instance that we are going to read data from.
87 // For supported culture, this will be the CultureData instance that read data from mscorlib assembly.
88 // For customized culture, this will be the CultureData instance that read data from user customized culture binary file.
90 [NonSerialized
]internal CultureData m_cultureData
;
92 [NonSerialized
]internal bool m_isInherited
;
93 #if FEATURE_LEAK_CULTURE_INFO
94 [NonSerialized
]private bool m_isSafeCrossDomain
;
95 [NonSerialized
]private int m_createdDomainID
;
96 #endif // !FEATURE_CORECLR
98 [NonSerialized
]private CultureInfo m_consoleFallbackCulture
;
99 #endif // !FEATURE_CORECLR
101 // Names are confusing. Here are 3 names we have:
103 // new CultureInfo() m_name m_nonSortName m_sortName
104 // en-US en-US en-US en-US
105 // de-de_phoneb de-DE_phoneb de-DE de-DE_phoneb
106 // fj-fj (custom) fj-FJ fj-FJ en-US (if specified sort is en-US)
109 // Note that in Silverlight we ask the OS for the text and sort behavior, so the
110 // textinfo and compareinfo names are the same as the name
112 // Note that the name used to be serialized for Everett; it is now serialized
113 // because alernate sorts can have alternate names.
114 // This has a de-DE, de-DE_phoneb or fj-FJ style name
115 internal string m_name
;
117 // This will hold the non sorting name to be returned from CultureInfo.Name property.
118 // This has a de-DE style name even for de-DE_phoneb type cultures
119 [NonSerialized
]private string m_nonSortName
;
121 // This will hold the sorting name to be returned from CultureInfo.SortName property.
122 // This might be completely unrelated to the culture name if a custom culture. Ie en-US for fj-FJ.
123 // Otherwise its the sort name, ie: de-DE or de-DE_phoneb
124 [NonSerialized
]private string m_sortName
;
127 //--------------------------------------------------------------------//
129 // Static data members
131 //--------------------------------------------------------------------//
133 //Get the current user default culture. This one is almost always used, so we create it by default.
134 private static volatile CultureInfo s_userDefaultCulture
;
137 // All of the following will be created on demand.
140 //The Invariant culture;
141 private static volatile CultureInfo s_InvariantCultureInfo
;
143 //The culture used in the user interface. This is mostly used to load correct localized resources.
144 private static volatile CultureInfo s_userDefaultUICulture
;
146 //This is the UI culture used to install the OS.
147 private static volatile CultureInfo s_InstalledUICultureInfo
;
149 //These are defaults that we use if a thread has not opted into having an explicit culture
150 private static volatile CultureInfo s_DefaultThreadCurrentUICulture
;
151 private static volatile CultureInfo s_DefaultThreadCurrentCulture
;
153 //This is a cache of all previously created cultures. Valid keys are LCIDs or the name. We use two hashtables to track them,
154 // depending on how they are called.
155 private static volatile Hashtable s_LcidCachedCultures
;
156 private static volatile Hashtable s_NameCachedCultures
;
159 // When running under AppX, we use this to get some information about the language list
161 private static volatile WindowsRuntimeResourceManagerBase s_WindowsRuntimeResourceManager
;
164 private static bool ts_IsDoingAppXCultureInfoLookup
;
167 //The parent culture.
168 [NonSerialized
]private CultureInfo m_parent
;
170 // LOCALE constants of interest to us internally and privately for LCID functions
171 // (ie: avoid using these and use names if possible)
172 internal const int LOCALE_NEUTRAL
= 0x0000;
173 private const int LOCALE_USER_DEFAULT
= 0x0400;
174 private const int LOCALE_SYSTEM_DEFAULT
= 0x0800;
175 internal const int LOCALE_CUSTOM_DEFAULT
= 0x0c00;
176 internal const int LOCALE_CUSTOM_UNSPECIFIED
= 0x1000;
177 internal const int LOCALE_INVARIANT
= 0x007F;
178 private const int LOCALE_TRADITIONAL_SPANISH
= 0x040a;
181 // The CultureData instance that reads the data provided by our CultureData class.
183 //Using a field initializer rather than a static constructor so that the whole class can be lazy
185 private static readonly bool init
= Init();
186 private static bool Init()
189 if (s_InvariantCultureInfo
== null)
191 CultureInfo temp
= new CultureInfo("", false);
192 temp
.m_isReadOnly
= true;
193 s_InvariantCultureInfo
= temp
;
195 // First we set it to Invariant in case someone needs it before we're done finding it.
196 // For example, if we throw an exception in InitUserDefaultCulture, we will still need an valid
197 // s_userDefaultCulture to be used in Thread.CurrentCulture.
198 s_userDefaultCulture
= s_userDefaultUICulture
= s_InvariantCultureInfo
;
200 s_userDefaultCulture
= InitUserDefaultCulture();
201 s_userDefaultUICulture
= InitUserDefaultUICulture();
205 [System
.Security
.SecuritySafeCritical
] // auto-generated
206 static CultureInfo
InitUserDefaultCulture()
208 String strDefault
= GetDefaultLocaleName(LOCALE_USER_DEFAULT
);
209 if (strDefault
== null)
211 strDefault
= GetDefaultLocaleName(LOCALE_SYSTEM_DEFAULT
);
213 if (strDefault
== null)
215 // If system default doesn't work, keep using the invariant
216 return (CultureInfo
.InvariantCulture
);
219 CultureInfo temp
= GetCultureByName(strDefault
, true);
221 temp
.m_isReadOnly
= true;
226 static CultureInfo
InitUserDefaultUICulture()
228 String strDefault
= GetUserDefaultUILanguage();
230 // In most of cases, UserDefaultCulture == UserDefaultUICulture, so we should use the same instance if possible.
231 if (strDefault
== UserDefaultCulture
.Name
)
233 return (UserDefaultCulture
);
236 CultureInfo temp
= GetCultureByName( strDefault
, true);
240 return (CultureInfo
.InvariantCulture
);
243 temp
.m_isReadOnly
= true;
249 [SecuritySafeCritical
]
250 internal static CultureInfo
GetCultureInfoForUserPreferredLanguageInAppX()
252 // If a call to GetCultureInfoForUserPreferredLanguageInAppX() generated a recursive
253 // call to itself, return null, since we don't want to stack overflow. For example,
254 // this can happen if some code in this method ends up calling CultureInfo.CurrentCulture
255 // (which is common on check'd build because of BCLDebug logging which calls Int32.ToString()).
256 // In this case, returning null will mean CultureInfo.CurrentCulture gets the default Win32
257 // value, which should be fine.
258 if(ts_IsDoingAppXCultureInfoLookup
)
263 // If running within a compilation process (mscorsvw.exe, for example), it is illegal to
264 // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives
265 // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value,
266 // which should be fine because we should only ever need to access FX resources during NGEN.
267 // FX resources are always loaded from satellite assemblies - even in AppX processes (see the
268 // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details).
269 if (AppDomain
.IsAppXNGen
)
274 CultureInfo toReturn
= null;
278 ts_IsDoingAppXCultureInfoLookup
= true;
280 if(s_WindowsRuntimeResourceManager
== null)
282 s_WindowsRuntimeResourceManager
= ResourceManager
.GetWinRTResourceManager();
285 toReturn
= s_WindowsRuntimeResourceManager
.GlobalResourceContextBestFitCultureInfo
;
289 ts_IsDoingAppXCultureInfoLookup
= false;
295 [SecuritySafeCritical
]
296 internal static bool SetCultureInfoForUserPreferredLanguageInAppX(CultureInfo ci
)
298 // If running within a compilation process (mscorsvw.exe, for example), it is illegal to
299 // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives
300 // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value,
301 // which should be fine because we should only ever need to access FX resources during NGEN.
302 // FX resources are always loaded from satellite assemblies - even in AppX processes (see the
303 // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details).
304 if (AppDomain
.IsAppXNGen
)
309 if (s_WindowsRuntimeResourceManager
== null)
311 s_WindowsRuntimeResourceManager
= ResourceManager
.GetWinRTResourceManager();
314 return s_WindowsRuntimeResourceManager
.SetGlobalResourceContextDefaultCulture(ci
);
318 ////////////////////////////////////////////////////////////////////////
320 // CultureInfo Constructors
322 ////////////////////////////////////////////////////////////////////////
325 public CultureInfo(String name
) : this(name
, true) {
329 public CultureInfo(String name
, bool useUserOverride
) {
331 throw new ArgumentNullException("name",
332 Environment
.GetResourceString("ArgumentNull_String"));
334 Contract
.EndContractBlock();
336 #if FEATURE_LEGACYNETCF
337 // Windows Phone 7 and 7.1 do not support Bengali. When running on Windows Phone 8,
338 // WinPhone 7.x apps get the old Mango text stack, not the Apollo text stack. The Mango
339 // text stack cannot display characters in Bengali, such as the culture's native name.
340 // Phone apps are already written to catch an exception here and bypass this culture.
341 if (CompatibilitySwitches
.IsAppEarlierThanWindowsPhone8
&&
342 (name
== "bn" || name
== "bn-BD" || name
== "bn-IN" || name
== "ml" || name
== "or"))
343 throw new ArgumentException(Environment
.GetResourceString("Argument_CultureNotSupported"));
346 // Get our data providing record
347 this.m_cultureData
= CultureData
.GetCultureData(name
, useUserOverride
);
349 if (this.m_cultureData
== null) {
350 #if FEATURE_LEGACYNETCF
351 if (CompatibilitySwitches
.IsAppEarlierThanWindowsPhone8
)
352 throw new PlatformNotSupportedException(Environment
.GetResourceString("Argument_CultureNotSupported"));
354 throw new CultureNotFoundException("name", name
, Environment
.GetResourceString("Argument_CultureNotSupported"));
357 this.m_name
= this.m_cultureData
.CultureName
;
358 this.m_isInherited
= (this.GetType() != typeof(System
.Globalization
.CultureInfo
));
361 private CultureInfo(CultureData cultureData
)
363 Contract
.Assert(cultureData
!= null);
364 m_cultureData
= cultureData
;
365 m_name
= cultureData
.CultureName
;
366 m_isInherited
= false;
369 private static CultureInfo
CreateCultureInfoNoThrow(string name
, bool useUserOverride
)
371 Contract
.Assert(name
!= null);
372 CultureData cultureData
= CultureData
.GetCultureData(name
, useUserOverride
);
373 if (cultureData
== null)
378 return new CultureInfo(cultureData
);
382 public CultureInfo(int culture
) : this(culture
, true) {
385 public CultureInfo(int culture
, bool useUserOverride
) {
386 // We don't check for other invalid LCIDS here...
388 throw new ArgumentOutOfRangeException("culture",
389 Environment
.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
391 Contract
.EndContractBlock();
393 InitializeFromCultureId(culture
, useUserOverride
);
396 private void InitializeFromCultureId(int culture
, bool useUserOverride
)
400 case LOCALE_CUSTOM_DEFAULT
:
401 case LOCALE_SYSTEM_DEFAULT
:
403 case LOCALE_USER_DEFAULT
:
404 case LOCALE_CUSTOM_UNSPECIFIED
:
405 // Can't support unknown custom cultures and we do not support neutral or
406 // non-custom user locales.
407 throw new CultureNotFoundException(
408 "culture", culture
, Environment
.GetResourceString("Argument_CultureNotSupported"));
411 // Now see if this LCID is supported in the system default CultureData table.
412 this.m_cultureData
= CultureData
.GetCultureData(culture
, useUserOverride
);
415 this.m_isInherited
= (this.GetType() != typeof(System
.Globalization
.CultureInfo
));
416 this.m_name
= this.m_cultureData
.CultureName
;
418 #endif // FEATURE_USE_LCID
421 // CheckDomainSafetyObject throw if the object is customized object which cannot be attached to
422 // other object (like CultureInfo or DateTimeFormatInfo).
425 internal static void CheckDomainSafetyObject(Object obj
, Object container
)
427 if (obj
.GetType().Assembly
!= typeof(System
.Globalization
.CultureInfo
).Assembly
) {
429 throw new InvalidOperationException(
431 CultureInfo
.CurrentCulture
,
432 Environment
.GetResourceString("InvalidOperation_SubclassedObject"),
434 container
.GetType()));
436 Contract
.EndContractBlock();
439 #region Serialization
440 // We need to store the override from the culture data record.
441 private bool m_useUserOverride
;
444 private void OnDeserialized(StreamingContext ctx
)
447 // Whidbey+ should remember our name
448 // but v1 and v1.1 did not store name -- only lcid
449 // Whidbey did not store actual alternate sort name in m_name
450 // like we do in v4 so we can't use name for alternate sort
451 // e.g. for es-ES_tradnl: v2 puts es-ES in m_name; v4 puts es-ES_tradnl
452 if (m_name
== null || IsAlternateSortLcid(cultureID
))
454 Contract
.Assert(cultureID
>=0, "[CultureInfo.OnDeserialized] cultureID >= 0");
455 InitializeFromCultureId(cultureID
, m_useUserOverride
);
460 Contract
.Assert(m_name
!= null, "[CultureInfo.OnDeserialized] m_name != null");
463 this.m_cultureData
= CultureData
.GetCultureData(m_name
, m_useUserOverride
);
464 if (this.m_cultureData
== null)
465 throw new CultureNotFoundException(
466 "m_name", m_name
, Environment
.GetResourceString("Argument_CultureNotSupported"));
471 m_isInherited
= (this.GetType() != typeof(System
.Globalization
.CultureInfo
));
473 // in case we have non customized CultureInfo object we shouldn't allow any customized object
474 // to be attached to it for cross app domain safety.
475 if (this.GetType().Assembly
== typeof(System
.Globalization
.CultureInfo
).Assembly
)
477 if (textInfo
!= null)
479 CheckDomainSafetyObject(textInfo
, this);
482 if (compareInfo
!= null)
484 CheckDomainSafetyObject(compareInfo
, this);
490 // A locale ID is a 32 bit value which is the combination of a
491 // language ID, a sort ID, and a reserved area. The bits are
492 // allocated as follows:
494 // +------------------------+-------+--------------------------------+
495 // | Reserved |Sort ID| Language ID |
496 // +------------------------+-------+--------------------------------+
497 // 31 20 19 16 15 0 bit
498 private const int LOCALE_SORTID_MASK
= 0x000f0000;
500 static private bool IsAlternateSortLcid(int lcid
)
502 if(lcid
== LOCALE_TRADITIONAL_SPANISH
)
507 return (lcid
& LOCALE_SORTID_MASK
) != 0;
512 private void OnSerializing(StreamingContext ctx
)
514 this.m_name
= this.m_cultureData
.CultureName
;
515 this.m_useUserOverride
= this.m_cultureData
.UseUserOverride
;
517 // for compatibility with v2 serialize cultureID
518 this.cultureID
= this.m_cultureData
.ILANGUAGE
;
521 #endregion Serialization
523 #if FEATURE_LEAK_CULTURE_INFO
524 // Is it safe to send this CultureInfo as an instance member of a Thread cross AppDomain boundaries?
525 // For Silverlight, the answer is always no.
526 internal bool IsSafeCrossDomain
{
528 Contract
.Assert(m_createdDomainID
!= 0, "[CultureInfo.IsSafeCrossDomain] m_createdDomainID != 0");
529 return m_isSafeCrossDomain
;
533 internal int CreatedDomainID
{
535 Contract
.Assert(m_createdDomainID
!= 0, "[CultureInfo.CreatedDomain] m_createdDomainID != 0");
536 return m_createdDomainID
;
540 internal void StartCrossDomainTracking() {
542 // If we have decided about cross domain safety of this instance, we are done
543 if (m_createdDomainID
!= 0)
546 // If FEATURE_LEAK_CULTURE_INFO isn't enabled, we never want to pass
547 // CultureInfo as an instance member of a Thread.
548 if (CanSendCrossDomain())
550 m_isSafeCrossDomain
= true;
553 // m_createdDomainID has to be assigned last. We use it to signal that we have
554 // completed the check.
555 System
.Threading
.Thread
.MemoryBarrier();
556 m_createdDomainID
= Thread
.GetDomainID();
558 #endif // FEATURE_LEAK_CULTURE_INFO
560 // Is it safe to pass the CultureInfo cross AppDomain boundaries, not necessarily as an instance
561 // member of Thread. This is different from IsSafeCrossDomain, which implies passing the CultureInfo
562 // as a Thread instance member.
563 internal bool CanSendCrossDomain()
566 if (this.GetType() == typeof(System
.Globalization
.CultureInfo
))
573 // Constructor called by SQL Server's special munged culture - creates a culture with
574 // a TextInfo and CompareInfo that come from a supplied alternate source. This object
575 // is ALWAYS read-only.
576 // Note that we really cannot use an LCID version of this override as the cached
577 // name we create for it has to include both names, and the logic for this is in
578 // the GetCultureInfo override *only*.
579 internal CultureInfo(String cultureName
, String textAndCompareCultureName
)
581 if (cultureName
==null) {
582 throw new ArgumentNullException("cultureName",
583 Environment
.GetResourceString("ArgumentNull_String"));
585 Contract
.EndContractBlock();
587 this.m_cultureData
= CultureData
.GetCultureData(cultureName
, false);
588 if (this.m_cultureData
== null)
589 throw new CultureNotFoundException(
590 "cultureName", cultureName
, Environment
.GetResourceString("Argument_CultureNotSupported"));
592 this.m_name
= this.m_cultureData
.CultureName
;
594 CultureInfo altCulture
= GetCultureInfo(textAndCompareCultureName
);
595 this.compareInfo
= altCulture
.CompareInfo
;
596 this.textInfo
= altCulture
.TextInfo
;
599 // We do this to try to return the system UI language and the default user languages
600 // The callers should have a fallback if this fails (like Invariant)
601 private static CultureInfo
GetCultureByName(String name
, bool userOverride
)
603 // Try to get our culture
606 return userOverride
? new CultureInfo(name
) : CultureInfo
.GetCultureInfo(name
);
608 catch (ArgumentException
)
616 // Return a specific culture. A tad irrelevent now since we always return valid data
617 // for neutral locales.
619 // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647,
620 // if we can't find a bigger name. That doesn't help with things like "zh" though, so
621 // the approach is of questionable value
624 public static CultureInfo
CreateSpecificCulture(String name
) {
625 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
630 culture
= new CultureInfo(name
);
631 } catch(ArgumentException
) {
632 // When CultureInfo throws this exception, it may be because someone passed the form
633 // like "az-az" because it came out of an http accept lang. We should try a little
634 // parsing to perhaps fall back to "az" here and use *it* to create the neutral.
639 for(idx
= 0; idx
< name
.Length
; idx
++) {
640 if('-' == name
[idx
]) {
642 culture
= new CultureInfo(name
.Substring(0, idx
));
644 } catch(ArgumentException
) {
645 // throw the original exception so the name in the string will be right
651 if(null == culture
) {
652 // nothing to save here; throw the original exception
657 //In the most common case, they've given us a specific culture, so we'll just return that.
658 if (!(culture
.IsNeutralCulture
)) {
662 return (new CultureInfo(culture
.m_cultureData
.SSPECIFICCULTURE
));
664 #endif // !FEATURE_CORECLR
666 internal static bool VerifyCultureName(String cultureName
, bool throwException
)
668 // This function is used by ResourceManager.GetResourceFileName().
669 // ResourceManager searches for resource using CultureInfo.Name,
670 // so we should check against CultureInfo.Name.
672 for (int i
=0; i
<cultureName
.Length
; i
++) {
673 char c
= cultureName
[i
];
676 if (Char
.IsLetterOrDigit(c
) || c
=='-' || c
=='_') {
679 if (throwException
) {
680 throw new ArgumentException(Environment
.GetResourceString("Argument_InvalidResourceCultureName", cultureName
));
688 internal static bool VerifyCultureName(CultureInfo culture
, bool throwException
) {
689 Contract
.Assert(culture
!=null, "[CultureInfo.VerifyCultureName]culture!=null");
691 //If we have an instance of one of our CultureInfos, the user can't have changed the
692 //name and we know that all names are valid in files.
693 if (!culture
.m_isInherited
) {
697 return VerifyCultureName(culture
.Name
, throwException
);
701 ////////////////////////////////////////////////////////////////////////
705 // This instance provides methods based on the current user settings.
706 // These settings are volatile and may change over the lifetime of the
709 ////////////////////////////////////////////////////////////////////////
712 public static CultureInfo CurrentCulture
715 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
718 return Thread
.CurrentThread
.CurrentCulture
;
720 // In the case of CoreCLR, Thread.m_CurrentCulture and
721 // Thread.m_CurrentUICulture are thread static so as not to let
722 // CultureInfo objects leak across AppDomain boundaries. The
723 // fact that these fields are thread static introduces overhead
724 // in accessing them (through Thread.CurrentCulture). There is
725 // also overhead in accessing Thread.CurrentThread. In this
726 // case, we can avoid the overhead of Thread.CurrentThread
727 // because these fields are thread static, and so do not
728 // require a Thread instance to be accessed.
730 if(AppDomain
.IsAppXModel()) {
731 CultureInfo culture
= GetCultureInfoForUserPreferredLanguageInAppX();
736 return Thread
.m_CurrentCulture
??
737 s_DefaultThreadCurrentCulture
??
738 s_userDefaultCulture
??
746 throw new ArgumentNullException("value");
749 if (AppDomain
.IsAppXModel()) {
750 if (SetCultureInfoForUserPreferredLanguageInAppX(value)) {
751 // successfully set the culture, otherwise fallback to legacy path
756 Thread
.CurrentThread
.CurrentCulture
= value;
761 // This is the equivalence of the Win32 GetUserDefaultLCID()
763 internal static CultureInfo UserDefaultCulture
{
766 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
768 CultureInfo temp
= s_userDefaultCulture
;
772 // setting the s_userDefaultCulture with invariant culture before intializing it is a protection
773 // against recursion problem just in case if somebody called CurrentCulture from the CultureInfo
774 // creation path. the recursion can happen if the current user culture is a replaced custom culture.
777 s_userDefaultCulture
= CultureInfo
.InvariantCulture
;
778 temp
= InitUserDefaultCulture();
779 s_userDefaultCulture
= temp
;
786 // This is the equivalence of the Win32 GetUserDefaultUILanguage()
788 internal static CultureInfo UserDefaultUICulture
{
790 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
792 CultureInfo temp
= s_userDefaultUICulture
;
796 // setting the s_userDefaultCulture with invariant culture before intializing it is a protection
797 // against recursion problem just in case if somebody called CurrentUICulture from the CultureInfo
798 // creation path. the recursion can happen if the current user culture is a replaced custom culture.
801 s_userDefaultUICulture
= CultureInfo
.InvariantCulture
;
803 temp
= InitUserDefaultUICulture();
804 s_userDefaultUICulture
= temp
;
811 public static CultureInfo CurrentUICulture
{
813 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
816 return Thread
.CurrentThread
.CurrentUICulture
;
818 // In the case of CoreCLR, Thread.m_CurrentCulture and
819 // Thread.m_CurrentUICulture are thread static so as not to let
820 // CultureInfo objects leak across AppDomain boundaries. The
821 // fact that these fields are thread static introduces overhead
822 // in accessing them (through Thread.CurrentCulture). There is
823 // also overhead in accessing Thread.CurrentThread. In this
824 // case, we can avoid the overhead of Thread.CurrentThread
825 // because these fields are thread static, and so do not
826 // require a Thread instance to be accessed.
828 if(AppDomain
.IsAppXModel()) {
829 CultureInfo culture
= GetCultureInfoForUserPreferredLanguageInAppX();
834 return Thread
.m_CurrentUICulture
??
835 s_DefaultThreadCurrentUICulture
??
836 s_userDefaultUICulture
??
837 UserDefaultUICulture
;
844 throw new ArgumentNullException("value");
847 if (AppDomain
.IsAppXModel()) {
848 if (SetCultureInfoForUserPreferredLanguageInAppX(value)) {
849 // successfully set the culture, otherwise fallback to legacy path
854 Thread
.CurrentThread
.CurrentUICulture
= value;
860 // This is the equivalence of the Win32 GetSystemDefaultUILanguage()
863 public static CultureInfo InstalledUICulture
{
865 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
867 CultureInfo temp
= s_InstalledUICultureInfo
;
869 String strDefault
= GetSystemDefaultUILanguage();
870 temp
= GetCultureByName(strDefault
, true);
874 temp
= InvariantCulture
;
877 temp
.m_isReadOnly
= true;
878 s_InstalledUICultureInfo
= temp
;
884 public static CultureInfo DefaultThreadCurrentCulture
{
886 return s_DefaultThreadCurrentCulture
;
889 [System
.Security
.SecuritySafeCritical
] // auto-generated
890 #pragma warning disable 618
891 [SecurityPermission(SecurityAction
.Demand
, ControlThread
= true)]
892 #pragma warning restore 618
895 // If you add pre-conditions to this method, check to see if you also need to
896 // add them to Thread.CurrentCulture.set.
898 s_DefaultThreadCurrentCulture
= value;
902 public static CultureInfo DefaultThreadCurrentUICulture
{
904 return s_DefaultThreadCurrentUICulture
;
907 [System
.Security
.SecuritySafeCritical
] // auto-generated
908 #pragma warning disable 618
909 [SecurityPermission(SecurityAction
.Demand
, ControlThread
= true)]
910 #pragma warning restore 618
913 //If they're trying to use a Culture with a name that we can't use in resource lookup,
914 //don't even let them set it on the thread.
916 // If you add more pre-conditions to this method, check to see if you also need to
917 // add them to Thread.CurrentUICulture.set.
921 CultureInfo
.VerifyCultureName(value, true);
924 s_DefaultThreadCurrentUICulture
= value;
928 #if FEATURE_LEGACYNETCF
930 // Helper methods to set default thread culture without security demand. Used
931 // by NetCF compatibility quirk. See comment in Thread.CurrentUICulture setter for details.
933 internal static void SetCurrentUICultureQuirk(CultureInfo
value) {
934 s_DefaultThreadCurrentUICulture
= value;
937 internal static void SetCurrentCultureQuirk(CultureInfo
value) {
938 s_DefaultThreadCurrentCulture
= value;
943 ////////////////////////////////////////////////////////////////////////
947 // This instance provides methods, for example for casing and sorting,
948 // that are independent of the system and current user settings. It
949 // should be used only by processes such as some system services that
950 // require such invariant results (eg. file systems). In general,
951 // the results are not linguistically correct and do not match any
954 ////////////////////////////////////////////////////////////////////////
957 public static CultureInfo InvariantCulture
{
960 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
961 return (s_InvariantCultureInfo
);
966 ////////////////////////////////////////////////////////////////////////
970 // Return the parent CultureInfo for the current instance.
972 ////////////////////////////////////////////////////////////////////////
974 public virtual CultureInfo Parent
976 [System
.Security
.SecuritySafeCritical
] // auto-generated
979 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
980 CultureInfo culture
= null;
982 if (null == m_parent
)
984 string parentName
= this.m_cultureData
.SPARENT
;
986 if (String
.IsNullOrEmpty(parentName
))
988 culture
= InvariantCulture
;
992 culture
= CreateCultureInfoNoThrow(parentName
, m_cultureData
.UseUserOverride
);
995 // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
996 // We can't allow ourselves to fail. In case of custom cultures the parent of the
997 // current custom culture isn't installed.
998 culture
= InvariantCulture
;
1002 Interlocked
.CompareExchange
<CultureInfo
>(ref m_parent
, culture
, null);
1008 ////////////////////////////////////////////////////////////////////////
1012 // Returns a properly formed culture identifier for the current
1015 ////////////////////////////////////////////////////////////////////////
1017 #if FEATURE_USE_LCID
1018 public virtual int LCID
{
1020 return (this.m_cultureData
.ILANGUAGE
);
1025 ////////////////////////////////////////////////////////////////////////
1027 // BaseInputLanguage
1029 // Essentially an LCID, though one that may be different than LCID in the case
1030 // of a customized culture (LCID == LOCALE_CUSTOM_UNSPECIFIED).
1032 ////////////////////////////////////////////////////////////////////////
1033 #if FEATURE_USE_LCID
1034 [System
.Runtime
.InteropServices
.ComVisible(false)]
1035 public virtual int KeyboardLayoutId
1039 int keyId
= this.m_cultureData
.IINPUTLANGUAGEHANDLE
;
1041 // Not a customized culture, return the default Keyboard layout ID, which is the same as the language ID.
1047 #if !FEATURE_CORECLR
1048 public static CultureInfo
[] GetCultures(CultureTypes types
) {
1049 Contract
.Ensures(Contract
.Result
<CultureInfo
[]>() != null);
1050 // internally we treat UserCustomCultures as Supplementals but v2
1051 // treats as Supplementals and Replacements
1052 if((types
& CultureTypes
.UserCustomCulture
) == CultureTypes
.UserCustomCulture
)
1054 types
|= CultureTypes
.ReplacementCultures
;
1056 return (CultureData
.GetCultures(types
));
1060 ////////////////////////////////////////////////////////////////////////
1064 // Returns the full name of the CultureInfo. The name is in format like
1065 // "en-US" This version does NOT include sort information in the name.
1067 ////////////////////////////////////////////////////////////////////////
1068 public virtual String Name
{
1070 Contract
.Ensures(Contract
.Result
<String
>() != null);
1072 // We return non sorting name here.
1073 if (this.m_nonSortName
== null) {
1074 this.m_nonSortName
= this.m_cultureData
.SNAME
;
1075 if (this.m_nonSortName
== null) {
1076 this.m_nonSortName
= String
.Empty
;
1079 return this.m_nonSortName
;
1083 // This one has the sort information (ie: de-DE_phoneb)
1084 internal String SortName
1088 if (this.m_sortName
== null)
1090 this.m_sortName
= this.m_cultureData
.SCOMPAREINFO
;
1093 return this.m_sortName
;
1098 #if !FEATURE_CORECLR
1099 [System
.Runtime
.InteropServices
.ComVisible(false)]
1100 public String IetfLanguageTag
1104 Contract
.Ensures(Contract
.Result
<String
>() != null);
1106 // special case the compatibility cultures
1120 ////////////////////////////////////////////////////////////////////////
1124 // Returns the full name of the CultureInfo in the localized language.
1125 // For example, if the localized language of the runtime is Spanish and the CultureInfo is
1126 // US English, "Ingles (Estados Unidos)" will be returned.
1128 ////////////////////////////////////////////////////////////////////////
1129 public virtual String DisplayName
1131 [System
.Security
.SecuritySafeCritical
] // auto-generated
1134 Contract
.Ensures(Contract
.Result
<String
>() != null);
1135 Contract
.Assert(m_name
!= null, "[CultureInfo.DisplayName]Always expect m_name to be set");
1137 return m_cultureData
.SLOCALIZEDDISPLAYNAME
;
1141 ////////////////////////////////////////////////////////////////////////
1145 // Returns the full name of the CultureInfo in the native language.
1146 // For example, if the CultureInfo is US English, "English
1147 // (United States)" will be returned.
1149 ////////////////////////////////////////////////////////////////////////
1150 public virtual String NativeName
{
1151 [System
.Security
.SecuritySafeCritical
] // auto-generated
1153 Contract
.Ensures(Contract
.Result
<String
>() != null);
1154 return (this.m_cultureData
.SNATIVEDISPLAYNAME
);
1158 ////////////////////////////////////////////////////////////////////////
1162 // Returns the full name of the CultureInfo in English.
1163 // For example, if the CultureInfo is US English, "English
1164 // (United States)" will be returned.
1166 ////////////////////////////////////////////////////////////////////////
1167 public virtual String EnglishName
{
1168 [System
.Security
.SecuritySafeCritical
] // auto-generated
1170 Contract
.Ensures(Contract
.Result
<String
>() != null);
1171 return (this.m_cultureData
.SENGDISPLAYNAME
);
1176 public virtual String TwoLetterISOLanguageName
{
1177 [System
.Security
.SecuritySafeCritical
] // auto-generated
1179 Contract
.Ensures(Contract
.Result
<String
>() != null);
1180 return (this.m_cultureData
.SISO639LANGNAME
);
1184 #if !FEATURE_CORECLR
1186 public virtual String ThreeLetterISOLanguageName
{
1187 [System
.Security
.SecuritySafeCritical
] // auto-generated
1189 Contract
.Ensures(Contract
.Result
<String
>() != null);
1190 return (this.m_cultureData
.SISO639LANGNAME2
);
1194 ////////////////////////////////////////////////////////////////////////
1196 // ThreeLetterWindowsLanguageName
1198 // Returns the 3 letter windows language name for the current instance. eg: "ENU"
1199 // The ISO names are much preferred
1201 ////////////////////////////////////////////////////////////////////////
1202 public virtual String ThreeLetterWindowsLanguageName
{
1203 [System
.Security
.SecuritySafeCritical
] // auto-generated
1205 Contract
.Ensures(Contract
.Result
<String
>() != null);
1206 return (this.m_cultureData
.SABBREVLANGNAME
);
1211 ////////////////////////////////////////////////////////////////////////
1213 // CompareInfo Read-Only Property
1215 // Gets the CompareInfo for this culture.
1217 ////////////////////////////////////////////////////////////////////////
1218 public virtual CompareInfo CompareInfo
1222 Contract
.Ensures(Contract
.Result
<CompareInfo
>() != null);
1224 if (this.compareInfo
== null)
1226 // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from
1227 // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture
1228 CompareInfo temp
= UseUserOverride
1229 ? GetCultureInfo(this.m_name
).CompareInfo
1230 : new CompareInfo(this);
1231 if (CompatibilitySwitches
.IsCompatibilityBehaviorDefined
)
1233 this.compareInfo
= temp
;
1240 return (compareInfo
);
1244 #if !FEATURE_CORECLR
1245 ////////////////////////////////////////////////////////////////////////
1249 // Gets the RegionInfo for this culture.
1251 ////////////////////////////////////////////////////////////////////////
1252 private RegionInfo Region
1256 if (regionInfo
==null)
1258 // Make a new regionInfo
1259 RegionInfo tempRegionInfo
= new RegionInfo(this.m_cultureData
);
1260 regionInfo
= tempRegionInfo
;
1262 return (regionInfo
);
1265 #endif // FEATURE_CORECLR
1269 ////////////////////////////////////////////////////////////////////////
1273 // Gets the TextInfo for this culture.
1275 ////////////////////////////////////////////////////////////////////////
1278 public virtual TextInfo TextInfo
{
1280 Contract
.Ensures(Contract
.Result
<TextInfo
>() != null);
1284 // Make a new textInfo
1285 TextInfo tempTextInfo
= new TextInfo(this.m_cultureData
);
1286 tempTextInfo
.SetReadOnlyState(m_isReadOnly
);
1288 if (CompatibilitySwitches
.IsCompatibilityBehaviorDefined
)
1290 textInfo
= tempTextInfo
;
1294 return tempTextInfo
;
1301 ////////////////////////////////////////////////////////////////////////
1305 // Implements Object.Equals(). Returns a boolean indicating whether
1306 // or not object refers to the same CultureInfo as the current instance.
1308 ////////////////////////////////////////////////////////////////////////
1311 public override bool Equals(Object
value)
1313 if (Object
.ReferenceEquals(this, value))
1316 CultureInfo that
= value as CultureInfo
;
1320 // using CompareInfo to verify the data passed through the constructor
1321 // CultureInfo(String cultureName, String textAndCompareCultureName)
1323 return (this.Name
.Equals(that
.Name
) && this.CompareInfo
.Equals(that
.CompareInfo
));
1330 ////////////////////////////////////////////////////////////////////////
1334 // Implements Object.GetHashCode(). Returns the hash code for the
1335 // CultureInfo. The hash code is guaranteed to be the same for CultureInfo A
1336 // and B where A.Equals(B) is true.
1338 ////////////////////////////////////////////////////////////////////////
1340 public override int GetHashCode()
1342 return (this.Name
.GetHashCode() + this.CompareInfo
.GetHashCode());
1346 ////////////////////////////////////////////////////////////////////////
1350 // Implements Object.ToString(). Returns the name of the CultureInfo,
1351 // eg. "de-DE_phoneb", "en-US", or "fj-FJ".
1353 ////////////////////////////////////////////////////////////////////////
1356 public override String
ToString()
1358 Contract
.Ensures(Contract
.Result
<String
>() != null);
1360 Contract
.Assert(m_name
!= null, "[CultureInfo.ToString]Always expect m_name to be set");
1365 public virtual Object
GetFormat(Type formatType
) {
1366 if (formatType
== typeof(NumberFormatInfo
)) {
1367 return (NumberFormat
);
1369 if (formatType
== typeof(DateTimeFormatInfo
)) {
1370 return (DateTimeFormat
);
1375 public virtual bool IsNeutralCulture
{
1377 return this.m_cultureData
.IsNeutralCulture
;
1381 #if !FEATURE_CORECLR
1382 [System
.Runtime
.InteropServices
.ComVisible(false)]
1383 public CultureTypes CultureTypes
1387 CultureTypes types
= 0;
1389 if (m_cultureData
.IsNeutralCulture
)
1390 types
|= CultureTypes
.NeutralCultures
;
1392 types
|= CultureTypes
.SpecificCultures
;
1394 types
|= m_cultureData
.IsWin32Installed
? CultureTypes
.InstalledWin32Cultures
: 0;
1396 // Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
1397 #pragma warning disable 618
1398 types
|= m_cultureData
.IsFramework
? CultureTypes
.FrameworkCultures
: 0;
1400 #pragma warning restore 618
1401 types
|= m_cultureData
.IsSupplementalCustomCulture
? CultureTypes
.UserCustomCulture
: 0;
1402 types
|= m_cultureData
.IsReplacementCulture
? CultureTypes
.ReplacementCultures
| CultureTypes
.UserCustomCulture
: 0;
1409 public virtual NumberFormatInfo NumberFormat
{
1412 Contract
.Ensures(Contract
.Result
<NumberFormatInfo
>() != null);
1414 if (numInfo
== null) {
1415 NumberFormatInfo temp
= new NumberFormatInfo(this.m_cultureData
);
1416 temp
.isReadOnly
= m_isReadOnly
;
1422 if (value == null) {
1423 throw new ArgumentNullException("value",
1424 Environment
.GetResourceString("ArgumentNull_Obj"));
1426 Contract
.EndContractBlock();
1432 ////////////////////////////////////////////////////////////////////////
1434 // GetDateTimeFormatInfo
1436 // Create a DateTimeFormatInfo, and fill in the properties according to
1439 ////////////////////////////////////////////////////////////////////////
1442 public virtual DateTimeFormatInfo DateTimeFormat
{
1444 Contract
.Ensures(Contract
.Result
<DateTimeFormatInfo
>() != null);
1446 if (dateTimeInfo
== null) {
1447 // Change the calendar of DTFI to the specified calendar of this CultureInfo.
1448 DateTimeFormatInfo temp
= new DateTimeFormatInfo(
1449 this.m_cultureData
, this.Calendar
);
1450 temp
.m_isReadOnly
= m_isReadOnly
;
1451 System
.Threading
.Thread
.MemoryBarrier();
1452 dateTimeInfo
= temp
;
1454 return (dateTimeInfo
);
1458 if (value == null) {
1459 throw new ArgumentNullException("value",
1460 Environment
.GetResourceString("ArgumentNull_Obj"));
1462 Contract
.EndContractBlock();
1464 dateTimeInfo
= value;
1470 public void ClearCachedData() {
1471 s_userDefaultUICulture
= null;
1472 s_userDefaultCulture
= null;
1474 RegionInfo
.s_currentRegionInfo
= null;
1475 #if !FEATURE_CORECLR && !FEATURE_PAL // System.TimeZone does not exist in CoreCLR
1476 TimeZone
.ResetTimeZone();
1477 #endif // FEATURE_CORECLR
1478 TimeZoneInfo
.ClearCachedData();
1479 // Delete the cached cultures.
1480 s_LcidCachedCultures
= null;
1481 s_NameCachedCultures
= null;
1483 CultureData
.ClearCachedData();
1486 /*=================================GetCalendarInstance==========================
1487 **Action: Map a Win32 CALID to an instance of supported calendar.
1488 **Returns: An instance of calendar.
1489 **Arguments: calType The Win32 CALID
1491 ** Shouldn't throw exception since the calType value is from our data table or from Win32 registry.
1492 ** If we are in trouble (like getting a weird value from Win32 registry), just return the GregorianCalendar.
1493 ============================================================================*/
1494 internal static Calendar
GetCalendarInstance(int calType
) {
1495 if (calType
==Calendar
.CAL_GREGORIAN
) {
1496 return (new GregorianCalendar());
1498 return GetCalendarInstanceRare(calType
);
1501 //This function exists as a shortcut to prevent us from loading all of the non-gregorian
1502 //calendars unless they're required.
1503 internal static Calendar
GetCalendarInstanceRare(int calType
) {
1504 Contract
.Assert(calType
!=Calendar
.CAL_GREGORIAN
, "calType!=Calendar.CAL_GREGORIAN");
1507 case Calendar
.CAL_GREGORIAN_US
: // Gregorian (U.S.) calendar
1508 case Calendar
.CAL_GREGORIAN_ME_FRENCH
: // Gregorian Middle East French calendar
1509 case Calendar
.CAL_GREGORIAN_ARABIC
: // Gregorian Arabic calendar
1510 case Calendar
.CAL_GREGORIAN_XLIT_ENGLISH
: // Gregorian Transliterated English calendar
1511 case Calendar
.CAL_GREGORIAN_XLIT_FRENCH
: // Gregorian Transliterated French calendar
1512 return (new GregorianCalendar((GregorianCalendarTypes
)calType
));
1513 case Calendar
.CAL_TAIWAN
: // Taiwan Era calendar
1514 return (new TaiwanCalendar());
1515 case Calendar
.CAL_JAPAN
: // Japanese Emperor Era calendar
1516 return (new JapaneseCalendar());
1517 case Calendar
.CAL_KOREA
: // Korean Tangun Era calendar
1518 return (new KoreanCalendar());
1519 case Calendar
.CAL_THAI
: // Thai calendar
1520 return (new ThaiBuddhistCalendar());
1521 case Calendar
.CAL_HIJRI
: // Hijri (Arabic Lunar) calendar
1522 return (new HijriCalendar());
1523 case Calendar
.CAL_HEBREW
: // Hebrew (Lunar) calendar
1524 return (new HebrewCalendar());
1525 case Calendar
.CAL_UMALQURA
:
1526 return (new UmAlQuraCalendar());
1527 case Calendar
.CAL_PERSIAN
:
1528 return (new PersianCalendar());
1529 case Calendar
.CAL_CHINESELUNISOLAR
:
1530 return (new ChineseLunisolarCalendar());
1531 case Calendar
.CAL_JAPANESELUNISOLAR
:
1532 return (new JapaneseLunisolarCalendar());
1533 case Calendar
.CAL_KOREANLUNISOLAR
:
1534 return (new KoreanLunisolarCalendar());
1535 case Calendar
.CAL_TAIWANLUNISOLAR
:
1536 return (new TaiwanLunisolarCalendar());
1538 return (new GregorianCalendar());
1542 /*=================================Calendar==========================
1543 **Action: Return/set the default calendar used by this culture.
1544 ** This value can be overridden by regional option if this is a current culture.
1548 ** ArgumentNull_Obj if the set value is null.
1549 ============================================================================*/
1552 public virtual Calendar Calendar
{
1554 Contract
.Ensures(Contract
.Result
<Calendar
>() != null);
1555 if (calendar
== null) {
1556 Contract
.Assert(this.m_cultureData
.CalendarIds
.Length
> 0, "this.m_cultureData.CalendarIds.Length > 0");
1557 // Get the default calendar for this culture. Note that the value can be
1558 // from registry if this is a user default culture.
1559 Calendar newObj
= this.m_cultureData
.DefaultCalendar
;
1561 System
.Threading
.Thread
.MemoryBarrier();
1562 newObj
.SetReadOnlyState(m_isReadOnly
);
1569 /*=================================OptionCalendars==========================
1570 **Action: Return an array of the optional calendar for this culture.
1571 **Returns: an array of Calendar.
1574 ============================================================================*/
1577 public virtual Calendar
[] OptionalCalendars
{
1579 Contract
.Ensures(Contract
.Result
<Calendar
[]>() != null);
1582 // This property always returns a new copy of the calendar array.
1584 int[] calID
= this.m_cultureData
.CalendarIds
;
1585 Calendar
[] cals
= new Calendar
[calID
.Length
];
1586 for (int i
= 0; i
< cals
.Length
; i
++) {
1587 cals
[i
] = GetCalendarInstance(calID
[i
]);
1594 public bool UseUserOverride
{
1596 return (this.m_cultureData
.UseUserOverride
);
1600 #if !FEATURE_CORECLR
1601 [System
.Security
.SecuritySafeCritical
] // auto-generated
1602 [System
.Runtime
.InteropServices
.ComVisible(false)]
1603 public CultureInfo
GetConsoleFallbackUICulture()
1605 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
1607 CultureInfo temp
= m_consoleFallbackCulture
;
1610 temp
= CreateSpecificCulture(this.m_cultureData
.SCONSOLEFALLBACKNAME
);
1611 temp
.m_isReadOnly
= true;
1612 m_consoleFallbackCulture
= temp
;
1618 public virtual Object
Clone()
1620 Contract
.Ensures(Contract
.Result
<Object
>() != null);
1622 CultureInfo ci
= (CultureInfo
)MemberwiseClone();
1623 ci
.m_isReadOnly
= false;
1625 //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
1626 //they've already been allocated. If this is a derived type, we'll take a more generic codepath.
1629 if (this.dateTimeInfo
!= null)
1631 ci
.dateTimeInfo
= (DateTimeFormatInfo
)this.dateTimeInfo
.Clone();
1633 if (this.numInfo
!= null)
1635 ci
.numInfo
= (NumberFormatInfo
)this.numInfo
.Clone();
1641 ci
.DateTimeFormat
= (DateTimeFormatInfo
)this.DateTimeFormat
.Clone();
1642 ci
.NumberFormat
= (NumberFormatInfo
)this.NumberFormat
.Clone();
1645 if (textInfo
!= null)
1647 ci
.textInfo
= (TextInfo
) textInfo
.Clone();
1650 if (calendar
!= null)
1652 ci
.calendar
= (Calendar
) calendar
.Clone();
1659 public static CultureInfo
ReadOnly(CultureInfo ci
) {
1661 throw new ArgumentNullException("ci");
1663 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
1664 Contract
.EndContractBlock();
1666 if (ci
.IsReadOnly
) {
1669 CultureInfo newInfo
= (CultureInfo
)(ci
.MemberwiseClone());
1671 if (!ci
.IsNeutralCulture
)
1673 //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
1674 //they've already been allocated. If this is a derived type, we'll take a more generic codepath.
1675 if (!ci
.m_isInherited
) {
1676 if (ci
.dateTimeInfo
!= null) {
1677 newInfo
.dateTimeInfo
= DateTimeFormatInfo
.ReadOnly(ci
.dateTimeInfo
);
1679 if (ci
.numInfo
!= null) {
1680 newInfo
.numInfo
= NumberFormatInfo
.ReadOnly(ci
.numInfo
);
1684 newInfo
.DateTimeFormat
= DateTimeFormatInfo
.ReadOnly(ci
.DateTimeFormat
);
1685 newInfo
.NumberFormat
= NumberFormatInfo
.ReadOnly(ci
.NumberFormat
);
1689 if (ci
.textInfo
!= null)
1691 newInfo
.textInfo
= TextInfo
.ReadOnly(ci
.textInfo
);
1694 if (ci
.calendar
!= null)
1696 newInfo
.calendar
= Calendar
.ReadOnly(ci
.calendar
);
1699 // Don't set the read-only flag too early.
1700 // We should set the read-only flag here. Otherwise, info.DateTimeFormat will not be able to set.
1701 newInfo
.m_isReadOnly
= true;
1707 public bool IsReadOnly
{
1709 return (m_isReadOnly
);
1713 private void VerifyWritable() {
1715 throw new InvalidOperationException(Environment
.GetResourceString("InvalidOperation_ReadOnly"));
1717 Contract
.EndContractBlock();
1720 // For resource lookup, we consider a culture the invariant culture by name equality.
1721 // We perform this check frequently during resource lookup, so adding a property for
1722 // improved readability.
1723 internal bool HasInvariantCultureName
1725 get { return Name == CultureInfo.InvariantCulture.Name; }
1728 // Helper function both both overloads of GetCachedReadOnlyCulture. If lcid is 0, we use the name.
1729 // If lcid is -1, use the altName and create one of those special SQL cultures.
1730 internal static CultureInfo
GetCultureInfoHelper(int lcid
, string name
, string altName
)
1732 // There is a race condition in this code with the side effect that the second thread's value
1733 // clobbers the first in the dictionary. This is an acceptable ---- since the CultureInfo objects
1734 // are content equal (but not reference equal). Since we make no guarantees there, this ---- is
1736 // See code:Dictionary#DictionaryVersusHashtableThreadSafety for details on Dictionary versus
1737 // Hashtable thread safety.
1739 // retval is our return value.
1742 // Temporary hashtable for the names.
1743 Hashtable tempNameHT
= s_NameCachedCultures
;
1747 name
= CultureData
.AnsiToLower(name
);
1750 if (altName
!= null)
1752 altName
= CultureData
.AnsiToLower(altName
);
1755 // We expect the same result for both hashtables, but will test individually for added safety.
1756 if (tempNameHT
== null)
1758 tempNameHT
= Hashtable
.Synchronized(new Hashtable());
1762 // If we are called by name, check if the object exists in the hashtable. If so, return it.
1765 retval
= (CultureInfo
)tempNameHT
[name
+ '\xfffd' + altName
];
1773 retval
= (CultureInfo
)tempNameHT
[name
];
1780 #if FEATURE_USE_LCID
1781 // Next, the Lcid table.
1782 Hashtable tempLcidHT
= s_LcidCachedCultures
;
1784 if (tempLcidHT
== null)
1786 // Case insensitive is not an issue here, save the constructor call.
1787 tempLcidHT
= Hashtable
.Synchronized(new Hashtable());
1791 // If we were called by Lcid, check if the object exists in the table. If so, return it.
1794 retval
= (CultureInfo
) tempLcidHT
[lcid
];
1802 // We now have two temporary hashtables and the desired object was not found.
1803 // We'll construct it. We catch any exceptions from the constructor call and return null.
1809 // call the private constructor
1810 retval
= new CultureInfo(name
, altName
);
1814 retval
= new CultureInfo(name
, false);
1818 #if FEATURE_USE_LCID
1819 retval
= new CultureInfo(lcid
, false);
1826 catch(ArgumentException
)
1831 // Set it to read-only
1832 retval
.m_isReadOnly
= true;
1836 // This new culture will be added only to the name hash table.
1837 tempNameHT
[name
+ '\xfffd' + altName
] = retval
;
1839 // when lcid == -1 then TextInfo object is already get created and we need to set it as read only.
1840 retval
.TextInfo
.SetReadOnlyState(true);
1844 // Remember our name (as constructed). Do NOT use alternate sort name versions because
1845 // we have internal state representing the sort. (So someone would get the wrong cached version)
1846 string newName
= CultureData
.AnsiToLower(retval
.m_name
);
1848 // We add this new culture info object to both tables.
1849 tempNameHT
[newName
] = retval
;
1850 #if FEATURE_USE_LCID
1851 const int LCID_ZH_CHS_HANS
= 0x0004;
1852 const int LCID_ZH_CHT_HANT
= 0x7c04;
1854 if ((retval
.LCID
== LCID_ZH_CHS_HANS
&& newName
== "zh-hans")
1855 || (retval
.LCID
== LCID_ZH_CHT_HANT
&& newName
== "zh-hant"))
1857 // do nothing because we only want zh-CHS and zh-CHT to cache
1862 tempLcidHT
[retval
.LCID
] = retval
;
1868 #if FEATURE_USE_LCID
1869 // Copy the two hashtables to the corresponding member variables. This will potentially overwrite
1870 // new tables simultaneously created by a new thread, but maximizes thread safety.
1873 // Only when we modify the lcid hash table, is there a need to overwrite.
1874 s_LcidCachedCultures
= tempLcidHT
;
1878 s_NameCachedCultures
= tempNameHT
;
1880 // Finally, return our new CultureInfo object.
1884 #if FEATURE_USE_LCID
1885 // Gets a cached copy of the specified culture from an internal hashtable (or creates it
1886 // if not found). (LCID version)... use named version
1887 public static CultureInfo
GetCultureInfo(int culture
)
1889 // Must check for -1 now since the helper function uses the value to signal
1890 // the altCulture code path for SQL Server.
1891 // Also check for zero as this would fail trying to add as a key to the hash.
1893 throw new ArgumentOutOfRangeException("culture",
1894 Environment
.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
1896 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
1897 Contract
.EndContractBlock();
1898 CultureInfo retval
= GetCultureInfoHelper(culture
, null, null);
1901 throw new CultureNotFoundException(
1902 "culture", culture
, Environment
.GetResourceString("Argument_CultureNotSupported"));
1908 // Gets a cached copy of the specified culture from an internal hashtable (or creates it
1909 // if not found). (Named version)
1910 public static CultureInfo
GetCultureInfo(string name
)
1912 // Make sure we have a valid, non-zero length string as name
1915 throw new ArgumentNullException("name");
1917 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
1918 Contract
.EndContractBlock();
1920 CultureInfo retval
= GetCultureInfoHelper(0, name
, null);
1923 throw new CultureNotFoundException(
1924 "name", name
, Environment
.GetResourceString("Argument_CultureNotSupported"));
1930 // Gets a cached copy of the specified culture from an internal hashtable (or creates it
1932 public static CultureInfo
GetCultureInfo(string name
, string altName
)
1934 // Make sure we have a valid, non-zero length string as name
1937 throw new ArgumentNullException("name");
1940 if (null == altName
)
1942 throw new ArgumentNullException("altName");
1944 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
1945 Contract
.EndContractBlock();
1947 CultureInfo retval
= GetCultureInfoHelper(-1, name
, altName
);
1950 throw new CultureNotFoundException("name or altName",
1952 CultureInfo
.CurrentCulture
,
1953 Environment
.GetResourceString("Argument_OneOfCulturesNotSupported"),
1961 #if !FEATURE_CORECLR
1962 // This function is deprecated, we don't like it
1963 public static CultureInfo
GetCultureInfoByIetfLanguageTag(string name
)
1965 Contract
.Ensures(Contract
.Result
<CultureInfo
>() != null);
1967 // Disallow old zh-CHT/zh-CHS names
1968 if (name
== "zh-CHT" || name
== "zh-CHS")
1970 throw new CultureNotFoundException(
1972 String
.Format(CultureInfo
.CurrentCulture
, Environment
.GetResourceString("Argument_CultureIetfNotSupported"), name
)
1976 CultureInfo ci
= GetCultureInfo(name
);
1978 // Disallow alt sorts and es-es_TS
1979 if (ci
.LCID
> 0xffff || ci
.LCID
== 0x040a)
1981 throw new CultureNotFoundException(
1983 String
.Format(CultureInfo
.CurrentCulture
, Environment
.GetResourceString("Argument_CultureIetfNotSupported"), name
)
1990 private static volatile bool s_isTaiwanSku
;
1991 private static volatile bool s_haveIsTaiwanSku
;
1992 internal static bool IsTaiwanSku
1996 if (!s_haveIsTaiwanSku
)
1998 s_isTaiwanSku
= (GetSystemDefaultUILanguage() == "zh-TW");
1999 s_haveIsTaiwanSku
= true;
2001 return (bool)s_isTaiwanSku
;
2009 // Get Locale Info Ex calls. So we don't have to muck with the different int/string return types we declared two of these:
2010 [System
.Security
.SecurityCritical
] // auto-generated
2011 [ResourceExposure(ResourceScope
.None
)]
2012 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
2013 internal static extern String
nativeGetLocaleInfoEx(String localeName
, uint field
);
2015 [System
.Security
.SecuritySafeCritical
] // auto-generated
2016 [ResourceExposure(ResourceScope
.None
)]
2017 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
2018 internal static extern int nativeGetLocaleInfoExInt(String localeName
, uint field
);
2020 [System
.Security
.SecurityCritical
] // auto-generated
2021 [ResourceExposure(ResourceScope
.None
)]
2022 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
2023 internal static extern bool nativeSetThreadLocale(String localeName
);
2025 [System
.Security
.SecurityCritical
]
2026 private static String
GetDefaultLocaleName(int localeType
)
2028 Contract
.Assert(localeType
== LOCALE_USER_DEFAULT
|| localeType
== LOCALE_SYSTEM_DEFAULT
, "[CultureInfo.GetDefaultLocaleName] localeType must be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT");
2030 string localeName
= null;
2031 if(InternalGetDefaultLocaleName(localeType
, JitHelpers
.GetStringHandleOnStack(ref localeName
)))
2035 return string.Empty
;
2038 // Get the default locale name
2039 [System
.Security
.SecurityCritical
] // auto-generated
2040 [ResourceExposure(ResourceScope
.None
)]
2041 [SuppressUnmanagedCodeSecurity
]
2042 [DllImport(JitHelpers
.QCall
, CharSet
= CharSet
.Unicode
)]
2043 [return: MarshalAs(UnmanagedType
.Bool
)]
2044 private static extern bool InternalGetDefaultLocaleName(int localetype
, StringHandleOnStack localeString
);
2046 [System
.Security
.SecuritySafeCritical
] // auto-generated
2047 private static String
GetUserDefaultUILanguage()
2049 string userDefaultUiLanguage
= null;
2050 if(InternalGetUserDefaultUILanguage(JitHelpers
.GetStringHandleOnStack(ref userDefaultUiLanguage
)))
2052 return userDefaultUiLanguage
;
2054 return String
.Empty
;
2057 // Get the user's default UI language, return locale name
2058 [System
.Security
.SecurityCritical
] // auto-generated
2059 [ResourceExposure(ResourceScope
.None
)]
2060 [SuppressUnmanagedCodeSecurity
]
2061 [DllImport(JitHelpers
.QCall
, CharSet
= CharSet
.Unicode
)]
2062 [return: MarshalAs(UnmanagedType
.Bool
)]
2063 private static extern bool InternalGetUserDefaultUILanguage(StringHandleOnStack userDefaultUiLanguage
);
2065 [System
.Security
.SecuritySafeCritical
] // auto-generated
2066 private static String
GetSystemDefaultUILanguage()
2068 string systemDefaultUiLanguage
= null;
2069 if(InternalGetSystemDefaultUILanguage(JitHelpers
.GetStringHandleOnStack(ref systemDefaultUiLanguage
)))
2071 return systemDefaultUiLanguage
;
2073 return String
.Empty
;
2077 [System
.Security
.SecurityCritical
] // auto-generated
2078 [ResourceExposure(ResourceScope
.None
)]
2079 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
2080 [SuppressUnmanagedCodeSecurity
]
2081 [DllImport(JitHelpers
.QCall
, CharSet
= CharSet
.Unicode
)]
2082 [return: MarshalAs(UnmanagedType
.Bool
)]
2083 private static extern bool InternalGetSystemDefaultUILanguage(StringHandleOnStack systemDefaultUiLanguage
);
2085 // Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
2087 [System
.Security
.SecurityCritical
] // auto-generated
2088 [ResourceExposure(ResourceScope
.None
)]
2089 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
2090 internal static extern String
[] nativeGetResourceFallbackArray();