While Keith Hill's helpful answer shows you how to change the current script culture on demand (a more modern alternative to PSV3 + and the .NET framework v4.6 +:
[cultureinfo]::CurrentCulture = [cultureinfo]::InvariantCulture ), you donโt need to change the culture , because - as you found in your second update, the question is that the PowerShell syntax line (as opposed to using -f ) always uses the invariant, and not the current culture :
In other words:
If you replace 'val: {0}' -f 1.2 with "val: $(1.2)" , the literal 1.2 will not be formatted according to the rules of the current culture.
You can check in the console by doing (in one line: PSv3 +,. NET framework v4.6 +):
> [cultureinfo]::currentculture = 'de-DE'; 'val: {0}' -f 1.2; "val: $(1.2)" val: 1,2
Background:
Surprisingly, PowerShell always applies the invariant rather than the current culture in the following string contexts if the type at hand supports culture-oriented conversion to and from strings:
Based in part on this detailed answer , PowerShell explicitly requests culture-independent processing by passing a [cultureinfo]::InvariantCulture instance in the following scenarios:
When the string is interpolation : if the object type implements the IFormattable interface; otherwise, PowerShell calls .psobject.ToString() on the object.
When casting :
- to a string , including when binding to a
[string] -typed parameter : if the source type implements the [IFormattable] interface; otherwise, PowerShell calls .psobject.ToString() . - from the line : if the static
.Parse() method of the target type has an overload with [IFormatProvider] -typed (which is the interface implemented by [cultureinfo] ).
When comparing strings ( -eq , -lt , -gt ) using String.Compare() , which takes a CultureInfo parameter .
Others?
Regarding the fact that the invariant culture is / for:
Invariant culture is insensitive to culture; It is associated with the English language, but not with any country / region .
[...]
Unlike culture-sensitive data, which can be changed using customization or updates in the .NET Framework or operating system, invariant culture data is stable over time and in established cultures and cannot be changed by users. This makes an invariant culture particularly useful for operations that require culture-independent results, such as formatting and parsing operations that store formatted data or sort and order operations that require that data be displayed in a fixed order regardless of culture.
Presumably, stability in cultures has prompted PowerShell designers to consistently use an invariant culture when they are implicitly converted to and from strings .
For example, if you hard-code a date string, such as '7/21/2017' , into a script, and then try to convert it to date using the [date] cast, PowerShell culture-specific behavior ensures that the script is not interrupted even at startup, while a culture other than the US English is valid - fortunately, the invariant culture also recognizes ISO 8601 date and time strings .
for example, [datetime] '2017-07-21' .
On the other hand, if you want to convert strings and corresponding strings corresponding to the current culture, you must do this explicitly .
Summarizing:
Convert to strings :
- Embedding instances of data types with representations of the string depending on the default culture inside
"..." results in displaying an invariant culture ( [double] or [datetime] are examples of such types). - To get an idea of โโthe current culture, call
.ToString() explicitly or use the -f format operator (possibly inside "..." with $(...) ).
Convert from strings :
Live broadcasting ( [<type>] ... ) only ever recognizes culture-invariant string representations.
To convert from a string representation that matches the current culture (or a specific culture representation), use the target type static method ::Parse() explicitly (optionally with an explicit instance of [cultureinfo] to represent a particular culture).
Examples of "Culture-INVARIANT":
string interpolation and cast :
"$(1/10)" and [string] 1/10
- both output a string literal of
0.1 , with a decimal mark . , regardless of the current culture.
Similarly, line castings are culturally invariant; for example, [double] '1.2'
. always recognized as a decimal mark, regardless of the current culture.- Another way:
[double] 1.2 not translated into the overload [double]::Parse('1.2') method, depending on the culture, by default, but to the cultural invariant [double]::Parse('1.2', [cultureinfo]::InvariantCulture)
string comparison (suppose [cultureinfo]::CurrentCulture='tr-TR' is valid - Turkish, where i NOT a string representation of i )
[string]::Equals('i', 'I', 'CurrentCultureIgnoreCase')$false with current Turkish culture.'i'.ToUpper() shows that in Turkish culture the upper case is ฤฐ , not i .
'i' -eq 'I'- still
$true since invariant culture is applied. - implicitly the same as:
[string]::Equals('i', 'I', 'InvariantCultureIgnoreCase')
Culture Examples: SENSITIVE:
The current culture is observed in the following cases:
C -f string format operator (as above):
[cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2 [cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2 gives 1,2- Pitfall: due to operator precedence, any expression like RHS
-f must be enclosed in (...) in order to be recognized as such:- For example,
'{0}' -f 1/10 is evaluated as specified ('{0}' -f 1) / 10 ,
Use '{0}' -f (1/10) instead.
The default output to the console is :
for example, [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 gives 1,2
The same applies to the conclusions of the cmdlets; eg,
[cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01' [cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01' gives Sonntag, 1. Januar 2017 00:00:00
Warning. There seems to be a bug with Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5: in certain scripts, literals are passed to the script block, since unlimited parameters can lead to culturally invariant default output - see this GitHub issue
When writing to a file with Set-Content / Add-Content or Out-File / > / >> :
- for example,
[cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt gives 1,2
When using the static methods ::Parse() / ::TryParse() for number types such as [double] when passing only strings for parsing; for example, with a culture fr-FR (where , denotes a decimal place), [double]::Parse('1,2') returns double 1.2 (ie 1 + 2/10 ).
- Warning. According to bviktor , thousands separators are recognized by default, but very easily: efficiently, a thousand separator can be placed anywhere inside the integer part, regardless of how many digits are in the resulting groups, and the leading
0 also accepted; for example, in en-US culture (where , is the thousands separator), [double]::Parse('0,18') may succeed unexpectedly and give 18 .- To suppress recognition of thousands separators, use something like
[double]::Parse('0,18', 'Float') using the NumberStyles parameter
Others?