Commit 9cd5d4b9 authored by Aya Elgendy's avatar Aya Elgendy Committed by Chromium LUCI CQ

Fix singular/plural in pin dialog error message

Fix a typo in the pin dialog error message which read
"1 attempts left" instead of "1 attempt left" when the user has
attempted incorrect pins and there's only 1 attempt remaining.

This CL is the second attempt to solve the issue after being
reverted in commit 7672be058caa26d14678f8b0d4a06de56c155309
due to an issue in the error message format of the SAML login.
The first attempt only handled the normal login while this one
handles both the SAML login and the normal login.

Bug: 1060695
Change-Id: Ieac135c90ef6e20cf53bd26d2ab87cf0147c21a0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2599814
Commit-Queue: Aya Nader Elgendy‎ <ayag@chromium.org>
Reviewed-by: default avatarRoman Sorokin [CET] <rsorokin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841990}
parent 983a28cc
...@@ -67,9 +67,9 @@ constexpr char kPinDialogDefaultTitle[] = "Smart card PIN"; ...@@ -67,9 +67,9 @@ constexpr char kPinDialogDefaultTitle[] = "Smart card PIN";
constexpr char kPinDialogInvalidPinTitle[] = "Invalid PIN."; constexpr char kPinDialogInvalidPinTitle[] = "Invalid PIN.";
constexpr char kPinDialogInvalidPin2AttemptsTitle[] = constexpr char kPinDialogInvalidPin2AttemptsTitle[] =
"Invalid PIN. 2 attempts left"; "Invalid PIN. 2 attempts left";
// TODO(crbug.com/1060695): Fix the incorrect plural in the message.
constexpr char kPinDialogInvalidPin1AttemptTitle[] = constexpr char kPinDialogInvalidPin1AttemptTitle[] =
"Invalid PIN. 1 attempts left"; "Invalid PIN. 1 attempt left";
constexpr char kPinDialogNoAttemptsLeftTitle[] = constexpr char kPinDialogNoAttemptsLeftTitle[] =
"Maximum allowed attempts exceeded."; "Maximum allowed attempts exceeded.";
......
...@@ -129,8 +129,10 @@ OobeTypes.SecurityTokenPinDialogErrorType = { ...@@ -129,8 +129,10 @@ OobeTypes.SecurityTokenPinDialogErrorType = {
* @typedef {{ * @typedef {{
* codeType: OobeTypes.SecurityTokenPinDialogType, * codeType: OobeTypes.SecurityTokenPinDialogType,
* enableUserInput: boolean, * enableUserInput: boolean,
* errorLabel: OobeTypes.SecurityTokenPinDialogErrorType,
* attemptsLeft: number, * attemptsLeft: number,
* hasError: boolean,
* formattedError: string,
* formattedAttemptsLeft: string,
* }} * }}
*/ */
OobeTypes.SecurityTokenPinDialogParameters; OobeTypes.SecurityTokenPinDialogParameters;
......
...@@ -33,16 +33,14 @@ ...@@ -33,16 +33,14 @@
<div slot="footer"> <div slot="footer">
<div id="pinKeyboardContainer" hidden="[[processingCompletion_]]"> <div id="pinKeyboardContainer" hidden="[[processingCompletion_]]">
<pin-keyboard id="pinKeyboard" enable-letters allow-non-digit <pin-keyboard id="pinKeyboard" enable-letters allow-non-digit
has-error="[[isErrorLabelVisible_(errorLabelId_, userEdited_)]]" has-error="[[isErrorLabelVisible_(parameters, userEdited_)]]"
aria-label="[[getLabel_(locale, parameters, errorLabelId_, aria-label="[[getLabel_(parameters, userEdited_)]]"
userEdited_)]]"
on-pin-change="onPinChange_" on-submit="onSubmit_" on-pin-change="onPinChange_" on-submit="onSubmit_"
disabled="[[!canEdit_]]"> disabled="[[!canEdit_]]">
<div id="errorContainer" role="alert" problem <div id="errorContainer" role="alert" problem
invisible$="[[!isLabelVisible_(parameters, userEdited_)]]"> invisible$="[[!isLabelVisible_(parameters, userEdited_)]]">
<iron-icon id="errorIcon" icon="cr:error-outline"></iron-icon> <iron-icon id="errorIcon" icon="cr:error-outline"></iron-icon>
<span id="error">[[getLabel_(locale, parameters, errorLabelId_, <span id="error">[[getLabel_(parameters, userEdited_)]]</span>
userEdited_)]]</span>
</div> </div>
</pin-keyboard> </pin-keyboard>
</div> </div>
......
...@@ -34,16 +34,6 @@ Polymer({ ...@@ -34,16 +34,6 @@ Polymer({
observer: 'onParametersChanged_', observer: 'onParametersChanged_',
}, },
/**
* The i18n string ID containing the error label to be shown to the user.
* Is null when there's no error label.
* @private
*/
errorLabelId_: {
type: String,
computed: 'computeErrorLabelId_(parameters)',
},
/** /**
* Whether the current state is the wait for the processing completion * Whether the current state is the wait for the processing completion
* (i.e., the backend is verifying the entered PIN). * (i.e., the backend is verifying the entered PIN).
...@@ -80,7 +70,7 @@ Polymer({ ...@@ -80,7 +70,7 @@ Polymer({
canEdit_: { canEdit_: {
type: Boolean, type: Boolean,
computed: computed:
'computeCanEdit_(parameters.attemptsLeft, processingCompletion_)', 'computeCanEdit_(parameters.enableUserInput, processingCompletion_)',
}, },
/** /**
...@@ -89,7 +79,7 @@ Polymer({ ...@@ -89,7 +79,7 @@ Polymer({
*/ */
canSubmit_: { canSubmit_: {
type: Boolean, type: Boolean,
computed: 'computeCanSubmit_(parameters.attemptsLeft, ' + computed: 'computeCanSubmit_(parameters.enableUserInput, ' +
'hasValue_, processingCompletion_)', 'hasValue_, processingCompletion_)',
}, },
}, },
...@@ -101,52 +91,27 @@ Polymer({ ...@@ -101,52 +91,27 @@ Polymer({
this.$.pinKeyboard.focusInputSynchronously(); this.$.pinKeyboard.focusInputSynchronously();
}, },
/**
* Returns the i18n string ID for the current error label.
* @param {OobeTypes.SecurityTokenPinDialogParameters} parameters
* @return {string|null}
* @private
*/
computeErrorLabelId_(parameters) {
if (!parameters)
return null;
switch (parameters.errorLabel) {
case OobeTypes.SecurityTokenPinDialogErrorType.NONE:
return null;
case OobeTypes.SecurityTokenPinDialogErrorType.UNKNOWN:
return 'securityTokenPinDialogUnknownError';
case OobeTypes.SecurityTokenPinDialogErrorType.INVALID_PIN:
return 'securityTokenPinDialogUnknownInvalidPin';
case OobeTypes.SecurityTokenPinDialogErrorType.INVALID_PUK:
return 'securityTokenPinDialogUnknownInvalidPuk';
case OobeTypes.SecurityTokenPinDialogErrorType.MAX_ATTEMPTS_EXCEEDED:
return 'securityTokenPinDialogUnknownMaxAttemptsExceeded';
default:
assertNotReached(`Unexpected enum value: ${parameters.errorLabel}`);
}
},
/** /**
* Computes the value of the canEdit_ property. * Computes the value of the canEdit_ property.
* @param {number} attemptsLeft * @param {boolean} enableUserInput
* @param {boolean} processingCompletion * @param {boolean} processingCompletion
* @return {boolean} * @return {boolean}
* @private * @private
*/ */
computeCanEdit_(attemptsLeft, processingCompletion) { computeCanEdit_(enableUserInput, processingCompletion) {
return attemptsLeft != 0 && !processingCompletion; return enableUserInput && !processingCompletion;
}, },
/** /**
* Computes the value of the canSubmit_ property. * Computes the value of the canSubmit_ property.
* @param {number} attemptsLeft * @param {boolean} enableUserInput
* @param {boolean} hasValue * @param {boolean} hasValue
* @param {boolean} processingCompletion * @param {boolean} processingCompletion
* @return {boolean} * @return {boolean}
* @private * @private
*/ */
computeCanSubmit_(attemptsLeft, hasValue, processingCompletion) { computeCanSubmit_(enableUserInput, hasValue, processingCompletion) {
return attemptsLeft != 0 && hasValue && !processingCompletion; return enableUserInput && hasValue && !processingCompletion;
}, },
/** /**
...@@ -203,10 +168,7 @@ Polymer({ ...@@ -203,10 +168,7 @@ Polymer({
* @private * @private
*/ */
isErrorLabelVisible_(parameters, userEdited) { isErrorLabelVisible_(parameters, userEdited) {
return parameters && return parameters && parameters.hasError && !userEdited;
parameters.errorLabel !==
OobeTypes.SecurityTokenPinDialogErrorType.NONE &&
!userEdited;
}, },
/** /**
...@@ -234,14 +196,12 @@ Polymer({ ...@@ -234,14 +196,12 @@ Polymer({
/** /**
* Returns the label to be used for the PIN input field. * Returns the label to be used for the PIN input field.
* @param {string} locale
* @param {OobeTypes.SecurityTokenPinDialogParameters} parameters * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters
* @param {string|null} errorLabelId
* @param {boolean} userEdited * @param {boolean} userEdited
* @return {string} * @return {string}
* @private * @private
*/ */
getLabel_(locale, parameters, errorLabelId, userEdited) { getLabel_(parameters, userEdited) {
if (!this.isLabelVisible_(parameters, userEdited)) { if (!this.isLabelVisible_(parameters, userEdited)) {
// Neither error nor the number of left attempts are to be displayed. // Neither error nor the number of left attempts are to be displayed.
return ''; return '';
...@@ -249,20 +209,9 @@ Polymer({ ...@@ -249,20 +209,9 @@ Polymer({
if (!this.isErrorLabelVisible_(parameters, userEdited) && if (!this.isErrorLabelVisible_(parameters, userEdited) &&
this.isAttemptsLeftVisible_(parameters)) { this.isAttemptsLeftVisible_(parameters)) {
// There's no error, but the number of left attempts has to be displayed. // There's no error, but the number of left attempts has to be displayed.
return this.i18n( return parameters.formattedAttemptsLeft;
'securityTokenPinDialogAttemptsLeft', parameters.attemptsLeft);
}
// If we get here, |parameters| must be defined, and |parameters.errorLabel|
// != NONE, so |errorLabelId| will be defined.
assert(errorLabelId);
// Format the error and, if present, the number of left attempts.
if ((parameters && !parameters.enableUserInput) ||
!this.isAttemptsLeftVisible_(parameters)) {
return this.i18n(errorLabelId);
} }
return this.i18n( return parameters.formattedError;
'securityTokenPinDialogErrorAttempts', this.i18n(errorLabelId),
parameters.attemptsLeft);
}, },
}); });
})(); })();
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "base/containers/flat_set.h" #include "base/containers/flat_set.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/guid.h" #include "base/guid.h"
#include "base/i18n/message_formatter.h"
#include "base/i18n/number_formatting.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
...@@ -65,6 +67,7 @@ ...@@ -65,6 +67,7 @@
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "chrome/installer/util/google_update_settings.h" #include "chrome/installer/util/google_update_settings.h"
#include "chromeos/components/security_token_pin/constants.h" #include "chromeos/components/security_token_pin/constants.h"
#include "chromeos/components/security_token_pin/error_generator.h"
#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_features.h"
#include "chromeos/constants/chromeos_switches.h" #include "chromeos/constants/chromeos_switches.h"
#include "chromeos/constants/devicetype.h" #include "chromeos/constants/devicetype.h"
...@@ -270,8 +273,17 @@ base::Value MakeSecurityTokenPinDialogParameters( ...@@ -270,8 +273,17 @@ base::Value MakeSecurityTokenPinDialogParameters(
base::Value params(base::Value::Type::DICTIONARY); base::Value params(base::Value::Type::DICTIONARY);
params.SetIntKey("codeType", static_cast<int>(code_type)); params.SetIntKey("codeType", static_cast<int>(code_type));
params.SetBoolKey("enableUserInput", enable_user_input); params.SetBoolKey("enableUserInput", enable_user_input);
params.SetIntKey("errorLabel", static_cast<int>(error_label));
params.SetIntKey("attemptsLeft", attempts_left); params.SetIntKey("attemptsLeft", attempts_left);
params.SetBoolKey("hasError",
error_label != security_token_pin::ErrorLabel::kNone);
params.SetStringKey(
"formattedError",
GenerateErrorMessage(error_label, attempts_left, enable_user_input));
params.SetStringKey(
"formattedAttemptsLeft",
base::i18n::MessageFormatter::FormatWithNumberedArgs(
l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT),
attempts_left));
return params; return params;
} }
......
...@@ -322,10 +322,14 @@ Try tapping the mic to ask me anything. ...@@ -322,10 +322,14 @@ Try tapping the mic to ask me anything.
Unknown error. Unknown error.
</message> </message>
<message name="IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT" desc="The text displayed in the certificate provider PIN request dialog about the number of attempts left"> <message name="IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT" desc="The text displayed in the certificate provider PIN request dialog about the number of attempts left">
<ph name="ATTEMPTS_LEFT">$1<ex>3</ex></ph> attempts left {ATTEMPTS_LEFT, plural,
=1 {{0} attempt left}
other {{0} attempts left}}
</message> </message>
<message name="IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS" desc="The text displayed in the certificate provider PIN request dialog when the previous login attempt was unsuccessful but there are more attempts remaining. Includes the reason for the previous failure."> <message name="IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS" desc="The text displayed in the certificate provider PIN request dialog when the previous login attempt was unsuccessful but there are more attempts remaining. Includes the reason for the previous failure.">
<ph name="ERROR_MESSAGE">$1<ex>Invalid PIN.</ex></ph> <ph name="ATTEMPTS_LEFT">$2<ex>3</ex></ph> attempts left {ATTEMPTS_LEFT, plural,
=1 {<ph name="ERROR_MESSAGE">{1}<ex>Invalid PIN.</ex></ph> {0} attempt left}
other {<ph name="ERROR_MESSAGE">{1}<ex>Invalid PIN.</ex></ph> {0} attempts left}}
</message> </message>
<!-- Print Management App --> <!-- Print Management App -->
......
3d613d7a3005a79de03176b1adcd93150b92b64c
\ No newline at end of file
bff3e9c779eeec926cb2a4e6483f615b8b797900 81517747d7433f99ec8277b79a4654f45d72ea68
\ No newline at end of file \ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "chromeos/components/security_token_pin/error_generator.h" #include "chromeos/components/security_token_pin/error_generator.h"
#include "base/i18n/message_formatter.h"
#include "base/i18n/number_formatting.h" #include "base/i18n/number_formatting.h"
#include "chromeos/strings/grit/chromeos_strings.h" #include "chromeos/strings/grit/chromeos_strings.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
...@@ -48,12 +49,13 @@ base::string16 GenerateErrorMessage(ErrorLabel error_label, ...@@ -48,12 +49,13 @@ base::string16 GenerateErrorMessage(ErrorLabel error_label,
return error_message; return error_message;
} }
if (error_message.empty()) { if (error_message.empty()) {
return l10n_util::GetStringFUTF16(IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT, return base::i18n::MessageFormatter::FormatWithNumberedArgs(
base::FormatNumber(attempts_left)); l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT),
attempts_left);
} }
return l10n_util::GetStringFUTF16(IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS, return base::i18n::MessageFormatter::FormatWithNumberedArgs(
error_message, l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS),
base::FormatNumber(attempts_left)); attempts_left, error_message);
} }
} // namespace security_token_pin } // namespace security_token_pin
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment