Fix localizability issues in Windows Terminal (#5339)

Loc issues are given to us through the internal bug tracker.

* Lock some strings, or parts of strings, that should not be localized.
* Switch to positional format parameters
* Remove the forced newlines in the warning resources; insert them at
  runtime

Fixes MSFT:25936156.
This commit is contained in:
Dustin L. Howett (MSFT) 2020-04-14 13:48:46 -07:00 committed by GitHub
parent 348f46866a
commit 37e62dabd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 46 deletions

View file

@ -339,12 +339,14 @@ namespace winrt::TerminalApp::implementation
const auto errorLabel = GetLibraryResourceString(contentKey);
errorRun.Text(errorLabel);
warningsTextBlock.Inlines().Append(errorRun);
warningsTextBlock.Inlines().Append(Documents::LineBreak{});
if (FAILED(settingsLoadedResult))
{
if (!_settingsLoadExceptionText.empty())
{
warningsTextBlock.Inlines().Append(_BuildErrorRun(_settingsLoadExceptionText, ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Resources()));
warningsTextBlock.Inlines().Append(Documents::LineBreak{});
}
}
@ -352,6 +354,7 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::UI::Xaml::Documents::Run usingDefaultsRun;
const auto usingDefaultsText = RS_(L"UsingDefaultSettingsText");
usingDefaultsRun.Text(usingDefaultsText);
warningsTextBlock.Inlines().Append(Documents::LineBreak{});
warningsTextBlock.Inlines().Append(usingDefaultsRun);
Controls::ContentDialog dialog;
@ -388,6 +391,7 @@ namespace winrt::TerminalApp::implementation
if (!warningText.empty())
{
warningsTextBlock.Inlines().Append(_BuildErrorRun(warningText, ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Resources()));
warningsTextBlock.Inlines().Append(Documents::LineBreak{});
}
}

View file

