Skip to content

Commit d49c1a6

Browse files
committed
login: translations
1 parent 990548f commit d49c1a6

File tree

2 files changed

+124
-21
lines changed

2 files changed

+124
-21
lines changed

assets/l10n/app_en.arb

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,41 @@
6363
"@errorCopyingFailed": {
6464
"description": "Dialog message when copying the text of a message to the users system clipboard failed."
6565
},
66+
"errorLoginInvalidInputTitle": "Invalid input",
67+
"@errorLoginInvalidInputTitle": {
68+
"description": "Error dialog title for login dialog when input is invalid."
69+
},
70+
"errorLoginFailed": "Login failed",
71+
"@errorLoginFailed": {
72+
"description": "Error dialog title when login for a Zulip server fails."
73+
},
6674
"errorMessageDoesNotSeemToExist": "That message does not seem to exist.",
6775
"@errorMessageDoesNotSeemToExist": {
68-
"description": "Dialog message in action sheet when loading a message that does not exist."
76+
"description": "Error message when loading a message that does not exist."
77+
},
78+
"errorServerErrorMessage": "The server said:\n\n{message}",
79+
"@errorServerErrorMessage": {
80+
"description": "Error message that quotes an error from the server.",
81+
"placeholders": {
82+
"message": {
83+
"type": "String",
84+
"example": "Invalid format"
85+
}
86+
}
87+
},
88+
"errorLoginCouldNotConnect": "Failed to connect to server:\n{url}",
89+
"@errorLoginCouldNotConnect": {
90+
"description": "Error message when the app could not connect to the server.",
91+
"placeholders": {
92+
"url": {
93+
"type": "String",
94+
"example": "http://example.com/"
95+
}
96+
}
97+
},
98+
"errorLoginCouldNotConnectTitle": "Could not connect",
99+
"@errorLoginCouldNotConnectTitle": {
100+
"description": "Error title when the app could not connect to the server."
69101
},
70102
"errorQuotationFailed": "Quotation failed",
71103
"@errorQuotationFailed": {
@@ -95,6 +127,54 @@
95127
"@lightboxCopyLinkTooltip": {
96128
"description": "Tooltip in lightbox for the copy link action."
97129
},
130+
"loginPageTitle": "Log in",
131+
"@loginPageTitle": {
132+
"description": "Page title for login page."
133+
},
134+
"loginFormSubmitLabel": "Log in",
135+
"@loginFormSubmitLabel": {
136+
"description": "Button text to submit login credentials."
137+
},
138+
"loginAddAnAccount": "Add an account",
139+
"@loginAddAnAccount": {
140+
"description": "Page title for screen to add a zulip account."
141+
},
142+
"loginAddAnAccountConfirm": "Continue",
143+
"@loginAddAnAccountConfirm": {
144+
"description": "Button label to submit form for adding an account."
145+
},
146+
"loginServerUrlInputLabel": "Your Zulip server URL",
147+
"@loginServerUrlInputLabel": {
148+
"description": "Input label in login page for Zulip server URL entry."
149+
},
150+
"loginHidePassword": "Hide password",
151+
"@loginHidePassword": {
152+
"description": "Icon label for button to hide password in input form."
153+
},
154+
"loginValidationPassword": "Please enter your password",
155+
"@loginValidationPassword": {
156+
"description": "Prompt for input for password field."
157+
},
158+
"loginValidationPasswordLabel": "Password",
159+
"@loginValidationPasswordLabel": {
160+
"description": "Label for input for password field."
161+
},
162+
"loginValidationRequireEmail": "Please enter your email",
163+
"@loginValidationRequireEmail": {
164+
"description": "Prompt when an email is required to login."
165+
},
166+
"loginValidationRequireEmailLabel": "Email",
167+
"@loginValidationRequireEmailLabel": {
168+
"description": "Label for input when an email is required to login."
169+
},
170+
"loginValidationRequireUsername": "Please enter your username",
171+
"@loginValidationRequireUsername": {
172+
"description": "Prompt when a username is required to login."
173+
},
174+
"loginValidationRequireUsernameLabel": "Username",
175+
"@loginValidationRequireUsernameLabel": {
176+
"description": "Label for input when a username is required to login."
177+
},
98178
"subscribedToNStreams": "Subscribed to {num, plural, =0{no streams} =1{1 stream} other{{num} streams}}",
99179
"@subscribedToNStreams": {
100180
"description": "Test page label showing number of streams user is subscribed to.",
@@ -125,6 +205,22 @@
125205
}
126206
}
127207
},
208+
"serverUrlValidationErrorEmpty": "Please enter a URL.",
209+
"@serverUrlValidationErrorEmpty": {
210+
"description": "Server validation error message when URL is empty"
211+
},
212+
"serverUrlValidationErrorInvalidUrl": "Please enter a valid URL.",
213+
"@serverUrlValidationErrorInvalidUrl": {
214+
"description": "Server validation error message when URL is not in a valid format."
215+
},
216+
"serverUrlValidationErrorNoUseEmail": "Please enter the server URL, not your email.",
217+
"@serverUrlValidationErrorNoUseEmail": {
218+
"description": "Server validation error message when URL provided looks like an email"
219+
},
220+
"serverUrlValidationErrorUnsupportedScheme": "The server URL must start with http:// or https://.",
221+
"@serverUrlValidationErrorUnsupportedScheme": {
222+
"description": "Server validation error message when URL does not have a scheme defined."
223+
},
128224
"userRoleOwner": "Owner",
129225
"@userRoleOwner": {
130226
"description": "Label for UserRole.owner"

lib/widgets/login.dart

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ enum ServerUrlValidationError {
4343
}
4444
}
4545

