Merge pull request #7021 from nguerrera/loc-override
Allow CLI UI language to be overridden by an environment variable
This commit is contained in:
commit
86d9577606
8 changed files with 111 additions and 11 deletions
|
@ -28,6 +28,7 @@ namespace Microsoft.DotNet.Cli.Build
|
|||
private IEnumerable<string> _environmentVariablesToKeep = new string []
|
||||
{
|
||||
"DOTNET_CLI_TELEMETRY_SESSIONID",
|
||||
"DOTNET_CLI_UI_LANGUAGE",
|
||||
"DOTNET_MULTILEVEL_LOOKUP",
|
||||
"DOTNET_RUNTIME_ID",
|
||||
"DOTNET_SKIP_FIRST_TIME_EXPERIENCE",
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Microsoft.DotNet.Cli.Utils
|
|||
{
|
||||
public class Product
|
||||
{
|
||||
public static readonly string LongName = LocalizableStrings.DotNetCommandLineTools;
|
||||
public static string LongName => LocalizableStrings.DotNetCommandLineTools;
|
||||
public static readonly string Version = GetProductVersion();
|
||||
|
||||
private static string GetProductVersion()
|
||||
|
|
|
@ -198,6 +198,8 @@ namespace Microsoft.DotNet.Cli
|
|||
// by default, .NET Core doesn't have all code pages needed for Console apps.
|
||||
// see the .NET Core Notes in https://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
|
||||
UILanguageOverride.Setup();
|
||||
}
|
||||
|
||||
internal static bool TryGetBuiltInCommand(string commandName, out BuiltInCommandMetadata builtInCommand)
|
||||
|
|
81
src/dotnet/UILanguageOverride.cs
Normal file
81
src/dotnet/UILanguageOverride.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Microsoft.DotNet.Cli
|
||||
{
|
||||
internal static class UILanguageOverride
|
||||
{
|
||||
private const string DOTNET_CLI_UI_LANGUAGE = nameof(DOTNET_CLI_UI_LANGUAGE);
|
||||
private const string VSLANG = nameof(VSLANG);
|
||||
private const string PreferredUILang = nameof(PreferredUILang);
|
||||
|
||||
public static void Setup()
|
||||
{
|
||||
CultureInfo language = GetOverriddenUILanguage();
|
||||
if (language != null)
|
||||
{
|
||||
ApplyOverrideToCurrentProcess(language);
|
||||
FlowOverrideToChildProcesses(language);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyOverrideToCurrentProcess(CultureInfo language)
|
||||
{
|
||||
CultureInfo.DefaultThreadCurrentUICulture = language;
|
||||
}
|
||||
|
||||
private static void FlowOverrideToChildProcesses(CultureInfo language)
|
||||
{
|
||||
// Do not override any environment variables that are already set as we do not want to clobber a more granular setting with our global setting.
|
||||
SetIfNotAlreadySet(DOTNET_CLI_UI_LANGUAGE, language.Name);
|
||||
SetIfNotAlreadySet(VSLANG, language.LCID); // for tools following VS guidelines to just work in CLI
|
||||
SetIfNotAlreadySet(PreferredUILang, language.Name); // for C#/VB targets that pass $(PreferredUILang) to compiler
|
||||
}
|
||||
|
||||
private static CultureInfo GetOverriddenUILanguage()
|
||||
{
|
||||
// DOTNET_CLI_UI_LANGUAGE=<culture name> is the main way for users to customize the CLI's UI language.
|
||||
string dotnetCliLanguage = Environment.GetEnvironmentVariable(DOTNET_CLI_UI_LANGUAGE);
|
||||
if (dotnetCliLanguage != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CultureInfo(dotnetCliLanguage);
|
||||
}
|
||||
catch (CultureNotFoundException) { }
|
||||
}
|
||||
|
||||
// VSLANG=<lcid> is set by VS and we respect that as well so that we will respect the VS
|
||||
// language preference if we're invoked by VS.
|
||||
string vsLang = Environment.GetEnvironmentVariable(VSLANG);
|
||||
if (vsLang != null && int.TryParse(vsLang, out int vsLcid))
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CultureInfo(vsLcid);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException) { }
|
||||
catch (CultureNotFoundException) { }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void SetIfNotAlreadySet(string environmentVariableName, string value)
|
||||
{
|
||||
string currentValue = Environment.GetEnvironmentVariable(environmentVariableName);
|
||||
if (currentValue == null)
|
||||
{
|
||||
Environment.SetEnvironmentVariable(environmentVariableName, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetIfNotAlreadySet(string environmentVariableName, int value)
|
||||
{
|
||||
SetIfNotAlreadySet(environmentVariableName, value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -23,6 +24,15 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
private TempRoot _temp;
|
||||
private static TestAssets s_testAssets;
|
||||
|
||||
static TestBase()
|
||||
{
|
||||
// set culture of test process to match CLI sub-processes when the UI language is overriden.
|
||||
string overriddenUILanguage = Environment.GetEnvironmentVariable("DOTNET_CLI_UI_LANGUAGE");
|
||||
if (overriddenUILanguage != null)
|
||||
{
|
||||
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(overriddenUILanguage);
|
||||
}
|
||||
}
|
||||
|
||||
protected static string RepoRoot
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.DotNet.New.Tests
|
||||
{
|
||||
public class NewCommandTests
|
||||
public class NewCommandTests : TestBase
|
||||
{
|
||||
[Fact]
|
||||
public void WhenSwitchIsSkippedThenItPrintsError()
|
||||
|
@ -16,7 +16,10 @@ namespace Microsoft.DotNet.New.Tests
|
|||
|
||||
cmd.ExitCode.Should().NotBe(0);
|
||||
|
||||
cmd.StdErr.Should().StartWith("No templates matched the input template name: Web1.1.");
|
||||
if (!DotnetUnderTest.IsLocalized())
|
||||
{
|
||||
cmd.StdErr.Should().StartWith("No templates matched the input template name: Web1.1.");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -26,7 +29,10 @@ namespace Microsoft.DotNet.New.Tests
|
|||
|
||||
cmd.ExitCode.Should().NotBe(0);
|
||||
|
||||
cmd.StdErr.Should().StartWith("Unable to determine the desired template from the input template name: c.");
|
||||
if (!DotnetUnderTest.IsLocalized())
|
||||
{
|
||||
cmd.StdErr.Should().StartWith("Unable to determine the desired template from the input template name: c.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ using Microsoft.DotNet.TestFramework;
|
|||
using Microsoft.DotNet.Tools.Test.Utilities;
|
||||
using Xunit;
|
||||
|
||||
using LocalizableStrings = Microsoft.DotNet.Tools.Run.LocalizableStrings;
|
||||
|
||||
namespace Microsoft.DotNet.Cli.Run.Tests
|
||||
{
|
||||
public class GivenDotnetRunBuildsCsproj : TestBase
|
||||
|
@ -280,7 +282,7 @@ namespace Microsoft.DotNet.Cli.Run.Tests
|
|||
.ExecuteWithCapturedOutput("--launch-profile test")
|
||||
.Should().Pass()
|
||||
.And.HaveStdOutContaining("Hello World!")
|
||||
.And.HaveStdErrContaining("The specified launch profile could not be located.");
|
||||
.And.HaveStdErrContaining(LocalizableStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -368,7 +370,7 @@ namespace Microsoft.DotNet.Cli.Run.Tests
|
|||
.ExecuteWithCapturedOutput("--launch-profile Third")
|
||||
.Should().Pass()
|
||||
.And.HaveStdOutContaining("(NO MESSAGE)")
|
||||
.And.HaveStdErrContaining("The launch profile \"Third\" could not be applied.");
|
||||
.And.HaveStdErrContaining(string.Format(LocalizableStrings.RunCommandExceptionCouldNotApplyLaunchSettings, "Third", "").Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -396,7 +398,7 @@ namespace Microsoft.DotNet.Cli.Run.Tests
|
|||
.ExecuteWithCapturedOutput("--launch-profile \"IIS Express\"")
|
||||
.Should().Pass()
|
||||
.And.HaveStdOutContaining("(NO MESSAGE)")
|
||||
.And.HaveStdErrContaining("The launch profile \"IIS Express\" could not be applied.");
|
||||
.And.HaveStdErrContaining(string.Format(LocalizableStrings.RunCommandExceptionCouldNotApplyLaunchSettings, "IIS Express", "").Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -485,7 +487,7 @@ namespace Microsoft.DotNet.Cli.Run.Tests
|
|||
|
||||
cmd.Should().Pass()
|
||||
.And.HaveStdOutContaining("(NO MESSAGE)")
|
||||
.And.HaveStdErrContaining("The launch profile \"(Default)\" could not be applied.");
|
||||
.And.HaveStdErrContaining(string.Format(LocalizableStrings.RunCommandExceptionCouldNotApplyLaunchSettings, LocalizableStrings.DefaultLaunchProfileDisplayName, "").Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -514,7 +516,7 @@ namespace Microsoft.DotNet.Cli.Run.Tests
|
|||
|
||||
cmd.Should().Pass()
|
||||
.And.HaveStdOutContaining("(NO MESSAGE)")
|
||||
.And.HaveStdErrContaining("The launch profile \"(Default)\" could not be applied.");
|
||||
.And.HaveStdErrContaining(string.Format(LocalizableStrings.RunCommandExceptionCouldNotApplyLaunchSettings, LocalizableStrings.DefaultLaunchProfileDisplayName, "").Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ namespace Microsoft.DotNet.Tests.ParserTests
|
|||
{
|
||||
public class ValidationMessageTests
|
||||
{
|
||||
private readonly ITestOutputHelper output;
|
||||
|
||||
[Fact]
|
||||
public void ValidationMessagesFormatCorrectly()
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue