注意事项:
-
PowerShell [Core] 本身在 v7.0 中尚未本地化; this GitHub issue 中正在跟踪进度;但是,以下解决方案确实适用于附带本地化消息和帮助内容的第三方模块。
-
由于 Windows PowerShell 中的一个错误(PowerShell [Core] v6+ 不受影响),会话中更改为[cultureinfo]::CurrentUICulture 和 [cultureinfo]::CurrentCulture 在命令提示符处自动重置,只要命令完成执行;但是,对于给定脚本,更改对整个脚本及其被调用者仍然有效 - 请参阅 this answer。
退后一步:
我编写了一些使用系统(powershell)命令输出的软件,但没有预见到除英语以外的其他语言的输出会有所不同。
这正是通常值得寻找PowerShell-native解决方案而不是调用外部程序的原因:
不必解析 - 可能是本地化的 - 文本,例如 netstat.exe,PowerShell 命令返回 对象,您可以可靠地访问其属性以独立于文化的方式。
具体来说,Mathias R. Jessen 建议将Get-NetTCPConnection 视为netstat.exe 的PowerShell 替代品(适用于Windows Server 2012 / Windows 8 及更高版本)。
为了帮助解决 (b),下面是 helper 函数 Use-Culture,您可以按如下方式使用它来执行给定的脚本块 ({ ... })给定 (UI) 文化的背景:
# Windows PowerShell: emit an error message in *French* (culture 'fr-FR')
# Note: Does not yet work as of PowerShell [Core] 7.0
PS> Use-Culture fr-FR { try { 1/0 } catch { "Localized message: $_" } }
Localized message: Tentative de division par zéro.
请注意,文化和 UI 文化的文化变化是命令范围的;也就是说,在命令完成后,之前的设置再次生效。
函数Use-Culture的源代码:
注意:代码改编自this venerable blog post。
# Runs a script block in the context of the specified culture, without changing
# the session's culture persistently.
# Handy for quickly testing the behavior of a command in the context of a different culture.
# Example:
# Use-Culture fr-FR { Get-Date }
function Use-Culture
{
param(
[Parameter(Mandatory)] [cultureinfo] $Culture,
[Parameter(Mandatory)] [scriptblock] $ScriptBlock
)
# Note: In Windows 10, a culture-info object can be created from *any* string.
# However, an identifier that does't refer to a *predefined* culture is
# reflected in .LCID containing 4096 (0x1000)
if ($Culture.LCID -eq 4096) { Throw "Unrecognized culture: $($Culture.DisplayName)" }
# Save the current culture / UI culture values.
$PrevCultures = [Threading.Thread]::CurrentThread.CurrentCulture, [Threading.Thread]::CurrentThread.CurrentUICulture
try {
# (Temporarily) set the culture and UI culture for the current thread.
[Threading.Thread]::CurrentThread.CurrentCulture = [Threading.Thread]::CurrentThread.CurrentUICulture = $Culture
# Now invoke the given code.
& $ScriptBlock
}
finally {
# Restore the previous culture / UI culture values.
[Threading.Thread]::CurrentThread.CurrentCulture = $PrevCultures[0]
[Threading.Thread]::CurrentThread.CurrentUICulture = $PrevCultures[1]
}
}