@ -118,37 +118,30 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="InitialJsonParseErrorText" xml:space="preserve">
<value>Settings could not be loaded from file. Check for syntax errors, including trailing commas.
</value>
<value>Settings could not be loaded from file. Check for syntax errors, including trailing commas.</value>
</data>
<data name="MissingDefaultProfileText" xml:space="preserve">
<value>Could not find your default profile in your list of profiles - using the first profile. Check to make sure the defaultProfile matches the GUID of one of your profiles.
</value>
<value>Could not find your default profile in your list of profiles - using the first profile. Check to make sure the "defaultProfile" matches the GUID of one of your profiles.</value>
<comment>{Locked="\"defaultProfile\""}</comment>
</data>
<data name="DuplicateProfileText" xml:space="preserve">
<value>Found multiple profiles with the same GUID in your settings file - ignoring duplicates. Make sure each profile's GUID is unique.
</value>
<value>Found multiple profiles with the same GUID in your settings file - ignoring duplicates. Make sure each profile's GUID is unique.</value>
</data>
<data name="UnknownColorSchemeText" xml:space="preserve">
<value>Found a profile with an invalid "colorScheme". Defaulting that profile to the default colors. Make sure that when setting a "colorScheme", the value matches the "name" of a color scheme in the "schemes" list.
</value>
<value>Found a profile with an invalid "colorScheme". Defaulting that profile to the default colors. Make sure that when setting a "colorScheme", the value matches the "name" of a color scheme in the "schemes" list.</value>
<comment>{Locked="\"colorScheme\"","\"name\"","\"schemes\""}</comment>
</data>
<data name="NoProfilesText" xml:space="preserve">
<value>No profiles were found in your settings.
</value>
<value>No profiles were found in your settings.</value>
</data>
<data name="AllProfilesHiddenText" xml:space="preserve">
<value>All profiles were hidden in your settings. You must have at least one non-hidden profile.
</value>
<value>All profiles were hidden in your settings. You must have at least one non-hidden profile.</value>
</data>
<data name="ReloadJsonParseErrorText" xml:space="preserve">
<value>Settings could not be reloaded from file. Check for syntax errors, including trailing commas.
</value>
<value>Settings could not be reloaded from file. Check for syntax errors, including trailing commas.</value>
</data>
<data name="UsingDefaultSettingsText" xml:space="preserve">
<value>
Temporarily using the Windows Terminal default settings.
</value>
<value>Temporarily using the Windows Terminal default settings.</value>
</data>
<data name="InitialJsonParseErrorTitle" xml:space="preserve">
<value>Failed to load settings</value>
@ -164,6 +157,7 @@ Temporarily using the Windows Terminal default settings.
</data>
<data name="FeedbackUriValue" xml:space="preserve">
<value>https://go.microsoft.com/fwlink/?linkid=2125419</value>
<comment>{Locked}This is a FWLink, so it will be localized with the fwlink tool</comment>
</data>
<data name="AboutMenuItem" xml:space="preserve">
<value>About</value>
@ -176,21 +170,22 @@ Temporarily using the Windows Terminal default settings.
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>Found a profile with an invalid "backgroundImage". Defaulting that profile to have no background image. Make sure that when setting a "backgroundImage", the value is a valid file path to an image.</value>
<comment>{Locked="\"backgroundImage\""}</comment>
</data>
<data name="InvalidIcon" xml:space="preserve">
<value>Found a profile with an invalid "icon". Defaulting that profile to have no icon. Make sure that when setting an "icon", the value is a valid file path to an image.</value>
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
</data>
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
<value>Warnings were found while parsing your keybindings:
</value>
<value>Warnings were found while parsing your keybindings:</value>
</data>
<data name="TooManyKeysForChord" xml:space="preserve">
<value> Found a keybinding with too many strings for the "keys" array. There should only be one string value in the "keys" array.
</value>
<value>&#x2022; Found a keybinding with too many strings for the "keys" array. There should only be one string value in the "keys" array.</value>
<comment>{Locked="\"keys\"","&#x2022;"} This glyph is a bullet, used in a bulleted list.</comment>
</data>
<data name="MissingRequiredParameter" xml:space="preserve">
<value> Found a keybinding that was missing a required parameter value. This keybinding will be ignored.
</value>
<value>&#x2022; Found a keybinding that was missing a required parameter value. This keybinding will be ignored.</value>
<comment>{Locked="&#x2022;"} This glyph is a bullet, used in a bulleted list.</comment>
</data>
<data name="CmdCommandArgDesc" xml:space="preserve">
<value>An optional command, with arguments, to be spawned in the new tab or pane</value>
@ -211,7 +206,7 @@ Temporarily using the Windows Terminal default settings.
<value>Create a new tab</value>
</data>
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Open with the given profile. Accepts either the name or guid of a profile</value>
<value>Open with the given profile. Accepts either the name or GUID of a profile</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Create a new split pane</value>
@ -223,7 +218,8 @@ Temporarily using the Windows Terminal default settings.
<value>Create the new pane as a vertical split (think [|])</value>
</data>
<data name="CmdStartingDirArgDesc" xml:space="preserve">
<value>Open in the given directory instead of the profile's set startingDirectory</value>
<value>Open in the given directory instead of the profile's set "startingDirectory"</value>
<comment>{Locked="\"startingDirectory\""}</comment>
</data>
<data name="NewTabSplitButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.HelpText" xml:space="preserve">
<value>Press the button to open a new terminal tab with your default profile. Open the flyout to select which profile you want to open.</value>
@ -287,4 +283,4 @@ Temporarily using the Windows Terminal default settings.
<value>Command Prompt</value>
<comment>This is the name of "Command Prompt", as localized in Windows. The localization here should match the one in the Windows product for "Command Prompt"</comment>
</data>
</root>
</root>

View file

