mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-11-22 00:12:09 +03:00
Change prefixes and add check_strings.py
This commit is contained in:
parent
fd1046eb72
commit
b33dca3900
110
check_strings.py
Executable file
110
check_strings.py
Executable file
@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Yubico.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
|
||||||
|
def check_duplicate_keys(pairs):
|
||||||
|
seen = set()
|
||||||
|
for d in [k for k, v in pairs if k in seen or seen.add(k)]:
|
||||||
|
errors.append(f"Duplicate key: {d}")
|
||||||
|
return dict(pairs)
|
||||||
|
|
||||||
|
|
||||||
|
def check_duplicate_values(strings):
|
||||||
|
seen = {}
|
||||||
|
for k, v in strings.items():
|
||||||
|
if isinstance(v, str):
|
||||||
|
if v in seen:
|
||||||
|
errors.append(
|
||||||
|
f"Duplicate value in key: {k} (originally in {seen[v]}): {v}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
seen[v] = k
|
||||||
|
|
||||||
|
|
||||||
|
def check_prefixes(k, v, s_max_words, s_max_len):
|
||||||
|
errs = []
|
||||||
|
if k.startswith("s_"):
|
||||||
|
if len(v) > s_max_len:
|
||||||
|
errs.append(f"Too long ({len(v)} chars)")
|
||||||
|
if len(v.split()) > s_max_words:
|
||||||
|
errs.append(f"Too many words ({len(v.split())})")
|
||||||
|
elif k.startswith("l_"):
|
||||||
|
if v.endswith("."):
|
||||||
|
errs.append("Ends with '.'")
|
||||||
|
if ". " in v:
|
||||||
|
errs.append("Spans multiple sentences")
|
||||||
|
elif k.startswith("p_"):
|
||||||
|
if v[-1] not in ".!":
|
||||||
|
errs.append("Doesn't end in punctuation")
|
||||||
|
elif k.startswith("q_"):
|
||||||
|
if not v.endswith("?"):
|
||||||
|
errs.append("Doesn't end in '?'")
|
||||||
|
return errs
|
||||||
|
|
||||||
|
|
||||||
|
def check_misc(k, v):
|
||||||
|
errs = []
|
||||||
|
if "..." in v:
|
||||||
|
errs.append("'...' should be replaced with '\\u2026'")
|
||||||
|
return errs
|
||||||
|
|
||||||
|
|
||||||
|
def lint_strings(strings, rules):
|
||||||
|
for k, v in strings.items():
|
||||||
|
errs = []
|
||||||
|
errs.extend(
|
||||||
|
check_prefixes(
|
||||||
|
k,
|
||||||
|
v,
|
||||||
|
rules.get("s_max_words", 4),
|
||||||
|
rules.get("s_max_len", 32),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
errs.extend(check_misc(k, v))
|
||||||
|
if errs:
|
||||||
|
errors.append(f'Errors in {k}: "{v}"')
|
||||||
|
errors.extend([f" {e}" for e in errs])
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("USAGE: check_strings.py <ARB_FILE>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
target = sys.argv[1]
|
||||||
|
with open(target) as f:
|
||||||
|
values = json.load(f, object_pairs_hook=check_duplicate_keys)
|
||||||
|
|
||||||
|
strings = {k: v for k, v in values.items() if not k.startswith("@")}
|
||||||
|
|
||||||
|
check_duplicate_values(strings)
|
||||||
|
lint_strings(strings, strings.get("@_lint_rules", {}))
|
||||||
|
|
||||||
|
print(len(strings), "strings in file")
|
||||||
|
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
for e in errors:
|
||||||
|
print(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("OK")
|
@ -42,7 +42,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.w_about),
|
title: Text(l10n.s_about),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -63,7 +63,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_terms_of_use,
|
l10n.s_terms_of_use,
|
||||||
style:
|
style:
|
||||||
const TextStyle(decoration: TextDecoration.underline),
|
const TextStyle(decoration: TextDecoration.underline),
|
||||||
),
|
),
|
||||||
@ -73,7 +73,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_privacy_policy,
|
l10n.s_privacy_policy,
|
||||||
style:
|
style:
|
||||||
const TextStyle(decoration: TextDecoration.underline),
|
const TextStyle(decoration: TextDecoration.underline),
|
||||||
),
|
),
|
||||||
@ -85,7 +85,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_open_src_licenses,
|
l10n.s_open_src_licenses,
|
||||||
style: const TextStyle(decoration: TextDecoration.underline),
|
style: const TextStyle(decoration: TextDecoration.underline),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -104,7 +104,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_help_and_feedback,
|
l10n.s_help_and_feedback,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -113,7 +113,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_send_feedback,
|
l10n.s_send_feedback,
|
||||||
style:
|
style:
|
||||||
const TextStyle(decoration: TextDecoration.underline),
|
const TextStyle(decoration: TextDecoration.underline),
|
||||||
),
|
),
|
||||||
@ -123,7 +123,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_i_need_help,
|
l10n.s_i_need_help,
|
||||||
style:
|
style:
|
||||||
const TextStyle(decoration: TextDecoration.underline),
|
const TextStyle(decoration: TextDecoration.underline),
|
||||||
),
|
),
|
||||||
@ -140,7 +140,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.w_troubleshooting,
|
l10n.s_troubleshooting,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -151,7 +151,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
const SizedBox(height: 12.0),
|
const SizedBox(height: 12.0),
|
||||||
ActionChip(
|
ActionChip(
|
||||||
avatar: const Icon(Icons.bug_report_outlined),
|
avatar: const Icon(Icons.bug_report_outlined),
|
||||||
label: Text(l10n.l_run_diagnostics),
|
label: Text(l10n.s_run_diagnostics),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
_log.info('Running diagnostics...');
|
_log.info('Running diagnostics...');
|
||||||
final response = await ref
|
final response = await ref
|
||||||
@ -180,7 +180,7 @@ class AboutPage extends ConsumerWidget {
|
|||||||
if (isAndroid) ...[
|
if (isAndroid) ...[
|
||||||
const SizedBox(height: 12.0),
|
const SizedBox(height: 12.0),
|
||||||
FilterChip(
|
FilterChip(
|
||||||
label: Text(l10n.l_allow_screenshots),
|
label: Text(l10n.s_allow_screenshots),
|
||||||
selected: ref.watch(androidAllowScreenshotsProvider),
|
selected: ref.watch(androidAllowScreenshotsProvider),
|
||||||
onSelected: (value) async {
|
onSelected: (value) async {
|
||||||
ref
|
ref
|
||||||
@ -216,7 +216,7 @@ class LoggingPanel extends ConsumerWidget {
|
|||||||
value: logLevel,
|
value: logLevel,
|
||||||
items: Levels.LEVELS,
|
items: Levels.LEVELS,
|
||||||
selected: logLevel != Level.INFO,
|
selected: logLevel != Level.INFO,
|
||||||
labelBuilder: (value) => Text(l10n.l_log_level(
|
labelBuilder: (value) => Text(l10n.s_log_level(
|
||||||
value.name[0] + value.name.substring(1).toLowerCase())),
|
value.name[0] + value.name.substring(1).toLowerCase())),
|
||||||
itemBuilder: (value) =>
|
itemBuilder: (value) =>
|
||||||
Text('${value.name[0]}${value.name.substring(1).toLowerCase()}'),
|
Text('${value.name[0]}${value.name.substring(1).toLowerCase()}'),
|
||||||
@ -227,7 +227,7 @@ class LoggingPanel extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
ActionChip(
|
ActionChip(
|
||||||
avatar: const Icon(Icons.copy),
|
avatar: const Icon(Icons.copy),
|
||||||
label: Text(l10n.l_copy_log),
|
label: Text(l10n.s_copy_log),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
_log.info('Copying log to clipboard ($version)...');
|
_log.info('Copying log to clipboard ($version)...');
|
||||||
final logs = await ref.read(logLevelProvider.notifier).getLogs();
|
final logs = await ref.read(logLevelProvider.notifier).getLogs();
|
||||||
|
@ -195,7 +195,7 @@ class _AndroidCredentialListNotifier extends OathCredentialListNotifier {
|
|||||||
return promptUserInteraction(
|
return promptUserInteraction(
|
||||||
context,
|
context,
|
||||||
icon: const Icon(Icons.touch_app),
|
icon: const Icon(Icons.touch_app),
|
||||||
title: l10n.l_touch_required,
|
title: l10n.s_touch_required,
|
||||||
description: l10n.l_touch_button_now,
|
description: l10n.l_touch_button_now,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -75,7 +75,7 @@ class QRScannerPermissionsUI extends StatelessWidget {
|
|||||||
Navigator.of(context).pop('');
|
Navigator.of(context).pop('');
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_enter_manually,
|
l10n.s_enter_manually,
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
@ -92,7 +92,7 @@ class QRScannerPermissionsUI extends StatelessWidget {
|
|||||||
onPermissionRequest();
|
onPermissionRequest();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_review_permissions,
|
l10n.s_review_permissions,
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
|
@ -73,7 +73,7 @@ class QRScannerUI extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
key: keys.manualEntryButton,
|
key: keys.manualEntryButton,
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.l_enter_manually,
|
l10n.s_enter_manually,
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
|
@ -114,7 +114,7 @@ class _QrScannerViewState extends State<QrScannerView> {
|
|||||||
extendBody: true,
|
extendBody: true,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
l10n.l_add_account,
|
l10n.s_add_account,
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
|
@ -80,11 +80,11 @@ extension on ThemeMode {
|
|||||||
String getDisplayName(AppLocalizations l10n) {
|
String getDisplayName(AppLocalizations l10n) {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case ThemeMode.system:
|
case ThemeMode.system:
|
||||||
return l10n.l_system_default;
|
return l10n.s_system_default;
|
||||||
case ThemeMode.light:
|
case ThemeMode.light:
|
||||||
return l10n.l_light_mode;
|
return l10n.s_light_mode;
|
||||||
case ThemeMode.dark:
|
case ThemeMode.dark:
|
||||||
return l10n.l_dark_mode;
|
return l10n.s_dark_mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
|||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.w_settings),
|
title: Text(l10n.s_settings),
|
||||||
child: Theme(
|
child: Theme(
|
||||||
// Make the headers use the primary color to pop a bit.
|
// Make the headers use the primary color to pop a bit.
|
||||||
// Once M3 is implemented this will probably not be needed.
|
// Once M3 is implemented this will probably not be needed.
|
||||||
@ -127,7 +127,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ListTitle(l10n.l_nfc_options),
|
ListTitle(l10n.s_nfc_options),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(l10n.l_on_yk_nfc_tap),
|
title: Text(l10n.l_on_yk_nfc_tap),
|
||||||
subtitle: Text(tapAction.getDescription(l10n)),
|
subtitle: Text(tapAction.getDescription(l10n)),
|
||||||
@ -166,7 +166,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
title: Text(l10n.l_silence_nfc_sounds),
|
title: Text(l10n.s_silence_nfc_sounds),
|
||||||
subtitle: Text(nfcSilenceSounds
|
subtitle: Text(nfcSilenceSounds
|
||||||
? l10n.l_silence_nfc_sounds_on
|
? l10n.l_silence_nfc_sounds_on
|
||||||
: l10n.l_silence_nfc_sounds_off),
|
: l10n.l_silence_nfc_sounds_off),
|
||||||
@ -177,7 +177,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
|||||||
prefs.setBool(prefNfcSilenceSounds, value);
|
prefs.setBool(prefNfcSilenceSounds, value);
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
ListTitle(l10n.l_usb_options),
|
ListTitle(l10n.s_usb_options),
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
title: Text(l10n.l_launch_app_on_usb),
|
title: Text(l10n.l_launch_app_on_usb),
|
||||||
subtitle: Text(usbOpenApp
|
subtitle: Text(usbOpenApp
|
||||||
@ -190,9 +190,9 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
|||||||
prefs.setBool(prefUsbOpenApp, value);
|
prefs.setBool(prefUsbOpenApp, value);
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
ListTitle(l10n.w_appearance),
|
ListTitle(l10n.s_appearance),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(l10n.l_app_theme),
|
title: Text(l10n.s_app_theme),
|
||||||
subtitle: Text(themeMode.getDisplayName(l10n)),
|
subtitle: Text(themeMode.getDisplayName(l10n)),
|
||||||
key: keys.themeModeSetting,
|
key: keys.themeModeSetting,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
@ -239,7 +239,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return SimpleDialog(
|
return SimpleDialog(
|
||||||
title: Text(l10n.l_choose_kbd_layout),
|
title: Text(l10n.s_choose_kbd_layout),
|
||||||
children: _keyboardLayouts
|
children: _keyboardLayouts
|
||||||
.map(
|
.map(
|
||||||
(e) => RadioListTile<String>(
|
(e) => RadioListTile<String>(
|
||||||
@ -264,7 +264,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return SimpleDialog(
|
return SimpleDialog(
|
||||||
title: Text(l10n.l_choose_app_theme),
|
title: Text(l10n.s_choose_app_theme),
|
||||||
children: supportedThemes
|
children: supportedThemes
|
||||||
.map((e) => RadioListTile(
|
.map((e) => RadioListTile(
|
||||||
title: Text(e.getDisplayName(l10n)),
|
title: Text(e.getDisplayName(l10n)),
|
||||||
|
@ -62,9 +62,9 @@ enum Application {
|
|||||||
String getDisplayName(AppLocalizations l10n) {
|
String getDisplayName(AppLocalizations l10n) {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case Application.oath:
|
case Application.oath:
|
||||||
return l10n.w_authenticator;
|
return l10n.s_authenticator;
|
||||||
case Application.fido:
|
case Application.fido:
|
||||||
return l10n.w_webauthn;
|
return l10n.s_webauthn;
|
||||||
default:
|
default:
|
||||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ class AppFailurePage extends ConsumerWidget {
|
|||||||
case 'ccid':
|
case 'ccid':
|
||||||
header = l10n.l_ccid_connection_failed;
|
header = l10n.l_ccid_connection_failed;
|
||||||
if (Platform.isMacOS) {
|
if (Platform.isMacOS) {
|
||||||
message = l10n.l_try_reinsert_yk;
|
message = l10n.p_try_reinsert_yk;
|
||||||
} else if (Platform.isLinux) {
|
} else if (Platform.isLinux) {
|
||||||
message = l10n.p_pcscd_unavailable;
|
message = l10n.p_pcscd_unavailable;
|
||||||
} else {
|
} else {
|
||||||
@ -63,7 +63,7 @@ class AppFailurePage extends ConsumerWidget {
|
|||||||
message = l10n.p_webauthn_elevated_permissions_required;
|
message = l10n.p_webauthn_elevated_permissions_required;
|
||||||
actions = [
|
actions = [
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
label: Text(l10n.w_unlock),
|
label: Text(l10n.s_unlock),
|
||||||
icon: const Icon(Icons.lock_open),
|
icon: const Icon(Icons.lock_open),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final closeMessage = showMessage(
|
final closeMessage = showMessage(
|
||||||
@ -77,7 +77,7 @@ class AppFailurePage extends ConsumerWidget {
|
|||||||
(context) async {
|
(context) async {
|
||||||
showMessage(
|
showMessage(
|
||||||
context,
|
context,
|
||||||
l10n.l_permission_denied,
|
l10n.s_permission_denied,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -92,7 +92,7 @@ class AppFailurePage extends ConsumerWidget {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
header = l10n.l_open_connection_failed;
|
header = l10n.l_open_connection_failed;
|
||||||
message = l10n.l_try_reinsert_yk;
|
message = l10n.p_try_reinsert_yk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ class AppPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Icons.tune),
|
icon: const Icon(Icons.tune),
|
||||||
iconSize: 24,
|
iconSize: 24,
|
||||||
tooltip: AppLocalizations.of(context)!.l_configure_yk,
|
tooltip: AppLocalizations.of(context)!.s_configure_yk,
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -45,7 +45,7 @@ class DeviceButton extends ConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
tooltip: AppLocalizations.of(context)!.l_select_yk,
|
tooltip: AppLocalizations.of(context)!.s_select_yk,
|
||||||
icon: _CircledDeviceAvatar(radius),
|
icon: _CircledDeviceAvatar(radius),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await showBlurDialog(
|
await showBlurDialog(
|
||||||
|
@ -44,7 +44,7 @@ class DeviceErrorScreen extends ConsumerWidget {
|
|||||||
message: l10n.p_elevated_permissions_required,
|
message: l10n.p_elevated_permissions_required,
|
||||||
actions: [
|
actions: [
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
label: Text(l10n.w_unlock),
|
label: Text(l10n.s_unlock),
|
||||||
icon: const Icon(Icons.lock_open),
|
icon: const Icon(Icons.lock_open),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final closeMessage = showMessage(
|
final closeMessage = showMessage(
|
||||||
@ -55,7 +55,7 @@ class DeviceErrorScreen extends ConsumerWidget {
|
|||||||
ref.invalidate(rpcProvider);
|
ref.invalidate(rpcProvider);
|
||||||
} else {
|
} else {
|
||||||
await ref.read(withContextProvider)((context) async =>
|
await ref.read(withContextProvider)((context) async =>
|
||||||
showMessage(context, l10n.l_permission_denied));
|
showMessage(context, l10n.s_permission_denied));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
closeMessage();
|
closeMessage();
|
||||||
@ -81,7 +81,7 @@ class DeviceErrorScreen extends ConsumerWidget {
|
|||||||
final String message;
|
final String message;
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case 'unknown-device':
|
case 'unknown-device':
|
||||||
message = l10n.l_unknown_device;
|
message = l10n.s_unknown_device;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
message = l10n.l_place_on_nfc_reader;
|
message = l10n.l_place_on_nfc_reader;
|
||||||
|
@ -122,7 +122,7 @@ class _DevicePickerContent extends ConsumerWidget {
|
|||||||
title: Center(child: Text(l10n.l_no_yk_present)),
|
title: Center(child: Text(l10n.l_no_yk_present)),
|
||||||
subtitle: Center(
|
subtitle: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
Platform.isAndroid ? l10n.l_insert_or_tap_yk : l10n.w_usb)),
|
Platform.isAndroid ? l10n.l_insert_or_tap_yk : l10n.s_usb)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -136,7 +136,7 @@ class _DevicePickerContent extends ConsumerWidget {
|
|||||||
padding: EdgeInsets.symmetric(horizontal: 4),
|
padding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
child: DeviceAvatar(child: Icon(Icons.usb)),
|
child: DeviceAvatar(child: Icon(Icons.usb)),
|
||||||
),
|
),
|
||||||
title: Text(l10n.w_usb),
|
title: Text(l10n.s_usb),
|
||||||
subtitle: Text(l10n.l_no_yk_present),
|
subtitle: Text(l10n.l_no_yk_present),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref.read(currentDeviceProvider.notifier).setCurrentDevice(null);
|
ref.read(currentDeviceProvider.notifier).setCurrentDevice(null);
|
||||||
@ -168,7 +168,7 @@ class _DevicePickerContent extends ConsumerWidget {
|
|||||||
ref.read(_hiddenDevicesProvider.notifier).showAll();
|
ref.read(_hiddenDevicesProvider.notifier).showAll();
|
||||||
},
|
},
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text(l10n.l_show_hidden_devices),
|
title: Text(l10n.s_show_hidden_devices),
|
||||||
dense: true,
|
dense: true,
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
@ -195,11 +195,11 @@ String _getDeviceInfoString(BuildContext context, DeviceInfo info) {
|
|||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
final serial = info.serial;
|
final serial = info.serial;
|
||||||
return [
|
return [
|
||||||
if (serial != null) l10n.l_sn_serial(serial),
|
if (serial != null) l10n.s_sn_serial(serial),
|
||||||
if (info.version.isAtLeast(1))
|
if (info.version.isAtLeast(1))
|
||||||
l10n.l_fw_version(info.version)
|
l10n.s_fw_version(info.version)
|
||||||
else
|
else
|
||||||
l10n.l_unknown_type,
|
l10n.s_unknown_type,
|
||||||
].join(' ');
|
].join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,9 +211,9 @@ List<String> _getDeviceStrings(
|
|||||||
error: (error, _) {
|
error: (error, _) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case 'device-inaccessible':
|
case 'device-inaccessible':
|
||||||
return [node.name, l10n.l_yk_inaccessible];
|
return [node.name, l10n.s_yk_inaccessible];
|
||||||
case 'unknown-device':
|
case 'unknown-device':
|
||||||
return [l10n.l_unknown_device];
|
return [l10n.s_unknown_device];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@ -306,9 +306,9 @@ class _DeviceRow extends ConsumerWidget {
|
|||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
node.when(
|
node.when(
|
||||||
usbYubiKey: (_, __, ___, info) => info == null
|
usbYubiKey: (_, __, ___, info) => info == null
|
||||||
? l10n.l_yk_inaccessible
|
? l10n.s_yk_inaccessible
|
||||||
: _getDeviceInfoString(context, info),
|
: _getDeviceInfoString(context, info),
|
||||||
nfcReader: (_, __) => l10n.l_select_to_scan,
|
nfcReader: (_, __) => l10n.s_select_to_scan,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -344,7 +344,7 @@ class _NfcDeviceRow extends ConsumerWidget {
|
|||||||
ref.read(_hiddenDevicesProvider.notifier).showAll();
|
ref.read(_hiddenDevicesProvider.notifier).showAll();
|
||||||
},
|
},
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text(l10n.l_show_hidden_devices),
|
title: Text(l10n.s_show_hidden_devices),
|
||||||
dense: true,
|
dense: true,
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
enabled: hidden.isNotEmpty,
|
enabled: hidden.isNotEmpty,
|
||||||
@ -355,7 +355,7 @@ class _NfcDeviceRow extends ConsumerWidget {
|
|||||||
ref.read(_hiddenDevicesProvider.notifier).hideDevice(node.path);
|
ref.read(_hiddenDevicesProvider.notifier).hideDevice(node.path);
|
||||||
},
|
},
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text(l10n.l_hide_device),
|
title: Text(l10n.s_hide_device),
|
||||||
dense: true,
|
dense: true,
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
|
@ -142,7 +142,7 @@ class MainPageDrawer extends ConsumerWidget {
|
|||||||
NavigationDrawerDestination(
|
NavigationDrawerDestination(
|
||||||
key: managementAppDrawer,
|
key: managementAppDrawer,
|
||||||
label: Text(
|
label: Text(
|
||||||
l10n.l_toggle_applications,
|
l10n.s_toggle_applications,
|
||||||
),
|
),
|
||||||
icon: Icon(Application.management._icon),
|
icon: Icon(Application.management._icon),
|
||||||
selectedIcon: Icon(Application.management._filledIcon),
|
selectedIcon: Icon(Application.management._filledIcon),
|
||||||
@ -152,11 +152,11 @@ class MainPageDrawer extends ConsumerWidget {
|
|||||||
],
|
],
|
||||||
// Non-YubiKey pages
|
// Non-YubiKey pages
|
||||||
NavigationDrawerDestination(
|
NavigationDrawerDestination(
|
||||||
label: Text(l10n.w_settings),
|
label: Text(l10n.s_settings),
|
||||||
icon: const Icon(Icons.settings_outlined),
|
icon: const Icon(Icons.settings_outlined),
|
||||||
),
|
),
|
||||||
NavigationDrawerDestination(
|
NavigationDrawerDestination(
|
||||||
label: Text(l10n.l_help_and_about),
|
label: Text(l10n.s_help_and_about),
|
||||||
icon: const Icon(Icons.help_outline),
|
icon: const Icon(Icons.help_outline),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -88,7 +88,7 @@ class MainPage extends ConsumerWidget {
|
|||||||
actions: [
|
actions: [
|
||||||
if (hasNfcSupport && !isNfcEnabled)
|
if (hasNfcSupport && !isNfcEnabled)
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
label: Text(l10n.l_enable_nfc),
|
label: Text(l10n.s_enable_nfc),
|
||||||
icon: nfcIcon,
|
icon: nfcIcon,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await openNfcSettings();
|
await openNfcSettings();
|
||||||
@ -96,7 +96,7 @@ class MainPage extends ConsumerWidget {
|
|||||||
],
|
],
|
||||||
actionButtonBuilder: (context) => IconButton(
|
actionButtonBuilder: (context) => IconButton(
|
||||||
icon: const Icon(Icons.person_add_alt_1),
|
icon: const Icon(Icons.person_add_alt_1),
|
||||||
tooltip: l10n.l_add_account,
|
tooltip: l10n.s_add_account,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
CredentialData? otpauth;
|
CredentialData? otpauth;
|
||||||
final scanner = ref.read(qrScannerProvider);
|
final scanner = ref.read(qrScannerProvider);
|
||||||
@ -142,17 +142,17 @@ class MainPage extends ConsumerWidget {
|
|||||||
if (data.info.supportedCapabilities.isEmpty &&
|
if (data.info.supportedCapabilities.isEmpty &&
|
||||||
data.name == 'Unrecognized device') {
|
data.name == 'Unrecognized device') {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
header: l10n.l_yk_not_recognized,
|
header: l10n.s_yk_not_recognized,
|
||||||
);
|
);
|
||||||
} else if (app.getAvailability(data) ==
|
} else if (app.getAvailability(data) ==
|
||||||
Availability.unsupported) {
|
Availability.unsupported) {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
header: l10n.l_app_not_supported,
|
header: l10n.s_app_not_supported,
|
||||||
message: l10n.l_app_not_supported_on_yk(app.name),
|
message: l10n.l_app_not_supported_on_yk(app.name),
|
||||||
);
|
);
|
||||||
} else if (app.getAvailability(data) != Availability.enabled) {
|
} else if (app.getAvailability(data) != Availability.enabled) {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
header: l10n.l_app_disabled,
|
header: l10n.s_app_disabled,
|
||||||
message: l10n.l_app_disabled_desc(app.name),
|
message: l10n.l_app_disabled_desc(app.name),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ class MainPage extends ConsumerWidget {
|
|||||||
return FidoScreen(data);
|
return FidoScreen(data);
|
||||||
default:
|
default:
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
header: l10n.l_app_not_supported,
|
header: l10n.s_app_not_supported,
|
||||||
message: l10n.l_app_not_supported_desc,
|
message: l10n.l_app_not_supported_desc,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ class _HelperWaiterState extends ConsumerState<_HelperWaiter> {
|
|||||||
actions: [
|
actions: [
|
||||||
ActionChip(
|
ActionChip(
|
||||||
avatar: const Icon(Icons.copy),
|
avatar: const Icon(Icons.copy),
|
||||||
label: Text(l10n.l_copy_log),
|
label: Text(l10n.s_copy_log),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
_log.info('Copying log to clipboard ($version)...');
|
_log.info('Copying log to clipboard ($version)...');
|
||||||
final logs = await ref.read(logLevelProvider.notifier).getLogs();
|
final logs = await ref.read(logLevelProvider.notifier).getLogs();
|
||||||
|
@ -271,7 +271,7 @@ class DesktopCredentialListNotifier extends OathCredentialListNotifier {
|
|||||||
return promptUserInteraction(
|
return promptUserInteraction(
|
||||||
context,
|
context,
|
||||||
icon: const Icon(Icons.touch_app),
|
icon: const Icon(Icons.touch_app),
|
||||||
title: l10n.l_touch_required,
|
title: l10n.s_touch_required,
|
||||||
description: l10n.l_touch_button_now,
|
description: l10n.l_touch_button_now,
|
||||||
headless: headless,
|
headless: headless,
|
||||||
);
|
);
|
||||||
|
@ -176,7 +176,7 @@ class _Systray extends TrayListener {
|
|||||||
.read(clipboardProvider)
|
.read(clipboardProvider)
|
||||||
.setText(code.value, isSensitive: true);
|
.setText(code.value, isSensitive: true);
|
||||||
final notification = LocalNotification(
|
final notification = LocalNotification(
|
||||||
title: _l10n.l_code_copied,
|
title: _l10n.s_code_copied,
|
||||||
body: _l10n.p_target_copied_clipboard(label),
|
body: _l10n.p_target_copied_clipboard(label),
|
||||||
silent: true,
|
silent: true,
|
||||||
);
|
);
|
||||||
@ -190,12 +190,12 @@ class _Systray extends TrayListener {
|
|||||||
),
|
),
|
||||||
if (_credentials.isEmpty)
|
if (_credentials.isEmpty)
|
||||||
MenuItem(
|
MenuItem(
|
||||||
label: _l10n.l_no_pinned_accounts,
|
label: _l10n.s_no_pinned_accounts,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
),
|
),
|
||||||
MenuItem.separator(),
|
MenuItem.separator(),
|
||||||
MenuItem(
|
MenuItem(
|
||||||
label: _isHidden ? _l10n.l_show_window : _l10n.l_hide_window,
|
label: _isHidden ? _l10n.s_show_window : _l10n.s_hide_window,
|
||||||
onClick: (_) {
|
onClick: (_) {
|
||||||
_ref
|
_ref
|
||||||
.read(desktopWindowStateProvider.notifier)
|
.read(desktopWindowStateProvider.notifier)
|
||||||
@ -204,7 +204,7 @@ class _Systray extends TrayListener {
|
|||||||
),
|
),
|
||||||
MenuItem.separator(),
|
MenuItem.separator(),
|
||||||
MenuItem(
|
MenuItem(
|
||||||
label: _l10n.w_quit,
|
label: _l10n.s_quit,
|
||||||
onClick: (_) {
|
onClick: (_) {
|
||||||
_ref.read(withContextProvider)(
|
_ref.read(withContextProvider)(
|
||||||
(context) async {
|
(context) async {
|
||||||
|
@ -25,7 +25,7 @@ class ErrorPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(AppLocalizations.of(context)!.l_application_error),
|
title: Text(AppLocalizations.of(context)!.s_application_error),
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -146,7 +146,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
|
|||||||
.renameFingerprint(_fingerprint!, _label);
|
.renameFingerprint(_fingerprint!, _label);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
showMessage(context, l10n.l_fingerprint_added);
|
showMessage(context, l10n.s_fingerprint_added);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
final String errorMessage;
|
final String errorMessage;
|
||||||
// TODO: Make this cleaner than importing desktop specific RpcError.
|
// TODO: Make this cleaner than importing desktop specific RpcError.
|
||||||
@ -169,7 +169,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
|
|||||||
final progress = _samples == 0 ? 0.0 : _samples / (_samples + _remaining);
|
final progress = _samples == 0 ? 0.0 : _samples / (_samples + _remaining);
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_add_fingerprint),
|
title: Text(l10n.s_add_fingerprint),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -208,7 +208,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
enabled: _fingerprint != null,
|
enabled: _fingerprint != null,
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.w_name,
|
labelText: l10n.s_name,
|
||||||
prefixIcon: const Icon(Icons.fingerprint_outlined),
|
prefixIcon: const Icon(Icons.fingerprint_outlined),
|
||||||
),
|
),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -234,7 +234,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _fingerprint != null && _label.isNotEmpty ? _submit : null,
|
onPressed: _fingerprint != null && _label.isNotEmpty ? _submit : null,
|
||||||
child: Text(l10n.w_save),
|
child: Text(l10n.s_save),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -38,7 +38,7 @@ class DeleteCredentialDialog extends ConsumerWidget {
|
|||||||
final label = credential.userName;
|
final label = credential.userName;
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_delete_credential),
|
title: Text(l10n.s_delete_credential),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -63,11 +63,11 @@ class DeleteCredentialDialog extends ConsumerWidget {
|
|||||||
await ref.read(withContextProvider)(
|
await ref.read(withContextProvider)(
|
||||||
(context) async {
|
(context) async {
|
||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
showMessage(context, l10n.l_credential_deleted);
|
showMessage(context, l10n.s_credential_deleted);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(l10n.w_delete),
|
child: Text(l10n.s_delete),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -36,7 +36,7 @@ class DeleteFingerprintDialog extends ConsumerWidget {
|
|||||||
final label = fingerprint.label;
|
final label = fingerprint.label;
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_delete_fingerprint),
|
title: Text(l10n.s_delete_fingerprint),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@ -45,10 +45,10 @@ class DeleteFingerprintDialog extends ConsumerWidget {
|
|||||||
.deleteFingerprint(fingerprint);
|
.deleteFingerprint(fingerprint);
|
||||||
await ref.read(withContextProvider)((context) async {
|
await ref.read(withContextProvider)((context) async {
|
||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
showMessage(context, l10n.l_fingerprint_deleted);
|
showMessage(context, l10n.s_fingerprint_deleted);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Text(l10n.w_delete),
|
child: Text(l10n.s_delete),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
@ -37,7 +37,7 @@ class FidoScreen extends ConsumerWidget {
|
|||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return ref.watch(fidoStateProvider(deviceData.node.path)).when(
|
return ref.watch(fidoStateProvider(deviceData.node.path)).when(
|
||||||
loading: () => AppPage(
|
loading: () => AppPage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
centered: true,
|
centered: true,
|
||||||
delayedContent: true,
|
delayedContent: true,
|
||||||
child: const CircularProgressIndicator(),
|
child: const CircularProgressIndicator(),
|
||||||
@ -48,7 +48,7 @@ class FidoScreen extends ConsumerWidget {
|
|||||||
0;
|
0;
|
||||||
if (Capability.fido2.value & supported == 0) {
|
if (Capability.fido2.value & supported == 0) {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
graphic: manageAccounts,
|
graphic: manageAccounts,
|
||||||
header: l10n.l_ready_to_use,
|
header: l10n.l_ready_to_use,
|
||||||
message: l10n.l_register_sk_on_websites,
|
message: l10n.l_register_sk_on_websites,
|
||||||
@ -59,14 +59,14 @@ class FidoScreen extends ConsumerWidget {
|
|||||||
0;
|
0;
|
||||||
if (Capability.fido2.value & enabled == 0) {
|
if (Capability.fido2.value & enabled == 0) {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
header: l10n.l_fido_disabled,
|
header: l10n.s_fido_disabled,
|
||||||
message: l10n.l_webauthn_req_fido2,
|
message: l10n.l_webauthn_req_fido2,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AppFailurePage(
|
return AppFailurePage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
cause: error,
|
cause: error,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -32,11 +32,11 @@ Widget fidoBuildActions(
|
|||||||
return SimpleDialog(
|
return SimpleDialog(
|
||||||
children: [
|
children: [
|
||||||
if (state.bioEnroll != null) ...[
|
if (state.bioEnroll != null) ...[
|
||||||
ListTitle(l10n.w_setup,
|
ListTitle(l10n.s_setup,
|
||||||
textStyle: Theme.of(context).textTheme.bodyLarge),
|
textStyle: Theme.of(context).textTheme.bodyLarge),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const CircleAvatar(child: Icon(Icons.fingerprint_outlined)),
|
leading: const CircleAvatar(child: Icon(Icons.fingerprint_outlined)),
|
||||||
title: Text(l10n.l_add_fingerprint),
|
title: Text(l10n.s_add_fingerprint),
|
||||||
subtitle: state.unlocked
|
subtitle: state.unlocked
|
||||||
? Text(l10n.l_fingerprints_used(fingerprints))
|
? Text(l10n.l_fingerprints_used(fingerprints))
|
||||||
: Text(state.hasPin
|
: Text(state.hasPin
|
||||||
@ -54,13 +54,13 @@ Widget fidoBuildActions(
|
|||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
ListTitle(l10n.w_manage,
|
ListTitle(l10n.s_manage,
|
||||||
textStyle: Theme.of(context).textTheme.bodyLarge),
|
textStyle: Theme.of(context).textTheme.bodyLarge),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const CircleAvatar(child: Icon(Icons.pin_outlined)),
|
leading: const CircleAvatar(child: Icon(Icons.pin_outlined)),
|
||||||
title: Text(state.hasPin ? l10n.l_change_pin : l10n.l_set_pin),
|
title: Text(state.hasPin ? l10n.s_change_pin : l10n.s_set_pin),
|
||||||
subtitle: Text(state.hasPin
|
subtitle: Text(state.hasPin
|
||||||
? l10n.l_fido_pin_protection
|
? l10n.s_fido_pin_protection
|
||||||
: l10n.l_fido_pin_protection_optional),
|
: l10n.l_fido_pin_protection_optional),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
@ -75,7 +75,7 @@ Widget fidoBuildActions(
|
|||||||
backgroundColor: theme.error,
|
backgroundColor: theme.error,
|
||||||
child: const Icon(Icons.delete_outline),
|
child: const Icon(Icons.delete_outline),
|
||||||
),
|
),
|
||||||
title: Text(l10n.l_reset_fido),
|
title: Text(l10n.s_reset_fido),
|
||||||
subtitle: Text(l10n.l_factory_reset_this_app),
|
subtitle: Text(l10n.l_factory_reset_this_app),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
@ -38,15 +38,15 @@ class FidoLockedPage extends ConsumerWidget {
|
|||||||
if (!state.hasPin) {
|
if (!state.hasPin) {
|
||||||
if (state.bioEnroll != null) {
|
if (state.bioEnroll != null) {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
graphic: noFingerprints,
|
graphic: noFingerprints,
|
||||||
header: l10n.l_no_fingerprints,
|
header: l10n.s_no_fingerprints,
|
||||||
message: l10n.l_set_pin_fingerprints,
|
message: l10n.l_set_pin_fingerprints,
|
||||||
keyActionsBuilder: _buildActions,
|
keyActionsBuilder: _buildActions,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
graphic: manageAccounts,
|
graphic: manageAccounts,
|
||||||
header: state.credMgmt
|
header: state.credMgmt
|
||||||
? l10n.l_no_discoverable_accounts
|
? l10n.l_no_discoverable_accounts
|
||||||
@ -59,7 +59,7 @@ class FidoLockedPage extends ConsumerWidget {
|
|||||||
|
|
||||||
if (!state.credMgmt && state.bioEnroll == null) {
|
if (!state.credMgmt && state.bioEnroll == null) {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
graphic: manageAccounts,
|
graphic: manageAccounts,
|
||||||
header: l10n.l_ready_to_use,
|
header: l10n.l_ready_to_use,
|
||||||
message: l10n.l_register_sk_on_websites,
|
message: l10n.l_register_sk_on_websites,
|
||||||
@ -68,7 +68,7 @@ class FidoLockedPage extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return AppPage(
|
return AppPage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
keyActionsBuilder: _buildActions,
|
keyActionsBuilder: _buildActions,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -148,7 +148,7 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> {
|
|||||||
controller: _pinController,
|
controller: _pinController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.w_pin,
|
labelText: l10n.s_pin,
|
||||||
helperText: '', // Prevents dialog resizing
|
helperText: '', // Prevents dialog resizing
|
||||||
errorText: _pinIsWrong ? _getErrorText() : null,
|
errorText: _pinIsWrong ? _getErrorText() : null,
|
||||||
errorMaxLines: 3,
|
errorMaxLines: 3,
|
||||||
@ -187,7 +187,7 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> {
|
|||||||
minLeadingWidth: 0,
|
minLeadingWidth: 0,
|
||||||
trailing: ElevatedButton.icon(
|
trailing: ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.lock_open),
|
icon: const Icon(Icons.lock_open),
|
||||||
label: Text(l10n.w_unlock),
|
label: Text(l10n.s_unlock),
|
||||||
onPressed:
|
onPressed:
|
||||||
_pinController.text.isNotEmpty && !_blocked ? _submit : null,
|
_pinController.text.isNotEmpty && !_blocked ? _submit : null,
|
||||||
),
|
),
|
||||||
|
@ -57,11 +57,11 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
final minPinLength = widget.state.minPinLength;
|
final minPinLength = widget.state.minPinLength;
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(hasPin ? l10n.l_change_pin : l10n.l_set_pin),
|
title: Text(hasPin ? l10n.s_change_pin : l10n.s_set_pin),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: isValid ? _submit : null,
|
onPressed: isValid ? _submit : null,
|
||||||
child: Text(l10n.w_save),
|
child: Text(l10n.s_save),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -77,7 +77,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_current_pin,
|
labelText: l10n.s_current_pin,
|
||||||
errorText: _currentIsWrong ? _currentPinError : null,
|
errorText: _currentIsWrong ? _currentPinError : null,
|
||||||
errorMaxLines: 3,
|
errorMaxLines: 3,
|
||||||
prefixIcon: const Icon(Icons.pin_outlined),
|
prefixIcon: const Icon(Icons.pin_outlined),
|
||||||
@ -98,7 +98,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_new_pin,
|
labelText: l10n.s_new_pin,
|
||||||
enabled: !hasPin || _currentPin.isNotEmpty,
|
enabled: !hasPin || _currentPin.isNotEmpty,
|
||||||
errorText: _newIsWrong ? _newPinError : null,
|
errorText: _newIsWrong ? _newPinError : null,
|
||||||
errorMaxLines: 3,
|
errorMaxLines: 3,
|
||||||
@ -116,7 +116,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_confirm_pin,
|
labelText: l10n.s_confirm_pin,
|
||||||
prefixIcon: const Icon(Icons.pin_outlined),
|
prefixIcon: const Icon(Icons.pin_outlined),
|
||||||
enabled:
|
enabled:
|
||||||
(!hasPin || _currentPin.isNotEmpty) && _newPin.isNotEmpty,
|
(!hasPin || _currentPin.isNotEmpty) && _newPin.isNotEmpty,
|
||||||
@ -160,7 +160,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
|
|||||||
.setPin(_newPin, oldPin: oldPin);
|
.setPin(_newPin, oldPin: oldPin);
|
||||||
result.when(success: () {
|
result.when(success: () {
|
||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
showMessage(context, l10n.l_pin_set);
|
showMessage(context, l10n.s_pin_set);
|
||||||
}, failed: (retries, authBlocked) {
|
}, failed: (retries, authBlocked) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (authBlocked) {
|
if (authBlocked) {
|
||||||
|
@ -54,7 +54,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
|
|||||||
.renameFingerprint(widget.fingerprint, _label);
|
.renameFingerprint(widget.fingerprint, _label);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.of(context).pop(renamed);
|
Navigator.of(context).pop(renamed);
|
||||||
showMessage(context, l10n.l_fingerprint_renamed);
|
showMessage(context, l10n.s_fingerprint_renamed);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
final String errorMessage;
|
final String errorMessage;
|
||||||
// TODO: Make this cleaner than importing desktop specific RpcError.
|
// TODO: Make this cleaner than importing desktop specific RpcError.
|
||||||
@ -75,11 +75,11 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_rename_fp),
|
title: Text(l10n.s_rename_fp),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _label.isNotEmpty ? _submit : null,
|
onPressed: _label.isNotEmpty ? _submit : null,
|
||||||
child: Text(l10n.w_save),
|
child: Text(l10n.s_save),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -96,7 +96,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
|
|||||||
buildCounter: buildByteCounterFor(_label),
|
buildCounter: buildByteCounterFor(_label),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.w_label,
|
labelText: l10n.s_label,
|
||||||
prefixIcon: const Icon(Icons.fingerprint_outlined),
|
prefixIcon: const Icon(Icons.fingerprint_outlined),
|
||||||
),
|
),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
@ -63,7 +63,7 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_factory_reset),
|
title: Text(l10n.s_factory_reset),
|
||||||
onCancel: () {
|
onCancel: () {
|
||||||
_subscription?.cancel();
|
_subscription?.cancel();
|
||||||
},
|
},
|
||||||
@ -100,7 +100,7 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: Text(l10n.w_reset),
|
child: Text(l10n.s_reset),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
@ -48,7 +48,7 @@ class FidoUnlockedPage extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
final creds = data.value;
|
final creds = data.value;
|
||||||
if (creds.isNotEmpty) {
|
if (creds.isNotEmpty) {
|
||||||
children.add(ListTitle(l10n.w_credentials));
|
children.add(ListTitle(l10n.s_credentials));
|
||||||
children.addAll(
|
children.addAll(
|
||||||
creds.map(
|
creds.map(
|
||||||
(cred) => ListTile(
|
(cred) => ListTile(
|
||||||
@ -96,7 +96,7 @@ class FidoUnlockedPage extends ConsumerWidget {
|
|||||||
final fingerprints = data.value;
|
final fingerprints = data.value;
|
||||||
if (fingerprints.isNotEmpty) {
|
if (fingerprints.isNotEmpty) {
|
||||||
nFingerprints = fingerprints.length;
|
nFingerprints = fingerprints.length;
|
||||||
children.add(ListTitle(l10n.w_fingerprints));
|
children.add(ListTitle(l10n.s_fingerprints));
|
||||||
children.addAll(fingerprints.map((fp) => ListTile(
|
children.addAll(fingerprints.map((fp) => ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
foregroundColor: Theme.of(context).colorScheme.onSecondary,
|
foregroundColor: Theme.of(context).colorScheme.onSecondary,
|
||||||
@ -137,7 +137,7 @@ class FidoUnlockedPage extends ConsumerWidget {
|
|||||||
|
|
||||||
if (children.isNotEmpty) {
|
if (children.isNotEmpty) {
|
||||||
return AppPage(
|
return AppPage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
keyActionsBuilder: (context) =>
|
keyActionsBuilder: (context) =>
|
||||||
fidoBuildActions(context, node, state, nFingerprints),
|
fidoBuildActions(context, node, state, nFingerprints),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -147,9 +147,9 @@ class FidoUnlockedPage extends ConsumerWidget {
|
|||||||
|
|
||||||
if (state.bioEnroll != null) {
|
if (state.bioEnroll != null) {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
graphic: noFingerprints,
|
graphic: noFingerprints,
|
||||||
header: l10n.l_no_fingerprints,
|
header: l10n.s_no_fingerprints,
|
||||||
message: l10n.l_add_one_or_more_fps,
|
message: l10n.l_add_one_or_more_fps,
|
||||||
keyActionsBuilder: (context) =>
|
keyActionsBuilder: (context) =>
|
||||||
fidoBuildActions(context, node, state, 0),
|
fidoBuildActions(context, node, state, 0),
|
||||||
@ -157,7 +157,7 @@ class FidoUnlockedPage extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: Text(l10n.w_webauthn),
|
title: Text(l10n.s_webauthn),
|
||||||
graphic: manageAccounts,
|
graphic: manageAccounts,
|
||||||
header: l10n.l_no_discoverable_accounts,
|
header: l10n.l_no_discoverable_accounts,
|
||||||
message: l10n.l_register_sk_on_websites,
|
message: l10n.l_register_sk_on_websites,
|
||||||
@ -166,7 +166,7 @@ class FidoUnlockedPage extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLoadingPage(BuildContext context) => AppPage(
|
Widget _buildLoadingPage(BuildContext context) => AppPage(
|
||||||
title: Text(AppLocalizations.of(context)!.w_webauthn),
|
title: Text(AppLocalizations.of(context)!.s_webauthn),
|
||||||
centered: true,
|
centered: true,
|
||||||
delayedContent: true,
|
delayedContent: true,
|
||||||
child: const CircularProgressIndicator(),
|
child: const CircularProgressIndicator(),
|
||||||
|
@ -4,31 +4,37 @@
|
|||||||
"@_readme": {
|
"@_readme": {
|
||||||
"notes": [
|
"notes": [
|
||||||
"All strings start with a Captial letter.",
|
"All strings start with a Captial letter.",
|
||||||
"Group strings by category, but don't needlessly tie them to a section of the app if they can be re-used between several."
|
"Group strings by category, but don't needlessly tie them to a section of the app if they can be re-used between several.",
|
||||||
|
"Run check_strings.py on the .arb file to detect problems, tweak @_lint_rules as needed per language."
|
||||||
],
|
],
|
||||||
"prefixes": {
|
"prefixes": {
|
||||||
"w_": "A single word",
|
"s_": "A single, or few words. Should be short enough to display on a button, or a header.",
|
||||||
"l_": "A single line. Should not be more than one sentence, and not end with a period.",
|
"l_": "A single line, can be wrapped. Should not be more than one sentence, and not end with a period.",
|
||||||
"p_": "One or more full sentences, with proper punctuation.",
|
"p_": "One or more full sentences, with proper punctuation.",
|
||||||
"q_": "A question, ending in question mark."
|
"q_": "A question, ending in question mark."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"@_lint_rules": {
|
||||||
|
"s_max_words": 4,
|
||||||
|
"s_max_length": 32
|
||||||
|
},
|
||||||
|
|
||||||
"app_name": "Yubico Authenticator",
|
"app_name": "Yubico Authenticator",
|
||||||
|
|
||||||
"w_save": "Save",
|
"s_save": "Save",
|
||||||
"w_cancel": "Cancel",
|
"s_cancel": "Cancel",
|
||||||
"w_close": "Close",
|
"s_close": "Close",
|
||||||
"w_delete": "Delete",
|
"s_delete": "Delete",
|
||||||
"w_quit": "Quit",
|
"s_quit": "Quit",
|
||||||
"w_unlock": "Unlock",
|
"s_unlock": "Unlock",
|
||||||
"w_calculate": "Calculate",
|
"s_calculate": "Calculate",
|
||||||
"w_label": "Label",
|
"s_label": "Label",
|
||||||
"w_name": "Name",
|
"s_name": "Name",
|
||||||
"w_usb": "USB",
|
"s_usb": "USB",
|
||||||
"w_nfc": "NFC",
|
"s_nfc": "NFC",
|
||||||
"l_show_window": "Show window",
|
"s_show_window": "Show window",
|
||||||
"l_hide_window": "Hide window",
|
"s_hide_window": "Hide window",
|
||||||
"q_rename_target": "Rename {label}?",
|
"q_rename_target": "Rename {label}?",
|
||||||
"@q_rename_target" : {
|
"@q_rename_target" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -36,62 +42,62 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"w_about": "About",
|
"s_about": "About",
|
||||||
"w_appearance": "Appearance",
|
"s_appearance": "Appearance",
|
||||||
"w_authenticator": "Authenticator",
|
"s_authenticator": "Authenticator",
|
||||||
"w_manage": "Manage",
|
"s_manage": "Manage",
|
||||||
"w_setup": "Setup",
|
"s_setup": "Setup",
|
||||||
"w_settings": "Settings",
|
"s_settings": "Settings",
|
||||||
"w_webauthn": "WebAuthn",
|
"s_webauthn": "WebAuthn",
|
||||||
"l_help_and_about": "Help and about",
|
"s_help_and_about": "Help and about",
|
||||||
"l_help_and_feedback": "Help and feedback",
|
"s_help_and_feedback": "Help and feedback",
|
||||||
"l_send_feedback": "Send us feedback",
|
"s_send_feedback": "Send us feedback",
|
||||||
"l_i_need_help": "I need help",
|
"s_i_need_help": "I need help",
|
||||||
"w_troubleshooting": "Troubleshooting",
|
"s_troubleshooting": "Troubleshooting",
|
||||||
"l_terms_of_use": "Terms of use",
|
"s_terms_of_use": "Terms of use",
|
||||||
"l_privacy_policy": "Privacy policy",
|
"s_privacy_policy": "Privacy policy",
|
||||||
"l_open_src_licenses": "Open source licenses",
|
"s_open_src_licenses": "Open source licenses",
|
||||||
"l_configure_yk": "Configure YubiKey",
|
"s_configure_yk": "Configure YubiKey",
|
||||||
"l_please_wait": "Please wait\u2026",
|
"s_please_wait": "Please wait\u2026",
|
||||||
"l_secret_key": "Secret key",
|
"s_secret_key": "Secret key",
|
||||||
"l_invalid_length": "Invalid length",
|
"s_invalid_length": "Invalid length",
|
||||||
"l_require_touch": "Require touch",
|
"s_require_touch": "Require touch",
|
||||||
"q_have_account_info": "Have account info?",
|
"q_have_account_info": "Have account info?",
|
||||||
"l_run_diagnostics": "Run diagnostics",
|
"s_run_diagnostics": "Run diagnostics",
|
||||||
"l_log_level": "Log level: {level}",
|
"s_log_level": "Log level: {level}",
|
||||||
"@l_log_level": {
|
"@s_log_level": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"level": {}
|
"level": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_character_count": "Character count",
|
"s_character_count": "Character count",
|
||||||
"l_learn_more": "Learn\u00a0more",
|
"s_learn_more": "Learn\u00a0more",
|
||||||
|
|
||||||
"@_language": {},
|
"@_language": {},
|
||||||
"w_language": "Language",
|
"s_language": "Language",
|
||||||
"l_enable_community_translations": "Enable community translations",
|
"l_enable_community_translations": "Enable community translations",
|
||||||
"p_community_translations_desc": "These translations are provided and maintained by the community. They may contain errors or be incomplete.",
|
"p_community_translations_desc": "These translations are provided and maintained by the community. They may contain errors or be incomplete.",
|
||||||
|
|
||||||
"@_theme": {},
|
"@_theme": {},
|
||||||
"l_app_theme": "App theme",
|
"s_app_theme": "App theme",
|
||||||
"l_choose_app_theme": "Choose app theme",
|
"s_choose_app_theme": "Choose app theme",
|
||||||
"l_system_default": "System default",
|
"s_system_default": "System default",
|
||||||
"l_light_mode": "Light mode",
|
"s_light_mode": "Light mode",
|
||||||
"l_dark_mode": "Dark mode",
|
"s_dark_mode": "Dark mode",
|
||||||
|
|
||||||
"@_yubikey_selection": {},
|
"@_yubikey_selection": {},
|
||||||
"l_select_yk": "Select YubiKey",
|
"s_select_yk": "Select YubiKey",
|
||||||
"l_select_to_scan": "Select to scan",
|
"s_select_to_scan": "Select to scan",
|
||||||
"l_hide_device": "Hide device",
|
"s_hide_device": "Hide device",
|
||||||
"l_show_hidden_devices": "Show hidden devices",
|
"s_show_hidden_devices": "Show hidden devices",
|
||||||
"l_sn_serial": "S/N: {serial}",
|
"s_sn_serial": "S/N: {serial}",
|
||||||
"@l_sn_serial" : {
|
"@s_sn_serial" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"serial": {}
|
"serial": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_fw_version": "F/W: {version}",
|
"s_fw_version": "F/W: {version}",
|
||||||
"@l_fw_version" : {
|
"@s_fw_version" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"version": {}
|
"version": {}
|
||||||
}
|
}
|
||||||
@ -105,18 +111,18 @@
|
|||||||
"l_place_on_nfc_reader": "Place your YubiKey on the NFC reader",
|
"l_place_on_nfc_reader": "Place your YubiKey on the NFC reader",
|
||||||
"l_replace_yk_on_reader": "Place your YubiKey back on the reader",
|
"l_replace_yk_on_reader": "Place your YubiKey back on the reader",
|
||||||
"l_remove_yk_from_reader": "Remove your YubiKey from the NFC reader",
|
"l_remove_yk_from_reader": "Remove your YubiKey from the NFC reader",
|
||||||
"l_try_reinsert_yk": "Try to remove and reinsert your YubiKey.",
|
"p_try_reinsert_yk": "Try to remove and reinsert your YubiKey.",
|
||||||
"l_touch_required": "Touch required",
|
"s_touch_required": "Touch required",
|
||||||
"l_touch_button_now": "Touch the button on your YubiKey now",
|
"l_touch_button_now": "Touch the button on your YubiKey now",
|
||||||
"l_keep_touching_yk": "Keep touching your YubiKey repeatedly\u2026",
|
"l_keep_touching_yk": "Keep touching your YubiKey repeatedly\u2026",
|
||||||
|
|
||||||
"@_app_configuration": {},
|
"@_app_configuration": {},
|
||||||
"l_toggle_applications": "Toggle applications",
|
"s_toggle_applications": "Toggle applications",
|
||||||
"l_min_one_interface": "At least one interface must be enabled",
|
"l_min_one_interface": "At least one interface must be enabled",
|
||||||
"l_reconfiguring_yk": "Reconfiguring YubiKey\u2026",
|
"s_reconfiguring_yk": "Reconfiguring YubiKey\u2026",
|
||||||
"l_config_updated": "Configuration updated",
|
"s_config_updated": "Configuration updated",
|
||||||
"l_config_updated_reinsert": "Configuration updated, remove and reinsert your YubiKey",
|
"l_config_updated_reinsert": "Configuration updated, remove and reinsert your YubiKey",
|
||||||
"l_app_not_supported": "Application not supported",
|
"s_app_not_supported": "Application not supported",
|
||||||
"l_app_not_supported_on_yk": "The used YubiKey does not support '${app}' application",
|
"l_app_not_supported_on_yk": "The used YubiKey does not support '${app}' application",
|
||||||
"@l_app_not_supported_on_yk" : {
|
"@l_app_not_supported_on_yk" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -124,65 +130,65 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_app_not_supported_desc": "This application is not supported",
|
"l_app_not_supported_desc": "This application is not supported",
|
||||||
"l_app_disabled": "Application disabled",
|
"s_app_disabled": "Application disabled",
|
||||||
"l_app_disabled_desc": "Enable the '{app}' application on your YubiKey to access",
|
"l_app_disabled_desc": "Enable the '{app}' application on your YubiKey to access",
|
||||||
"@l_app_disabled_desc" : {
|
"@l_app_disabled_desc" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"app": {}
|
"app": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_fido_disabled": "FIDO2 disabled",
|
"s_fido_disabled": "FIDO2 disabled",
|
||||||
"l_webauthn_req_fido2": "WebAuthn requires the FIDO2 application to be enabled on your YubiKey",
|
"l_webauthn_req_fido2": "WebAuthn requires the FIDO2 application to be enabled on your YubiKey",
|
||||||
|
|
||||||
"@_connectivity_issues": {},
|
"@_connectivity_issues": {},
|
||||||
"l_helper_not_responding": "The Helper process isn't responding",
|
"l_helper_not_responding": "The Helper process isn't responding",
|
||||||
"l_yk_no_access": "This YubiKey cannot be accessed",
|
"l_yk_no_access": "This YubiKey cannot be accessed",
|
||||||
"l_yk_inaccessible": "Device inaccessible",
|
"s_yk_inaccessible": "Device inaccessible",
|
||||||
"l_open_connection_failed": "Failed to open connection",
|
"l_open_connection_failed": "Failed to open connection",
|
||||||
"l_ccid_connection_failed": "Failed to open smart card connection",
|
"l_ccid_connection_failed": "Failed to open smart card connection",
|
||||||
"p_ccid_service_unavailable": "Make sure your smart card service is functioning.",
|
"p_ccid_service_unavailable": "Make sure your smart card service is functioning.",
|
||||||
"p_pcscd_unavailable": "Make sure pcscd is installed and running.",
|
"p_pcscd_unavailable": "Make sure pcscd is installed and running.",
|
||||||
"l_no_yk_present": "No YubiKey present",
|
"l_no_yk_present": "No YubiKey present",
|
||||||
"l_unknown_type": "Unknown type",
|
"s_unknown_type": "Unknown type",
|
||||||
"l_unknown_device": "Unrecognized device",
|
"s_unknown_device": "Unrecognized device",
|
||||||
"l_unsupported_yk": "Unsupported YubiKey",
|
"s_unsupported_yk": "Unsupported YubiKey",
|
||||||
"l_yk_not_recognized": "Device not recognized",
|
"s_yk_not_recognized": "Device not recognized",
|
||||||
|
|
||||||
"@_general_errors": {},
|
"@_general_errors": {},
|
||||||
"l_error_occured": "An error has occured",
|
"l_error_occured": "An error has occured",
|
||||||
"l_application_error": "Application error",
|
"s_application_error": "Application error",
|
||||||
"l_import_error": "Import error",
|
"l_import_error": "Import error",
|
||||||
"l_file_not_found": "File not found",
|
"l_file_not_found": "File not found",
|
||||||
"l_file_too_big": "File size too big",
|
"l_file_too_big": "File size too big",
|
||||||
"l_filesystem_error": "File system operation error",
|
"l_filesystem_error": "File system operation error",
|
||||||
|
|
||||||
"@_pins": {},
|
"@_pins": {},
|
||||||
"w_pin": "PIN",
|
"s_pin": "PIN",
|
||||||
"l_set_pin": "Set PIN",
|
"s_set_pin": "Set PIN",
|
||||||
"l_change_pin": "Change PIN",
|
"s_change_pin": "Change PIN",
|
||||||
"l_current_pin": "Current PIN",
|
"s_current_pin": "Current PIN",
|
||||||
"l_new_pin": "New PIN",
|
"s_new_pin": "New PIN",
|
||||||
"l_confirm_pin": "Confirm PIN",
|
"s_confirm_pin": "Confirm PIN",
|
||||||
"l_new_pin_len": "New PIN must be at least {length} characters",
|
"l_new_pin_len": "New PIN must be at least {length} characters",
|
||||||
"@l_new_pin_len" : {
|
"@l_new_pin_len" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"length": {}
|
"length": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_pin_set": "PIN set",
|
"s_pin_set": "PIN set",
|
||||||
"l_set_pin_failed": "Failed to set PIN: {message}",
|
"l_set_pin_failed": "Failed to set PIN: {message}",
|
||||||
"@l_set_pin_failed" : {
|
"@l_set_pin_failed" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"message": {}
|
"message": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_wrong_pin_attempts_remaining": "Wrong PIN. {retries} attempt(s) remaining.",
|
"l_wrong_pin_attempts_remaining": "Wrong PIN, {retries} attempt(s) remaining",
|
||||||
"@l_wrong_pin_attempts_remaining" : {
|
"@l_wrong_pin_attempts_remaining" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"retries": {}
|
"retries": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_fido_pin_protection": "FIDO PIN protection",
|
"s_fido_pin_protection": "FIDO PIN protection",
|
||||||
"l_fido_pin_protection_optional": "Optional FIDO PIN protection",
|
"l_fido_pin_protection_optional": "Optional FIDO PIN protection",
|
||||||
"l_enter_fido2_pin": "Enter the FIDO2 PIN for your YubiKey",
|
"l_enter_fido2_pin": "Enter the FIDO2 PIN for your YubiKey",
|
||||||
"l_optionally_set_a_pin": "Optionally set a PIN to protect access to your YubiKey\nRegister as a Security Key on websites",
|
"l_optionally_set_a_pin": "Optionally set a PIN to protect access to your YubiKey\nRegister as a Security Key on websites",
|
||||||
@ -199,20 +205,20 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"@_passwords": {},
|
"@_passwords": {},
|
||||||
"w_password": "Password",
|
"s_password": "Password",
|
||||||
"l_manage_password": "Manage password",
|
"s_manage_password": "Manage password",
|
||||||
"l_set_password": "Set password",
|
"s_set_password": "Set password",
|
||||||
"l_password_set": "Password set",
|
"s_password_set": "Password set",
|
||||||
"l_optional_password_protection": "Optional password protection",
|
"l_optional_password_protection": "Optional password protection",
|
||||||
"l_new_password": "New password",
|
"s_new_password": "New password",
|
||||||
"l_current_password": "Current password",
|
"s_current_password": "Current password",
|
||||||
"l_confirm_password": "Confirm password",
|
"s_confirm_password": "Confirm password",
|
||||||
"l_wrong_password": "Wrong password",
|
"s_wrong_password": "Wrong password",
|
||||||
"l_remove_password": "Remove password",
|
"s_remove_password": "Remove password",
|
||||||
"l_password_removed": "Password removed",
|
"s_password_removed": "Password removed",
|
||||||
"l_remember_password": "Remember password",
|
"s_remember_password": "Remember password",
|
||||||
"l_clear_saved_password": "Clear saved password",
|
"s_clear_saved_password": "Clear saved password",
|
||||||
"l_password_forgotten": "Password forgotten",
|
"s_password_forgotten": "Password forgotten",
|
||||||
"l_keystore_unavailable": "OS Keystore unavailable",
|
"l_keystore_unavailable": "OS Keystore unavailable",
|
||||||
"l_remember_pw_failed": "Failed to remember password",
|
"l_remember_pw_failed": "Failed to remember password",
|
||||||
"l_unlock_first": "Unlock with password first",
|
"l_unlock_first": "Unlock with password first",
|
||||||
@ -227,10 +233,10 @@
|
|||||||
"label": {}
|
"label": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"w_accounts": "Accounts",
|
"s_accounts": "Accounts",
|
||||||
"l_no_accounts": "No accounts",
|
"s_no_accounts": "No accounts",
|
||||||
"l_add_account": "Add account",
|
"s_add_account": "Add account",
|
||||||
"l_account_added": "Account added",
|
"s_account_added": "Account added",
|
||||||
"l_account_add_failed": "Failed adding account: {message}",
|
"l_account_add_failed": "Failed adding account: {message}",
|
||||||
"@l_account_add_failed" : {
|
"@l_account_add_failed" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -240,19 +246,19 @@
|
|||||||
"l_account_name_required": "Your account must have a name",
|
"l_account_name_required": "Your account must have a name",
|
||||||
"l_name_already_exists": "This name already exists for the issuer",
|
"l_name_already_exists": "This name already exists for the issuer",
|
||||||
"l_invalid_character_issuer": "Invalid character: ':' is not allowed in issuer",
|
"l_invalid_character_issuer": "Invalid character: ':' is not allowed in issuer",
|
||||||
"w_pinned": "Pinned",
|
"s_pinned": "Pinned",
|
||||||
"l_pin_account": "Pin account",
|
"s_pin_account": "Pin account",
|
||||||
"l_unpin_account": "Unpin account",
|
"s_unpin_account": "Unpin account",
|
||||||
"l_no_pinned_accounts": "No pinned accounts",
|
"s_no_pinned_accounts": "No pinned accounts",
|
||||||
"l_rename_account": "Rename account",
|
"s_rename_account": "Rename account",
|
||||||
"l_account_renamed": "Account renamed",
|
"s_account_renamed": "Account renamed",
|
||||||
"p_rename_will_change_account_displayed": "This will change how the account is displayed in the list.",
|
"p_rename_will_change_account_displayed": "This will change how the account is displayed in the list.",
|
||||||
"l_delete_account": "Delete account",
|
"s_delete_account": "Delete account",
|
||||||
"l_account_deleted": "Account deleted",
|
"s_account_deleted": "Account deleted",
|
||||||
"p_warning_delete_account": "Warning! This action will delete the account from your YubiKey.",
|
"p_warning_delete_account": "Warning! This action will delete the account from your YubiKey.",
|
||||||
"p_warning_disable_credential": "You will no longer be able to generate OTPs for this account. Make sure to first disable this credential from the website to avoid being locked out of your account.",
|
"p_warning_disable_credential": "You will no longer be able to generate OTPs for this account. Make sure to first disable this credential from the website to avoid being locked out of your account.",
|
||||||
"l_account_name": "Account name",
|
"s_account_name": "Account name",
|
||||||
"l_search_accounts": "Search accounts",
|
"s_search_accounts": "Search accounts",
|
||||||
"l_accounts_used": "{used} of {capacity} accounts used",
|
"l_accounts_used": "{used} of {capacity} accounts used",
|
||||||
"@l_accounts_used" : {
|
"@l_accounts_used" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@ -260,19 +266,19 @@
|
|||||||
"capacity": {}
|
"capacity": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_num_digits": "{num} digits",
|
"s_num_digits": "{num} digits",
|
||||||
"@l_num_digits" : {
|
"@s_num_digits" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"num": {}
|
"num": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_num_sec": "{num} sec",
|
"s_num_sec": "{num} sec",
|
||||||
"@l_num_sec" : {
|
"@s_num_sec" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"num": {}
|
"num": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_issuer_optional": "Issuer (optional)",
|
"s_issuer_optional": "Issuer (optional)",
|
||||||
|
|
||||||
"@_fido_credentials": {},
|
"@_fido_credentials": {},
|
||||||
"l_credential": "Credential: {label}",
|
"l_credential": "Credential: {label}",
|
||||||
@ -281,12 +287,12 @@
|
|||||||
"label": {}
|
"label": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"w_credentials": "Credentials",
|
"s_credentials": "Credentials",
|
||||||
"l_ready_to_use": "Ready to use",
|
"l_ready_to_use": "Ready to use",
|
||||||
"l_register_sk_on_websites": "Register as a Security Key on websites",
|
"l_register_sk_on_websites": "Register as a Security Key on websites",
|
||||||
"l_no_discoverable_accounts": "No discoverable accounts",
|
"l_no_discoverable_accounts": "No discoverable accounts",
|
||||||
"l_delete_credential": "Delete credential",
|
"s_delete_credential": "Delete credential",
|
||||||
"l_credential_deleted": "Credential deleted",
|
"s_credential_deleted": "Credential deleted",
|
||||||
"p_warning_delete_credential": "This will delete the credential from your YubiKey.",
|
"p_warning_delete_credential": "This will delete the credential from your YubiKey.",
|
||||||
|
|
||||||
"@_fingerprints": {},
|
"@_fingerprints": {},
|
||||||
@ -296,32 +302,32 @@
|
|||||||
"label": {}
|
"label": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"w_fingerprints": "Fingerprints",
|
"s_fingerprints": "Fingerprints",
|
||||||
"l_fingerprint_captured": "Fingerprint captured successfully!",
|
"l_fingerprint_captured": "Fingerprint captured successfully!",
|
||||||
"l_fingerprint_added": "Fingerprint added",
|
"s_fingerprint_added": "Fingerprint added",
|
||||||
"l_setting_name_failed": "Error setting name: {message}",
|
"l_setting_name_failed": "Error setting name: {message}",
|
||||||
"@l_setting_name_failed" : {
|
"@l_setting_name_failed" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"message": {}
|
"message": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_add_fingerprint": "Add fingerprint",
|
"s_add_fingerprint": "Add fingerprint",
|
||||||
"l_fp_step_1_capture": "Step 1/2: Capture fingerprint",
|
"l_fp_step_1_capture": "Step 1/2: Capture fingerprint",
|
||||||
"l_fp_step_2_name": "Step 2/2: Name fingerprint",
|
"l_fp_step_2_name": "Step 2/2: Name fingerprint",
|
||||||
"l_delete_fingerprint": "Delete fingerprint",
|
"s_delete_fingerprint": "Delete fingerprint",
|
||||||
"l_fingerprint_deleted": "Fingerprint deleted",
|
"s_fingerprint_deleted": "Fingerprint deleted",
|
||||||
"p_warning_delete_fingerprint": "This will delete the fingerprint from your YubiKey.",
|
"p_warning_delete_fingerprint": "This will delete the fingerprint from your YubiKey.",
|
||||||
"l_no_fingerprints": "No fingerprints",
|
"s_no_fingerprints": "No fingerprints",
|
||||||
"l_set_pin_fingerprints": "Set a PIN to register fingerprints",
|
"l_set_pin_fingerprints": "Set a PIN to register fingerprints",
|
||||||
"l_no_fps_added": "No fingerprints have been added",
|
"l_no_fps_added": "No fingerprints have been added",
|
||||||
"l_fingerprint_renamed": "Fingerprint renamed",
|
"s_rename_fp": "Rename fingerprint",
|
||||||
|
"s_fingerprint_renamed": "Fingerprint renamed",
|
||||||
"l_rename_fp_failed": "Error renaming: {message}",
|
"l_rename_fp_failed": "Error renaming: {message}",
|
||||||
"@l_rename_fp_failed" : {
|
"@l_rename_fp_failed" : {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"message": {}
|
"message": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"l_rename_fp": "Rename fingerprint",
|
|
||||||
"l_add_one_or_more_fps": "Add one or more (up to five) fingerprints",
|
"l_add_one_or_more_fps": "Add one or more (up to five) fingerprints",
|
||||||
"l_fingerprints_used": "{used}/5 fingerprints registered",
|
"l_fingerprints_used": "{used}/5 fingerprints registered",
|
||||||
"@l_fingerprints_used": {
|
"@l_fingerprints_used": {
|
||||||
@ -333,16 +339,16 @@
|
|||||||
"p_will_change_label_fp": "This will change the label of the fingerprint.",
|
"p_will_change_label_fp": "This will change the label of the fingerprint.",
|
||||||
|
|
||||||
"@_permissions": {},
|
"@_permissions": {},
|
||||||
"l_enable_nfc": "Enable NFC",
|
"s_enable_nfc": "Enable NFC",
|
||||||
"l_permission_denied": "Permission denied",
|
"s_permission_denied": "Permission denied",
|
||||||
"l_elevating_permissions": "Elevating permissions\u2026",
|
"l_elevating_permissions": "Elevating permissions\u2026",
|
||||||
"l_review_permissions": "Review permissions",
|
"s_review_permissions": "Review permissions",
|
||||||
"p_elevated_permissions_required": "Managing this device requires elevated privileges.",
|
"p_elevated_permissions_required": "Managing this device requires elevated privileges.",
|
||||||
"p_webauthn_elevated_permissions_required": "WebAuthn management requires elevated privileges.",
|
"p_webauthn_elevated_permissions_required": "WebAuthn management requires elevated privileges.",
|
||||||
"p_need_camera_permission": "Yubico Authenticator needs Camera permissions for scanning QR codes.",
|
"p_need_camera_permission": "Yubico Authenticator needs Camera permissions for scanning QR codes.",
|
||||||
|
|
||||||
"@_qr_codes": {},
|
"@_qr_codes": {},
|
||||||
"l_qr_scan": "Scan QR code",
|
"s_qr_scan": "Scan QR code",
|
||||||
"l_qr_scanned": "Scanned QR code",
|
"l_qr_scanned": "Scanned QR code",
|
||||||
"l_invalid_qr": "Invalid QR code",
|
"l_invalid_qr": "Invalid QR code",
|
||||||
"l_qr_not_found": "No QR code found",
|
"l_qr_not_found": "No QR code found",
|
||||||
@ -355,15 +361,15 @@
|
|||||||
"l_point_camera_scan": "Point your camera at a QR code to scan it",
|
"l_point_camera_scan": "Point your camera at a QR code to scan it",
|
||||||
"q_want_to_scan": "Would like to scan?",
|
"q_want_to_scan": "Would like to scan?",
|
||||||
"q_no_qr": "No QR code?",
|
"q_no_qr": "No QR code?",
|
||||||
"l_enter_manually": "Enter manually",
|
"s_enter_manually": "Enter manually",
|
||||||
|
|
||||||
"@_factory_reset": {},
|
"@_factory_reset": {},
|
||||||
"w_reset": "Reset",
|
"s_reset": "Reset",
|
||||||
"l_factory_reset": "Factory reset",
|
"s_factory_reset": "Factory reset",
|
||||||
"l_factory_reset_this_app": "Factory reset this application",
|
"l_factory_reset_this_app": "Factory reset this application",
|
||||||
"l_reset_oath": "Reset OATH",
|
"s_reset_oath": "Reset OATH",
|
||||||
"l_oath_application_reset": "OATH application reset",
|
"l_oath_application_reset": "OATH application reset",
|
||||||
"l_reset_fido": "Reset FIDO",
|
"s_reset_fido": "Reset FIDO",
|
||||||
"l_fido_app_reset": "FIDO application reset",
|
"l_fido_app_reset": "FIDO application reset",
|
||||||
"l_press_reset_to_begin": "Press reset to begin\u2026",
|
"l_press_reset_to_begin": "Press reset to begin\u2026",
|
||||||
"l_reset_failed": "Error performing reset: {message}",
|
"l_reset_failed": "Error performing reset: {message}",
|
||||||
@ -379,9 +385,9 @@
|
|||||||
|
|
||||||
"@_copy_to_clipboard": {},
|
"@_copy_to_clipboard": {},
|
||||||
"l_copy_to_clipboard": "Copy to clipboard",
|
"l_copy_to_clipboard": "Copy to clipboard",
|
||||||
"l_code_copied": "Code copied",
|
"s_code_copied": "Code copied",
|
||||||
"l_code_copied_clipboard": "Code copied to clipboard",
|
"l_code_copied_clipboard": "Code copied to clipboard",
|
||||||
"l_copy_log": "Copy log",
|
"s_copy_log": "Copy log",
|
||||||
"l_log_copied": "Log copied to clipboard",
|
"l_log_copied": "Log copied to clipboard",
|
||||||
"l_diagnostics_copied": "Diagnostic data copied to clipboard",
|
"l_diagnostics_copied": "Diagnostic data copied to clipboard",
|
||||||
"p_target_copied_clipboard": "{label} copied to clipboard.",
|
"p_target_copied_clipboard": "{label} copied to clipboard.",
|
||||||
@ -392,16 +398,16 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"@_custom_icons": {},
|
"@_custom_icons": {},
|
||||||
"l_custom_icons": "Custom icons",
|
"s_custom_icons": "Custom icons",
|
||||||
"l_set_icons_for_accounts": "Set icons for accounts",
|
"l_set_icons_for_accounts": "Set icons for accounts",
|
||||||
"p_custom_icons_description": "Icon packs can make your accounts more easily distinguishable with familiar logos and colors.",
|
"p_custom_icons_description": "Icon packs can make your accounts more easily distinguishable with familiar logos and colors.",
|
||||||
"l_replace_icon_pack": "Replace icon pack",
|
"s_replace_icon_pack": "Replace icon pack",
|
||||||
"l_loading_icon_pack": "Loading icon pack\u2026",
|
"l_loading_icon_pack": "Loading icon pack\u2026",
|
||||||
"l_load_icon_pack": "Load icon pack",
|
"s_load_icon_pack": "Load icon pack",
|
||||||
"l_remove_icon_pack": "Remove icon pack",
|
"s_remove_icon_pack": "Remove icon pack",
|
||||||
"l_icon_pack_removed": "Icon pack removed",
|
"l_icon_pack_removed": "Icon pack removed",
|
||||||
"l_remove_icon_pack_failed": "Error removing icon pack",
|
"l_remove_icon_pack_failed": "Error removing icon pack",
|
||||||
"l_choose_icon_pack": "Choose icon pack",
|
"s_choose_icon_pack": "Choose icon pack",
|
||||||
"l_icon_pack_imported": "Icon pack imported",
|
"l_icon_pack_imported": "Icon pack imported",
|
||||||
"l_import_icon_pack_failed": "Error importing icon pack: {message}",
|
"l_import_icon_pack_failed": "Error importing icon pack: {message}",
|
||||||
"@l_import_icon_pack_failed": {
|
"@l_import_icon_pack_failed": {
|
||||||
@ -412,24 +418,24 @@
|
|||||||
"l_invalid_icon_pack": "Invalid icon pack",
|
"l_invalid_icon_pack": "Invalid icon pack",
|
||||||
|
|
||||||
"@_android_settings": {},
|
"@_android_settings": {},
|
||||||
"l_nfc_options": "NFC options",
|
"s_nfc_options": "NFC options",
|
||||||
"l_on_yk_nfc_tap": "On YubiKey NFC tap",
|
"l_on_yk_nfc_tap": "On YubiKey NFC tap",
|
||||||
"l_launch_ya": "Launch Yubico Authenticator",
|
"l_launch_ya": "Launch Yubico Authenticator",
|
||||||
"l_copy_otp_clipboard": "Copy OTP to clipboard",
|
"l_copy_otp_clipboard": "Copy OTP to clipboard",
|
||||||
"l_launch_and_copy_otp": "Launch app and copy OTP",
|
"l_launch_and_copy_otp": "Launch app and copy OTP",
|
||||||
"l_kbd_layout_for_static": "Keyboard layout (for static password)",
|
"l_kbd_layout_for_static": "Keyboard layout (for static password)",
|
||||||
"l_choose_kbd_layout": "Choose keyboard layout",
|
"s_choose_kbd_layout": "Choose keyboard layout",
|
||||||
"l_bypass_touch_requirement": "Bypass touch requirement",
|
"l_bypass_touch_requirement": "Bypass touch requirement",
|
||||||
"l_bypass_touch_requirement_on": "Accounts that require touch are automatically shown over NFC",
|
"l_bypass_touch_requirement_on": "Accounts that require touch are automatically shown over NFC",
|
||||||
"l_bypass_touch_requirement_off": "Accounts that require touch need an additional tap over NFC",
|
"l_bypass_touch_requirement_off": "Accounts that require touch need an additional tap over NFC",
|
||||||
"l_silence_nfc_sounds": "Silence NFC sounds",
|
"s_silence_nfc_sounds": "Silence NFC sounds",
|
||||||
"l_silence_nfc_sounds_on": "No sounds will be played on NFC tap",
|
"l_silence_nfc_sounds_on": "No sounds will be played on NFC tap",
|
||||||
"l_silence_nfc_sounds_off": "Sound will play on NFC tap",
|
"l_silence_nfc_sounds_off": "Sound will play on NFC tap",
|
||||||
"l_usb_options": "USB options",
|
"s_usb_options": "USB options",
|
||||||
"l_launch_app_on_usb": "Launch when YubiKey is connected",
|
"l_launch_app_on_usb": "Launch when YubiKey is connected",
|
||||||
"l_launch_app_on_usb_on": "This prevents other apps from using the YubiKey over USB",
|
"l_launch_app_on_usb_on": "This prevents other apps from using the YubiKey over USB",
|
||||||
"l_launch_app_on_usb_off": "Other apps can use the YubiKey over USB",
|
"l_launch_app_on_usb_off": "Other apps can use the YubiKey over USB",
|
||||||
"l_allow_screenshots": "Allow screenshots",
|
"s_allow_screenshots": "Allow screenshots",
|
||||||
|
|
||||||
"@_eof": {}
|
"@_eof": {}
|
||||||
}
|
}
|
@ -116,7 +116,7 @@ class _CapabilitiesForm extends StatelessWidget {
|
|||||||
if (usbCapabilities != 0) ...[
|
if (usbCapabilities != 0) ...[
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.usb),
|
leading: const Icon(Icons.usb),
|
||||||
title: Text(l10n.w_usb),
|
title: Text(l10n.s_usb),
|
||||||
contentPadding: const EdgeInsets.only(bottom: 8),
|
contentPadding: const EdgeInsets.only(bottom: 8),
|
||||||
horizontalTitleGap: 0,
|
horizontalTitleGap: 0,
|
||||||
),
|
),
|
||||||
@ -137,7 +137,7 @@ class _CapabilitiesForm extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: nfcIcon,
|
leading: nfcIcon,
|
||||||
title: Text(l10n.w_nfc),
|
title: Text(l10n.s_nfc),
|
||||||
contentPadding: const EdgeInsets.only(bottom: 8),
|
contentPadding: const EdgeInsets.only(bottom: 8),
|
||||||
horizontalTitleGap: 0,
|
horizontalTitleGap: 0,
|
||||||
),
|
),
|
||||||
@ -212,7 +212,7 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
|
|||||||
// This will take longer, show a message
|
// This will take longer, show a message
|
||||||
close = showMessage(
|
close = showMessage(
|
||||||
context,
|
context,
|
||||||
l10n.l_reconfiguring_yk,
|
l10n.s_reconfiguring_yk,
|
||||||
duration: const Duration(seconds: 8),
|
duration: const Duration(seconds: 8),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -225,7 +225,7 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
|
|||||||
);
|
);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
if (!reboot) Navigator.pop(context);
|
if (!reboot) Navigator.pop(context);
|
||||||
showMessage(context, l10n.l_config_updated);
|
showMessage(context, l10n.s_config_updated);
|
||||||
} finally {
|
} finally {
|
||||||
close?.call();
|
close?.call();
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
|
|||||||
showMessage(
|
showMessage(
|
||||||
context,
|
context,
|
||||||
widget.deviceData.node.maybeMap(
|
widget.deviceData.node.maybeMap(
|
||||||
nfcReader: (_) => l10n.l_config_updated,
|
nfcReader: (_) => l10n.s_config_updated,
|
||||||
orElse: () => l10n.l_config_updated_reinsert));
|
orElse: () => l10n.l_config_updated_reinsert));
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
@ -318,12 +318,12 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_toggle_applications),
|
title: Text(l10n.s_toggle_applications),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: canSave ? _submitForm : null,
|
onPressed: canSave ? _submitForm : null,
|
||||||
key: management_keys.saveButtonKey,
|
key: management_keys.saveButtonKey,
|
||||||
child: Text(l10n.w_save),
|
child: Text(l10n.s_save),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: child,
|
child: child,
|
||||||
|
@ -34,7 +34,7 @@ class IconPackDialog extends ConsumerWidget {
|
|||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
final iconPack = ref.watch(iconPackProvider);
|
final iconPack = ref.watch(iconPackProvider);
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_custom_icons),
|
title: Text(l10n.s_custom_icons),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -66,9 +66,9 @@ class IconPackDialog extends ConsumerWidget {
|
|||||||
Widget? _action(AsyncValue<IconPack?> iconPack, AppLocalizations l10n) =>
|
Widget? _action(AsyncValue<IconPack?> iconPack, AppLocalizations l10n) =>
|
||||||
iconPack.when(
|
iconPack.when(
|
||||||
data: (IconPack? data) => _ImportActionChip(
|
data: (IconPack? data) => _ImportActionChip(
|
||||||
data != null ? l10n.l_replace_icon_pack : l10n.l_load_icon_pack),
|
data != null ? l10n.s_replace_icon_pack : l10n.s_load_icon_pack),
|
||||||
error: (Object error, StackTrace stackTrace) =>
|
error: (Object error, StackTrace stackTrace) =>
|
||||||
_ImportActionChip(l10n.l_load_icon_pack),
|
_ImportActionChip(l10n.s_load_icon_pack),
|
||||||
loading: () => _ImportActionChip(
|
loading: () => _ImportActionChip(
|
||||||
l10n.l_loading_icon_pack,
|
l10n.l_loading_icon_pack,
|
||||||
avatar: const CircularProgressIndicator(),
|
avatar: const CircularProgressIndicator(),
|
||||||
@ -96,7 +96,7 @@ class _DialogDescription extends ConsumerWidget {
|
|||||||
TextSpan _createLearnMoreLink(BuildContext context) {
|
TextSpan _createLearnMoreLink(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
return TextSpan(
|
return TextSpan(
|
||||||
text: AppLocalizations.of(context)!.l_learn_more,
|
text: AppLocalizations.of(context)!.s_learn_more,
|
||||||
style: theme.textTheme.bodyMedium
|
style: theme.textTheme.bodyMedium
|
||||||
?.copyWith(color: theme.colorScheme.primary),
|
?.copyWith(color: theme.colorScheme.primary),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
@ -134,7 +134,7 @@ class _IconPackDescription extends ConsumerWidget {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: l10n.l_remove_icon_pack,
|
tooltip: l10n.s_remove_icon_pack,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final removePackStatus =
|
final removePackStatus =
|
||||||
await ref.read(iconPackProvider.notifier).removePack();
|
await ref.read(iconPackProvider.notifier).removePack();
|
||||||
@ -179,7 +179,7 @@ class _ImportActionChip extends ConsumerWidget {
|
|||||||
type: FileType.custom,
|
type: FileType.custom,
|
||||||
allowMultiple: false,
|
allowMultiple: false,
|
||||||
lockParentWindow: true,
|
lockParentWindow: true,
|
||||||
dialogTitle: l10n.l_choose_icon_pack);
|
dialogTitle: l10n.s_choose_icon_pack);
|
||||||
if (result != null && result.files.isNotEmpty) {
|
if (result != null && result.files.isNotEmpty) {
|
||||||
final importStatus = await ref
|
final importStatus = await ref
|
||||||
.read(iconPackProvider.notifier)
|
.read(iconPackProvider.notifier)
|
||||||
|
@ -46,7 +46,7 @@ class AccountDialog extends ConsumerWidget {
|
|||||||
|
|
||||||
final copy =
|
final copy =
|
||||||
actions.firstWhere(((e) => e.text == l10n.l_copy_to_clipboard));
|
actions.firstWhere(((e) => e.text == l10n.l_copy_to_clipboard));
|
||||||
final delete = actions.firstWhere(((e) => e.text == l10n.l_delete_account));
|
final delete = actions.firstWhere(((e) => e.text == l10n.s_delete_account));
|
||||||
final colors = {
|
final colors = {
|
||||||
copy: Pair(theme.primary, theme.onPrimary),
|
copy: Pair(theme.primary, theme.onPrimary),
|
||||||
delete: Pair(theme.error, theme.onError),
|
delete: Pair(theme.error, theme.onError),
|
||||||
@ -54,7 +54,7 @@ class AccountDialog extends ConsumerWidget {
|
|||||||
|
|
||||||
// If we can't copy, but can calculate, highlight that button instead
|
// If we can't copy, but can calculate, highlight that button instead
|
||||||
if (copy.intent == null) {
|
if (copy.intent == null) {
|
||||||
final calculates = actions.where(((e) => e.text == l10n.w_calculate));
|
final calculates = actions.where(((e) => e.text == l10n.s_calculate));
|
||||||
if (calculates.isNotEmpty) {
|
if (calculates.isNotEmpty) {
|
||||||
colors[calculates.first] = Pair(theme.primary, theme.onPrimary);
|
colors[calculates.first] = Pair(theme.primary, theme.onPrimary);
|
||||||
}
|
}
|
||||||
|
@ -73,12 +73,12 @@ class AccountHelper {
|
|||||||
),
|
),
|
||||||
if (manual)
|
if (manual)
|
||||||
MenuAction(
|
MenuAction(
|
||||||
text: l10n.w_calculate,
|
text: l10n.s_calculate,
|
||||||
icon: const Icon(Icons.refresh),
|
icon: const Icon(Icons.refresh),
|
||||||
intent: ready ? const CalculateIntent() : null,
|
intent: ready ? const CalculateIntent() : null,
|
||||||
),
|
),
|
||||||
MenuAction(
|
MenuAction(
|
||||||
text: pinned ? l10n.l_unpin_account : l10n.l_pin_account,
|
text: pinned ? l10n.s_unpin_account : l10n.s_pin_account,
|
||||||
icon: pinned
|
icon: pinned
|
||||||
? pushPinStrokeIcon
|
? pushPinStrokeIcon
|
||||||
: const Icon(Icons.push_pin_outlined),
|
: const Icon(Icons.push_pin_outlined),
|
||||||
@ -87,11 +87,11 @@ class AccountHelper {
|
|||||||
if (data.info.version.isAtLeast(5, 3))
|
if (data.info.version.isAtLeast(5, 3))
|
||||||
MenuAction(
|
MenuAction(
|
||||||
icon: const Icon(Icons.edit_outlined),
|
icon: const Icon(Icons.edit_outlined),
|
||||||
text: l10n.l_rename_account,
|
text: l10n.s_rename_account,
|
||||||
intent: const EditIntent(),
|
intent: const EditIntent(),
|
||||||
),
|
),
|
||||||
MenuAction(
|
MenuAction(
|
||||||
text: l10n.l_delete_account,
|
text: l10n.s_delete_account,
|
||||||
icon: const Icon(Icons.delete_outline),
|
icon: const Icon(Icons.delete_outline),
|
||||||
intent: const DeleteIntent(),
|
intent: const DeleteIntent(),
|
||||||
),
|
),
|
||||||
|
@ -34,7 +34,7 @@ class AccountList extends ConsumerWidget {
|
|||||||
final favorites = ref.watch(favoritesProvider);
|
final favorites = ref.watch(favoritesProvider);
|
||||||
if (credentials.isEmpty) {
|
if (credentials.isEmpty) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(l10n.l_no_accounts),
|
child: Text(l10n.s_no_accounts),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,13 +47,13 @@ class AccountList extends ConsumerWidget {
|
|||||||
policy: WidgetOrderTraversalPolicy(),
|
policy: WidgetOrderTraversalPolicy(),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (pinnedCreds.isNotEmpty) ListTitle(l10n.w_pinned),
|
if (pinnedCreds.isNotEmpty) ListTitle(l10n.s_pinned),
|
||||||
...pinnedCreds.map(
|
...pinnedCreds.map(
|
||||||
(entry) => AccountView(
|
(entry) => AccountView(
|
||||||
entry.credential,
|
entry.credential,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (creds.isNotEmpty) ListTitle(l10n.w_accounts),
|
if (creds.isNotEmpty) ListTitle(l10n.s_accounts),
|
||||||
...creds.map(
|
...creds.map(
|
||||||
(entry) => AccountView(
|
(entry) => AccountView(
|
||||||
entry.credential,
|
entry.credential,
|
||||||
|
@ -188,7 +188,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
}
|
}
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
showMessage(context, l10n.l_account_added);
|
showMessage(context, l10n.s_account_added);
|
||||||
} on CancellationException catch (_) {
|
} on CancellationException catch (_) {
|
||||||
// ignored
|
// ignored
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -244,7 +244,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
0) !=
|
0) !=
|
||||||
0) {
|
0) {
|
||||||
if (oathState == null) {
|
if (oathState == null) {
|
||||||
_promptController?.updateContent(title: l10n.l_please_wait);
|
_promptController?.updateContent(title: l10n.s_please_wait);
|
||||||
} else if (oathState.locked) {
|
} else if (oathState.locked) {
|
||||||
_promptController?.close();
|
_promptController?.close();
|
||||||
} else {
|
} else {
|
||||||
@ -256,12 +256,12 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_promptController?.updateContent(title: l10n.l_unsupported_yk);
|
_promptController?.updateContent(title: l10n.s_unsupported_yk);
|
||||||
}
|
}
|
||||||
}, error: (error, _) {
|
}, error: (error, _) {
|
||||||
_promptController?.updateContent(title: l10n.l_unsupported_yk);
|
_promptController?.updateContent(title: l10n.s_unsupported_yk);
|
||||||
}, loading: () {
|
}, loading: () {
|
||||||
_promptController?.updateContent(title: l10n.l_please_wait);
|
_promptController?.updateContent(title: l10n.s_please_wait);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +343,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
_promptController = promptUserInteraction(
|
_promptController = promptUserInteraction(
|
||||||
context,
|
context,
|
||||||
title: l10n.l_insert_yk,
|
title: l10n.l_insert_yk,
|
||||||
description: l10n.l_add_account,
|
description: l10n.s_add_account,
|
||||||
icon: const Icon(Icons.usb),
|
icon: const Icon(Icons.usb),
|
||||||
onCancel: () {
|
onCancel: () {
|
||||||
_otpauthUri = null;
|
_otpauthUri = null;
|
||||||
@ -358,11 +358,11 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_add_account),
|
title: Text(l10n.s_add_account),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: isValid ? submit : null,
|
onPressed: isValid ? submit : null,
|
||||||
child: Text(l10n.w_save, key: keys.saveButton),
|
child: Text(l10n.s_save, key: keys.saveButton),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: FileDropTarget(
|
child: FileDropTarget(
|
||||||
@ -402,7 +402,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
buildCounter: buildByteCounterFor(issuerText),
|
buildCounter: buildByteCounterFor(issuerText),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_issuer_optional,
|
labelText: l10n.s_issuer_optional,
|
||||||
helperText:
|
helperText:
|
||||||
'', // Prevents dialog resizing when disabled
|
'', // Prevents dialog resizing when disabled
|
||||||
prefixIcon: const Icon(Icons.business_outlined),
|
prefixIcon: const Icon(Icons.business_outlined),
|
||||||
@ -431,7 +431,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
prefixIcon: const Icon(Icons.person_outline),
|
prefixIcon: const Icon(Icons.person_outline),
|
||||||
labelText: l10n.l_account_name,
|
labelText: l10n.s_account_name,
|
||||||
helperText:
|
helperText:
|
||||||
'', // Prevents dialog resizing when disabled
|
'', // Prevents dialog resizing when disabled
|
||||||
errorText: (byteLength(nameText) > nameMaxLength)
|
errorText: (byteLength(nameText) > nameMaxLength)
|
||||||
@ -474,9 +474,9 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
),
|
),
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
prefixIcon: const Icon(Icons.key_outlined),
|
prefixIcon: const Icon(Icons.key_outlined),
|
||||||
labelText: l10n.l_secret_key,
|
labelText: l10n.s_secret_key,
|
||||||
errorText: _validateSecretLength && !secretLengthValid
|
errorText: _validateSecretLength && !secretLengthValid
|
||||||
? l10n.l_invalid_length
|
? l10n.s_invalid_length
|
||||||
: null),
|
: null),
|
||||||
readOnly: _qrState == _QrScanState.success,
|
readOnly: _qrState == _QrScanState.success,
|
||||||
textInputAction: TextInputAction.done,
|
textInputAction: TextInputAction.done,
|
||||||
@ -502,7 +502,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
strokeWidth: 2.0),
|
strokeWidth: 2.0),
|
||||||
label: _qrState == _QrScanState.success
|
label: _qrState == _QrScanState.success
|
||||||
? Text(l10n.l_qr_scanned)
|
? Text(l10n.l_qr_scanned)
|
||||||
: Text(l10n.l_qr_scan),
|
: Text(l10n.s_qr_scan),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_scanQrCode(qrScanner);
|
_scanQrCode(qrScanner);
|
||||||
}),
|
}),
|
||||||
@ -515,7 +515,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
children: [
|
children: [
|
||||||
if (oathState?.version.isAtLeast(4, 2) ?? true)
|
if (oathState?.version.isAtLeast(4, 2) ?? true)
|
||||||
FilterChip(
|
FilterChip(
|
||||||
label: Text(l10n.l_require_touch),
|
label: Text(l10n.s_require_touch),
|
||||||
selected: _touch,
|
selected: _touch,
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -557,7 +557,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
selected: int.tryParse(_periodController.text) !=
|
selected: int.tryParse(_periodController.text) !=
|
||||||
defaultPeriod,
|
defaultPeriod,
|
||||||
itemBuilder: ((value) =>
|
itemBuilder: ((value) =>
|
||||||
Text(l10n.l_num_sec(value))),
|
Text(l10n.s_num_sec(value))),
|
||||||
onChanged: _qrState != _QrScanState.success
|
onChanged: _qrState != _QrScanState.success
|
||||||
? (period) {
|
? (period) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -571,7 +571,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
|
|||||||
value: _digits,
|
value: _digits,
|
||||||
selected: _digits != defaultDigits,
|
selected: _digits != defaultDigits,
|
||||||
itemBuilder: (value) =>
|
itemBuilder: (value) =>
|
||||||
Text(l10n.l_num_digits(value)),
|
Text(l10n.s_num_digits(value)),
|
||||||
onChanged: _qrState != _QrScanState.success
|
onChanged: _qrState != _QrScanState.success
|
||||||
? (digits) {
|
? (digits) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -37,7 +37,7 @@ class DeleteAccountDialog extends ConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_delete_account),
|
title: Text(l10n.s_delete_account),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
key: keys.deleteButton,
|
key: keys.deleteButton,
|
||||||
@ -49,14 +49,14 @@ class DeleteAccountDialog extends ConsumerWidget {
|
|||||||
await ref.read(withContextProvider)(
|
await ref.read(withContextProvider)(
|
||||||
(context) async {
|
(context) async {
|
||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
showMessage(context, l10n.l_account_deleted);
|
showMessage(context, l10n.s_account_deleted);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} on CancellationException catch (_) {
|
} on CancellationException catch (_) {
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(l10n.w_delete),
|
child: Text(l10n.s_delete),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
@ -45,9 +45,9 @@ Widget oathBuildActions(
|
|||||||
final theme = Theme.of(context).colorScheme;
|
final theme = Theme.of(context).colorScheme;
|
||||||
return SimpleDialog(
|
return SimpleDialog(
|
||||||
children: [
|
children: [
|
||||||
ListTitle(l10n.w_setup, textStyle: Theme.of(context).textTheme.bodyLarge),
|
ListTitle(l10n.s_setup, textStyle: Theme.of(context).textTheme.bodyLarge),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(l10n.l_add_account),
|
title: Text(l10n.s_add_account),
|
||||||
key: keys.addAccountAction,
|
key: keys.addAccountAction,
|
||||||
leading:
|
leading:
|
||||||
const CircleAvatar(child: Icon(Icons.person_add_alt_1_outlined)),
|
const CircleAvatar(child: Icon(Icons.person_add_alt_1_outlined)),
|
||||||
@ -87,11 +87,11 @@ Widget oathBuildActions(
|
|||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
ListTitle(l10n.w_manage,
|
ListTitle(l10n.s_manage,
|
||||||
textStyle: Theme.of(context).textTheme.bodyLarge),
|
textStyle: Theme.of(context).textTheme.bodyLarge),
|
||||||
ListTile(
|
ListTile(
|
||||||
key: keys.customIconsAction,
|
key: keys.customIconsAction,
|
||||||
title: Text(l10n.l_custom_icons),
|
title: Text(l10n.s_custom_icons),
|
||||||
subtitle: Text(l10n.l_set_icons_for_accounts),
|
subtitle: Text(l10n.l_set_icons_for_accounts),
|
||||||
leading: const CircleAvatar(
|
leading: const CircleAvatar(
|
||||||
child: Icon(Icons.image_outlined),
|
child: Icon(Icons.image_outlined),
|
||||||
@ -108,7 +108,7 @@ Widget oathBuildActions(
|
|||||||
ListTile(
|
ListTile(
|
||||||
key: keys.setOrManagePasswordAction,
|
key: keys.setOrManagePasswordAction,
|
||||||
title: Text(
|
title: Text(
|
||||||
oathState.hasKey ? l10n.l_manage_password : l10n.l_set_password),
|
oathState.hasKey ? l10n.s_manage_password : l10n.s_set_password),
|
||||||
subtitle: Text(l10n.l_optional_password_protection),
|
subtitle: Text(l10n.l_optional_password_protection),
|
||||||
leading: const CircleAvatar(child: Icon(Icons.password_outlined)),
|
leading: const CircleAvatar(child: Icon(Icons.password_outlined)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -120,7 +120,7 @@ Widget oathBuildActions(
|
|||||||
}),
|
}),
|
||||||
ListTile(
|
ListTile(
|
||||||
key: keys.resetAction,
|
key: keys.resetAction,
|
||||||
title: Text(l10n.l_reset_oath),
|
title: Text(l10n.s_reset_oath),
|
||||||
subtitle: Text(l10n.l_factory_reset_this_app),
|
subtitle: Text(l10n.l_factory_reset_this_app),
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
foregroundColor: theme.onError,
|
foregroundColor: theme.onError,
|
||||||
|
@ -48,7 +48,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
|||||||
if (result) {
|
if (result) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
showMessage(context, AppLocalizations.of(context)!.l_password_set);
|
showMessage(context, AppLocalizations.of(context)!.s_password_set);
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
_currentIsWrong = true;
|
_currentIsWrong = true;
|
||||||
@ -64,12 +64,12 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
|||||||
(!widget.state.hasKey || _currentPassword.isNotEmpty);
|
(!widget.state.hasKey || _currentPassword.isNotEmpty);
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_manage_password),
|
title: Text(l10n.s_manage_password),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: isValid ? _submit : null,
|
onPressed: isValid ? _submit : null,
|
||||||
key: keys.savePasswordButton,
|
key: keys.savePasswordButton,
|
||||||
child: Text(l10n.w_save),
|
child: Text(l10n.s_save),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -85,9 +85,9 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
|||||||
key: keys.currentPasswordField,
|
key: keys.currentPasswordField,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_current_password,
|
labelText: l10n.s_current_password,
|
||||||
prefixIcon: const Icon(Icons.password_outlined),
|
prefixIcon: const Icon(Icons.password_outlined),
|
||||||
errorText: _currentIsWrong ? l10n.l_wrong_password : null,
|
errorText: _currentIsWrong ? l10n.s_wrong_password : null,
|
||||||
errorMaxLines: 3),
|
errorMaxLines: 3),
|
||||||
textInputAction: TextInputAction.next,
|
textInputAction: TextInputAction.next,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@ -111,7 +111,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
|||||||
if (result) {
|
if (result) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
showMessage(context, l10n.l_password_removed);
|
showMessage(context, l10n.s_password_removed);
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
_currentIsWrong = true;
|
_currentIsWrong = true;
|
||||||
@ -119,18 +119,18 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: Text(l10n.l_remove_password),
|
child: Text(l10n.s_remove_password),
|
||||||
),
|
),
|
||||||
if (widget.state.remembered)
|
if (widget.state.remembered)
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
child: Text(l10n.l_clear_saved_password),
|
child: Text(l10n.s_clear_saved_password),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await ref
|
await ref
|
||||||
.read(oathStateProvider(widget.path).notifier)
|
.read(oathStateProvider(widget.path).notifier)
|
||||||
.forgetPassword();
|
.forgetPassword();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
showMessage(context, l10n.l_password_forgotten);
|
showMessage(context, l10n.s_password_forgotten);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -143,7 +143,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_new_password,
|
labelText: l10n.s_new_password,
|
||||||
prefixIcon: const Icon(Icons.password_outlined),
|
prefixIcon: const Icon(Icons.password_outlined),
|
||||||
enabled: !widget.state.hasKey || _currentPassword.isNotEmpty,
|
enabled: !widget.state.hasKey || _currentPassword.isNotEmpty,
|
||||||
),
|
),
|
||||||
@ -164,7 +164,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_confirm_password,
|
labelText: l10n.s_confirm_password,
|
||||||
prefixIcon: const Icon(Icons.password_outlined),
|
prefixIcon: const Icon(Icons.password_outlined),
|
||||||
enabled:
|
enabled:
|
||||||
(!widget.state.hasKey || _currentPassword.isNotEmpty) &&
|
(!widget.state.hasKey || _currentPassword.isNotEmpty) &&
|
||||||
|
@ -42,12 +42,12 @@ class OathScreen extends ConsumerWidget {
|
|||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return ref.watch(oathStateProvider(devicePath)).when(
|
return ref.watch(oathStateProvider(devicePath)).when(
|
||||||
loading: () => MessagePage(
|
loading: () => MessagePage(
|
||||||
title: Text(l10n.w_authenticator),
|
title: Text(l10n.s_authenticator),
|
||||||
graphic: const CircularProgressIndicator(),
|
graphic: const CircularProgressIndicator(),
|
||||||
delayedContent: true,
|
delayedContent: true,
|
||||||
),
|
),
|
||||||
error: (error, _) => AppFailurePage(
|
error: (error, _) => AppFailurePage(
|
||||||
title: Text(l10n.w_authenticator),
|
title: Text(l10n.s_authenticator),
|
||||||
cause: error,
|
cause: error,
|
||||||
),
|
),
|
||||||
data: (oathState) => oathState.locked
|
data: (oathState) => oathState.locked
|
||||||
@ -66,7 +66,7 @@ class _LockedView extends ConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return AppPage(
|
return AppPage(
|
||||||
title: Text(AppLocalizations.of(context)!.w_authenticator),
|
title: Text(AppLocalizations.of(context)!.s_authenticator),
|
||||||
keyActionsBuilder: (context) =>
|
keyActionsBuilder: (context) =>
|
||||||
oathBuildActions(context, devicePath, oathState, ref),
|
oathBuildActions(context, devicePath, oathState, ref),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -116,10 +116,10 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
|||||||
.select((value) => value?.length));
|
.select((value) => value?.length));
|
||||||
if (numCreds == 0) {
|
if (numCreds == 0) {
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: Text(l10n.w_authenticator),
|
title: Text(l10n.s_authenticator),
|
||||||
key: keys.noAccountsView,
|
key: keys.noAccountsView,
|
||||||
graphic: noAccounts,
|
graphic: noAccounts,
|
||||||
header: l10n.l_no_accounts,
|
header: l10n.s_no_accounts,
|
||||||
keyActionsBuilder: (context) => oathBuildActions(
|
keyActionsBuilder: (context) => oathBuildActions(
|
||||||
context, widget.devicePath, widget.oathState, ref,
|
context, widget.devicePath, widget.oathState, ref,
|
||||||
used: 0),
|
used: 0),
|
||||||
@ -154,7 +154,7 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
|||||||
style: textTheme.titleMedium
|
style: textTheme.titleMedium
|
||||||
?.copyWith(fontSize: textTheme.titleSmall?.fontSize),
|
?.copyWith(fontSize: textTheme.titleSmall?.fontSize),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: l10n.l_search_accounts,
|
hintText: l10n.s_search_accounts,
|
||||||
border: const OutlineInputBorder(
|
border: const OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(32)),
|
borderRadius: BorderRadius.all(Radius.circular(32)),
|
||||||
),
|
),
|
||||||
|
@ -73,7 +73,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
|
|||||||
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.of(context).pop(renamed);
|
Navigator.of(context).pop(renamed);
|
||||||
showMessage(context, l10n.l_account_renamed);
|
showMessage(context, l10n.s_account_renamed);
|
||||||
} on CancellationException catch (_) {
|
} on CancellationException catch (_) {
|
||||||
// ignored
|
// ignored
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -127,12 +127,12 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
|
|||||||
final isValid = isUnique && isValidFormat;
|
final isValid = isUnique && isValidFormat;
|
||||||
|
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_rename_account),
|
title: Text(l10n.s_rename_account),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: didChange && isValid ? _submit : null,
|
onPressed: didChange && isValid ? _submit : null,
|
||||||
key: keys.saveButton,
|
key: keys.saveButton,
|
||||||
child: Text(l10n.w_save),
|
child: Text(l10n.s_save),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -151,7 +151,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
|
|||||||
key: keys.issuerField,
|
key: keys.issuerField,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_issuer_optional,
|
labelText: l10n.s_issuer_optional,
|
||||||
helperText: '', // Prevents dialog resizing when disabled
|
helperText: '', // Prevents dialog resizing when disabled
|
||||||
prefixIcon: const Icon(Icons.business_outlined),
|
prefixIcon: const Icon(Icons.business_outlined),
|
||||||
),
|
),
|
||||||
@ -170,7 +170,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
|
|||||||
key: keys.nameField,
|
key: keys.nameField,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.l_account_name,
|
labelText: l10n.s_account_name,
|
||||||
helperText: '', // Prevents dialog resizing when disabled
|
helperText: '', // Prevents dialog resizing when disabled
|
||||||
errorText: !isValidFormat
|
errorText: !isValidFormat
|
||||||
? l10n.l_account_name_required
|
? l10n.l_account_name_required
|
||||||
|
@ -32,7 +32,7 @@ class ResetDialog extends ConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.l_factory_reset),
|
title: Text(l10n.s_factory_reset),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@ -42,7 +42,7 @@ class ResetDialog extends ConsumerWidget {
|
|||||||
showMessage(context, l10n.l_oath_application_reset);
|
showMessage(context, l10n.l_oath_application_reset);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Text(l10n.w_reset),
|
child: Text(l10n.s_reset),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
@ -79,8 +79,8 @@ class _UnlockFormState extends ConsumerState<UnlockForm> {
|
|||||||
obscureText: _isObscure,
|
obscureText: _isObscure,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: l10n.w_password,
|
labelText: l10n.s_password,
|
||||||
errorText: _passwordIsWrong ? l10n.l_wrong_password : null,
|
errorText: _passwordIsWrong ? l10n.s_wrong_password : null,
|
||||||
helperText: '', // Prevents resizing when errorText shown
|
helperText: '', // Prevents resizing when errorText shown
|
||||||
prefixIcon: const Icon(Icons.password_outlined),
|
prefixIcon: const Icon(Icons.password_outlined),
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
@ -111,7 +111,7 @@ class _UnlockFormState extends ConsumerState<UnlockForm> {
|
|||||||
minLeadingWidth: 0,
|
minLeadingWidth: 0,
|
||||||
)
|
)
|
||||||
: CheckboxListTile(
|
: CheckboxListTile(
|
||||||
title: Text(l10n.l_remember_password),
|
title: Text(l10n.s_remember_password),
|
||||||
dense: true,
|
dense: true,
|
||||||
controlAffinity: ListTileControlAffinity.leading,
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
value: _remember,
|
value: _remember,
|
||||||
@ -127,7 +127,7 @@ class _UnlockFormState extends ConsumerState<UnlockForm> {
|
|||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: ElevatedButton.icon(
|
child: ElevatedButton.icon(
|
||||||
key: keys.unlockButton,
|
key: keys.unlockButton,
|
||||||
label: Text(l10n.w_unlock),
|
label: Text(l10n.s_unlock),
|
||||||
icon: const Icon(Icons.lock_open),
|
icon: const Icon(Icons.lock_open),
|
||||||
onPressed: _passwordController.text.isNotEmpty ? _submit : null,
|
onPressed: _passwordController.text.isNotEmpty ? _submit : null,
|
||||||
),
|
),
|
||||||
|
@ -39,7 +39,7 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final enableTranslations = ref.watch(communityTranslationsProvider);
|
final enableTranslations = ref.watch(communityTranslationsProvider);
|
||||||
return ResponsiveDialog(
|
return ResponsiveDialog(
|
||||||
title: Text(l10n.w_settings),
|
title: Text(l10n.s_settings),
|
||||||
child: Theme(
|
child: Theme(
|
||||||
// Make the headers use the primary color to pop a bit.
|
// Make the headers use the primary color to pop a bit.
|
||||||
// Once M3 is implemented this will probably not be needed.
|
// Once M3 is implemented this will probably not be needed.
|
||||||
@ -52,9 +52,9 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ListTitle(l10n.w_appearance),
|
ListTitle(l10n.s_appearance),
|
||||||
RadioListTile<ThemeMode>(
|
RadioListTile<ThemeMode>(
|
||||||
title: Text(l10n.l_system_default),
|
title: Text(l10n.s_system_default),
|
||||||
value: ThemeMode.system,
|
value: ThemeMode.system,
|
||||||
groupValue: themeMode,
|
groupValue: themeMode,
|
||||||
onChanged: (mode) {
|
onChanged: (mode) {
|
||||||
@ -63,7 +63,7 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
RadioListTile<ThemeMode>(
|
RadioListTile<ThemeMode>(
|
||||||
title: Text(l10n.l_light_mode),
|
title: Text(l10n.s_light_mode),
|
||||||
value: ThemeMode.light,
|
value: ThemeMode.light,
|
||||||
groupValue: themeMode,
|
groupValue: themeMode,
|
||||||
onChanged: (mode) {
|
onChanged: (mode) {
|
||||||
@ -72,7 +72,7 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
RadioListTile<ThemeMode>(
|
RadioListTile<ThemeMode>(
|
||||||
title: Text(l10n.l_dark_mode),
|
title: Text(l10n.s_dark_mode),
|
||||||
value: ThemeMode.dark,
|
value: ThemeMode.dark,
|
||||||
groupValue: themeMode,
|
groupValue: themeMode,
|
||||||
onChanged: (mode) {
|
onChanged: (mode) {
|
||||||
@ -84,7 +84,7 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
basicLocaleListResolution(window.locales, officialLocales) !=
|
basicLocaleListResolution(window.locales, officialLocales) !=
|
||||||
basicLocaleListResolution(
|
basicLocaleListResolution(
|
||||||
window.locales, AppLocalizations.supportedLocales)) ...[
|
window.locales, AppLocalizations.supportedLocales)) ...[
|
||||||
ListTitle(l10n.w_language),
|
ListTitle(l10n.s_language),
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
title: Text(l10n.l_enable_community_translations),
|
title: Text(l10n.l_enable_community_translations),
|
||||||
subtitle: Text(l10n.p_community_translations_desc),
|
subtitle: Text(l10n.p_community_translations_desc),
|
||||||
|
@ -62,8 +62,8 @@ class _ResponsiveDialogState extends State<ResponsiveDialog> {
|
|||||||
} else {
|
} else {
|
||||||
// Dialog
|
// Dialog
|
||||||
final cancelText = widget.onCancel == null && widget.actions.isEmpty
|
final cancelText = widget.onCancel == null && widget.actions.isEmpty
|
||||||
? l10n.w_close
|
? l10n.s_close
|
||||||
: l10n.w_cancel;
|
: l10n.s_cancel;
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: widget.title,
|
title: widget.title,
|
||||||
titlePadding: const EdgeInsets.only(top: 24, left: 18, right: 18),
|
titlePadding: const EdgeInsets.only(top: 24, left: 18, right: 18),
|
||||||
|
@ -38,7 +38,7 @@ InputCounterWidgetBuilder buildByteCounterFor(String currentValue) =>
|
|||||||
return Text(
|
return Text(
|
||||||
maxLength != null ? '${byteLength(currentValue)}/$maxLength' : '',
|
maxLength != null ? '${byteLength(currentValue)}/$maxLength' : '',
|
||||||
style: style,
|
style: style,
|
||||||
semanticsLabel: AppLocalizations.of(context)!.l_character_count,
|
semanticsLabel: AppLocalizations.of(context)!.s_character_count,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user