Restructure external strings.

This commit is contained in:
Dain Nilsson 2023-02-28 15:02:12 +01:00
parent 6bf231dc7d
commit 1d389e3185
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8
46 changed files with 661 additions and 676 deletions

View File

@ -42,7 +42,7 @@ class AboutPage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final l10n = AppLocalizations.of(context)!;
return ResponsiveDialog(
title: Text(l10n.general_about),
title: Text(l10n.w_about),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 32),
child: Column(
@ -52,7 +52,7 @@ class AboutPage extends ConsumerWidget {
Padding(
padding: const EdgeInsets.only(top: 24.0),
child: Text(
l10n.general_app_name,
l10n.app_name,
style: Theme.of(context).textTheme.titleMedium,
),
),
@ -63,7 +63,7 @@ class AboutPage extends ConsumerWidget {
children: [
TextButton(
child: Text(
l10n.general_terms_of_use,
l10n.l_terms_of_use,
style:
const TextStyle(decoration: TextDecoration.underline),
),
@ -73,7 +73,7 @@ class AboutPage extends ConsumerWidget {
),
TextButton(
child: Text(
l10n.general_privacy_policy,
l10n.l_privacy_policy,
style:
const TextStyle(decoration: TextDecoration.underline),
),
@ -85,7 +85,7 @@ class AboutPage extends ConsumerWidget {
),
TextButton(
child: Text(
l10n.general_open_src_licenses,
l10n.l_open_src_licenses,
style: const TextStyle(decoration: TextDecoration.underline),
),
onPressed: () {
@ -104,7 +104,7 @@ class AboutPage extends ConsumerWidget {
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text(
l10n.general_help_and_feedback,
l10n.l_help_and_feedback,
style: Theme.of(context).textTheme.titleMedium,
),
),
@ -113,7 +113,7 @@ class AboutPage extends ConsumerWidget {
children: [
TextButton(
child: Text(
l10n.general_send_feedback,
l10n.l_send_feedback,
style:
const TextStyle(decoration: TextDecoration.underline),
),
@ -123,7 +123,7 @@ class AboutPage extends ConsumerWidget {
),
TextButton(
child: Text(
l10n.general_i_need_help,
l10n.l_i_need_help,
style:
const TextStyle(decoration: TextDecoration.underline),
),
@ -140,7 +140,7 @@ class AboutPage extends ConsumerWidget {
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text(
l10n.general_troubleshooting,
l10n.w_troubleshooting,
style: Theme.of(context).textTheme.titleMedium,
),
),
@ -151,7 +151,7 @@ class AboutPage extends ConsumerWidget {
const SizedBox(height: 12.0),
ActionChip(
avatar: const Icon(Icons.bug_report_outlined),
label: Text(l10n.general_run_diagnostics),
label: Text(l10n.l_run_diagnostics),
onPressed: () async {
_log.info('Running diagnostics...');
final response = await ref
@ -169,7 +169,7 @@ class AboutPage extends ConsumerWidget {
await ref.read(clipboardProvider).setText(text);
await ref.read(withContextProvider)(
(context) async {
showMessage(context, l10n.general_diagnostics_copied);
showMessage(context, l10n.l_diagnostics_copied);
},
);
},
@ -180,7 +180,7 @@ class AboutPage extends ConsumerWidget {
if (isAndroid) ...[
const SizedBox(height: 12.0),
FilterChip(
label: Text(l10n.general_allow_screenshots),
label: Text(l10n.l_allow_screenshots),
selected: ref.watch(androidAllowScreenshotsProvider),
onSelected: (value) async {
ref
@ -217,7 +217,7 @@ class LoggingPanel extends ConsumerWidget {
items: Levels.LEVELS,
selected: logLevel != Level.INFO,
labelBuilder: (value) => Text(
'${l10n.general_log_level}: ${value.name[0]}${value.name.substring(1).toLowerCase()}'),
'${l10n.l_log_level}: ${value.name[0]}${value.name.substring(1).toLowerCase()}'),
itemBuilder: (value) =>
Text('${value.name[0]}${value.name.substring(1).toLowerCase()}'),
onChanged: (level) {
@ -227,7 +227,7 @@ class LoggingPanel extends ConsumerWidget {
),
ActionChip(
avatar: const Icon(Icons.copy),
label: Text(l10n.general_copy_log),
label: Text(l10n.l_copy_log),
onPressed: () async {
_log.info('Copying log to clipboard ($version)...');
final logs = await ref.read(logLevelProvider.notifier).getLogs();
@ -236,7 +236,7 @@ class LoggingPanel extends ConsumerWidget {
if (!clipboard.platformGivesFeedback()) {
await ref.read(withContextProvider)(
(context) async {
showMessage(context, l10n.general_log_copied);
showMessage(context, l10n.l_log_copied);
},
);
}

View File

@ -195,8 +195,8 @@ class _AndroidCredentialListNotifier extends OathCredentialListNotifier {
return promptUserInteraction(
context,
icon: const Icon(Icons.touch_app),
title: l10n.oath_touch_required,
description: l10n.oath_touch_now,
title: l10n.l_touch_required,
description: l10n.l_touch_button_now,
);
},
);

View File

@ -47,7 +47,7 @@ class QRScannerPermissionsUI extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 36),
child: Text(
l10n.androidQrScanner_need_camera_permission,
l10n.p_need_camera_permission,
style: const TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
@ -66,7 +66,7 @@ class QRScannerPermissionsUI extends StatelessWidget {
Column(
children: [
Text(
l10n.androidQrScanner_have_account_info,
l10n.q_have_account_info,
textScaleFactor: 0.7,
style: const TextStyle(color: Colors.white),
),
@ -75,7 +75,7 @@ class QRScannerPermissionsUI extends StatelessWidget {
Navigator.of(context).pop('');
},
child: Text(
l10n.androidQrScanner_enter_manually,
l10n.l_enter_manually,
style: const TextStyle(color: Colors.white),
)),
],
@ -83,7 +83,7 @@ class QRScannerPermissionsUI extends StatelessWidget {
Column(
children: [
Text(
l10n.androidQrScanner_want_to_scan,
l10n.q_want_to_scan,
textScaleFactor: 0.7,
style: const TextStyle(color: Colors.white),
),
@ -92,7 +92,7 @@ class QRScannerPermissionsUI extends StatelessWidget {
onPermissionRequest();
},
child: Text(
l10n.androidQrScanner_review_permissions,
l10n.l_review_permissions,
style: const TextStyle(color: Colors.white),
)),
],

View File

@ -46,8 +46,8 @@ class QRScannerUI extends StatelessWidget {
height: screenSize.height),
child: Text(
status != ScanStatus.error
? l10n.androidQrScanner_point_and_scan
: l10n.androidQrScanner_invalid_code,
? l10n.l_point_camera_scan
: l10n.l_invalid_qr,
style: const TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
@ -63,7 +63,7 @@ class QRScannerUI extends StatelessWidget {
child: Column(
children: [
Text(
l10n.androidQrScanner_no_code,
l10n.q_no_qr,
textScaleFactor: 0.7,
style: const TextStyle(color: Colors.white),
),
@ -73,7 +73,7 @@ class QRScannerUI extends StatelessWidget {
},
key: keys.manualEntryButton,
child: Text(
l10n.androidQrScanner_enter_manually,
l10n.l_enter_manually,
style: const TextStyle(color: Colors.white),
)),
],

View File

@ -114,7 +114,7 @@ class _QrScannerViewState extends State<QrScannerView> {
extendBody: true,
appBar: AppBar(
title: Text(
l10n.oath_add_account,
l10n.l_add_account,
style: const TextStyle(color: Colors.white),
),
backgroundColor: Colors.transparent,

View File

@ -38,11 +38,11 @@ enum _TapAction {
String getDescription(AppLocalizations l10n) {
switch (this) {
case _TapAction.launch:
return l10n.androidSettings_launch_app;
return l10n.l_launch_ya;
case _TapAction.copy:
return l10n.androidSettings_copy_otp;
return l10n.l_copy_otp_clipboard;
case _TapAction.both:
return l10n.androidSettings_launch_and_copy;
return l10n.l_launch_and_copy_otp;
}
}
@ -80,11 +80,11 @@ extension on ThemeMode {
String getDisplayName(AppLocalizations l10n) {
switch (this) {
case ThemeMode.system:
return l10n.general_system_default;
return l10n.l_system_default;
case ThemeMode.light:
return l10n.general_light_mode;
return l10n.l_light_mode;
case ThemeMode.dark:
return l10n.general_dark_mode;
return l10n.l_dark_mode;
}
}
}
@ -114,7 +114,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
final theme = Theme.of(context);
return ResponsiveDialog(
title: Text(l10n.general_settings),
title: Text(l10n.w_settings),
child: Theme(
// Make the headers use the primary color to pop a bit.
// Once M3 is implemented this will probably not be needed.
@ -127,9 +127,9 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTitle(l10n.androidSettings_nfc_options),
ListTitle(l10n.l_nfc_options),
ListTile(
title: Text(l10n.androidSettings_nfc_on_tap),
title: Text(l10n.l_on_yk_nfc_tap),
subtitle: Text(tapAction.getDescription(l10n)),
key: keys.nfcTapSetting,
onTap: () async {
@ -140,7 +140,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
},
),
ListTile(
title: Text(l10n.androidSettings_keyboard_layout),
title: Text(l10n.l_kbd_layout_for_static),
subtitle: Text(clipKbdLayout),
key: keys.nfcKeyboardLayoutSetting,
enabled: tapAction != _TapAction.launch,
@ -154,10 +154,10 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
},
),
SwitchListTile(
title: Text(l10n.androidSettings_bypass_touch),
title: Text(l10n.l_bypass_touch_requirement),
subtitle: Text(nfcBypassTouch
? l10n.androidSettings_bypass_touch_on
: l10n.androidSettings_bypass_touch_off),
? l10n.l_bypass_touch_requirement_on
: l10n.l_bypass_touch_requirement_off),
value: nfcBypassTouch,
key: keys.nfcBypassTouchSetting,
onChanged: (value) {
@ -166,10 +166,10 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
});
}),
SwitchListTile(
title: Text(l10n.androidSettings_silence_nfc),
title: Text(l10n.l_silence_nfc_sounds),
subtitle: Text(nfcSilenceSounds
? l10n.androidSettings_silence_nfc_on
: l10n.androidSettings_silence_nfc_off),
? l10n.l_silence_nfc_sounds_on
: l10n.l_silence_nfc_sounds_off),
value: nfcSilenceSounds,
key: keys.nfcSilenceSoundsSettings,
onChanged: (value) {
@ -177,12 +177,12 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
prefs.setBool(prefNfcSilenceSounds, value);
});
}),
ListTitle(l10n.androidSettings_usb_options),
ListTitle(l10n.l_usb_options),
SwitchListTile(
title: Text(l10n.androidSettings_usb_launch),
title: Text(l10n.l_launch_app_on_usb),
subtitle: Text(usbOpenApp
? l10n.androidSettings_usb_launch_on
: l10n.androidSettings_usb_launch_off),
? l10n.l_launch_app_on_usb_on
: l10n.l_launch_app_on_usb_off),
value: usbOpenApp,
key: keys.usbOpenApp,
onChanged: (value) {
@ -190,9 +190,9 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
prefs.setBool(prefUsbOpenApp, value);
});
}),
ListTitle(l10n.general_appearance),
ListTitle(l10n.w_appearance),
ListTile(
title: Text(l10n.androidSettings_app_theme),
title: Text(l10n.l_app_theme),
subtitle: Text(themeMode.getDisplayName(l10n)),
key: keys.themeModeSetting,
onTap: () async {
@ -214,7 +214,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
builder: (BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return SimpleDialog(
title: Text(l10n.androidSettings_nfc_on_tap),
title: Text(l10n.l_on_yk_nfc_tap),
children: _TapAction.values
.map(
(e) => RadioListTile<_TapAction>(
@ -239,7 +239,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
builder: (BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return SimpleDialog(
title: Text(l10n.androidSettings_choose_keyboard_layout),
title: Text(l10n.l_choose_kbd_layout),
children: _keyboardLayouts
.map(
(e) => RadioListTile<String>(
@ -264,7 +264,7 @@ class _AndroidSettingsPageState extends ConsumerState<AndroidSettingsPage> {
builder: (BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return SimpleDialog(
title: Text(l10n.androidSettings_choose_app_theme),
title: Text(l10n.l_choose_app_theme),
children: supportedThemes
.map((e) => RadioListTile(
title: Text(e.getDisplayName(l10n)),

View File

@ -62,9 +62,9 @@ enum Application {
String getDisplayName(AppLocalizations l10n) {
switch (this) {
case Application.oath:
return l10n.oath_authenticator;
return l10n.w_authenticator;
case Application.fido:
return l10n.fido_webauthn;
return l10n.w_webauthn;
default:
return name.substring(0, 1).toUpperCase() + name.substring(1);
}

View File

@ -38,7 +38,7 @@ class AppFailurePage extends ConsumerWidget {
final reason = cause;
Widget? graphic = const Icon(Icons.error);
String? header = l10n.appFailurePage_error_occured;
String? header = l10n.l_error_occured;
String? message = reason.toString();
List<Widget> actions = [];
@ -46,13 +46,13 @@ class AppFailurePage extends ConsumerWidget {
if (reason.status == 'connection-error') {
switch (reason.body['connection']) {
case 'ccid':
header = l10n.appFailurePage_ccid_failed;
header = l10n.l_ccid_connection_failed;
if (Platform.isMacOS) {
message = l10n.appFailurePage_msg_reinsert;
message = l10n.l_try_reinsert_yk;
} else if (Platform.isLinux) {
message = l10n.appFailurePage_pcscd_unavailable;
message = l10n.p_pcscd_unavailable;
} else {
message = l10n.appFailurePage_ccid_unavailable;
message = l10n.p_ccid_service_unavailable;
}
break;
case 'fido':
@ -60,14 +60,14 @@ class AppFailurePage extends ConsumerWidget {
!ref.watch(rpcStateProvider.select((state) => state.isAdmin))) {
graphic = noPermission;
header = null;
message = l10n.appFailurePage_txt_info;
message = l10n.p_webauthn_elevated_permissions_required;
actions = [
ElevatedButton.icon(
label: Text(l10n.appFailurePage_btn_unlock),
label: Text(l10n.w_unlock),
icon: const Icon(Icons.lock_open),
onPressed: () async {
final closeMessage = showMessage(
context, l10n.appFailurePage_msg_permission,
context, l10n.l_elevating_permissions,
duration: const Duration(seconds: 30));
try {
if (await ref.read(rpcProvider).requireValue.elevate()) {
@ -77,7 +77,7 @@ class AppFailurePage extends ConsumerWidget {
(context) async {
showMessage(
context,
l10n.general_permission_denied,
l10n.l_permission_denied,
);
},
);
@ -91,8 +91,8 @@ class AppFailurePage extends ConsumerWidget {
}
break;
default:
header = l10n.appFailurePage_failed_connection;
message = l10n.appFailurePage_msg_reinsert;
header = l10n.l_open_connection_failed;
message = l10n.l_try_reinsert_yk;
}
}
}

View File

@ -129,8 +129,7 @@ class AppPage extends StatelessWidget {
},
icon: const Icon(Icons.tune),
iconSize: 24,
tooltip:
AppLocalizations.of(context)!.general_configure_yubikey,
tooltip: AppLocalizations.of(context)!.l_configure_yk,
padding: const EdgeInsets.all(12),
),
),

View File

@ -41,21 +41,21 @@ class DeviceErrorScreen extends ConsumerWidget {
!ref.watch(rpcStateProvider.select((state) => state.isAdmin))) {
return MessagePage(
graphic: noPermission,
message: l10n.general_elevated_permissions_required,
message: l10n.p_elevated_permissions_required,
actions: [
ElevatedButton.icon(
label: Text(l10n.appFailurePage_btn_unlock),
label: Text(l10n.w_unlock),
icon: const Icon(Icons.lock_open),
onPressed: () async {
final closeMessage = showMessage(
context, l10n.appFailurePage_msg_permission,
context, l10n.l_elevating_permissions,
duration: const Duration(seconds: 30));
try {
if (await ref.read(rpcProvider).requireValue.elevate()) {
ref.invalidate(rpcProvider);
} else {
await ref.read(withContextProvider)((context) async =>
showMessage(context, l10n.general_permission_denied));
showMessage(context, l10n.l_permission_denied));
}
} finally {
closeMessage();
@ -68,7 +68,7 @@ class DeviceErrorScreen extends ConsumerWidget {
}
return MessagePage(
graphic: const DeviceAvatar(child: Icon(Icons.usb_off)),
message: l10n.general_yubikey_no_access,
message: l10n.l_yk_no_access,
);
}
@ -81,10 +81,10 @@ class DeviceErrorScreen extends ConsumerWidget {
final String message;
switch (error) {
case 'unknown-device':
message = l10n.devicePicker_unknown_device;
message = l10n.l_unknown_device;
break;
default:
message = l10n.general_place_on_nfc_reader;
message = l10n.l_place_on_nfc_reader;
}
return MessagePage(message: message);
},

View File

@ -119,12 +119,11 @@ class _DevicePickerContent extends ConsumerWidget {
),
ListTile(
title: Center(
child: Text(
AppLocalizations.of(context)!.devicePicker_no_yubikey)),
child: Text(AppLocalizations.of(context)!.l_no_yk_present)),
subtitle: Center(
child: Text(Platform.isAndroid
? AppLocalizations.of(context)!.devicePicker_insert_or_tap
: AppLocalizations.of(context)!.general_usb)),
? AppLocalizations.of(context)!.l_insert_or_tap_yk
: AppLocalizations.of(context)!.w_usb)),
),
],
);
@ -138,8 +137,8 @@ class _DevicePickerContent extends ConsumerWidget {
padding: EdgeInsets.symmetric(horizontal: 4),
child: DeviceAvatar(child: Icon(Icons.usb)),
),
title: Text(AppLocalizations.of(context)!.general_usb),
subtitle: Text(AppLocalizations.of(context)!.devicePicker_no_yubikey),
title: Text(AppLocalizations.of(context)!.w_usb),
subtitle: Text(AppLocalizations.of(context)!.l_no_yk_present),
onTap: () {
ref.read(currentDeviceProvider.notifier).setCurrentDevice(null);
},
@ -170,8 +169,8 @@ class _DevicePickerContent extends ConsumerWidget {
ref.read(_hiddenDevicesProvider.notifier).showAll();
},
child: ListTile(
title: Text(AppLocalizations.of(context)!
.devicePicker_show_hidden),
title: Text(
AppLocalizations.of(context)!.l_show_hidden_devices),
dense: true,
contentPadding: EdgeInsets.zero,
),
@ -197,11 +196,11 @@ class _DevicePickerContent extends ConsumerWidget {
String _getDeviceInfoString(BuildContext context, DeviceInfo info) {
final serial = info.serial;
return [
if (serial != null) AppLocalizations.of(context)!.devicePicker_sn(serial),
if (serial != null) AppLocalizations.of(context)!.l_sn_serial(serial),
if (info.version.isAtLeast(1))
AppLocalizations.of(context)!.devicePicker_fw(info.version)
AppLocalizations.of(context)!.l_fw_version(info.version)
else
AppLocalizations.of(context)!.devicePicker_unknown_type,
AppLocalizations.of(context)!.l_unknown_type,
].join(' ');
}
@ -214,17 +213,15 @@ List<String> _getDeviceStrings(
case 'device-inaccessible':
return [
node.name,
AppLocalizations.of(context)!.devicePicker_inaccessible
AppLocalizations.of(context)!.l_yk_inaccessible
];
case 'unknown-device':
return [
AppLocalizations.of(context)!.devicePicker_unknown_device
];
return [AppLocalizations.of(context)!.l_unknown_device];
}
return null;
},
) ??
[AppLocalizations.of(context)!.devicePicker_no_yubikey];
[AppLocalizations.of(context)!.l_no_yk_present];
// Add the NFC reader name, unless it's already included (as device name, like on Android)
if (node is NfcReaderNode && !messages.contains(node.name)) {
@ -311,10 +308,9 @@ class _DeviceRow extends ConsumerWidget {
subtitle: Text(
node.when(
usbYubiKey: (_, __, ___, info) => info == null
? AppLocalizations.of(context)!.devicePicker_inaccessible
? AppLocalizations.of(context)!.l_yk_inaccessible
: _getDeviceInfoString(context, info),
nfcReader: (_, __) =>
AppLocalizations.of(context)!.devicePicker_select_to_scan,
nfcReader: (_, __) => AppLocalizations.of(context)!.l_select_to_scan,
),
),
onTap: () {
@ -349,8 +345,8 @@ class _NfcDeviceRow extends ConsumerWidget {
ref.read(_hiddenDevicesProvider.notifier).showAll();
},
child: ListTile(
title: Text(
AppLocalizations.of(context)!.devicePicker_show_hidden),
title:
Text(AppLocalizations.of(context)!.l_show_hidden_devices),
dense: true,
contentPadding: EdgeInsets.zero,
enabled: hidden.isNotEmpty,
@ -361,8 +357,7 @@ class _NfcDeviceRow extends ConsumerWidget {
ref.read(_hiddenDevicesProvider.notifier).hideDevice(node.path);
},
child: ListTile(
title: Text(
AppLocalizations.of(context)!.devicePicker_hide_device),
title: Text(AppLocalizations.of(context)!.l_hide_device),
dense: true,
contentPadding: EdgeInsets.zero,
),

View File

@ -142,7 +142,7 @@ class MainPageDrawer extends ConsumerWidget {
NavigationDrawerDestination(
key: managementAppDrawer,
label: Text(
l10n.mainDrawer_txt_applications,
l10n.l_toggle_applications,
),
icon: Icon(Application.management._icon),
selectedIcon: Icon(Application.management._filledIcon),
@ -152,11 +152,11 @@ class MainPageDrawer extends ConsumerWidget {
],
// Non-YubiKey pages
NavigationDrawerDestination(
label: Text(l10n.mainDrawer_txt_settings),
label: Text(l10n.w_settings),
icon: const Icon(Icons.settings_outlined),
),
NavigationDrawerDestination(
label: Text(l10n.mainDrawer_txt_help),
label: Text(l10n.l_help_and_about),
icon: const Icon(Icons.help_outline),
),
],

View File

@ -83,12 +83,12 @@ class MainPage extends ConsumerWidget {
return MessagePage(
graphic: noKeyImage,
message: hasNfcSupport && isNfcEnabled
? l10n.devicePicker_insert_or_tap
: l10n.devicePicker_insert_yubikey,
? l10n.l_insert_or_tap_yk
: l10n.l_insert_yk,
actions: [
if (hasNfcSupport && !isNfcEnabled)
ElevatedButton.icon(
label: Text(l10n.general_enable_nfc),
label: Text(l10n.l_enable_nfc),
icon: nfcIcon,
onPressed: () async {
await openNfcSettings();
@ -96,7 +96,7 @@ class MainPage extends ConsumerWidget {
],
actionButtonBuilder: (context) => IconButton(
icon: const Icon(Icons.person_add_alt_1),
tooltip: l10n.oath_add_account,
tooltip: l10n.l_add_account,
onPressed: () async {
CredentialData? otpauth;
final scanner = ref.read(qrScannerProvider);
@ -132,7 +132,7 @@ class MainPage extends ConsumerWidget {
return MessagePage(
delayedContent: true,
graphic: noKeyImage,
message: l10n.devicePicker_insert_yubikey,
message: l10n.l_insert_yk,
);
}
} else {
@ -142,18 +142,18 @@ class MainPage extends ConsumerWidget {
if (data.info.supportedCapabilities.isEmpty &&
data.name == 'Unrecognized device') {
return MessagePage(
header: l10n.mainPage_not_recognized,
header: l10n.l_yk_not_recognized,
);
} else if (app.getAvailability(data) ==
Availability.unsupported) {
return MessagePage(
header: l10n.mainPage_app_not_supported,
message: l10n.mainPage_app_not_supported_on_yubikey(app.name),
header: l10n.l_app_not_supported,
message: l10n.l_app_not_supported_on_yk(app.name),
);
} else if (app.getAvailability(data) != Availability.enabled) {
return MessagePage(
header: l10n.mainPage_app_not_enabled,
message: l10n.mainPage_app_not_enabled_desc(app.name),
header: l10n.l_app_disabled,
message: l10n.l_app_disabled_desc(app.name),
);
}
@ -164,8 +164,8 @@ class MainPage extends ConsumerWidget {
return FidoScreen(data);
default:
return MessagePage(
header: l10n.mainPage_app_not_supported,
message: l10n.mainPage_app_not_supported_desc,
header: l10n.l_app_not_supported,
message: l10n.l_app_not_supported_desc,
);
}
},

View File

@ -278,13 +278,14 @@ class _HelperWaiterState extends ConsumerState<_HelperWaiter> {
@override
Widget build(BuildContext context) {
if (slow) {
final l10n = AppLocalizations.of(context)!;
return MessagePage(
graphic: const CircularProgressIndicator(),
message: 'The Helper process isn\'t responding',
message: l10n.l_helper_not_responding,
actions: [
ActionChip(
avatar: const Icon(Icons.copy),
label: Text(AppLocalizations.of(context)!.general_copy_log),
label: Text(l10n.l_copy_log),
onPressed: () async {
_log.info('Copying log to clipboard ($version)...');
final logs = await ref.read(logLevelProvider.notifier).getLogs();
@ -295,7 +296,7 @@ class _HelperWaiterState extends ConsumerState<_HelperWaiter> {
(context) async {
showMessage(
context,
AppLocalizations.of(context)!.general_log_copied,
l10n.l_log_copied,
);
},
);

View File

@ -271,8 +271,8 @@ class DesktopCredentialListNotifier extends OathCredentialListNotifier {
return promptUserInteraction(
context,
icon: const Icon(Icons.touch_app),
title: l10n.oath_touch_required,
description: l10n.oath_touch_now,
title: l10n.l_touch_required,
description: l10n.l_touch_button_now,
headless: headless,
);
},

View File

@ -111,7 +111,7 @@ class _Systray extends TrayListener {
Future<void> _init() async {
await trayManager.setIcon(_getIcon(), isTemplate: true);
if (!Platform.isLinux) {
await trayManager.setToolTip(_l10n.general_app_name);
await trayManager.setToolTip(_l10n.app_name);
}
await _updateContextMenu();
@ -176,8 +176,8 @@ class _Systray extends TrayListener {
.read(clipboardProvider)
.setText(code.value, isSensitive: true);
final notification = LocalNotification(
title: _l10n.systray_oath_copied,
body: _l10n.systray_oath_copied_to_clipboard(label),
title: _l10n.l_code_copied,
body: _l10n.p_target_copied_clipboard(label),
silent: true,
);
await notification.show();
@ -190,14 +190,12 @@ class _Systray extends TrayListener {
),
if (_credentials.isEmpty)
MenuItem(
label: _l10n.systray_no_pinned,
label: _l10n.l_no_pinned_accounts,
disabled: true,
),
MenuItem.separator(),
MenuItem(
label: _isHidden
? _l10n.general_show_window
: _l10n.general_hide_window,
label: _isHidden ? _l10n.l_show_window : _l10n.l_hide_window,
onClick: (_) {
_ref
.read(desktopWindowStateProvider.notifier)
@ -206,7 +204,7 @@ class _Systray extends TrayListener {
),
MenuItem.separator(),
MenuItem(
label: _l10n.general_quit,
label: _l10n.w_quit,
onClick: (_) {
_ref.read(withContextProvider)(
(context) async {

View File

@ -25,7 +25,7 @@ class ErrorPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.general_application_error),
title: Text(AppLocalizations.of(context)!.l_application_error),
),
body: Center(
child: Column(

View File

@ -128,12 +128,12 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
String _getMessage() {
if (_samples == 0) {
return AppLocalizations.of(context)!.fido_press_fingerprint_begin;
return AppLocalizations.of(context)!.p_press_fingerprint_begin;
}
if (_fingerprint == null) {
return AppLocalizations.of(context)!.fido_keep_touching_yubikey;
return AppLocalizations.of(context)!.l_keep_touching_yk;
} else {
return AppLocalizations.of(context)!.fido_fingerprint_captured;
return AppLocalizations.of(context)!.l_fingerprint_captured;
}
}
@ -144,8 +144,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
.renameFingerprint(_fingerprint!, _label);
if (!mounted) return;
Navigator.of(context).pop(true);
showMessage(
context, AppLocalizations.of(context)!.fido_fingerprint_added);
showMessage(context, AppLocalizations.of(context)!.l_fingerprint_added);
} catch (e) {
final String errorMessage;
// TODO: Make this cleaner than importing desktop specific RpcError.
@ -156,7 +155,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
}
showMessage(
context,
'${AppLocalizations.of(context)!.fido_error_setting_name}: $errorMessage',
'${AppLocalizations.of(context)!.l_setting_name_failed}: $errorMessage',
duration: const Duration(seconds: 4),
);
}
@ -167,13 +166,13 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
final progress = _samples == 0 ? 0.0 : _samples / (_samples + _remaining);
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.fido_add_fingerprint),
title: Text(AppLocalizations.of(context)!.l_add_fingerprint),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(AppLocalizations.of(context)!.fido_step_1_2),
Text(AppLocalizations.of(context)!.l_fp_step_1_capture),
Column(
children: [
Padding(
@ -196,7 +195,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
),
],
),
Text(AppLocalizations.of(context)!.fido_step_2_2),
Text(AppLocalizations.of(context)!.l_fp_step_2_name),
TextFormField(
focusNode: _nameFocus,
maxLength: 15,
@ -206,7 +205,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
decoration: InputDecoration(
enabled: _fingerprint != null,
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.fido_name,
labelText: AppLocalizations.of(context)!.w_name,
prefixIcon: const Icon(Icons.fingerprint_outlined),
),
onChanged: (value) {
@ -232,7 +231,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
actions: [
TextButton(
onPressed: _fingerprint != null && _label.isNotEmpty ? _submit : null,
child: Text(AppLocalizations.of(context)!.fido_save),
child: Text(AppLocalizations.of(context)!.w_save),
),
],
);

View File

@ -37,14 +37,14 @@ class DeleteCredentialDialog extends ConsumerWidget {
final label = credential.userName;
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.fido_delete_credential),
title: Text(AppLocalizations.of(context)!.l_delete_credential),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(AppLocalizations.of(context)!.fido_this_will_delete_cred),
Text('${AppLocalizations.of(context)!.fido_credential}: $label'),
Text(AppLocalizations.of(context)!.p_warning_delete_credential),
Text('${AppLocalizations.of(context)!.w_credential}: $label'),
]
.map((e) => Padding(
child: e,
@ -63,11 +63,11 @@ class DeleteCredentialDialog extends ConsumerWidget {
(context) async {
Navigator.of(context).pop(true);
showMessage(context,
AppLocalizations.of(context)!.fido_credential_deleted);
AppLocalizations.of(context)!.l_credential_deleted);
},
);
},
child: Text(AppLocalizations.of(context)!.fido_delete),
child: Text(AppLocalizations.of(context)!.w_delete),
),
],
);

View File

@ -35,7 +35,7 @@ class DeleteFingerprintDialog extends ConsumerWidget {
final label = fingerprint.label;
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.fido_delete_fingerprint),
title: Text(AppLocalizations.of(context)!.l_delete_fingerprint),
actions: [
TextButton(
onPressed: () async {
@ -44,11 +44,11 @@ class DeleteFingerprintDialog extends ConsumerWidget {
.deleteFingerprint(fingerprint);
await ref.read(withContextProvider)((context) async {
Navigator.of(context).pop(true);
showMessage(context,
AppLocalizations.of(context)!.fido_fingerprint_deleted);
showMessage(
context, AppLocalizations.of(context)!.l_fingerprint_deleted);
});
},
child: Text(AppLocalizations.of(context)!.fido_delete),
child: Text(AppLocalizations.of(context)!.w_delete),
),
],
child: Padding(
@ -56,8 +56,8 @@ class DeleteFingerprintDialog extends ConsumerWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(AppLocalizations.of(context)!.fido_this_will_delete_fp),
Text('${AppLocalizations.of(context)!.fido_fingerprint}: $label'),
Text(AppLocalizations.of(context)!.l_warning_delete_fingerprint),
Text('${AppLocalizations.of(context)!.w_fingerprint}: $label'),
]
.map((e) => Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),

View File

@ -36,7 +36,7 @@ class FidoScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) =>
ref.watch(fidoStateProvider(deviceData.node.path)).when(
loading: () => AppPage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
centered: true,
delayedContent: true,
child: const CircularProgressIndicator(),
@ -47,10 +47,11 @@ class FidoScreen extends ConsumerWidget {
0;
if (Capability.fido2.value & supported == 0) {
return MessagePage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
graphic: manageAccounts,
header: AppLocalizations.of(context)!.fido_ready_to_use,
message: AppLocalizations.of(context)!.fido_register_as_a_key,
header: AppLocalizations.of(context)!.l_ready_to_use,
message:
AppLocalizations.of(context)!.l_register_sk_on_websites,
);
}
final enabled = deviceData.info.config
@ -58,14 +59,14 @@ class FidoScreen extends ConsumerWidget {
0;
if (Capability.fido2.value & enabled == 0) {
return MessagePage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
header: AppLocalizations.of(context)!.fido_fido_disabled,
message: AppLocalizations.of(context)!.fido_webauthn_req_fido,
title: Text(AppLocalizations.of(context)!.w_webauthn),
header: AppLocalizations.of(context)!.l_fido_disabled,
message: AppLocalizations.of(context)!.l_webauthn_req_fido2,
);
}
return AppFailurePage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
cause: error,
);
},

View File

@ -31,17 +31,17 @@ Widget fidoBuildActions(
return SimpleDialog(
children: [
if (state.bioEnroll != null) ...[
ListTitle(AppLocalizations.of(context)!.general_setup,
ListTitle(AppLocalizations.of(context)!.w_setup,
textStyle: Theme.of(context).textTheme.bodyLarge),
ListTile(
leading: const CircleAvatar(child: Icon(Icons.fingerprint_outlined)),
title: Text(AppLocalizations.of(context)!.fido_add_fingerprint),
title: Text(AppLocalizations.of(context)!.l_add_fingerprint),
subtitle: state.unlocked
? Text(AppLocalizations.of(context)!
.fido_fingerprints_used(fingerprints))
.l_fingerprints_used(fingerprints))
: Text(state.hasPin
? AppLocalizations.of(context)!.fido_unlock_first
: AppLocalizations.of(context)!.fido_set_pin_first),
? AppLocalizations.of(context)!.l_unlock_pin_first
: AppLocalizations.of(context)!.l_set_pin_first),
enabled: state.unlocked && fingerprints < 5,
onTap: state.unlocked && fingerprints < 5
? () {
@ -54,16 +54,16 @@ Widget fidoBuildActions(
: null,
),
],
ListTitle(AppLocalizations.of(context)!.general_manage,
ListTitle(AppLocalizations.of(context)!.w_manage,
textStyle: Theme.of(context).textTheme.bodyLarge),
ListTile(
leading: const CircleAvatar(child: Icon(Icons.pin_outlined)),
title: Text(state.hasPin
? AppLocalizations.of(context)!.fido_change_pin
: AppLocalizations.of(context)!.fido_set_pin),
? AppLocalizations.of(context)!.l_change_pin
: AppLocalizations.of(context)!.l_set_pin),
subtitle: Text(state.hasPin
? AppLocalizations.of(context)!.fido_pin_protection
: AppLocalizations.of(context)!.fido_pin_protection_optional),
? AppLocalizations.of(context)!.l_fido_pin_protection
: AppLocalizations.of(context)!.l_fido_pin_protection_optional),
onTap: () {
Navigator.of(context).pop();
showBlurDialog(
@ -77,9 +77,8 @@ Widget fidoBuildActions(
backgroundColor: theme.error,
child: const Icon(Icons.delete_outline),
),
title: Text(AppLocalizations.of(context)!.fido_reset_fido),
subtitle:
Text(AppLocalizations.of(context)!.fido_factory_reset_description),
title: Text(AppLocalizations.of(context)!.l_reset_fido),
subtitle: Text(AppLocalizations.of(context)!.l_factory_reset_this_app),
onTap: () {
Navigator.of(context).pop();
showBlurDialog(

View File

@ -37,20 +37,20 @@ class FidoLockedPage extends ConsumerWidget {
if (!state.hasPin) {
if (state.bioEnroll != null) {
return MessagePage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
graphic: noFingerprints,
header: AppLocalizations.of(context)!.fido_no_fingerprints,
message: AppLocalizations.of(context)!.fido_set_pin_fingerprints,
header: AppLocalizations.of(context)!.l_no_fingerprints,
message: AppLocalizations.of(context)!.l_set_pin_fingerprints,
keyActionsBuilder: _buildActions,
);
} else {
return MessagePage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
graphic: manageAccounts,
header: state.credMgmt
? AppLocalizations.of(context)!.fido_no_discoverable_acc
: AppLocalizations.of(context)!.fido_ready_to_use,
message: AppLocalizations.of(context)!.fido_optionally_set_a_pin,
? AppLocalizations.of(context)!.l_no_discoverable_accounts
: AppLocalizations.of(context)!.l_ready_to_use,
message: AppLocalizations.of(context)!.l_optionally_set_a_pin,
keyActionsBuilder: _buildActions,
);
}
@ -58,16 +58,16 @@ class FidoLockedPage extends ConsumerWidget {
if (!state.credMgmt && state.bioEnroll == null) {
return MessagePage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
graphic: manageAccounts,
header: AppLocalizations.of(context)!.fido_ready_to_use,
message: AppLocalizations.of(context)!.fido_register_as_a_key,
header: AppLocalizations.of(context)!.l_ready_to_use,
message: AppLocalizations.of(context)!.l_register_sk_on_websites,
keyActionsBuilder: _buildActions,
);
}
return AppPage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
keyActionsBuilder: _buildActions,
child: Column(
children: [
@ -117,13 +117,14 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> {
String? _getErrorText() {
if (_retries == 0) {
return AppLocalizations.of(context)!.fido_pin_blocked_factory_reset;
return AppLocalizations.of(context)!.l_pin_blocked_reset;
}
if (_blocked) {
return AppLocalizations.of(context)!.fido_pin_temp_blocked;
return AppLocalizations.of(context)!.l_pin_soft_locked;
}
if (_retries != null) {
return AppLocalizations.of(context)!.fido_wrong_pin_attempts(_retries!);
return AppLocalizations.of(context)!
.l_wrong_pin_attempts_remaining(_retries!);
}
return null;
}
@ -136,7 +137,7 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(AppLocalizations.of(context)!.fido_enter_fido2_pin),
Text(AppLocalizations.of(context)!.l_enter_fido2_pin),
Padding(
padding: const EdgeInsets.only(top: 16.0, bottom: 16.0),
child: TextField(
@ -145,7 +146,7 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> {
controller: _pinController,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.fido_pin,
labelText: AppLocalizations.of(context)!.w_pin,
helperText: '', // Prevents dialog resizing
errorText: _pinIsWrong ? _getErrorText() : null,
errorMaxLines: 3,
@ -175,7 +176,7 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> {
noFingerprints ? const Icon(Icons.warning_amber_rounded) : null,
title: noFingerprints
? Text(
AppLocalizations.of(context)!.fido_no_fp_added,
AppLocalizations.of(context)!.l_no_fps_added,
overflow: TextOverflow.fade,
)
: null,
@ -184,7 +185,7 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> {
minLeadingWidth: 0,
trailing: ElevatedButton.icon(
icon: const Icon(Icons.lock_open),
label: Text(AppLocalizations.of(context)!.fido_unlock),
label: Text(AppLocalizations.of(context)!.w_unlock),
onPressed:
_pinController.text.isNotEmpty && !_blocked ? _submit : null,
),

View File

@ -57,12 +57,12 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
return ResponsiveDialog(
title: Text(hasPin
? AppLocalizations.of(context)!.fido_change_pin
: AppLocalizations.of(context)!.fido_set_pin),
? AppLocalizations.of(context)!.l_change_pin
: AppLocalizations.of(context)!.l_set_pin),
actions: [
TextButton(
onPressed: isValid ? _submit : null,
child: Text(AppLocalizations.of(context)!.fido_save),
child: Text(AppLocalizations.of(context)!.w_save),
),
],
child: Padding(
@ -71,14 +71,14 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (hasPin) ...[
Text(AppLocalizations.of(context)!.fido_enter_current_pin),
Text(AppLocalizations.of(context)!.p_enter_current_pin_or_reset),
TextFormField(
initialValue: _currentPin,
autofocus: true,
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.fido_current_pin,
labelText: AppLocalizations.of(context)!.l_current_pin,
errorText: _currentIsWrong ? _currentPinError : null,
errorMaxLines: 3,
prefixIcon: const Icon(Icons.pin_outlined),
@ -91,8 +91,8 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
},
),
],
Text(
AppLocalizations.of(context)!.fido_enter_new_pin(minPinLength)),
Text(AppLocalizations.of(context)!
.p_enter_new_fido2_pin(minPinLength)),
// TODO: Set max characters based on UTF-8 bytes
TextFormField(
initialValue: _newPin,
@ -100,7 +100,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.fido_new_pin,
labelText: AppLocalizations.of(context)!.l_new_pin,
enabled: !hasPin || _currentPin.isNotEmpty,
errorText: _newIsWrong ? _newPinError : null,
errorMaxLines: 3,
@ -118,7 +118,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.fido_confirm_pin,
labelText: AppLocalizations.of(context)!.l_confirm_pin,
prefixIcon: const Icon(Icons.pin_outlined),
enabled:
(!hasPin || _currentPin.isNotEmpty) && _newPin.isNotEmpty,
@ -151,7 +151,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
if (_newPin.length < minPinLength) {
setState(() {
_newPinError =
AppLocalizations.of(context)!.fido_new_pin_chars(minPinLength);
AppLocalizations.of(context)!.l_new_pin_len(minPinLength);
_newIsWrong = true;
});
return;
@ -162,15 +162,15 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
.setPin(_newPin, oldPin: oldPin);
result.when(success: () {
Navigator.of(context).pop(true);
showMessage(context, AppLocalizations.of(context)!.fido_pin_set);
showMessage(context, AppLocalizations.of(context)!.l_pin_set);
}, failed: (retries, authBlocked) {
setState(() {
if (authBlocked) {
_currentPinError = AppLocalizations.of(context)!.fido_pin_blocked;
_currentPinError = AppLocalizations.of(context)!.l_pin_soft_locked;
_currentIsWrong = true;
} else {
_currentPinError = AppLocalizations.of(context)!
.fido_wrong_pin_retries_remaining(retries);
.l_wrong_pin_attempts_remaining(retries);
_currentIsWrong = true;
}
});
@ -186,7 +186,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
}
showMessage(
context,
'${AppLocalizations.of(context)!.fido_fail_set_pin}: $errorMessage',
'${AppLocalizations.of(context)!.l_set_pin_failed}: $errorMessage',
duration: const Duration(seconds: 4),
);
}

View File

@ -53,8 +53,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
.renameFingerprint(widget.fingerprint, _label);
if (!mounted) return;
Navigator.of(context).pop(renamed);
showMessage(
context, AppLocalizations.of(context)!.fido_fingerprint_renamed);
showMessage(context, AppLocalizations.of(context)!.l_fingerprint_renamed);
} catch (e) {
final String errorMessage;
// TODO: Make this cleaner than importing desktop specific RpcError.
@ -65,7 +64,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
}
showMessage(
context,
'${AppLocalizations.of(context)!.fido_error_renaming}: $errorMessage',
'${AppLocalizations.of(context)!.l_rename_fp_failed}: $errorMessage',
duration: const Duration(seconds: 4),
);
}
@ -74,11 +73,11 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
@override
Widget build(BuildContext context) {
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.fido_rename_fingerprint),
title: Text(AppLocalizations.of(context)!.l_rename_fp),
actions: [
TextButton(
onPressed: _label.isNotEmpty ? _submit : null,
child: Text(AppLocalizations.of(context)!.fido_save),
child: Text(AppLocalizations.of(context)!.w_save),
),
],
child: Padding(
@ -87,8 +86,8 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(AppLocalizations.of(context)!
.fido_rename(widget.fingerprint.label)),
Text(AppLocalizations.of(context)!.fido_will_change_label_fp),
.q_rename_target(widget.fingerprint.label)),
Text(AppLocalizations.of(context)!.p_will_change_label_fp),
TextFormField(
initialValue: _label,
maxLength: 15,
@ -96,7 +95,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
buildCounter: buildByteCounterFor(_label),
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.fido_label,
labelText: AppLocalizations.of(context)!.w_label,
prefixIcon: const Icon(Icons.fingerprint_outlined),
),
onChanged: (value) {

View File

@ -49,23 +49,23 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
switch (_interaction) {
case InteractionEvent.remove:
return nfc
? AppLocalizations.of(context)!.fido_remove_from_reader
: AppLocalizations.of(context)!.fido_unplug_yubikey;
? AppLocalizations.of(context)!.l_remove_yk_from_reader
: AppLocalizations.of(context)!.l_unplug_yk;
case InteractionEvent.insert:
return nfc
? AppLocalizations.of(context)!.fido_place_back_on_reader
: AppLocalizations.of(context)!.fido_reinsert_yubikey;
? AppLocalizations.of(context)!.l_replace_yk_on_reader
: AppLocalizations.of(context)!.l_reinsert_yk;
case InteractionEvent.touch:
return AppLocalizations.of(context)!.fido_touch_yubikey;
return AppLocalizations.of(context)!.l_touch_button_now;
case null:
return AppLocalizations.of(context)!.fido_press_reset;
return AppLocalizations.of(context)!.l_press_reset_to_begin;
}
}
@override
Widget build(BuildContext context) {
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.fido_factory_reset),
title: Text(AppLocalizations.of(context)!.l_factory_reset),
onCancel: () {
_subscription?.cancel();
},
@ -84,7 +84,7 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
_subscription = null;
Navigator.of(context).pop();
showMessage(context,
AppLocalizations.of(context)!.fido_fido_app_reset);
AppLocalizations.of(context)!.l_fido_app_reset);
}, onError: (e) {
_log.error('Error performing FIDO reset', e);
Navigator.of(context).pop();
@ -97,13 +97,13 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
}
showMessage(
context,
'${AppLocalizations.of(context)!.fido_error_reset}: $errorMessage',
'${AppLocalizations.of(context)!.l_reset_failed}: $errorMessage',
duration: const Duration(seconds: 4),
);
});
}
: null,
child: Text(AppLocalizations.of(context)!.fido_reset),
child: Text(AppLocalizations.of(context)!.w_reset),
),
],
child: Padding(
@ -112,11 +112,11 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.fido_warning_will_delete_accounts,
AppLocalizations.of(context)!.p_warning_deletes_accounts,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text(
AppLocalizations.of(context)!.fido_warning_disable_these_creds,
AppLocalizations.of(context)!.p_warning_disable_accounts,
),
Center(
child: Text(_getMessage(),

View File

@ -47,7 +47,7 @@ class FidoUnlockedPage extends ConsumerWidget {
}
final creds = data.value;
if (creds.isNotEmpty) {
children.add(ListTitle(AppLocalizations.of(context)!.fido_credentials));
children.add(ListTitle(AppLocalizations.of(context)!.w_credentials));
children.addAll(
creds.map(
(cred) => ListTile(
@ -95,8 +95,7 @@ class FidoUnlockedPage extends ConsumerWidget {
final fingerprints = data.value;
if (fingerprints.isNotEmpty) {
nFingerprints = fingerprints.length;
children
.add(ListTitle(AppLocalizations.of(context)!.fido_fingerprints));
children.add(ListTitle(AppLocalizations.of(context)!.w_fingerprints));
children.addAll(fingerprints.map((fp) => ListTile(
leading: CircleAvatar(
foregroundColor: Theme.of(context).colorScheme.onSecondary,
@ -137,7 +136,7 @@ class FidoUnlockedPage extends ConsumerWidget {
if (children.isNotEmpty) {
return AppPage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
keyActionsBuilder: (context) =>
fidoBuildActions(context, node, state, nFingerprints),
child: Column(
@ -147,26 +146,26 @@ class FidoUnlockedPage extends ConsumerWidget {
if (state.bioEnroll != null) {
return MessagePage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
graphic: noFingerprints,
header: AppLocalizations.of(context)!.fido_no_fingerprints,
message: AppLocalizations.of(context)!.fido_add_one_or_more,
header: AppLocalizations.of(context)!.l_no_fingerprints,
message: AppLocalizations.of(context)!.l_add_one_or_more_fps,
keyActionsBuilder: (context) =>
fidoBuildActions(context, node, state, 0),
);
}
return MessagePage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
graphic: manageAccounts,
header: AppLocalizations.of(context)!.fido_no_discoverable_acc,
message: AppLocalizations.of(context)!.fido_register_as_a_key,
header: AppLocalizations.of(context)!.l_no_discoverable_accounts,
message: AppLocalizations.of(context)!.l_register_sk_on_websites,
keyActionsBuilder: (context) => fidoBuildActions(context, node, state, 0),
);
}
Widget _buildLoadingPage(BuildContext context) => AppPage(
title: Text(AppLocalizations.of(context)!.fido_webauthn),
title: Text(AppLocalizations.of(context)!.w_webauthn),
centered: true,
delayedContent: true,
child: const CircularProgressIndicator(),

View File

@ -1,87 +1,28 @@
{
"@@locale": "en",
"oath_no_credentials": "No credentials",
"oath_pinned": "Pinned",
"oath_accounts": "Accounts",
"oath_copied_to_clipboard": "Code copied to clipboard",
"oath_copy_to_clipboard": "Copy to clipboard",
"oath_calculate": "Calculate",
"oath_pin_account": "Pin account",
"oath_unpin_account": "Unpin account",
"oath_rename_account": "Rename account",
"oath_delete_account": "Delete account",
"oath_no_qr_code": "No QR code found",
"oath_failed_reading_qr": "Failed reading QR code",
"oath_success_add_account": "Account added",
"oath_fail_add_account": "Failed adding account",
"oath_add_account": "Add account",
"oath_save": "Save",
"oath_duplicate_name": "This name already exists for the Issuer",
"oath_issuer_optional": "Issuer (optional)",
"oath_account_name": "Account name",
"oath_secret_key": "Secret key",
"oath_invalid_length": "Invalid length",
"oath_scanned_qr": "Scanned QR code",
"oath_scan_qr": "Scan QR code",
"oath_require_touch": "Require touch",
"oath_touch_required": "Touch Required",
"oath_touch_now": "Touch the button on your YubiKey now",
"oath_sec": "sec",
"oath_digits": "digits",
"oath_success_delete_account": "Account deleted",
"oath_delete": "Delete",
"oath_warning_this_will_delete_account_from_key": "Warning! This action will delete the account from your YubiKey.",
"oath_warning_disable_this_cred": "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.",
"oath_account": "Account",
"oath_password_set": "Password set",
"oath_manage_password": "Manage password",
"oath_password_description": "Optional password protection",
"oath_enter_current_password": "Enter your current password. If you don't know your password, you'll need to reset the YubiKey.",
"oath_current_password": "Current password",
"oath_wrong_password": "Wrong password",
"oath_password_removed": "Password removed",
"oath_remove_password": "Remove password",
"oath_clear_saved_password": "Clear saved password",
"oath_password_forgotten": "Password forgotten",
"oath_enter_new_password": "Enter your new password. A password may contain letters, numbers and special characters.",
"oath_new_password": "New password",
"oath_confirm_password": "Confirm password",
"oath_authenticator": "Authenticator",
"oath_reset_oath": "Reset OATH",
"oath_no_accounts": "No accounts",
"oath_search_accounts": "Search accounts",
"oath_set_password": "Set password",
"oath_failed_remember_pw": "Failed to remember password",
"oath_enter_oath_pw": "Enter the OATH password for your YubiKey",
"oath_password": "Password",
"oath_keystore_unavailable": "OS Keystore unavailable",
"oath_remember_password": "Remember password",
"oath_unlock": "Unlock",
"oath_unlock_first": "Unlock with password first",
"oath_warning_will_change_account_displayed": "This will change how the account is displayed in the list.",
"oath_account_must_have_name": "Your account must have a name",
"oath_name_exists": "This name already exists for the Issuer",
"oath_account_renamed": "Account renamed",
"oath_rename": "Rename {label}?",
"@oath_rename" : {
"app_name": "Yubico Authenticator",
"w_save": "Save",
"w_cancel": "Cancel",
"w_close": "Close",
"w_delete": "Delete",
"w_quit": "Quit",
"w_unlock": "Unlock",
"w_calculate": "Calculate",
"w_label": "Label",
"w_name": "Name",
"w_usb": "USB",
"w_nfc": "NFC",
"l_show_window": "Show window",
"l_hide_window": "Hide window",
"q_rename_target": "Rename {label}?",
"@q_rename_target" : {
"placeholders": {
"label": {}
}
},
"oath_factory_reset": "Factory reset",
"oath_factory_reset_description": "Factory reset this application",
"oath_oath_application_reset": "OATH application reset",
"oath_reset": "Reset",
"oath_warning_will_delete_accounts": "Warning! This will irrevocably delete all OATH TOTP/HOTP accounts from your YubiKey.",
"oath_warning_disable_these_creds": "Your OATH credentials, as well as any password set, will be removed from this YubiKey. Make sure to first disable these from their respective web sites to avoid being locked out of your accounts.",
"oath_invalid_character_issuer": "Invalid character: ':' is not allowed in issuer",
"oath_accounts_used": "{used} of {capacity} accounts used",
"@oath_accounts_used" : {
"placeholders": {
"used": {},
"capacity": {}
}
},
"oath_custom_icons": "Custom icons",
"oath_custom_icons_description": "Icon packs can make your accounts more easily distinguishable with familiar logos and colors.",
"oath_custom_icons_replace": "Replace icon pack",
@ -105,252 +46,319 @@
"oath_custom_icons_err_invalid_icon_pack": "Invalid icon pack",
"oath_custom_icons_err_filesystem_error": "File system operation error",
"widgets_cancel": "Cancel",
"widgets_close": "Close",
"w_about": "About",
"w_appearance": "Appearance",
"w_authenticator": "Authenticator",
"w_manage": "Manage",
"w_setup": "Setup",
"w_settings": "Settings",
"w_webauthn": "WebAuthn",
"l_help_and_about": "Help and about",
"l_help_and_feedback": "Help and feedback",
"l_send_feedback": "Send us feedback",
"l_i_need_help": "I need help",
"w_troubleshooting": "Troubleshooting",
"l_terms_of_use": "Terms of use",
"l_privacy_policy": "Privacy policy",
"l_open_src_licenses": "Open source licenses",
"l_configure_yk": "Configure YubiKey",
"l_please_wait": "Please wait\u2026",
"l_secret_key": "Secret key",
"l_invalid_length": "Invalid length",
"l_require_touch": "Require touch",
"q_have_account_info": "Have account info?",
"l_run_diagnostics": "Run diagnostics",
"l_log_level": "Log level",
"l_character_count": "Character count",
"mgmt_min_one_interface": "At least one interface must be enabled",
"mgmt_reconfiguring_yubikey": "Reconfiguring YubiKey\u2026",
"mgmt_configuration_updated": "Configuration updated",
"mgmt_configuration_updated_remove_reinsert": "Configuration updated, remove and reinsert your YubiKey",
"mgmt_toggle_applications": "Toggle applications",
"mgmt_save": "Save",
"@_theme": {},
"l_app_theme": "App theme",
"l_choose_app_theme": "Choose app theme",
"l_system_default": "System default",
"l_light_mode": "Light mode",
"l_dark_mode": "Dark mode",
"general_app_name": "Yubico Authenticator",
"general_about": "About",
"general_terms_of_use": "Terms of use",
"general_privacy_policy": "Privacy policy",
"general_open_src_licenses": "Open source licenses",
"general_help_and_feedback": "Help and feedback",
"general_send_feedback": "Send us feedback",
"general_i_need_help": "I need help",
"general_application_error": "Application error",
"general_troubleshooting": "Troubleshooting",
"general_run_diagnostics": "Run diagnostics",
"general_diagnostics_copied": "Diagnostic data copied to clipboard",
"general_log_level": "Log level",
"general_copy_log": "Copy log",
"general_log_copied": "Log copied to clipboard",
"general_settings": "Settings",
"general_appearance": "Appearance",
"general_system_default": "System default",
"general_light_mode": "Light mode",
"general_dark_mode": "Dark mode",
"general_allow_screenshots": "Allow screenshots",
"general_usb": "USB",
"general_nfc": "NFC",
"general_enable_nfc": "Enable NFC",
"general_place_on_nfc_reader": "Place your YubiKey on the NFC reader",
"general_setup": "Setup",
"general_manage": "Manage",
"general_configure_yubikey": "Configure YubiKey",
"general_show_window": "Show window",
"general_hide_window": "Hide window",
"general_quit": "Quit",
"general_character_count": "Character count",
"general_please_wait": "Please wait\u2026",
"general_unsupported_yubikey": "Unsupported YubiKey",
"general_yubikey_no_access": "This YubiKey cannot be accessed",
"general_permission_denied": "Permission denied",
"general_elevated_permissions_required": "Managing this device requires elevated privileges.",
"fido_press_fingerprint_begin": "Press your finger against the YubiKey to begin.",
"fido_keep_touching_yubikey": "Keep touching your YubiKey repeatedly\u2026",
"fido_fingerprint_captured": "Fingerprint captured successfully!",
"fido_fingerprint_added": "Fingerprint added",
"fido_error_setting_name": "Error setting name",
"fido_add_fingerprint": "Add fingerprint",
"fido_step_1_2": "Step 1/2: Capture fingerprint",
"fido_step_2_2": "Step 2/2: Name fingerprint",
"fido_name": "Name",
"fido_save": "Save",
"fido_delete_credential": "Delete credential",
"fido_this_will_delete_cred": "This will delete the credential from your YubiKey.",
"fido_credential": "Credential",
"fido_credential_deleted": "Credential deleted",
"fido_delete": "Delete",
"fido_delete_fingerprint": "Delete fingerprint",
"fido_fingerprint_deleted": "Fingerprint deleted",
"fido_this_will_delete_fp": "This will delete the fingerprint from your YubiKey.",
"fido_fingerprint": "Fingerprint",
"fido_webauthn": "WebAuthn",
"fido_ready_to_use": "Ready to use",
"fido_register_as_a_key": "Register as a Security Key on websites",
"fido_fido_disabled": "FIDO2 disabled",
"fido_webauthn_req_fido": "WebAuthn requires the FIDO2 application to be enabled on your YubiKey",
"fido_wrong_pin_attempts": "Wrong PIN. {retries} attempt(s) remaining.",
"@fido_wrong_pin_attempts" : {
"placeholders": {
"retries": {}
}
},
"fido_no_fingerprints": "No fingerprints",
"fido_set_pin_fingerprints": "Set a PIN to register fingerprints",
"fido_no_discoverable_acc": "No discoverable accounts",
"fido_optionally_set_a_pin": "Optionally set a PIN to protect access to your YubiKey\nRegister as a Security Key on websites",
"fido_set_pin": "Set PIN",
"fido_reset_fido": "Reset FIDO",
"fido_pin_blocked_factory_reset": "PIN is blocked. Factory reset the FIDO application.",
"fido_pin_temp_blocked": "PIN temporarily blocked, remove and reinsert your YubiKey.",
"fido_enter_fido2_pin": "Enter the FIDO2 PIN for your YubiKey",
"fido_pin": "PIN",
"fido_pin_protection": "FIDO PIN protection",
"fido_pin_protection_optional": "Optional FIDO PIN protection",
"fido_no_fp_added": "No fingerprints have been added",
"fido_unlock": "Unlock",
"fido_unlock_first": "Unlock with PIN first",
"fido_set_pin_first": "A PIN is required first",
"fido_change_pin": "Change PIN",
"fido_enter_current_pin": "Enter your current PIN. If you don't know your PIN, you'll need to reset the YubiKey.",
"fido_current_pin": "Current PIN",
"fido_enter_new_pin": "Enter your new PIN. A PIN must be at least {length} characters long and may contain letters, numbers and special characters.",
"@fido_enter_new_pin" : {
"placeholders": {
"length": {}
}
},
"fido_new_pin": "New PIN",
"fido_confirm_pin": "Confirm PIN",
"fido_new_pin_chars": "New PIN must be at least {length} characters",
"@fido_new_pin_chars" : {
"placeholders": {
"length": {}
}
},
"fido_pin_set": "PIN set",
"fido_pin_blocked": "PIN has been blocked until the YubiKey is removed and reinserted",
"fido_wrong_pin_retries_remaining": "Wrong PIN ({length} tries remaining)",
"@fido_wrong_pin_retries_remaining" : {
"placeholders": {
"length": {}
}
},
"fido_fail_set_pin": "Failed to set PIN",
"fido_fingerprint_renamed": "Fingerprint renamed",
"fido_error_renaming": "Error renaming",
"fido_rename_fingerprint": "Rename fingerprint",
"fido_rename": "Rename {label}?",
"@fido_rename" : {
"placeholders": {
"label": {}
}
},
"fido_will_change_label_fp": "This will change the label of the fingerprint.",
"fido_label": "Label",
"fido_remove_from_reader": "Remove your YubiKey from the NFC reader",
"fido_unplug_yubikey": "Unplug your YubiKey",
"fido_place_back_on_reader": "Place your YubiKey back on the reader",
"fido_reinsert_yubikey": "Re-insert your YubiKey",
"fido_touch_yubikey": "Touch your YubiKey now",
"fido_press_reset": "Press reset to begin\u2026",
"fido_factory_reset": "Factory reset",
"fido_factory_reset_description": "Factory reset this application",
"fido_fido_app_reset": "FIDO application reset",
"fido_error_reset": "Error performing reset",
"fido_reset": "Reset",
"fido_warning_will_delete_accounts": "Warning! This will irrevocably delete all U2F and FIDO2 accounts from your YubiKey.",
"fido_warning_disable_these_creds": "Your credentials, as well as any PIN set, will be removed from this YubiKey. Make sure to first disable these from their respective web sites to avoid being locked out of your accounts.",
"fido_credentials": "Credentials",
"fido_fingerprints": "Fingerprints",
"fido_add_one_or_more": "Add one or more (up to five) fingerprints",
"fido_fingerprints_used": "{used}/5 fingerprints registered",
"@fido_fingerprints_used": {
"placeholders": {
"used": {}
}
},
"mainPage_not_recognized": "Device not recognized",
"mainPage_app_not_supported": "Application not supported",
"mainPage_app_not_supported_on_yubikey": "The used YubiKey does not support '${app}' application",
"@mainPage_app_not_supported_on_yubikey" : {
"placeholders": {
"app": {}
}
},
"mainPage_app_not_supported_desc": "This application is not supported",
"mainPage_app_not_enabled": "Application disabled",
"mainPage_app_not_enabled_desc": "Enable the '{app}' application on your YubiKey to access",
"@mainPage_app_not_enabled_desc" : {
"placeholders": {
"app": {}
}
},
"appFailurePage_btn_unlock": "Unlock",
"appFailurePage_txt_info": "WebAuthn management requires elevated privileges.",
"appFailurePage_msg_permission": "Elevating permissions\u2026",
"appFailurePage_error_occured": "An error has occured",
"appFailurePage_failed_connection": "Failed to open connection",
"appFailurePage_msg_reinsert": "Try to remove and re-insert your YubiKey.",
"appFailurePage_ccid_failed": "Failed to open smart card connection",
"appFailurePage_ccid_unavailable": "Make sure your smart card service is functioning.",
"appFailurePage_pcscd_unavailable": "Make sure pcscd is installed and running.",
"mainDrawer_txt_applications": "Toggle applications",
"mainDrawer_txt_settings": "Settings",
"mainDrawer_txt_help": "Help and about",
"devicePicker_no_yubikey": "No YubiKey present",
"devicePicker_insert_yubikey": "Insert your YubiKey",
"devicePicker_insert_or_tap": "Insert or tap a YubiKey",
"devicePicker_select_to_scan": "Select to scan",
"devicePicker_inaccessible": "Device inaccessible",
"devicePicker_unknown_type": "Unknown type",
"devicePicker_unknown_device": "Unrecognized device",
"devicePicker_hide_device": "Hide device",
"devicePicker_show_hidden": "Show hidden devices",
"devicePicker_sn": "S/N: {serial}",
"@devicePicker_sn" : {
"@_yubikey_selection": {},
"l_select_to_scan": "Select to scan",
"l_hide_device": "Hide device",
"l_show_hidden_devices": "Show hidden devices",
"l_sn_serial": "S/N: {serial}",
"@l_sn_serial" : {
"placeholders": {
"serial": {}
}
},
"devicePicker_fw": "F/W: {version}",
"@devicePicker_fw" : {
"l_fw_version": "F/W: {version}",
"@l_fw_version" : {
"placeholders": {
"version": {}
}
},
"@_yubikey_interactions": {},
"l_insert_yk": "Insert your YubiKey",
"l_insert_or_tap_yk": "Insert or tap a YubiKey",
"l_unplug_yk": "Unplug your YubiKey",
"l_reinsert_yk": "Reinsert your YubiKey",
"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_remove_yk_from_reader": "Remove your YubiKey from the NFC reader",
"l_try_reinsert_yk": "Try to remove and reinsert your YubiKey.",
"l_touch_required": "Touch Required",
"l_touch_button_now": "Touch your YubiKey now",
"l_touch_button_now": "Touch the button on your YubiKey now",
"l_keep_touching_yk": "Keep touching your YubiKey repeatedly\u2026",
"systray_oath_copied": "Code copied",
"systray_oath_copied_to_clipboard": "{label} copied to clipboard.",
"@systray_oath_copied_to_clipboard" : {
"@_app_configuration": {},
"l_toggle_applications": "Toggle applications",
"l_min_one_interface": "At least one interface must be enabled",
"l_reconfiguring_yk": "Reconfiguring YubiKey\u2026",
"l_config_updated": "Configuration updated",
"l_config_updated_reinsert": "Configuration updated, remove and reinsert your YubiKey",
"l_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" : {
"placeholders": {
"app": {}
}
},
"l_app_not_supported_desc": "This application is not supported",
"l_app_disabled": "Application disabled",
"l_app_disabled_desc": "Enable the '{app}' application on your YubiKey to access",
"@l_app_disabled_desc" : {
"placeholders": {
"app": {}
}
},
"l_fido_disabled": "FIDO2 disabled",
"l_webauthn_req_fido2": "WebAuthn requires the FIDO2 application to be enabled on your YubiKey",
"@_connectivity_issues": {},
"l_helper_not_responding": "The Helper process isn't responding",
"l_yk_no_access": "This YubiKey cannot be accessed",
"l_yk_inaccessible": "Device inaccessible",
"l_open_connection_failed": "Failed to open connection",
"l_ccid_connection_failed": "Failed to open smart card connection",
"p_ccid_service_unavailable": "Make sure your smart card service is functioning.",
"p_pcscd_unavailable": "Make sure pcscd is installed and running.",
"l_no_yk_present": "No YubiKey present",
"l_unknown_type": "Unknown type",
"l_unknown_device": "Unrecognized device",
"l_unsupported_yk": "Unsupported YubiKey",
"l_yk_not_recognized": "Device not recognized",
"l_error_occured": "An error has occured",
"l_application_error": "Application error",
"@_pins": {},
"w_pin": "PIN",
"l_set_pin": "Set PIN",
"l_change_pin": "Change PIN",
"l_current_pin": "Current PIN",
"l_new_pin": "New PIN",
"l_confirm_pin": "Confirm PIN",
"l_new_pin_len": "New PIN must be at least {length} characters",
"@l_new_pin_len" : {
"placeholders": {
"length": {}
}
},
"l_pin_set": "PIN set",
"l_set_pin_failed": "Failed to set PIN",
"l_wrong_pin_attempts_remaining": "Wrong PIN. {retries} attempt(s) remaining.",
"@l_wrong_pin_attempts_remaining" : {
"placeholders": {
"retries": {}
}
},
"l_fido_pin_protection": "FIDO PIN protection",
"l_fido_pin_protection_optional": "Optional FIDO PIN protection",
"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_pin_blocked_reset": "PIN is blocked. Factory reset the FIDO application.",
"l_set_pin_first": "A PIN is required first",
"l_unlock_pin_first": "Unlock with PIN first",
"l_pin_soft_locked": "PIN has been blocked until the YubiKey is removed and reinserted",
"p_enter_current_pin_or_reset": "Enter your current PIN. If you don't know your PIN, you'll need to reset the YubiKey.",
"p_enter_new_fido2_pin": "Enter your new PIN. A PIN must be at least {length} characters long and may contain letters, numbers and special characters.",
"@p_enter_new_fido2_pin" : {
"placeholders": {
"length": {}
}
},
"@_passwords": {},
"w_password": "Password",
"l_manage_password": "Manage password",
"l_set_password": "Set password",
"l_password_set": "Password set",
"l_optional_password_protection": "Optional password protection",
"l_new_password": "New password",
"l_current_password": "Current password",
"l_confirm_password": "Confirm password",
"l_wrong_password": "Wrong password",
"l_remove_password": "Remove password",
"l_password_removed": "Password removed",
"l_remember_password": "Remember password",
"l_clear_saved_password": "Clear saved password",
"l_password_forgotten": "Password forgotten",
"l_keystore_unavailable": "OS Keystore unavailable",
"l_remember_pw_failed": "Failed to remember password",
"l_unlock_first": "Unlock with password first",
"l_enter_oath_pw": "Enter the OATH password for your YubiKey",
"p_enter_current_password_or_reset": "Enter your current password. If you don't know your password, you'll need to reset the YubiKey.",
"p_enter_new_password": "Enter your new password. A password may contain letters, numbers and special characters.",
"@_oath_accounts": {},
"w_account": "Account",
"w_accounts": "Accounts",
"l_no_accounts": "No accounts",
"l_add_account": "Add account",
"l_account_added": "Account added",
"l_account_add_failed": "Failed adding account",
"l_account_name_required": "Your account must have a name",
"l_name_already_exists": "This name already exists for the Issuer",
"l_invalid_character_issuer": "Invalid character: ':' is not allowed in issuer",
"w_pinned": "Pinned",
"l_pin_account": "Pin account",
"l_unpin_account": "Unpin account",
"l_no_pinned_accounts": "No pinned accounts",
"l_rename_account": "Rename account",
"l_account_renamed": "Account renamed",
"p_rename_will_change_account_displayed": "This will change how the account is displayed in the list.",
"l_delete_account": "Delete account",
"l_account_deleted": "Account deleted",
"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.",
"l_account_name": "Account name",
"l_search_accounts": "Search accounts",
"l_accounts_used": "{used} of {capacity} accounts used",
"@l_accounts_used" : {
"placeholders": {
"used": {},
"capacity": {}
}
},
"l_num_digits": "{num} digits",
"@l_num_digits" : {
"placeholders": {
"num": {}
}
},
"l_num_sec": "{num} sec",
"@l_num_sec" : {
"placeholders": {
"num": {}
}
},
"l_duplicate_name": "This name already exists for the Issuer",
"l_issuer_optional": "Issuer (optional)",
"@_fido_credentials": {},
"w_credential": "Credential",
"w_credentials": "Credentials",
"l_ready_to_use": "Ready to use",
"l_register_sk_on_websites": "Register as a Security Key on websites",
"l_no_discoverable_accounts": "No discoverable accounts",
"l_delete_credential": "Delete credential",
"l_credential_deleted": "Credential deleted",
"p_warning_delete_credential": "This will delete the credential from your YubiKey.",
"@_fingerprints": {},
"w_fingerprint": "Fingerprint",
"w_fingerprints": "Fingerprints",
"l_fingerprint_captured": "Fingerprint captured successfully!",
"l_fingerprint_added": "Fingerprint added",
"l_setting_name_failed": "Error setting name",
"l_add_fingerprint": "Add fingerprint",
"l_fp_step_1_capture": "Step 1/2: Capture fingerprint",
"l_fp_step_2_name": "Step 2/2: Name fingerprint",
"l_delete_fingerprint": "Delete fingerprint",
"l_fingerprint_deleted": "Fingerprint deleted",
"l_warning_delete_fingerprint": "This will delete the fingerprint from your YubiKey.",
"l_no_fingerprints": "No fingerprints",
"l_set_pin_fingerprints": "Set a PIN to register fingerprints",
"l_no_fps_added": "No fingerprints have been added",
"l_fingerprint_renamed": "Fingerprint renamed",
"l_rename_fp_failed": "Error renaming",
"l_rename_fp": "Rename fingerprint",
"l_add_one_or_more_fps": "Add one or more (up to five) fingerprints",
"l_fingerprints_used": "{used}/5 fingerprints registered",
"@l_fingerprints_used": {
"placeholders": {
"used": {}
}
},
"p_press_fingerprint_begin": "Press your finger against the YubiKey to begin.",
"p_will_change_label_fp": "This will change the label of the fingerprint.",
"@_permissions": {},
"l_enable_nfc": "Enable NFC",
"l_permission_denied": "Permission denied",
"l_elevating_permissions": "Elevating permissions\u2026",
"l_review_permissions": "Review permissions",
"p_elevated_permissions_required": "Managing this device 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.",
"@_qr_codes": {},
"l_qr_scan": "Scan QR code",
"l_qr_scanned": "Scanned QR code",
"l_invalid_qr": "Invalid QR code",
"l_qr_not_found": "No QR code found",
"l_qr_not_read": "Failed reading QR code",
"l_point_camera_scan": "Point your camera at a QR code to scan it",
"q_want_to_scan": "Would like to scan?",
"q_no_qr": "No QR code?",
"l_enter_manually": "Enter manually",
"@_factory_reset": {},
"w_reset": "Reset",
"l_factory_reset": "Factory reset",
"l_factory_reset_this_app": "Factory reset this application",
"l_reset_oath": "Reset OATH",
"l_oath_application_reset": "OATH application reset",
"l_reset_fido": "Reset FIDO",
"l_fido_app_reset": "FIDO application reset",
"l_press_reset_to_begin": "Press reset to begin\u2026",
"l_reset_failed": "Error performing reset",
"p_warning_factory_reset": "Warning! This will irrevocably delete all OATH TOTP/HOTP accounts from your YubiKey.",
"p_warning_disable_credentials": "Your OATH credentials, as well as any password set, will be removed from this YubiKey. Make sure to first disable these from their respective web sites to avoid being locked out of your accounts.",
"p_warning_deletes_accounts": "Warning! This will irrevocably delete all U2F and FIDO2 accounts from your YubiKey.",
"p_warning_disable_accounts": "Your credentials, as well as any PIN set, will be removed from this YubiKey. Make sure to first disable these from their respective web sites to avoid being locked out of your accounts.",
"@_copy_to_clipboard": {},
"l_copy_to_clipboard": "Copy to clipboard",
"l_code_copied": "Code copied",
"l_code_copied_clipboard": "Code copied to clipboard",
"l_copy_log": "Copy log",
"l_log_copied": "Log copied to clipboard",
"l_diagnostics_copied": "Diagnostic data copied to clipboard",
"p_target_copied_clipboard": "{label} copied to clipboard.",
"@p_target_copied_clipboard" : {
"placeholders": {
"label": {}
}
},
"systray_no_pinned": "No pinned accounts",
"androidSettings_launch_app": "Launch Yubico Authenticator",
"androidSettings_copy_otp": "Copy OTP to clipboard",
"androidSettings_launch_and_copy": "Launch app and copy OTP",
"androidSettings_nfc_options": "NFC options",
"androidSettings_nfc_on_tap": "On YubiKey NFC tap",
"androidSettings_keyboard_layout": "Keyboard layout (for static password)",
"androidSettings_choose_keyboard_layout": "Choose keyboard layout",
"androidSettings_bypass_touch": "Bypass touch requirement",
"androidSettings_bypass_touch_on": "Accounts that require touch are automatically shown over NFC",
"androidSettings_bypass_touch_off": "Accounts that require touch need an additional tap over NFC",
"androidSettings_silence_nfc": "Silence NFC sounds",
"androidSettings_silence_nfc_on": "No sounds will be played on NFC tap",
"androidSettings_silence_nfc_off": "Sound will play on NFC tap",
"androidSettings_usb_options": "USB options",
"androidSettings_usb_launch": "Launch when YubiKey is connected",
"androidSettings_usb_launch_on": "This prevents other apps from using the YubiKey over USB",
"androidSettings_usb_launch_off": "Other apps can use the YubiKey over USB",
"androidSettings_app_theme": "App theme",
"androidSettings_choose_app_theme": "Choose app theme",
"@_android_settings": {},
"l_nfc_options": "NFC options",
"l_on_yk_nfc_tap": "On YubiKey NFC tap",
"l_launch_ya": "Launch Yubico Authenticator",
"l_copy_otp_clipboard": "Copy OTP to clipboard",
"l_launch_and_copy_otp": "Launch app and copy OTP",
"l_kbd_layout_for_static": "Keyboard layout (for static password)",
"l_choose_kbd_layout": "Choose keyboard layout",
"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_off": "Accounts that require touch need an additional tap over NFC",
"l_silence_nfc_sounds": "Silence NFC sounds",
"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_usb_options": "USB options",
"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_off": "Other apps can use the YubiKey over USB",
"l_allow_screenshots": "Allow screenshots",
"androidQrScanner_point_and_scan": "Point your camera at a QR code to scan it",
"androidQrScanner_invalid_code": "Invalid QR code",
"androidQrScanner_no_code": "No QR code?",
"androidQrScanner_enter_manually": "Enter manually",
"androidQrScanner_need_camera_permission": "Yubico Authenticator needs Camera permissions for scanning QR codes.",
"androidQrScanner_have_account_info": "Have account info?",
"androidQrScanner_want_to_scan": "Would like to scan?",
"androidQrScanner_review_permissions": "Review permissions",
"@_EOF": {}
"@_eof": {}
}

View File

@ -87,7 +87,7 @@ class _ModeForm extends StatelessWidget {
),
),
Text(interfaces == 0
? AppLocalizations.of(context)!.mgmt_min_one_interface
? AppLocalizations.of(context)!.l_min_one_interface
: ''),
]);
}
@ -115,7 +115,7 @@ class _CapabilitiesForm extends StatelessWidget {
if (usbCapabilities != 0) ...[
ListTile(
leading: const Icon(Icons.usb),
title: Text(AppLocalizations.of(context)!.general_usb),
title: Text(AppLocalizations.of(context)!.w_usb),
contentPadding: const EdgeInsets.only(bottom: 8),
horizontalTitleGap: 0,
),
@ -136,7 +136,7 @@ class _CapabilitiesForm extends StatelessWidget {
),
ListTile(
leading: nfcIcon,
title: Text(AppLocalizations.of(context)!.general_nfc),
title: Text(AppLocalizations.of(context)!.w_nfc),
contentPadding: const EdgeInsets.only(bottom: 8),
horizontalTitleGap: 0,
),
@ -210,7 +210,7 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
// This will take longer, show a message
close = showMessage(
context,
AppLocalizations.of(context)!.mgmt_reconfiguring_yubikey,
AppLocalizations.of(context)!.l_reconfiguring_yk,
duration: const Duration(seconds: 8),
);
}
@ -223,8 +223,7 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
);
if (!mounted) return;
if (!reboot) Navigator.pop(context);
showMessage(
context, AppLocalizations.of(context)!.mgmt_configuration_updated);
showMessage(context, AppLocalizations.of(context)!.l_config_updated);
} finally {
close?.call();
}
@ -248,10 +247,9 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
showMessage(
context,
widget.deviceData.node.maybeMap(
nfcReader: (_) =>
AppLocalizations.of(context)!.mgmt_configuration_updated,
orElse: () => AppLocalizations.of(context)!
.mgmt_configuration_updated_remove_reinsert));
nfcReader: (_) => AppLocalizations.of(context)!.l_config_updated,
orElse: () =>
AppLocalizations.of(context)!.l_config_updated_reinsert));
Navigator.pop(context);
}
@ -317,12 +315,12 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
);
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.mgmt_toggle_applications),
title: Text(AppLocalizations.of(context)!.l_toggle_applications),
actions: [
TextButton(
onPressed: canSave ? _submitForm : null,
key: management_keys.saveButtonKey,
child: Text(AppLocalizations.of(context)!.mgmt_save),
child: Text(AppLocalizations.of(context)!.w_save),
),
],
child: child,

View File

@ -18,7 +18,7 @@ import 'package:flutter/material.dart';
const _prefix = 'oath.keys';
const setOrManagePasswordAction = Key('$_prefix.set_or_manage_oath_password');
const setOrManagePasswordAction = Key('$_prefix.set_or_manage_w_password');
const addAccountAction = Key('$_prefix.add_account');
const resetAction = Key('$_prefix.reset');

View File

@ -45,9 +45,8 @@ class AccountDialog extends ConsumerWidget {
ButtonTheme.of(context).colorScheme ?? Theme.of(context).colorScheme;
final copy =
actions.firstWhere(((e) => e.text == l10n.oath_copy_to_clipboard));
final delete =
actions.firstWhere(((e) => e.text == l10n.oath_delete_account));
actions.firstWhere(((e) => e.text == l10n.l_copy_to_clipboard));
final delete = actions.firstWhere(((e) => e.text == l10n.l_delete_account));
final colors = {
copy: Pair(theme.primary, theme.onPrimary),
delete: Pair(theme.error, theme.onError),
@ -55,7 +54,7 @@ class AccountDialog extends ConsumerWidget {
// If we can't copy, but can calculate, highlight that button instead
if (copy.intent == null) {
final calculates = actions.where(((e) => e.text == l10n.oath_calculate));
final calculates = actions.where(((e) => e.text == l10n.w_calculate));
if (calculates.isNotEmpty) {
colors[calculates.first] = Pair(theme.primary, theme.onPrimary);
}

View File

@ -66,19 +66,19 @@ class AccountHelper {
final shortcut = Platform.isMacOS ? '\u2318 C' : 'Ctrl+C';
return [
MenuAction(
text: l10n.oath_copy_to_clipboard,
text: l10n.l_copy_to_clipboard,
icon: const Icon(Icons.copy),
intent: code == null || expired ? null : const CopyIntent(),
trailing: shortcut,
),
if (manual)
MenuAction(
text: l10n.oath_calculate,
text: l10n.w_calculate,
icon: const Icon(Icons.refresh),
intent: ready ? const CalculateIntent() : null,
),
MenuAction(
text: pinned ? l10n.oath_unpin_account : l10n.oath_pin_account,
text: pinned ? l10n.l_unpin_account : l10n.l_pin_account,
icon: pinned
? pushPinStrokeIcon
: const Icon(Icons.push_pin_outlined),
@ -87,11 +87,11 @@ class AccountHelper {
if (data.info.version.isAtLeast(5, 3))
MenuAction(
icon: const Icon(Icons.edit_outlined),
text: l10n.oath_rename_account,
text: l10n.l_rename_account,
intent: const EditIntent(),
),
MenuAction(
text: l10n.oath_delete_account,
text: l10n.l_delete_account,
icon: const Icon(Icons.delete_outline),
intent: const DeleteIntent(),
),

View File

@ -33,7 +33,7 @@ class AccountList extends ConsumerWidget {
final favorites = ref.watch(favoritesProvider);
if (credentials.isEmpty) {
return Center(
child: Text(AppLocalizations.of(context)!.oath_no_credentials),
child: Text(AppLocalizations.of(context)!.l_no_accounts),
);
}
@ -47,14 +47,14 @@ class AccountList extends ConsumerWidget {
child: Column(
children: [
if (pinnedCreds.isNotEmpty)
ListTitle(AppLocalizations.of(context)!.oath_pinned),
ListTitle(AppLocalizations.of(context)!.w_pinned),
...pinnedCreds.map(
(entry) => AccountView(
entry.credential,
),
),
if (creds.isNotEmpty)
ListTitle(AppLocalizations.of(context)!.oath_accounts),
ListTitle(AppLocalizations.of(context)!.w_accounts),
...creds.map(
(entry) => AccountView(
entry.credential,

View File

@ -53,7 +53,7 @@ Widget registerOathActions(
if (!clipboard.platformGivesFeedback()) {
await ref.read(withContextProvider)((context) async {
showMessage(context,
AppLocalizations.of(context)!.oath_copied_to_clipboard);
AppLocalizations.of(context)!.l_code_copied_clipboard);
});
}
}

View File

@ -126,7 +126,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
final otpauth = await qrScanner.scanQr();
if (otpauth == null) {
if (!mounted) return;
showMessage(context, l10n.oath_no_qr_code);
showMessage(context, l10n.l_qr_not_found);
setState(() {
_qrState = _QrScanState.failed;
});
@ -146,7 +146,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
if (e is! CancellationException) {
showMessage(
context,
'${l10n.oath_failed_reading_qr}: $errorMessage',
'${l10n.l_qr_not_read}: $errorMessage',
duration: const Duration(seconds: 4),
);
}
@ -188,7 +188,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
}
if (!mounted) return;
Navigator.of(context).pop();
showMessage(context, l10n.oath_success_add_account);
showMessage(context, l10n.l_account_added);
} on CancellationException catch (_) {
// ignored
} catch (e) {
@ -204,7 +204,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
}
showMessage(
context,
'${l10n.oath_fail_add_account}: $errorMessage',
'${l10n.l_account_add_failed}: $errorMessage',
duration: const Duration(seconds: 4),
);
}
@ -235,7 +235,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
}
final otpauthUri = _otpauthUri;
_promptController?.updateContent(title: l10n.devicePicker_insert_yubikey);
_promptController?.updateContent(title: l10n.l_insert_yk);
if (otpauthUri != null && deviceNode != null) {
final deviceData = ref.watch(currentDeviceDataProvider);
deviceData.when(data: (data) {
@ -244,7 +244,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
0) !=
0) {
if (oathState == null) {
_promptController?.updateContent(title: l10n.general_please_wait);
_promptController?.updateContent(title: l10n.l_please_wait);
} else if (oathState.locked) {
_promptController?.close();
} else {
@ -256,14 +256,12 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
));
}
} else {
_promptController?.updateContent(
title: l10n.general_unsupported_yubikey);
_promptController?.updateContent(title: l10n.l_unsupported_yk);
}
}, error: (error, _) {
_promptController?.updateContent(
title: l10n.general_unsupported_yubikey);
_promptController?.updateContent(title: l10n.l_unsupported_yk);
}, loading: () {
_promptController?.updateContent(title: l10n.general_please_wait);
_promptController?.updateContent(title: l10n.l_please_wait);
});
}
@ -344,8 +342,8 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
_otpauthUri = cred.toUri();
_promptController = promptUserInteraction(
context,
title: l10n.devicePicker_insert_yubikey,
description: l10n.oath_add_account,
title: l10n.l_insert_yk,
description: l10n.l_add_account,
icon: const Icon(Icons.usb),
onCancel: () {
_otpauthUri = null;
@ -360,11 +358,11 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
}
return ResponsiveDialog(
title: Text(l10n.oath_add_account),
title: Text(l10n.l_add_account),
actions: [
TextButton(
onPressed: isValid ? submit : null,
child: Text(l10n.oath_save, key: keys.saveButton),
child: Text(l10n.w_save, key: keys.saveButton),
),
],
child: FileDropTarget(
@ -374,7 +372,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
final otpauth = await qrScanner.scanQr(b64Image);
if (otpauth == null) {
if (!mounted) return;
showMessage(context, l10n.oath_no_qr_code);
showMessage(context, l10n.l_qr_not_found);
} else {
final data = CredentialData.fromUri(Uri.parse(otpauth));
_loadCredentialData(data);
@ -404,7 +402,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
buildCounter: buildByteCounterFor(issuerText),
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: l10n.oath_issuer_optional,
labelText: l10n.l_issuer_optional,
helperText:
'', // Prevents dialog resizing when disabled
prefixIcon: const Icon(Icons.business_outlined),
@ -412,7 +410,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
? '' // needs empty string to render as error
: issuerNoColon
? null
: l10n.oath_invalid_character_issuer,
: l10n.l_invalid_character_issuer,
),
textInputAction: TextInputAction.next,
onChanged: (value) {
@ -433,14 +431,14 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
decoration: InputDecoration(
border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.person_outline),
labelText: l10n.oath_account_name,
labelText: l10n.l_account_name,
helperText:
'', // Prevents dialog resizing when disabled
errorText: (byteLength(nameText) > nameMaxLength)
? '' // needs empty string to render as error
: isUnique
? null
: l10n.oath_duplicate_name,
: l10n.l_duplicate_name,
),
textInputAction: TextInputAction.next,
onChanged: (value) {
@ -476,9 +474,9 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
),
border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.key_outlined),
labelText: l10n.oath_secret_key,
labelText: l10n.l_secret_key,
errorText: _validateSecretLength && !secretLengthValid
? l10n.oath_invalid_length
? l10n.l_invalid_length
: null),
readOnly: _qrState == _QrScanState.success,
textInputAction: TextInputAction.done,
@ -503,8 +501,8 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
: const CircularProgressIndicator(
strokeWidth: 2.0),
label: _qrState == _QrScanState.success
? Text(l10n.oath_scanned_qr)
: Text(l10n.oath_scan_qr),
? Text(l10n.l_qr_scanned)
: Text(l10n.l_qr_scan),
onPressed: () {
_scanQrCode(qrScanner);
}),
@ -517,7 +515,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
children: [
if (oathState?.version.isAtLeast(4, 2) ?? true)
FilterChip(
label: Text(l10n.oath_require_touch),
label: Text(l10n.l_require_touch),
selected: _touch,
onSelected: (value) {
setState(() {
@ -559,7 +557,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
selected: int.tryParse(_periodController.text) !=
defaultPeriod,
itemBuilder: ((value) =>
Text('$value ${l10n.oath_sec}')),
Text(l10n.l_num_sec(value))),
onChanged: _qrState != _QrScanState.success
? (period) {
setState(() {
@ -573,7 +571,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
value: _digits,
selected: _digits != defaultDigits,
itemBuilder: (value) =>
Text('$value ${l10n.oath_digits}'),
Text(l10n.l_num_digits(value)),
onChanged: _qrState != _QrScanState.success
? (digits) {
setState(() {

View File

@ -36,7 +36,7 @@ class DeleteAccountDialog extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.oath_delete_account),
title: Text(AppLocalizations.of(context)!.l_delete_account),
actions: [
TextButton(
key: keys.deleteButton,
@ -49,16 +49,14 @@ class DeleteAccountDialog extends ConsumerWidget {
(context) async {
Navigator.of(context).pop(true);
showMessage(
context,
AppLocalizations.of(context)!
.oath_success_delete_account);
context, AppLocalizations.of(context)!.l_account_deleted);
},
);
} on CancellationException catch (_) {
// ignored
}
},
child: Text(AppLocalizations.of(context)!.oath_delete),
child: Text(AppLocalizations.of(context)!.w_delete),
),
],
child: Padding(
@ -66,14 +64,13 @@ class DeleteAccountDialog extends ConsumerWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(AppLocalizations.of(context)!
.oath_warning_this_will_delete_account_from_key),
Text(AppLocalizations.of(context)!.p_warning_delete_account),
Text(
AppLocalizations.of(context)!.oath_warning_disable_this_cred,
AppLocalizations.of(context)!.p_warning_disable_credential,
style: Theme.of(context).textTheme.bodyLarge,
),
Text(
'${AppLocalizations.of(context)!.oath_account} ${getTextName(credential)}'),
'${AppLocalizations.of(context)!.w_account} ${getTextName(credential)}'),
]
.map((e) => Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),

View File

@ -44,18 +44,17 @@ Widget oathBuildActions(
final theme = Theme.of(context).colorScheme;
return SimpleDialog(
children: [
ListTitle(AppLocalizations.of(context)!.general_setup,
ListTitle(AppLocalizations.of(context)!.w_setup,
textStyle: Theme.of(context).textTheme.bodyLarge),
ListTile(
title: Text(AppLocalizations.of(context)!.oath_add_account),
title: Text(AppLocalizations.of(context)!.l_add_account),
key: keys.addAccountAction,
leading:
const CircleAvatar(child: Icon(Icons.person_add_alt_1_outlined)),
subtitle: Text(used == null
? AppLocalizations.of(context)!.oath_unlock_first
? AppLocalizations.of(context)!.l_unlock_first
: (capacity != null
? AppLocalizations.of(context)!
.oath_accounts_used(used, capacity)
? AppLocalizations.of(context)!.l_accounts_used(used, capacity)
: '')),
enabled: used != null && (capacity == null || capacity > used),
onTap: used != null && (capacity == null || capacity > used)
@ -90,7 +89,7 @@ Widget oathBuildActions(
}
: null,
),
ListTitle(AppLocalizations.of(context)!.general_manage,
ListTitle(AppLocalizations.of(context)!.w_manage,
textStyle: Theme.of(context).textTheme.bodyLarge),
ListTile(
key: keys.customIconsAction,
@ -111,10 +110,10 @@ Widget oathBuildActions(
ListTile(
key: keys.setOrManagePasswordAction,
title: Text(oathState.hasKey
? AppLocalizations.of(context)!.oath_manage_password
: AppLocalizations.of(context)!.oath_set_password),
subtitle:
Text(AppLocalizations.of(context)!.oath_password_description),
? AppLocalizations.of(context)!.l_manage_password
: AppLocalizations.of(context)!.l_set_password),
subtitle: Text(
AppLocalizations.of(context)!.l_optional_password_protection),
leading: const CircleAvatar(child: Icon(Icons.password_outlined)),
onTap: () {
Navigator.of(context).pop();
@ -125,9 +124,9 @@ Widget oathBuildActions(
}),
ListTile(
key: keys.resetAction,
title: Text(AppLocalizations.of(context)!.oath_reset_oath),
subtitle: Text(
AppLocalizations.of(context)!.oath_factory_reset_description),
title: Text(AppLocalizations.of(context)!.l_reset_oath),
subtitle:
Text(AppLocalizations.of(context)!.l_factory_reset_this_app),
leading: CircleAvatar(
foregroundColor: theme.onError,
backgroundColor: theme.error,

View File

@ -48,7 +48,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
if (result) {
if (!mounted) return;
Navigator.of(context).pop();
showMessage(context, AppLocalizations.of(context)!.oath_password_set);
showMessage(context, AppLocalizations.of(context)!.l_password_set);
} else {
setState(() {
_currentIsWrong = true;
@ -63,12 +63,12 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
(!widget.state.hasKey || _currentPassword.isNotEmpty);
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.oath_manage_password),
title: Text(AppLocalizations.of(context)!.l_manage_password),
actions: [
TextButton(
onPressed: isValid ? _submit : null,
key: keys.savePasswordButton,
child: Text(AppLocalizations.of(context)!.oath_save),
child: Text(AppLocalizations.of(context)!.w_save),
)
],
child: Padding(
@ -77,18 +77,18 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.state.hasKey) ...[
Text(AppLocalizations.of(context)!.oath_enter_current_password),
Text(AppLocalizations.of(context)!
.p_enter_current_password_or_reset),
TextField(
autofocus: true,
obscureText: true,
key: keys.currentPasswordField,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText:
AppLocalizations.of(context)!.oath_current_password,
labelText: AppLocalizations.of(context)!.l_current_password,
prefixIcon: const Icon(Icons.password_outlined),
errorText: _currentIsWrong
? AppLocalizations.of(context)!.oath_wrong_password
? AppLocalizations.of(context)!.l_wrong_password
: null,
errorMaxLines: 3),
textInputAction: TextInputAction.next,
@ -116,7 +116,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
showMessage(
context,
AppLocalizations.of(context)!
.oath_password_removed);
.l_password_removed);
} else {
setState(() {
_currentIsWrong = true;
@ -124,36 +124,34 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
}
}
: null,
child: Text(
AppLocalizations.of(context)!.oath_remove_password),
child:
Text(AppLocalizations.of(context)!.l_remove_password),
),
if (widget.state.remembered)
OutlinedButton(
child: Text(AppLocalizations.of(context)!
.oath_clear_saved_password),
child: Text(
AppLocalizations.of(context)!.l_clear_saved_password),
onPressed: () async {
await ref
.read(oathStateProvider(widget.path).notifier)
.forgetPassword();
if (!mounted) return;
Navigator.of(context).pop();
showMessage(
context,
AppLocalizations.of(context)!
.oath_password_forgotten);
showMessage(context,
AppLocalizations.of(context)!.l_password_forgotten);
},
),
],
),
],
Text(AppLocalizations.of(context)!.oath_enter_new_password),
Text(AppLocalizations.of(context)!.p_enter_new_password),
TextField(
key: keys.newPasswordField,
autofocus: !widget.state.hasKey,
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.oath_new_password,
labelText: AppLocalizations.of(context)!.l_new_password,
prefixIcon: const Icon(Icons.password_outlined),
enabled: !widget.state.hasKey || _currentPassword.isNotEmpty,
),
@ -174,7 +172,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.oath_confirm_password,
labelText: AppLocalizations.of(context)!.l_confirm_password,
prefixIcon: const Icon(Icons.password_outlined),
enabled:
(!widget.state.hasKey || _currentPassword.isNotEmpty) &&

View File

@ -41,12 +41,12 @@ class OathScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
return ref.watch(oathStateProvider(devicePath)).when(
loading: () => MessagePage(
title: Text(AppLocalizations.of(context)!.oath_authenticator),
title: Text(AppLocalizations.of(context)!.w_authenticator),
graphic: const CircularProgressIndicator(),
delayedContent: true,
),
error: (error, _) => AppFailurePage(
title: Text(AppLocalizations.of(context)!.oath_authenticator),
title: Text(AppLocalizations.of(context)!.w_authenticator),
cause: error,
),
data: (oathState) => oathState.locked
@ -65,7 +65,7 @@ class _LockedView extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return AppPage(
title: Text(AppLocalizations.of(context)!.oath_authenticator),
title: Text(AppLocalizations.of(context)!.w_authenticator),
keyActionsBuilder: (context) =>
oathBuildActions(context, devicePath, oathState, ref),
child: Padding(
@ -114,10 +114,10 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
.select((value) => value?.length));
if (numCreds == 0) {
return MessagePage(
title: Text(AppLocalizations.of(context)!.oath_authenticator),
title: Text(AppLocalizations.of(context)!.w_authenticator),
key: keys.noAccountsView,
graphic: noAccounts,
header: AppLocalizations.of(context)!.oath_no_accounts,
header: AppLocalizations.of(context)!.l_no_accounts,
keyActionsBuilder: (context) => oathBuildActions(
context, widget.devicePath, widget.oathState, ref,
used: 0),
@ -152,7 +152,7 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
style: textTheme.titleMedium
?.copyWith(fontSize: textTheme.titleSmall?.fontSize),
decoration: InputDecoration(
hintText: AppLocalizations.of(context)!.oath_search_accounts,
hintText: AppLocalizations.of(context)!.l_search_accounts,
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(32)),
),

View File

@ -72,7 +72,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
if (!mounted) return;
Navigator.of(context).pop(renamed);
showMessage(context, AppLocalizations.of(context)!.oath_account_renamed);
showMessage(context, AppLocalizations.of(context)!.l_account_renamed);
} on CancellationException catch (_) {
// ignored
} catch (e) {
@ -86,7 +86,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
}
showMessage(
context,
'${AppLocalizations.of(context)!.oath_fail_add_account}: $errorMessage',
'${AppLocalizations.of(context)!.l_account_add_failed}: $errorMessage',
duration: const Duration(seconds: 4),
);
}
@ -125,12 +125,12 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
final isValid = isUnique && isValidFormat;
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.oath_rename_account),
title: Text(AppLocalizations.of(context)!.l_rename_account),
actions: [
TextButton(
onPressed: didChange && isValid ? _submit : null,
key: keys.saveButton,
child: Text(AppLocalizations.of(context)!.oath_save),
child: Text(AppLocalizations.of(context)!.w_save),
),
],
child: Padding(
@ -139,9 +139,9 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(AppLocalizations.of(context)!
.oath_rename(getTextName(credential))),
.q_rename_target(getTextName(credential))),
Text(AppLocalizations.of(context)!
.oath_warning_will_change_account_displayed),
.p_rename_will_change_account_displayed),
TextFormField(
initialValue: _issuer,
enabled: issuerRemaining > 0,
@ -151,7 +151,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
key: keys.issuerField,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.oath_issuer_optional,
labelText: AppLocalizations.of(context)!.l_issuer_optional,
helperText: '', // Prevents dialog resizing when disabled
prefixIcon: const Icon(Icons.business_outlined),
),
@ -170,12 +170,12 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
key: keys.nameField,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.oath_account_name,
labelText: AppLocalizations.of(context)!.l_account_name,
helperText: '', // Prevents dialog resizing when disabled
errorText: !isValidFormat
? AppLocalizations.of(context)!.oath_account_must_have_name
? AppLocalizations.of(context)!.l_account_name_required
: !isUnique
? AppLocalizations.of(context)!.oath_name_exists
? AppLocalizations.of(context)!.l_name_already_exists
: null,
prefixIcon: const Icon(Icons.people_alt_outlined),
),

View File

@ -30,19 +30,19 @@ class ResetDialog extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final l10n = AppLocalizations.of(context)!;
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.oath_factory_reset),
title: Text(l10n.l_factory_reset),
actions: [
TextButton(
onPressed: () async {
await ref.read(oathStateProvider(devicePath).notifier).reset();
await ref.read(withContextProvider)((context) async {
Navigator.of(context).pop();
showMessage(context,
AppLocalizations.of(context)!.oath_oath_application_reset);
showMessage(context, l10n.l_oath_application_reset);
});
},
child: Text(AppLocalizations.of(context)!.oath_reset),
child: Text(l10n.w_reset),
),
],
child: Padding(
@ -50,11 +50,10 @@ class ResetDialog extends ConsumerWidget {
child: Column(
children: [
Text(
AppLocalizations.of(context)!.oath_warning_will_delete_accounts,
l10n.p_warning_factory_reset,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text(
AppLocalizations.of(context)!.oath_warning_disable_these_creds),
Text(l10n.p_warning_disable_credentials),
]
.map((e) => Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),

View File

@ -53,8 +53,7 @@ class _UnlockFormState extends ConsumerState<UnlockForm> {
_passwordController.clear();
});
} else if (_remember && !result.second) {
showMessage(
context, AppLocalizations.of(context)!.oath_failed_remember_pw);
showMessage(context, AppLocalizations.of(context)!.l_remember_pw_failed);
}
}
@ -69,7 +68,7 @@ class _UnlockFormState extends ConsumerState<UnlockForm> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.oath_enter_oath_pw,
AppLocalizations.of(context)!.l_enter_oath_pw,
),
const SizedBox(height: 16.0),
TextField(
@ -79,9 +78,9 @@ class _UnlockFormState extends ConsumerState<UnlockForm> {
obscureText: _isObscure,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: AppLocalizations.of(context)!.oath_password,
labelText: AppLocalizations.of(context)!.w_password,
errorText: _passwordIsWrong
? AppLocalizations.of(context)!.oath_wrong_password
? AppLocalizations.of(context)!.l_wrong_password
: null,
helperText: '', // Prevents resizing when errorText shown
prefixIcon: const Icon(Icons.password_outlined),
@ -108,14 +107,13 @@ class _UnlockFormState extends ConsumerState<UnlockForm> {
keystoreFailed
? ListTile(
leading: const Icon(Icons.warning_amber_rounded),
title: Text(
AppLocalizations.of(context)!.oath_keystore_unavailable),
title:
Text(AppLocalizations.of(context)!.l_keystore_unavailable),
dense: true,
minLeadingWidth: 0,
)
: CheckboxListTile(
title:
Text(AppLocalizations.of(context)!.oath_remember_password),
title: Text(AppLocalizations.of(context)!.l_remember_password),
dense: true,
controlAffinity: ListTileControlAffinity.leading,
value: _remember,
@ -131,7 +129,7 @@ class _UnlockFormState extends ConsumerState<UnlockForm> {
alignment: Alignment.centerRight,
child: ElevatedButton.icon(
key: keys.unlockButton,
label: Text(AppLocalizations.of(context)!.oath_unlock),
label: Text(AppLocalizations.of(context)!.w_unlock),
icon: const Icon(Icons.lock_open),
onPressed: _passwordController.text.isNotEmpty ? _submit : null,
),

View File

@ -35,7 +35,7 @@ class SettingsPage extends ConsumerWidget {
final theme = Theme.of(context);
return ResponsiveDialog(
title: Text(AppLocalizations.of(context)!.general_settings),
title: Text(AppLocalizations.of(context)!.w_settings),
child: Theme(
// Make the headers use the primary color to pop a bit.
// Once M3 is implemented this will probably not be needed.
@ -48,9 +48,9 @@ class SettingsPage extends ConsumerWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTitle(AppLocalizations.of(context)!.general_appearance),
ListTitle(AppLocalizations.of(context)!.w_appearance),
RadioListTile<ThemeMode>(
title: Text(AppLocalizations.of(context)!.general_system_default),
title: Text(AppLocalizations.of(context)!.l_system_default),
value: ThemeMode.system,
groupValue: themeMode,
onChanged: (mode) {
@ -59,7 +59,7 @@ class SettingsPage extends ConsumerWidget {
},
),
RadioListTile<ThemeMode>(
title: Text(AppLocalizations.of(context)!.general_light_mode),
title: Text(AppLocalizations.of(context)!.l_light_mode),
value: ThemeMode.light,
groupValue: themeMode,
onChanged: (mode) {
@ -68,7 +68,7 @@ class SettingsPage extends ConsumerWidget {
},
),
RadioListTile<ThemeMode>(
title: Text(AppLocalizations.of(context)!.general_dark_mode),
title: Text(AppLocalizations.of(context)!.l_dark_mode),
value: ThemeMode.dark,
groupValue: themeMode,
onChanged: (mode) {

View File

@ -61,8 +61,8 @@ class _ResponsiveDialogState extends State<ResponsiveDialog> {
} else {
// Dialog
final cancelText = widget.onCancel == null && widget.actions.isEmpty
? AppLocalizations.of(context)!.widgets_close
: AppLocalizations.of(context)!.widgets_cancel;
? AppLocalizations.of(context)!.w_close
: AppLocalizations.of(context)!.w_cancel;
return AlertDialog(
title: widget.title,
titlePadding: const EdgeInsets.only(top: 24, left: 18, right: 18),

View File

@ -38,7 +38,7 @@ InputCounterWidgetBuilder buildByteCounterFor(String currentValue) =>
return Text(
maxLength != null ? '${byteLength(currentValue)}/$maxLength' : '',
style: style,
semanticsLabel: AppLocalizations.of(context)!.general_character_count,
semanticsLabel: AppLocalizations.of(context)!.l_character_count,
);
};

View File

@ -278,7 +278,7 @@ void main() {
// we expect System theme default
expect((tester.themeModeListTile().subtitle as Text).data,
equals('Light theme'));
equals('Light mode'));
});
testWidgets('Theme preferences update', (WidgetTester tester) async {