Repository navigation
Description
Note: As of v6-beta.1, Set-Culture isn't part of PowerShell Core yet, but I'm assuming it will be at some point (if technically feasible).
Set-Culture currently only changes the current user account's culture persistently, for future sessions.
Especially given that Get-Culture already reflects in-session changes of the culture (though it's not entirely clear at this point whether that's the intent - see #3831 ), it would be helpful to additionally support also / only setting the current session's culture.
Note that even without changes, the current help topic deserves updating to make it clear that the current session is not affected by the call.
Perhaps an optional -Scope parameter that supports the following values could be introduced:
CurrentUser... (persistently) set culture for the current user account for future sessions onlySession... (transiently) set culture for the current session onlyCurrentUserAndSession... (persistently) current user account + current session.
For backward compatibility, CurrentUser would have to be the default.
Environment data
PowerShell Core v6.0.0-beta (v6.0.0-beta.1)
Activity
iSazonov commentedon Oct 8, 2017
Steve Lee (@SteveL-MSFT) Have we plan to implement Set-Culture?
It seems we can change a culture for current thread only.
SteveL-MSFT commentedon Oct 8, 2017
Ilya (@iSazonov) no immediate plans
iSazonov commentedon Oct 9, 2017
We could use DefaultThreadCurrentCulture.
The problem is that we have some appdomains:
PowerShell/src/System.Management.Automation/singleshell/config/RegistryStringResourceIndirect.cs
Line 90 in 02b5f35
PowerShell/src/System.Management.Automation/engine/Modules/ModuleCmdletBase.cs
Line 6400 in db33d90
Steve Lee (@SteveL-MSFT) Dongbo Wang (@daxian-dbw) Jason Shirk (@lzybkr) Could you please comment? Is it possible to enumerate appdomains and set a culture?
mklement0 commentedon Oct 22, 2018
Ilya (@iSazonov):
CultureInfo.DefaultThreadCurrentCultureis a per-application default, which I don't think is appropriate for our needs.Looking at this again months later:
Presumably, we don't want to get into supporting persistent locale (culture) changes on Unix-like platforms, because there are no easy, standardized solutions.[1]
As far as I'm aware, there's no support in .NET Core for this, just as there is no support for persisting environment variables in general (
[environment]::SetEnvironmentVariable()doesn't support theUserandMachinetargets on Unix, and, similarly, our own RFC for enhanced environment-variable support only targets persistence support on Windows).This means that
Set-Culturewould only support-Scope Sessionon Unix and would therefore have to be the default there - which deviates from the default behavior (implied-Scope CurrentUser) in Windows PowerShell.That said, the same deviation already exists in the extant
Get-Culturecmdlet, which reports the current-thread culture (only and invariably) in PowerShell Core on all platforms vs. the persisted user culture (only and invariably) in Windows PowerShell (irrespective of the thread's current culture).In short: I think what is called for is:
Make
Set-Culturedefault to-Scope Sessionon all platforms, and support onlySessionon Unix-like platforms.[cultureinfo]::CurrentCulture = ...On Windows, also support
-Scope CurrentUser(current Windows PowerShell behavior) and-Scope CurrentUserAndSessionfor updating the user's default culture for future sessions and optionally also the current one.[1] Some pointers: On macOS,
defaults write -g AppleLocale <local-id>updates the current user's locale persistently. On Debian-like Linux distros such as Ubuntu it is file/etc/default/localethat stores the default locale, but system-wide. I'm unclear on how it works in other Linux distros. However, user-level defaults on Linux would generally require modifying user-level initialization files, which are shell-specific.mklement0 commentedon Oct 22, 2018
Taking a step back:
In Windows PowerShell:
Get-Cultureis built on the assumption that the culture won't change in-session, as it only ever reflects the persisted user-level setting.[cultureinfo]::CurrentCulture = ...) do they see a discrepancy between the (thread's) current culture and the value reported byGet-Culture(and$PSCultureand$host.CurrentCulture).Similarly,
Set-Cultureonly updates the persisted setting without changing the in-session culture.In PowerShell Core:
Get-Culture($host.CurrentCultureand$PSCulturepresumably soon (Get-Culture and $PSCulture do not (consistently) reflect in-session changes to another culture #3831) ) always reflects the thread's current culture, whether it was changed after session startup or not.Set-Culturedoesn't exist yet.The Windows PowerShell
*-Culturecmdlets were seemingly built with just reflecting / updating the persisted culture setting in mind, irrespective of in-session changes.In PowerShell Core we don't have support for that:
Get-Culturealready always reflects the current culture - whether it is the persisted setting or was changed in-sessionIf we were to implement
Set-Cultureto default to the session only, it would result in fundamentally different behavior than in Windows PowerShell, which is maybe too problematic.So, if consistency with Windows PowerShell's
Set-Cultureis paramount, the choices are:Continue to hold off on implementing
Set-Culturein PS Core.Get-CultureandSet-Culturehelp topics to show how to change the current culture in-session using the .NET framework.Implement it (as suggested in the initial post), but with the same default behavior as in Windows PowerShell, which means:
On Unix-like platforms, the only command form that will work is
Set-Culture -Scope Session ..., and neglecting to specify-Scope Sessionwill have to result in a not-implemented (statement-terminating) error.On Windows, the default behavior is as in Windows PowerShell (
-Scope CurrentUserimplied), with the (not-extant in WinPS) options to also change the in-session culture (-Scope CurrentUserAndSession) or just the in-session culture (-Scope Session).Note that the price for this nod to consistency with Windows PowerShell would be an asymmetry between
Get-CultureandSet-Culturein PS Core:In terms of the proposed
Set-Cultureimplementation,Get-Culture's default behavior is conceptually-Scope Session(and again we'd lack the ability to implement-Scope CurrentUseron Unix), whereasSet-Culture's would be-Scope CurrentUser.iSazonov commentedon Oct 22, 2018
Michael Klement (@mklement0) Thanks! We could start with
-Scope Session.mklement0 commentedon Oct 22, 2018
Yes, Ilya (@iSazonov), but we need to decide on whether:
-Scope Sessionshould be the default - which would make it consistent with PS CoreGet-Culture, but incompatible with Windows PowerShell'sSet-Culture.-Scope CurrentUsershould be the default, to align (conceptually) with Windows PowerShell, which, however, makes it asymmetrical with PS CoreGet-Cultureand requires explicit use of-Scope Sessionfor in-session changes (which would be the only scope supported on Unix, at least for now; in other words: something likeSet-Culture de-DEwould fail without-Scope Session).iSazonov commentedon Feb 4, 2019
Steve Lee (@SteveL-MSFT) Could PowerShell Committee consider the cmdlet and defaults options (keep backward compatibility with Windows PowerShell or consistency with Get-Culture)?
SteveL-MSFT commentedon Feb 6, 2019
@PowerShell/powershell-committee discussed this and would accept setting culture for PowerShell at system, user scopes, and process scope. The cmdlets would modify powershell.config.json and pwsh should read this on startup and set culture. Because these are PowerShell specific, recommendation is to call it
Set-PSCulture. If there is a need to set system culture, that's an ask for Windows to create such a cmdlet. Also have newGet-PSCulturecmdlets that are symmetric toSet-PSCulture. CurrentGet-Culturewould be deprecated.Set-PSCulturewould be expected to update$PSCulture10 remaining items
iSazonov commentedon Mar 1, 2019
Root problem is that there is no standard api for setting a culture on OS level. Therefore, everything else looks like a personal preference - in every possible scenario, one sees a problem and the other benefits.
mklement0 commentedon Mar 1, 2019
That's exactly what
Set-Culturewould enable you to do (at least if we also make it set[System.Threading.Thread]::CurrentThread.CurrentUICulture, which we should):Temporarily change the culture, for the duration of the session (or until changed again later in the session).
On a related note, it would be handy to have a command for running one or more commands with a given culture and then revert to the previous one; here's what I personally use, gratefully adapted from an ancient blog post by Keith Hill (@rkeithhill)
mklement0 commentedon Mar 1, 2019
It is a problem and it is unfortunate, but not one that must necessarily be solved by us.
Only supporting
-Scope Session(process) forSet-Cultureon Unix-like platforms and defaulting to that is the best we can do under the circumstances:It allows in-session changes, supporting the scenario you mentioned, for instance.
It allows users to place a
Set-Culturecall in their$PROFILE, if they really want to do that.$PROFILEeven in non-interactive scenarios (you can work around that with disciplined use of-noprofile, but note that if the culture were baked intopowershell.config.json, you wouldn't even have that option).Should CoreFx APIs someday allow changing the culture persistently on Unix, we can enable it in
Set-Culturethen.iSazonov commentedon Mar 13, 2019
For information https://github.com/dotnet/platform-compat/blob/master/docs/DE0008.md
mklement0 commentedon Mar 14, 2019
The analyzer warning you link to recommends settings (and getting)
[CultureInfo]::CurrentCulture]instead of[System.Threading.Thread]::CurrentThread.CurrentCulture], which in .NET Core is a must for cross-thread use.While that makes sense, we wouldn't be setting the culture for a different thread anyway, however (and assigning to
[CultureInfo]::CurrentCulture]still only changes the targeted thread's culture).So how does this fit into our conversation?
On a related note, however, with respect to in-session changes (the only kind we can currently provide on Unix, as discussed):
As a shell that provides an environment for external programs as well, we want to change the culture for them too - which assigning to
[CultureInfo]::CurrentCulture]by itself doesn't do:On Unix-like platforms, as stated, we change the culture for external programs launched thereafter by also setting the relevant locale environment variable,
LANG.On Windows, regrettably, we seemingly cannot do this, which is a limitation we'd have to document (setting
[cultureinfo]::DefaultThreadCurrentCultureonly sets the default for (all threads in) the current application domain, and has no effect on external processes, whether they run managed code or not; the Windows API also seems to offer no process-wide setting).microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 23, 2023
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.
rapettif commentedon Jul 22, 2025
Maybe it could be a bit odd, but if compatibility with Windows Powershell is to be mantained, then the defaults should be the same, even if the defaults don't work on linux (should throw an error). Even if that means that you always need to specify a scope in linux, because the default scope is not supported.