@ -47,7 +47,7 @@ static constexpr int USER_INFO_COLOR = 97; // white - the color of clarifying in
static inline std::wstring _colorize(const unsigned int colorCode, const std::wstring_view text)
{
return wil::str_printf<std::wstring>(L"\x1b[%um%.*s\x1b[m", colorCode, gsl::narrow_cast<size_t>(text.size()), text.data());
return fmt::format(L"\x1b[{0}m{1}\x1b[m", colorCode, text);
}
// Takes N resource names, loads the first one as a format string, and then
@ -57,12 +57,12 @@ static inline std::wstring _colorize(const unsigned int colorCode, const std::ws
template<typename... Args>
static inline std::wstring _formatResWithColoredUserInputOptions(const std::wstring_view resourceKey, Args&&... args)
{
return wil::str_printf<std::wstring>(GetLibraryResourceString(resourceKey).data(), (_colorize(USER_INPUT_COLOR, GetLibraryResourceString(args)).data())...);
return fmt::format(std::wstring_view{ GetLibraryResourceString(resourceKey) }, (_colorize(USER_INPUT_COLOR, GetLibraryResourceString(args)))...);
}
static inline std::wstring _formatTenantLine(int tenantNumber, const std::wstring_view tenantName, const std::wstring_view tenantID)
{
return wil::str_printf<std::wstring>(RS_(L"AzureIthTenant").data(), _colorize(USER_INPUT_COLOR, std::to_wstring(tenantNumber)).data(), _colorize(USER_INFO_COLOR, tenantName).data(), tenantID.data());
return fmt::format(std::wstring_view{ RS_(L"AzureIthTenant") }, _colorize(USER_INPUT_COLOR, std::to_wstring(tenantNumber)), _colorize(USER_INFO_COLOR, tenantName), tenantID);
}
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation

View file

@ -246,7 +246,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
// EXIT POINT
const auto hr = wil::ResultFromCaughtException();
winrt::hstring failureText{ wil::str_printf<std::wstring>(RS_(L"ProcessFailedToLaunch").c_str(), gsl::narrow_cast<unsigned int>(hr), _commandline.c_str()) };
winrt::hstring failureText{ fmt::format(std::wstring_view{ RS_(L"ProcessFailedToLaunch") }, gsl::narrow_cast<unsigned long>(hr), _commandline) };
_TerminalOutputHandlers(failureText);
_transitionToState(ConnectionState::Failed);
@ -262,7 +262,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
{
try
{
winrt::hstring exitText{ wil::str_printf<std::wstring>(RS_(L"ProcessExited").c_str(), status) };
winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, status) };
_TerminalOutputHandlers(L"\r\n");
_TerminalOutputHandlers(exitText);
}

View file