46-
String message() { // TODO(i18n)
46+
String message(ZulipLocalizations zulipLocalizations) {
4747
switch (this) {
4848
case empty:
49-
return 'Please enter a URL.';
49+
return zulipLocalizations.serverUrlValidationErrorEmpty;
5050
case invalidUrl:
51-
return 'Please enter a valid URL.';
51+
return zulipLocalizations.serverUrlValidationErrorInvalidUrl;
5252
case noUseEmail:
53-
return 'Please enter the server URL, not your email.';
53+
return zulipLocalizations.serverUrlValidationErrorNoUseEmail;
5454
case unsupportedSchemeZulip:
5555
case unsupportedSchemeOther:
56-
return 'The server URL must start with http:// or https://.';
56+
return zulipLocalizations.serverUrlValidationErrorUnsupportedScheme;
5757
}
5858
}
5959
}
@@ -136,11 +136,13 @@ class _AddAccountPageState extends State<AddAccountPage> {
136136
}
137137

138138
Future<void> _onSubmitted(BuildContext context) async {
139+
final zulipLocalizations = ZulipLocalizations.of(context);
139140
final url = _parseResult.url;
140141
final error = _parseResult.error;
141142
if (error != null) {
142143
showErrorDialog(context: context,
143-
title: 'Invalid input', message: error.message());
144+
title: zulipLocalizations.errorLoginInvalidInputTitle,
145+
message: error.message(zulipLocalizations));
144146
return;
145147
}
146148
assert(url != null);
@@ -159,7 +161,8 @@ class _AddAccountPageState extends State<AddAccountPage> {
159161
// TODO(#105) give more helpful feedback; see `fetchServerSettings`
160162
// in zulip-mobile's src/message/fetchActions.js.
161163
showErrorDialog(context: context,
162-
title: 'Could not connect', message: 'Failed to connect to server:\n$url');
164+
title: zulipLocalizations.errorLoginCouldNotConnectTitle,
165+
message: zulipLocalizations.errorLoginCouldNotConnect(url.toString()));
163166
return;
164167
}
165168
// https://github.com/dart-lang/linter/issues/4007
@@ -181,13 +184,14 @@ class _AddAccountPageState extends State<AddAccountPage> {
181184
@override
182185
Widget build(BuildContext context) {
183186
assert(!PerAccountStoreWidget.debugExistsOf(context));
187+
final zulipLocalizations = ZulipLocalizations.of(context);
184188
final error = _parseResult.error;
185189
final errorText = error == null || error.shouldDeferFeedback()
186190
? null
187-
: error.message();
191+
: error.message(zulipLocalizations);
188192

189193
return Scaffold(
190-
appBar: AppBar(title: const Text('Add an account'),
194+
appBar: AppBar(title: Text(zulipLocalizations.loginAddAnAccount),
191195
bottom: _inProgress
192196
? const PreferredSize(preferredSize: Size.fromHeight(4),
193197
child: LinearProgressIndicator(minHeight: 4)) // 4 restates default
@@ -212,7 +216,7 @@ class _AddAccountPageState extends State<AddAccountPage> {
212216
// …but leave out unfocusing the input in case more editing is needed.
213217
},
214218
decoration: InputDecoration(
215-
labelText: 'Your Zulip server URL',
219+
labelText: zulipLocalizations.loginServerUrlInputLabel,
216220
errorText: errorText,
217221
helperText: kLayoutPinningHelperText,
218222
hintText: 'your-org.zulipchat.com')),
@@ -221,7 +225,7 @@ class _AddAccountPageState extends State<AddAccountPage> {
221225
onPressed: !_inProgress && errorText == null
222226
? () => _onSubmitted(context)
223227
: null,
224-
child: const Text('Continue')),
228+
child: Text(zulipLocalizations.loginAddAnAccountConfirm)),
225229
])))));
226230
}
227231
}
@@ -292,7 +296,7 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
292296
// errors for deactivated user or realm (see zulip-mobile#4571).
293297
final zulipLocalizations = ZulipLocalizations.of(context);
294298
showErrorDialog(context: context,
295-
title: 'Login failed',
299+
title: zulipLocalizations.errorLoginFailed,
296300
message: e.message(zulipLocalizations));
297301
return;
298302
}
@@ -336,6 +340,7 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
336340
@override
337341
Widget build(BuildContext context) {
338342
assert(!PerAccountStoreWidget.debugExistsOf(context));
343+
final zulipLocalizations = ZulipLocalizations.of(context);
339344
final requireEmailFormatUsernames = widget.serverSettings.requireEmailFormatUsernames;
340345

341346
final usernameField = TextFormField(
@@ -351,8 +356,8 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
351356
validator: (value) {
352357
if (value == null || value.trim().isEmpty) {
353358
return requireEmailFormatUsernames
354-
? 'Please enter your email.'
355-
: 'Please enter your username.';
359+
? zulipLocalizations.loginValidationRequireEmail
360+
: zulipLocalizations.loginValidationRequireUsername;
356361
}
357362
if (requireEmailFormatUsernames) {
358363
// TODO(#106): validate is in the shape of an email
@@ -361,7 +366,9 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
361366
},
362367
textInputAction: TextInputAction.next,
363368
decoration: InputDecoration(
364-
labelText: requireEmailFormatUsernames ? 'Email address' : 'Username',
369+
labelText: requireEmailFormatUsernames
370+
? zulipLocalizations.loginValidationRequireEmailLabel
371+
: zulipLocalizations.loginValidationRequireUsernameLabel,
365372
helperText: kLayoutPinningHelperText,
366373
));
367374

@@ -373,14 +380,14 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
373380
autovalidateMode: AutovalidateMode.onUserInteraction,
374381
validator: (value) {
375382
if (value == null || value.isEmpty) {
376-
return 'Please enter your password.';
383+
return zulipLocalizations.loginValidationPassword;
377384
}
378385
return null;
379386
},
380387
textInputAction: TextInputAction.go,
381388
onFieldSubmitted: (value) => _submit(),
382389
decoration: InputDecoration(
383-
labelText: 'Password',
390+
labelText: zulipLocalizations.loginValidationPasswordLabel,
384391
helperText: kLayoutPinningHelperText,
385392
// TODO(material-3): Simplify away `Semantics` by using IconButton's
386393
// M3-only params `isSelected` / `selectedIcon`, after fixing
@@ -390,14 +397,14 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
390397
// [ButtonStyleButton].)
391398
suffixIcon: Semantics(toggled: _obscurePassword,
392399
child: IconButton(
393-
tooltip: 'Hide password',
400+
tooltip: zulipLocalizations.loginHidePassword,
394401
onPressed: _handlePasswordVisibilityPress,
395402
icon: _obscurePassword
396403
? const Icon(Icons.visibility_off)
397404
: const Icon(Icons.visibility)))));
398405

399406
return Scaffold(
400-
appBar: AppBar(title: const Text('Log in'),
407+
appBar: AppBar(title: Text(zulipLocalizations.loginPageTitle),
401408
bottom: _inProgress
402409
? const PreferredSize(preferredSize: Size.fromHeight(4),
403410
child: LinearProgressIndicator(minHeight: 4)) // 4 restates default
@@ -417,7 +424,7 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
417424
const SizedBox(height: 8),
418425
ElevatedButton(
419426
onPressed: _inProgress ? null : _submit,
420-
child: const Text('Log in')),
427+
child: Text(zulipLocalizations.loginFormSubmitLabel)),
421428
])))))));
422429
}
423430
}

0 commit comments

Comments
 (0)