mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Add Import-LocalizedData implicit Localization fallback (#19896)
* Adds culture fallback to Import-LocalizedData * Only add fallback if current culture is not en-US * Pester 4 compatibility * Missing param block in It * Missed param block for It * Skip UICulture name test for Linux and Mac * Removed test fragment
This commit is contained in:
@@ -1,181 +0,0 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
Describe 'Testing of script internationalization' -Tags "CI" {
|
||||
BeforeAll {
|
||||
$dir=$PSScriptRoot
|
||||
$defaultParamValues = $PSDefaultParameterValues.Clone()
|
||||
#This works only for en-US or fr-FR
|
||||
if ($PSUICulture -ne 'en-US' -and $PSUICulture -ne 'fr-FR')
|
||||
{
|
||||
$PSDefaultParameterValues["It:Skip"] = $true
|
||||
}
|
||||
}
|
||||
AfterAll {
|
||||
$global:PSDefaultParameterValues = $defaultParamValues
|
||||
}
|
||||
|
||||
It 'convertFromString-Data should work with data statement.' {
|
||||
|
||||
data mydata
|
||||
{
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1
|
||||
string2=string2
|
||||
'@
|
||||
}
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1'
|
||||
$mydata.string2 | Should -BeExactly 'string2'
|
||||
}
|
||||
|
||||
It 'Import default culture is done correctly' {
|
||||
|
||||
Import-LocalizedData mydata;
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 for en-US'
|
||||
$mydata.string2 | Should -BeExactly 'string2 for en-US'
|
||||
}
|
||||
|
||||
It 'Import specific culture(en-US)' {
|
||||
|
||||
Import-LocalizedData mydata -UICulture en-US
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 for en-US'
|
||||
$mydata.string2 | Should -BeExactly 'string2 for en-US'
|
||||
|
||||
Import-LocalizedData mydata -UICulture fr-FR
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 for fr-FR'
|
||||
$mydata.string2 | Should -BeExactly 'string2 for fr-FR'
|
||||
}
|
||||
|
||||
It 'Import non existing culture is done correctly' {
|
||||
|
||||
Import-LocalizedData mydata -UICulture nl-NL -ErrorAction SilentlyContinue -ErrorVariable ev
|
||||
|
||||
$ev | Should -Not -BeNullOrEmpty
|
||||
$ev[0].Exception | Should -BeOfType System.Management.Automation.PSInvalidOperationException
|
||||
}
|
||||
|
||||
It 'Import different file name is done correctly' {
|
||||
|
||||
Import-LocalizedData mydata -FileName foo
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 from foo in en-US'
|
||||
$mydata.string2 | Should -BeExactly 'string2 from foo in en-US'
|
||||
|
||||
Import-LocalizedData mydata -FileName foo -UICulture fr-FR
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 from foo in fr-FR'
|
||||
$mydata.string2 | Should -BeExactly 'string2 from foo in fr-FR'
|
||||
}
|
||||
|
||||
It 'Import different file base is done correctly' {
|
||||
|
||||
Import-LocalizedData mydata -BaseDirectory "${dir}\newbase"
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 for en-US under newbase'
|
||||
$mydata.string2 | Should -BeExactly 'string2 for en-US under newbase'
|
||||
|
||||
Import-LocalizedData mydata -BaseDirectory "${dir}\newbase" -UICulture fr-FR
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 for fr-FR under newbase'
|
||||
$mydata.string2 | Should -BeExactly 'string2 for fr-FR under newbase'
|
||||
}
|
||||
|
||||
It 'Import different file base and file name' {
|
||||
|
||||
Import-LocalizedData mydata -BaseDirectory "${dir}\newbase" -FileName foo
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 for en-US from foo under newbase'
|
||||
$mydata.string2 | Should -BeExactly 'string2 for en-US from foo under newbase'
|
||||
|
||||
Import-LocalizedData mydata -BaseDirectory "${dir}\newbase" -FileName foo -UICulture fr-FR
|
||||
|
||||
$mydata.string1 | Should -BeExactly 'string1 for fr-FR from foo under newbase'
|
||||
$mydata.string2 | Should -BeExactly 'string2 for fr-FR from foo under newbase'
|
||||
}
|
||||
|
||||
It "Import variable that doesn't exist" {
|
||||
|
||||
Import-LocalizedData mydata2
|
||||
|
||||
$mydata2.string1 | Should -BeExactly 'string1 for en-US'
|
||||
$mydata2.string2 | Should -BeExactly 'string2 for en-US'
|
||||
}
|
||||
|
||||
It 'Import bad psd1 file - tests the use of disallowed variables' {
|
||||
|
||||
$script:exception = $null
|
||||
& {
|
||||
trap {$script:exception = $_ ; continue }
|
||||
Import-LocalizedData mydata -FileName bad
|
||||
}
|
||||
|
||||
$script:exception.exception | Should -Not -BeNullOrEmpty
|
||||
$script:exception.exception | Should -BeOfType System.management.automation.psinvalidoperationexception
|
||||
}
|
||||
|
||||
It 'Import if psd1 file is done correctly' {
|
||||
|
||||
Import-LocalizedData mydata -FileName if
|
||||
|
||||
if ($PSCulture -eq 'en-US')
|
||||
{
|
||||
$mydata.string1 | Should -BeExactly 'string1 for en-US in if'
|
||||
$mydata.string2 | Should -BeExactly 'string2 for en-US in if'
|
||||
}
|
||||
else
|
||||
{
|
||||
$mydata | Should -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
$testData = @(
|
||||
@{cmd = 'data d { @{ x=$(get-command)} }';Expected='get-command'},
|
||||
@{cmd = 'data d { if ($(get-command)) {} }';Expected='get-command'},
|
||||
@{cmd = 'data d { @(get-command) }';Expected='get-command'}
|
||||
)
|
||||
|
||||
It 'Allowed cmdlets checked properly' -TestCase:$testData {
|
||||
param ($cmd, $Expected)
|
||||
|
||||
$script:exception = $null
|
||||
& {
|
||||
trap {$script:exception = $_.Exception ; continue }
|
||||
Invoke-Expression $cmd
|
||||
}
|
||||
|
||||
$exception | Should -Match $Expected
|
||||
}
|
||||
|
||||
It 'Check alternate syntax that also supports complex variable names' {
|
||||
|
||||
& {
|
||||
$script:mydata = data { 123 }
|
||||
}
|
||||
$mydata | Should -Be 123
|
||||
|
||||
$mydata = data { 456 }
|
||||
& {
|
||||
# This import should not clobber the one at script scope
|
||||
Import-LocalizedData mydata -UICulture en-US
|
||||
}
|
||||
$mydata | Should -Be 456
|
||||
|
||||
& {
|
||||
# This import should clobber the one at script scope
|
||||
Import-LocalizedData script:mydata -UICulture en-US
|
||||
}
|
||||
$script:mydata.string1 | Should -BeExactly 'string1 for en-US'
|
||||
}
|
||||
|
||||
It 'Check fallback to current directory plus -SupportedCommand parameter is done correctly' {
|
||||
|
||||
New-Alias MyConvertFrom-StringData ConvertFrom-StringData
|
||||
|
||||
Import-LocalizedData local:mydata -UICulture fr-ca -FileName I18n.Tests_fallback.psd1 -SupportedCommand MyConvertFrom-StringData
|
||||
$mydata[0].string1 | Should -BeExactly 'fallback string1 for en-US'
|
||||
$mydata[1] | Should -Be 42
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
MyConvertFrom-StringData @'
|
||||
string1=fallback string1 for en-US
|
||||
string2=fallback string2 for en-US
|
||||
'@
|
||||
42
|
||||
@@ -0,0 +1,192 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
Describe 'Testing of script internationalization' -Tags 'CI' {
|
||||
BeforeAll {
|
||||
$testCultures = @(
|
||||
@{ UICulture = 'en-US' }
|
||||
@{ UICulture = 'fr-FR' }
|
||||
)
|
||||
|
||||
$currentCulture = $PSUICulture
|
||||
[System.Globalization.CultureInfo]::CurrentUICulture = 'en-US'
|
||||
|
||||
$defaultParams = @{
|
||||
BindingVariable = 'data'
|
||||
}
|
||||
}
|
||||
|
||||
BeforeEach {
|
||||
Get-Variable -Name data -Scope Local -ErrorAction Ignore | Remove-Variable
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
[System.Globalization.CultureInfo]::CurrentUICulture = $currentCulture
|
||||
}
|
||||
|
||||
Context 'Data section' {
|
||||
It 'ConvertFrom-StringData is permitted in a Data section' {
|
||||
data dataVariable
|
||||
{
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1
|
||||
string2=string2
|
||||
'@
|
||||
}
|
||||
|
||||
$dataVariable.string1 | Should -BeExactly 'string1'
|
||||
$dataVariable.string2 | Should -BeExactly 'string2'
|
||||
}
|
||||
|
||||
It 'Throws an error if the data section contains a command which is not allowed' -TestCases @(
|
||||
@{ Script = 'data d { @{ x=$(Get-Command)} }'; }
|
||||
@{ Script = 'data d { if ($(Get-Command)) {} }' }
|
||||
@{ Script = 'data d { @(Get-Command) }' }
|
||||
) {
|
||||
param ( $Script )
|
||||
|
||||
{ Invoke-Expression $Script } | Should -Throw -ErrorId 'CmdletNotInAllowedListForDataSection,Microsoft.PowerShell.Commands.InvokeExpressionCommand'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'BindingVariable parameter' {
|
||||
It 'BindingVariable binds positionally' {
|
||||
Import-LocalizedData data
|
||||
|
||||
$data.string1 | Should -BeExactly 'string1 en-US'
|
||||
$data.string2 | Should -BeExactly 'string2 en-US'
|
||||
}
|
||||
|
||||
It 'Imports data into the BindingVariable based on the current UICulture' {
|
||||
Import-LocalizedData @defaultParams
|
||||
|
||||
$data.string1 | Should -BeExactly 'string1 en-US'
|
||||
$data.string2 | Should -BeExactly 'string2 en-US'
|
||||
}
|
||||
|
||||
It 'Does not clobber existing variables in a parent scope' {
|
||||
$data = data { 456 }
|
||||
& {
|
||||
Import-LocalizedData @defaultParams
|
||||
}
|
||||
$data | Should -Be 456
|
||||
}
|
||||
|
||||
It 'Replaces a BindingVariable in a parent scope if a scope modifier is specified' {
|
||||
$Script:bindingVariable = data { 456 }
|
||||
|
||||
$Script:bindingVariable | Should -Be 456
|
||||
|
||||
& {
|
||||
Import-LocalizedData -BindingVariable Script:bindingVariable
|
||||
}
|
||||
|
||||
$Script:bindingVariable.string1 | Should -BeExactly 'string1 en-US'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'UICulture parameter' {
|
||||
It 'Imports specific culture (<UICulture>) defined by the UICulture parameter' -TestCases $testCultures {
|
||||
param ( $UICulture )
|
||||
|
||||
[System.Globalization.CultureInfo]::CurrentUICulture = $UICulture
|
||||
|
||||
Import-LocalizedData @defaultParams -UICulture $UICulture
|
||||
|
||||
$data.string1 | Should -BeExactly ('string1 {0}' -f $UICulture)
|
||||
$data.string2 | Should -BeExactly ('string2 {0}' -f $UICulture)
|
||||
}
|
||||
|
||||
It 'Throws an error if the specified UICulture does not exist' -Skip:(-not $IsWindows) {
|
||||
{ Import-LocalizedData @defaultParams -UICulture none-none -ErrorAction Stop } |
|
||||
Should -Throw -ExceptionType 'System.Management.Automation.PSArgumentException'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'UICulture fallback' {
|
||||
It 'When the UICulture parameter is specified, searches parent culture and current directory' -TestCases @(
|
||||
@{ UICulture = 'en-US'; ExpectedString = 'en-US' }
|
||||
@{ UICulture = 'en-GB'; ExpectedString = 'en' }
|
||||
@{ UICulture = 'no-NL'; ExpectedString = 'fallback' }
|
||||
) {
|
||||
param ( $UICulture, $ExpectedString )
|
||||
|
||||
[System.Globalization.CultureInfo]::CurrentUICulture = $UICulture
|
||||
|
||||
$data = Import-LocalizedData -UICulture $UICulture
|
||||
|
||||
$data.string1 | Should -Be ('string1 {0}' -f $ExpectedString)
|
||||
$data.string2 | Should -Be ('string2 {0}' -f $ExpectedString)
|
||||
}
|
||||
|
||||
It 'When the UICulture parameter is not specified and no files exist falls back on en-US and parent cultures' -TestCases @(
|
||||
@{ UICulture = 'no-NL'; ExpectedString = 'en-US' }
|
||||
) {
|
||||
param ( $UICulture, $ExpectedString )
|
||||
|
||||
[System.Globalization.CultureInfo]::CurrentUICulture = $UICulture
|
||||
|
||||
$data = Import-LocalizedData -FileName 'I18n_altfilename'
|
||||
|
||||
$data.string1 | Should -Be ('string1 {0} I18n_altfilename' -f $ExpectedString)
|
||||
$data.string2 | Should -Be ('string2 {0} I18n_altfilename' -f $ExpectedString)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'FileName and BaseDirectory parameters' {
|
||||
BeforeAll {
|
||||
$fileName = @{ FileName = 'I18n_altfilename' }
|
||||
$baseDirectory = @{ BaseDirectory = Join-Path -Path $PSScriptRoot -ChildPath 'I18n_altbase' }
|
||||
}
|
||||
|
||||
It 'Imports from the "foo" file name when then FileName parameter is specified (<UICulture>)' -TestCases $testCultures {
|
||||
param ( $UICulture )
|
||||
|
||||
[System.Globalization.CultureInfo]::CurrentUICulture = $UICulture
|
||||
|
||||
Import-LocalizedData @defaultParams @fileName -UICulture $UICulture
|
||||
|
||||
$data.string1 | Should -BeExactly ('string1 {0} I18n_altfilename' -f $UICulture)
|
||||
$data.string2 | Should -BeExactly ('string2 {0} I18n_altfilename' -f $UICulture)
|
||||
}
|
||||
|
||||
It 'Imports from the "I18n_altfilename" directory when the BaseDirectory parameter is specified (<UICulture>)' -TestCases $testCultures {
|
||||
param ( $UICulture )
|
||||
|
||||
[System.Globalization.CultureInfo]::CurrentUICulture = $UICulture
|
||||
|
||||
Import-LocalizedData @defaultParams @baseDirectory -UICulture $UICulture
|
||||
|
||||
$data.string1 | Should -BeExactly ('string1 {0} I18n_altbase' -f $UICulture)
|
||||
$data.string2 | Should -BeExactly ('string2 {0} I18n_altbase' -f $UICulture)
|
||||
}
|
||||
|
||||
It 'Imports from the "I18n_altfilename" file name and "I18n_altbase" directory when both FileName and BaseDirectory are specified (<UICulture>)' -TestCases $testCultures {
|
||||
param ( $UICulture )
|
||||
|
||||
[System.Globalization.CultureInfo]::CurrentUICulture = $UICulture
|
||||
|
||||
Import-LocalizedData @defaultParams @fileName @baseDirectory -UICulture $UICulture
|
||||
|
||||
$data.string1 | Should -BeExactly ('string1 {0} I18n_altbase I18n_altfilename' -f $UICulture)
|
||||
$data.string2 | Should -BeExactly ('string2 {0} I18n_altbase I18n_altfilename' -f $UICulture)
|
||||
}
|
||||
|
||||
It 'Throws an error if the specified FileName does not exist in any path' {
|
||||
{ Import-LocalizedData @defaultParams -FileName doesNotExist -ErrorAction Stop } |
|
||||
Should -Throw -ExceptionType 'System.Management.Automation.PSInvalidOperationException'
|
||||
}
|
||||
|
||||
It 'Throws an error if the specified BaseDirectory does not exist' {
|
||||
{ Import-LocalizedData @defaultParams -BaseDirectory "$PSScriptRoot\doesNotExist" -ErrorAction Stop } |
|
||||
Should -Throw -ExceptionType 'System.Management.Automation.PSInvalidOperationException'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'SupportedCommand parameter' {
|
||||
It 'Allows non-standard commands to be used in a data file' {
|
||||
$data = Import-LocalizedData -FileName I18n_supportedcommands -SupportedCommand Get-Command
|
||||
|
||||
$data.Name | Should -Be 'Import-LocalizedData'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 fallback
|
||||
string2=string2 fallback
|
||||
'@
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 en-US I18n_altbase
|
||||
string2=string2 en-US I18n_altbase
|
||||
'@
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 en-US I18n_altbase I18n_altfilename
|
||||
string2=string2 en-US I18n_altbase I18n_altfilename
|
||||
'@
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 fr-FR I18n_altbase
|
||||
string2=string2 fr-FR I18n_altbase
|
||||
'@
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 fr-FR I18n_altbase I18n_altfilename
|
||||
string2=string2 fr-FR I18n_altbase I18n_altfilename
|
||||
'@
|
||||
@@ -0,0 +1 @@
|
||||
Get-Command Import-LocalizedData
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 for en-US
|
||||
string2=string2 for en-US
|
||||
string1=string1 en-US
|
||||
string2=string2 en-US
|
||||
'@ # SIG # Begin signature block
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 en-US I18n_altfilename
|
||||
string2=string2 en-US I18n_altfilename
|
||||
'@
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 en
|
||||
string2=string2 en
|
||||
'@ # SIG # Begin signature block
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 fr-FR
|
||||
string2=string2 fr-FR
|
||||
'@
|
||||
@@ -0,0 +1,4 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 fr-FR I18n_altfilename
|
||||
string2=string2 fr-FR I18n_altfilename
|
||||
'@
|
||||
@@ -1,7 +0,0 @@
|
||||
if($a -eq 'en-US')
|
||||
{
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 from foo in en-US
|
||||
string2=string2 from foo in en-US
|
||||
'@
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 from foo in en-US
|
||||
string2=string2 from foo in en-US
|
||||
'@
|
||||
@@ -1,7 +0,0 @@
|
||||
if($psculture -eq 'en-US')
|
||||
{
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 for en-US in if
|
||||
string2=string2 for en-US in if
|
||||
'@
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 for fr-FR
|
||||
string2=string2 for fr-FR
|
||||
'@
|
||||
@@ -1,4 +0,0 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 from foo in fr-FR
|
||||
string2=string2 from foo in fr-FR
|
||||
'@
|
||||
@@ -1,4 +0,0 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 for en-US under newbase
|
||||
string2=string2 for en-US under newbase
|
||||
'@
|
||||
@@ -1,4 +0,0 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 for en-US from foo under newbase
|
||||
string2=string2 for en-US from foo under newbase
|
||||
'@
|
||||
@@ -1,4 +0,0 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 for fr-FR under newbase
|
||||
string2=string2 for fr-FR under newbase
|
||||
'@
|
||||
@@ -1,4 +0,0 @@
|
||||
ConvertFrom-StringData @'
|
||||
string1=string1 for fr-FR from foo under newbase
|
||||
string2=string2 for fr-FR from foo under newbase
|
||||
'@
|
||||
Reference in New Issue
Block a user