@ -124,13 +124,16 @@
<value>Please enter the desired tenant number.</value>
</data>
<data name="AzureNewLogin" xml:space="default">
<value>Enter %s to login with a different account</value>
<value>Enter {0} to login with a new account</value>
<comment>{0} will be replaced with the resource from AzureUserEntry_NewLogin; it is intended to be a single-character shorthand for "new account"</comment>
</data>
<data name="AzureRemoveStored" xml:space="default">
<value>Enter %s to remove the above saved connection settings.</value>
<value>Enter {0} to remove the above saved connection settings.</value>
<comment>{0} will be replaced with the resource from AzureUserEntry_RemoveStored; it is intended to be a single-character shorthand for "remove stored"</comment>
</data>
<data name="AzureInvalidAccessInput" xml:space="default">
<value>Please enter a valid number to access the stored connection settings, %s to make a new one, or %s to remove the stored ones.</value>
<value>Please enter a valid number to access the stored connection settings, {0} to log in with a new account, or {1} to remove the saved connection settings.</value>
<comment>{0} will be replaced with the resource from AzureUserEntry_NewLogin, and {1} will be replaced with AzureUserEntry_RemoveStored. This is an error message, used after AzureNewLogin/AzureRemoveStored if the user enters an invalid value.</comment>
</data>
<data name="AzureNonNumberError" xml:space="preserve">
<value>Please enter a number.</value>
@ -143,12 +146,15 @@
</data>
<data name="AzureNoCloudAccount" xml:space="preserve">
<value>You have not set up your cloud shell account yet. Please go to https://shell.azure.com to set it up.</value>
<comment>{Locked="https://shell.azure.com"} This URL should not be localized. Everything else should.</comment>
</data>
<data name="AzureStorePrompt" xml:space="default">
<value>Do you want to save these connection settings for future logins? [%s/%s]</value>
<value>Do you want to save these connection settings for future logins? [{0}/{1}]</value>
<comment>{0} and {1} will be replaced with AzureUserEntry_Yes and AzureUserEntry_No. They are single-character shorthands for "yes" and "no" in this language.</comment>
</data>
<data name="AzureInvalidStoreInput" xml:space="default">
<value>Please enter %s or %s</value>
<value>Please enter {0} or {1}</value>
<comment>{0} and {1} will be replaced with AzureUserEntry_Yes and AzureUserEntry_No. This resource will be used as an error response after AzureStorePrompt.</comment>
</data>
<data name="AzureRequestingCloud" xml:space="preserve">
<value>Requesting a cloud shell instance...</value>
@ -184,35 +190,36 @@
<value>&lt;unknown tenant name&gt;</value>
</data>
<data name="AzureIthTenant" xml:space="default">
<value>Tenant %s: %s (%s)</value>
<value>Tenant {0}: {1} ({2})</value>
<comment>{0} is the tenant's number, which the user will enter to connect to the tenant. {1} is the tenant's display name, which will be meaningful for the user. {2} is the tenant's internal ID number.</comment>
</data>
<data name="AzureSuccessfullyAuthenticated" xml:space="preserve">
<value>Authenticated.</value>
</data>
<data name="AzureUserEntry_NewLogin" xml:space="preserve">
<value>n</value>
<comment>The user must enter this character to say NEW LOGIN (AzureInvalidAccessInput, AzureNewLogin)</comment>
<comment>This is shorthand for "new login". The user must enter this character to activate the New Login feature (AzureInvalidAccessInput, AzureNewLogin)</comment>
</data>
<data name="AzureUserEntry_RemoveStored" xml:space="preserve">
<value>r</value>
<comment>The user must enter this character to say REMOVE SAVED LOGINS (AzureRemoveStored, AzureInvalidAccessInput)</comment>
<comment>This is shorthand for "remove saved connections". The user must enter this character to activate the Remove Saved Logins feature (AzureRemoveStored, AzureInvalidAccessInput)</comment>
</data>
<data name="AzureUserEntry_Yes" xml:space="preserve">
<value>y</value>
<comment>The user must enter this character to signify YES</comment>
<comment>This is shorthand for "yes". The user must enter this character to CONFIRM a prompt.</comment>
</data>
<data name="AzureUserEntry_No" xml:space="preserve">
<value>n</value>
<comment>The user must enter this character to signify NO</comment>
<comment>This is shorthand for "no". The user must enter this character to DECLINE a prompt.</comment>
</data>
<data name="ProcessExited" xml:space="preserve">
<value>[process exited with code %u]</value>
<comment>The first argument (%u) is the (positive) error code of the process. 0 is success.</comment>
<value>[process exited with code {0}]</value>
<comment>The first argument {0} is the (positive) error code of the process. When there is no error, the number ZERO will be displayed.</comment>
</data>
<data name="ProcessFailedToLaunch" xml:space="preserve">
<value>[error 0x%8.08x when launching `%ls']</value>
<comment>The first argument is the hexadecimal error code. The second is the process name.
If this resource spans multiple lines, it will not be displayed properly. Yeah.</comment>
<value>[error {0:#08x} when launching `{1}']</value>
<comment>The first argument {0...} is the hexadecimal error code. The second argument {1} is the user-specified path to a program.
If this string is broken to multiple lines, it will not be displayed properly.</comment>
</data>
<data name="TelnetInternetOrServerIssue" xml:space="preserve">
<value>Could not connect to telnet server.</value>

View file

@ -163,6 +163,7 @@
</data>
<data name="SearchBox_Close.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Close Search Box</value>
<comment>The explanation of the search box close button used by Narrator and other screen readers.</comment>
</data>
<data name="TermControl_RendererFailedTextBlock.Text" xml:space="preserve">
<value>This terminal has encountered an issue with the graphics driver and it could not recover in time. It has been suspended.</value>