From b33dca39002b47b6259a2bd231097112bde0a89d Mon Sep 17 00:00:00 2001 From: Dain Nilsson Date: Thu, 2 Mar 2023 12:45:55 +0100 Subject: [PATCH] Change prefixes and add check_strings.py --- check_strings.py | 110 +++++++ lib/about_page.dart | 24 +- lib/android/oath/state.dart | 2 +- .../qr_scanner_permissions_view.dart | 4 +- .../qr_scanner/qr_scanner_ui_view.dart | 2 +- lib/android/qr_scanner/qr_scanner_view.dart | 2 +- lib/android/views/android_settings_page.dart | 22 +- lib/app/models.dart | 4 +- lib/app/views/app_failure_page.dart | 8 +- lib/app/views/app_page.dart | 2 +- lib/app/views/device_button.dart | 2 +- lib/app/views/device_error_screen.dart | 6 +- lib/app/views/device_picker_dialog.dart | 24 +- lib/app/views/main_drawer.dart | 6 +- lib/app/views/main_page.dart | 12 +- lib/desktop/init.dart | 2 +- lib/desktop/oath/state.dart | 2 +- lib/desktop/systray.dart | 8 +- lib/error_page.dart | 2 +- lib/fido/views/add_fingerprint_dialog.dart | 8 +- lib/fido/views/delete_credential_dialog.dart | 6 +- lib/fido/views/delete_fingerprint_dialog.dart | 6 +- lib/fido/views/fido_screen.dart | 10 +- lib/fido/views/key_actions.dart | 12 +- lib/fido/views/locked_page.dart | 14 +- lib/fido/views/pin_dialog.dart | 12 +- lib/fido/views/rename_fingerprint_dialog.dart | 8 +- lib/fido/views/reset_dialog.dart | 4 +- lib/fido/views/unlocked_page.dart | 14 +- lib/l10n/app_en.arb | 290 +++++++++--------- lib/management/views/management_screen.dart | 14 +- lib/oath/icon_provider/icon_pack_dialog.dart | 12 +- lib/oath/views/account_dialog.dart | 4 +- lib/oath/views/account_helper.dart | 8 +- lib/oath/views/account_list.dart | 6 +- lib/oath/views/add_account_page.dart | 32 +- lib/oath/views/delete_account_dialog.dart | 6 +- lib/oath/views/key_actions.dart | 12 +- lib/oath/views/manage_password_dialog.dart | 22 +- lib/oath/views/oath_screen.dart | 12 +- lib/oath/views/rename_account_dialog.dart | 10 +- lib/oath/views/reset_dialog.dart | 4 +- lib/oath/views/unlock_form.dart | 8 +- lib/settings_page.dart | 12 +- lib/widgets/responsive_dialog.dart | 4 +- lib/widgets/utf8_utils.dart | 2 +- 46 files changed, 456 insertions(+), 340 deletions(-) create mode 100755 check_strings.py diff --git a/check_strings.py b/check_strings.py new file mode 100755 index 00000000..a2ead0b7 --- /dev/null +++ b/check_strings.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2023 Yubico. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import sys +import json + +errors = [] + + +def check_duplicate_keys(pairs): + seen = set() + for d in [k for k, v in pairs if k in seen or seen.add(k)]: + errors.append(f"Duplicate key: {d}") + return dict(pairs) + + +def check_duplicate_values(strings): + seen = {} + for k, v in strings.items(): + if isinstance(v, str): + if v in seen: + errors.append( + f"Duplicate value in key: {k} (originally in {seen[v]}): {v}" + ) + else: + seen[v] = k + + +def check_prefixes(k, v, s_max_words, s_max_len): + errs = [] + if k.startswith("s_"): + if len(v) > s_max_len: + errs.append(f"Too long ({len(v)} chars)") + if len(v.split()) > s_max_words: + errs.append(f"Too many words ({len(v.split())})") + elif k.startswith("l_"): + if v.endswith("."): + errs.append("Ends with '.'") + if ". " in v: + errs.append("Spans multiple sentences") + elif k.startswith("p_"): + if v[-1] not in ".!": + errs.append("Doesn't end in punctuation") + elif k.startswith("q_"): + if not v.endswith("?"): + errs.append("Doesn't end in '?'") + return errs + + +def check_misc(k, v): + errs = [] + if "..." in v: + errs.append("'...' should be replaced with '\\u2026'") + return errs + + +def lint_strings(strings, rules): + for k, v in strings.items(): + errs = [] + errs.extend( + check_prefixes( + k, + v, + rules.get("s_max_words", 4), + rules.get("s_max_len", 32), + ) + ) + errs.extend(check_misc(k, v)) + if errs: + errors.append(f'Errors in {k}: "{v}"') + errors.extend([f" {e}" for e in errs]) + + +if len(sys.argv) != 2: + print("USAGE: check_strings.py ") + sys.exit(1) + + +target = sys.argv[1] +with open(target) as f: + values = json.load(f, object_pairs_hook=check_duplicate_keys) + +strings = {k: v for k, v in values.items() if not k.startswith("@")} + +check_duplicate_values(strings) +lint_strings(strings, strings.get("@_lint_rules", {})) + +print(len(strings), "strings in file") + + +if errors: + for e in errors: + print(e) + sys.exit(1) + +print("OK") diff --git a/lib/about_page.dart b/lib/about_page.dart index da7f3da4..f98ad07d 100755 --- a/lib/about_page.dart +++ b/lib/about_page.dart @@ -42,7 +42,7 @@ class AboutPage extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context)!; return ResponsiveDialog( - title: Text(l10n.w_about), + title: Text(l10n.s_about), child: Padding( padding: const EdgeInsets.symmetric(vertical: 32), child: Column( @@ -63,7 +63,7 @@ class AboutPage extends ConsumerWidget { children: [ TextButton( child: Text( - l10n.l_terms_of_use, + l10n.s_terms_of_use, style: const TextStyle(decoration: TextDecoration.underline), ), @@ -73,7 +73,7 @@ class AboutPage extends ConsumerWidget { ), TextButton( child: Text( - l10n.l_privacy_policy, + l10n.s_privacy_policy, style: const TextStyle(decoration: TextDecoration.underline), ), @@ -85,7 +85,7 @@ class AboutPage extends ConsumerWidget { ), TextButton( child: Text( - l10n.l_open_src_licenses, + l10n.s_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.l_help_and_feedback, + l10n.s_help_and_feedback, style: Theme.of(context).textTheme.titleMedium, ), ), @@ -113,7 +113,7 @@ class AboutPage extends ConsumerWidget { children: [ TextButton( child: Text( - l10n.l_send_feedback, + l10n.s_send_feedback, style: const TextStyle(decoration: TextDecoration.underline), ), @@ -123,7 +123,7 @@ class AboutPage extends ConsumerWidget { ), TextButton( child: Text( - l10n.l_i_need_help, + l10n.s_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.w_troubleshooting, + l10n.s_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.l_run_diagnostics), + label: Text(l10n.s_run_diagnostics), onPressed: () async { _log.info('Running diagnostics...'); final response = await ref @@ -180,7 +180,7 @@ class AboutPage extends ConsumerWidget { if (isAndroid) ...[ const SizedBox(height: 12.0), FilterChip( - label: Text(l10n.l_allow_screenshots), + label: Text(l10n.s_allow_screenshots), selected: ref.watch(androidAllowScreenshotsProvider), onSelected: (value) async { ref @@ -216,7 +216,7 @@ class LoggingPanel extends ConsumerWidget { value: logLevel, items: Levels.LEVELS, selected: logLevel != Level.INFO, - labelBuilder: (value) => Text(l10n.l_log_level( + labelBuilder: (value) => Text(l10n.s_log_level( value.name[0] + value.name.substring(1).toLowerCase())), itemBuilder: (value) => Text('${value.name[0]}${value.name.substring(1).toLowerCase()}'), @@ -227,7 +227,7 @@ class LoggingPanel extends ConsumerWidget { ), ActionChip( avatar: const Icon(Icons.copy), - label: Text(l10n.l_copy_log), + label: Text(l10n.s_copy_log), onPressed: () async { _log.info('Copying log to clipboard ($version)...'); final logs = await ref.read(logLevelProvider.notifier).getLogs(); diff --git a/lib/android/oath/state.dart b/lib/android/oath/state.dart index 9843fb98..cb258a05 100755 --- a/lib/android/oath/state.dart +++ b/lib/android/oath/state.dart @@ -195,7 +195,7 @@ class _AndroidCredentialListNotifier extends OathCredentialListNotifier { return promptUserInteraction( context, icon: const Icon(Icons.touch_app), - title: l10n.l_touch_required, + title: l10n.s_touch_required, description: l10n.l_touch_button_now, ); }, diff --git a/lib/android/qr_scanner/qr_scanner_permissions_view.dart b/lib/android/qr_scanner/qr_scanner_permissions_view.dart index 41e9db87..30bdb050 100644 --- a/lib/android/qr_scanner/qr_scanner_permissions_view.dart +++ b/lib/android/qr_scanner/qr_scanner_permissions_view.dart @@ -75,7 +75,7 @@ class QRScannerPermissionsUI extends StatelessWidget { Navigator.of(context).pop(''); }, child: Text( - l10n.l_enter_manually, + l10n.s_enter_manually, style: const TextStyle(color: Colors.white), )), ], @@ -92,7 +92,7 @@ class QRScannerPermissionsUI extends StatelessWidget { onPermissionRequest(); }, child: Text( - l10n.l_review_permissions, + l10n.s_review_permissions, style: const TextStyle(color: Colors.white), )), ], diff --git a/lib/android/qr_scanner/qr_scanner_ui_view.dart b/lib/android/qr_scanner/qr_scanner_ui_view.dart index 64a12e57..e730b964 100644 --- a/lib/android/qr_scanner/qr_scanner_ui_view.dart +++ b/lib/android/qr_scanner/qr_scanner_ui_view.dart @@ -73,7 +73,7 @@ class QRScannerUI extends StatelessWidget { }, key: keys.manualEntryButton, child: Text( - l10n.l_enter_manually, + l10n.s_enter_manually, style: const TextStyle(color: Colors.white), )), ], diff --git a/lib/android/qr_scanner/qr_scanner_view.dart b/lib/android/qr_scanner/qr_scanner_view.dart index 45c68b16..e60c8dfc 100755 --- a/lib/android/qr_scanner/qr_scanner_view.dart +++ b/lib/android/qr_scanner/qr_scanner_view.dart @@ -114,7 +114,7 @@ class _QrScannerViewState extends State { extendBody: true, appBar: AppBar( title: Text( - l10n.l_add_account, + l10n.s_add_account, style: const TextStyle(color: Colors.white), ), backgroundColor: Colors.transparent, diff --git a/lib/android/views/android_settings_page.dart b/lib/android/views/android_settings_page.dart index 651a22f2..192f20a3 100755 --- a/lib/android/views/android_settings_page.dart +++ b/lib/android/views/android_settings_page.dart @@ -80,11 +80,11 @@ extension on ThemeMode { String getDisplayName(AppLocalizations l10n) { switch (this) { case ThemeMode.system: - return l10n.l_system_default; + return l10n.s_system_default; case ThemeMode.light: - return l10n.l_light_mode; + return l10n.s_light_mode; case ThemeMode.dark: - return l10n.l_dark_mode; + return l10n.s_dark_mode; } } } @@ -114,7 +114,7 @@ class _AndroidSettingsPageState extends ConsumerState { final theme = Theme.of(context); return ResponsiveDialog( - title: Text(l10n.w_settings), + title: Text(l10n.s_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,7 +127,7 @@ class _AndroidSettingsPageState extends ConsumerState { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - ListTitle(l10n.l_nfc_options), + ListTitle(l10n.s_nfc_options), ListTile( title: Text(l10n.l_on_yk_nfc_tap), subtitle: Text(tapAction.getDescription(l10n)), @@ -166,7 +166,7 @@ class _AndroidSettingsPageState extends ConsumerState { }); }), SwitchListTile( - title: Text(l10n.l_silence_nfc_sounds), + title: Text(l10n.s_silence_nfc_sounds), subtitle: Text(nfcSilenceSounds ? l10n.l_silence_nfc_sounds_on : l10n.l_silence_nfc_sounds_off), @@ -177,7 +177,7 @@ class _AndroidSettingsPageState extends ConsumerState { prefs.setBool(prefNfcSilenceSounds, value); }); }), - ListTitle(l10n.l_usb_options), + ListTitle(l10n.s_usb_options), SwitchListTile( title: Text(l10n.l_launch_app_on_usb), subtitle: Text(usbOpenApp @@ -190,9 +190,9 @@ class _AndroidSettingsPageState extends ConsumerState { prefs.setBool(prefUsbOpenApp, value); }); }), - ListTitle(l10n.w_appearance), + ListTitle(l10n.s_appearance), ListTile( - title: Text(l10n.l_app_theme), + title: Text(l10n.s_app_theme), subtitle: Text(themeMode.getDisplayName(l10n)), key: keys.themeModeSetting, onTap: () async { @@ -239,7 +239,7 @@ class _AndroidSettingsPageState extends ConsumerState { builder: (BuildContext context) { final l10n = AppLocalizations.of(context)!; return SimpleDialog( - title: Text(l10n.l_choose_kbd_layout), + title: Text(l10n.s_choose_kbd_layout), children: _keyboardLayouts .map( (e) => RadioListTile( @@ -264,7 +264,7 @@ class _AndroidSettingsPageState extends ConsumerState { builder: (BuildContext context) { final l10n = AppLocalizations.of(context)!; return SimpleDialog( - title: Text(l10n.l_choose_app_theme), + title: Text(l10n.s_choose_app_theme), children: supportedThemes .map((e) => RadioListTile( title: Text(e.getDisplayName(l10n)), diff --git a/lib/app/models.dart b/lib/app/models.dart index b891b5dd..5a128a76 100755 --- a/lib/app/models.dart +++ b/lib/app/models.dart @@ -62,9 +62,9 @@ enum Application { String getDisplayName(AppLocalizations l10n) { switch (this) { case Application.oath: - return l10n.w_authenticator; + return l10n.s_authenticator; case Application.fido: - return l10n.w_webauthn; + return l10n.s_webauthn; default: return name.substring(0, 1).toUpperCase() + name.substring(1); } diff --git a/lib/app/views/app_failure_page.dart b/lib/app/views/app_failure_page.dart index f1f43a9f..a7ea8356 100755 --- a/lib/app/views/app_failure_page.dart +++ b/lib/app/views/app_failure_page.dart @@ -48,7 +48,7 @@ class AppFailurePage extends ConsumerWidget { case 'ccid': header = l10n.l_ccid_connection_failed; if (Platform.isMacOS) { - message = l10n.l_try_reinsert_yk; + message = l10n.p_try_reinsert_yk; } else if (Platform.isLinux) { message = l10n.p_pcscd_unavailable; } else { @@ -63,7 +63,7 @@ class AppFailurePage extends ConsumerWidget { message = l10n.p_webauthn_elevated_permissions_required; actions = [ ElevatedButton.icon( - label: Text(l10n.w_unlock), + label: Text(l10n.s_unlock), icon: const Icon(Icons.lock_open), onPressed: () async { final closeMessage = showMessage( @@ -77,7 +77,7 @@ class AppFailurePage extends ConsumerWidget { (context) async { showMessage( context, - l10n.l_permission_denied, + l10n.s_permission_denied, ); }, ); @@ -92,7 +92,7 @@ class AppFailurePage extends ConsumerWidget { break; default: header = l10n.l_open_connection_failed; - message = l10n.l_try_reinsert_yk; + message = l10n.p_try_reinsert_yk; } } } diff --git a/lib/app/views/app_page.dart b/lib/app/views/app_page.dart index 322149bc..4028ee28 100755 --- a/lib/app/views/app_page.dart +++ b/lib/app/views/app_page.dart @@ -129,7 +129,7 @@ class AppPage extends StatelessWidget { }, icon: const Icon(Icons.tune), iconSize: 24, - tooltip: AppLocalizations.of(context)!.l_configure_yk, + tooltip: AppLocalizations.of(context)!.s_configure_yk, padding: const EdgeInsets.all(12), ), ), diff --git a/lib/app/views/device_button.dart b/lib/app/views/device_button.dart index 2348f49b..c5e74b06 100755 --- a/lib/app/views/device_button.dart +++ b/lib/app/views/device_button.dart @@ -45,7 +45,7 @@ class DeviceButton extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return IconButton( - tooltip: AppLocalizations.of(context)!.l_select_yk, + tooltip: AppLocalizations.of(context)!.s_select_yk, icon: _CircledDeviceAvatar(radius), onPressed: () async { await showBlurDialog( diff --git a/lib/app/views/device_error_screen.dart b/lib/app/views/device_error_screen.dart index 4152c7bf..9a327213 100755 --- a/lib/app/views/device_error_screen.dart +++ b/lib/app/views/device_error_screen.dart @@ -44,7 +44,7 @@ class DeviceErrorScreen extends ConsumerWidget { message: l10n.p_elevated_permissions_required, actions: [ ElevatedButton.icon( - label: Text(l10n.w_unlock), + label: Text(l10n.s_unlock), icon: const Icon(Icons.lock_open), onPressed: () async { final closeMessage = showMessage( @@ -55,7 +55,7 @@ class DeviceErrorScreen extends ConsumerWidget { ref.invalidate(rpcProvider); } else { await ref.read(withContextProvider)((context) async => - showMessage(context, l10n.l_permission_denied)); + showMessage(context, l10n.s_permission_denied)); } } finally { closeMessage(); @@ -81,7 +81,7 @@ class DeviceErrorScreen extends ConsumerWidget { final String message; switch (error) { case 'unknown-device': - message = l10n.l_unknown_device; + message = l10n.s_unknown_device; break; default: message = l10n.l_place_on_nfc_reader; diff --git a/lib/app/views/device_picker_dialog.dart b/lib/app/views/device_picker_dialog.dart index 0c8581f3..7abfa14b 100755 --- a/lib/app/views/device_picker_dialog.dart +++ b/lib/app/views/device_picker_dialog.dart @@ -122,7 +122,7 @@ class _DevicePickerContent extends ConsumerWidget { title: Center(child: Text(l10n.l_no_yk_present)), subtitle: Center( child: Text( - Platform.isAndroid ? l10n.l_insert_or_tap_yk : l10n.w_usb)), + Platform.isAndroid ? l10n.l_insert_or_tap_yk : l10n.s_usb)), ), ], ); @@ -136,7 +136,7 @@ class _DevicePickerContent extends ConsumerWidget { padding: EdgeInsets.symmetric(horizontal: 4), child: DeviceAvatar(child: Icon(Icons.usb)), ), - title: Text(l10n.w_usb), + title: Text(l10n.s_usb), subtitle: Text(l10n.l_no_yk_present), onTap: () { ref.read(currentDeviceProvider.notifier).setCurrentDevice(null); @@ -168,7 +168,7 @@ class _DevicePickerContent extends ConsumerWidget { ref.read(_hiddenDevicesProvider.notifier).showAll(); }, child: ListTile( - title: Text(l10n.l_show_hidden_devices), + title: Text(l10n.s_show_hidden_devices), dense: true, contentPadding: EdgeInsets.zero, ), @@ -195,11 +195,11 @@ String _getDeviceInfoString(BuildContext context, DeviceInfo info) { final l10n = AppLocalizations.of(context)!; final serial = info.serial; return [ - if (serial != null) l10n.l_sn_serial(serial), + if (serial != null) l10n.s_sn_serial(serial), if (info.version.isAtLeast(1)) - l10n.l_fw_version(info.version) + l10n.s_fw_version(info.version) else - l10n.l_unknown_type, + l10n.s_unknown_type, ].join(' '); } @@ -211,9 +211,9 @@ List _getDeviceStrings( error: (error, _) { switch (error) { case 'device-inaccessible': - return [node.name, l10n.l_yk_inaccessible]; + return [node.name, l10n.s_yk_inaccessible]; case 'unknown-device': - return [l10n.l_unknown_device]; + return [l10n.s_unknown_device]; } return null; }, @@ -306,9 +306,9 @@ class _DeviceRow extends ConsumerWidget { subtitle: Text( node.when( usbYubiKey: (_, __, ___, info) => info == null - ? l10n.l_yk_inaccessible + ? l10n.s_yk_inaccessible : _getDeviceInfoString(context, info), - nfcReader: (_, __) => l10n.l_select_to_scan, + nfcReader: (_, __) => l10n.s_select_to_scan, ), ), onTap: () { @@ -344,7 +344,7 @@ class _NfcDeviceRow extends ConsumerWidget { ref.read(_hiddenDevicesProvider.notifier).showAll(); }, child: ListTile( - title: Text(l10n.l_show_hidden_devices), + title: Text(l10n.s_show_hidden_devices), dense: true, contentPadding: EdgeInsets.zero, enabled: hidden.isNotEmpty, @@ -355,7 +355,7 @@ class _NfcDeviceRow extends ConsumerWidget { ref.read(_hiddenDevicesProvider.notifier).hideDevice(node.path); }, child: ListTile( - title: Text(l10n.l_hide_device), + title: Text(l10n.s_hide_device), dense: true, contentPadding: EdgeInsets.zero, ), diff --git a/lib/app/views/main_drawer.dart b/lib/app/views/main_drawer.dart index abf641b2..885358c7 100755 --- a/lib/app/views/main_drawer.dart +++ b/lib/app/views/main_drawer.dart @@ -142,7 +142,7 @@ class MainPageDrawer extends ConsumerWidget { NavigationDrawerDestination( key: managementAppDrawer, label: Text( - l10n.l_toggle_applications, + l10n.s_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.w_settings), + label: Text(l10n.s_settings), icon: const Icon(Icons.settings_outlined), ), NavigationDrawerDestination( - label: Text(l10n.l_help_and_about), + label: Text(l10n.s_help_and_about), icon: const Icon(Icons.help_outline), ), ], diff --git a/lib/app/views/main_page.dart b/lib/app/views/main_page.dart index b1aae482..5e9d93e6 100755 --- a/lib/app/views/main_page.dart +++ b/lib/app/views/main_page.dart @@ -88,7 +88,7 @@ class MainPage extends ConsumerWidget { actions: [ if (hasNfcSupport && !isNfcEnabled) ElevatedButton.icon( - label: Text(l10n.l_enable_nfc), + label: Text(l10n.s_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.l_add_account, + tooltip: l10n.s_add_account, onPressed: () async { CredentialData? otpauth; final scanner = ref.read(qrScannerProvider); @@ -142,17 +142,17 @@ class MainPage extends ConsumerWidget { if (data.info.supportedCapabilities.isEmpty && data.name == 'Unrecognized device') { return MessagePage( - header: l10n.l_yk_not_recognized, + header: l10n.s_yk_not_recognized, ); } else if (app.getAvailability(data) == Availability.unsupported) { return MessagePage( - header: l10n.l_app_not_supported, + header: l10n.s_app_not_supported, message: l10n.l_app_not_supported_on_yk(app.name), ); } else if (app.getAvailability(data) != Availability.enabled) { return MessagePage( - header: l10n.l_app_disabled, + header: l10n.s_app_disabled, message: l10n.l_app_disabled_desc(app.name), ); } @@ -164,7 +164,7 @@ class MainPage extends ConsumerWidget { return FidoScreen(data); default: return MessagePage( - header: l10n.l_app_not_supported, + header: l10n.s_app_not_supported, message: l10n.l_app_not_supported_desc, ); } diff --git a/lib/desktop/init.dart b/lib/desktop/init.dart index e696355b..21569709 100755 --- a/lib/desktop/init.dart +++ b/lib/desktop/init.dart @@ -285,7 +285,7 @@ class _HelperWaiterState extends ConsumerState<_HelperWaiter> { actions: [ ActionChip( avatar: const Icon(Icons.copy), - label: Text(l10n.l_copy_log), + label: Text(l10n.s_copy_log), onPressed: () async { _log.info('Copying log to clipboard ($version)...'); final logs = await ref.read(logLevelProvider.notifier).getLogs(); diff --git a/lib/desktop/oath/state.dart b/lib/desktop/oath/state.dart index 172fcb34..af1e7f6a 100755 --- a/lib/desktop/oath/state.dart +++ b/lib/desktop/oath/state.dart @@ -271,7 +271,7 @@ class DesktopCredentialListNotifier extends OathCredentialListNotifier { return promptUserInteraction( context, icon: const Icon(Icons.touch_app), - title: l10n.l_touch_required, + title: l10n.s_touch_required, description: l10n.l_touch_button_now, headless: headless, ); diff --git a/lib/desktop/systray.dart b/lib/desktop/systray.dart index 78d695cd..4e249125 100755 --- a/lib/desktop/systray.dart +++ b/lib/desktop/systray.dart @@ -176,7 +176,7 @@ class _Systray extends TrayListener { .read(clipboardProvider) .setText(code.value, isSensitive: true); final notification = LocalNotification( - title: _l10n.l_code_copied, + title: _l10n.s_code_copied, body: _l10n.p_target_copied_clipboard(label), silent: true, ); @@ -190,12 +190,12 @@ class _Systray extends TrayListener { ), if (_credentials.isEmpty) MenuItem( - label: _l10n.l_no_pinned_accounts, + label: _l10n.s_no_pinned_accounts, disabled: true, ), MenuItem.separator(), MenuItem( - label: _isHidden ? _l10n.l_show_window : _l10n.l_hide_window, + label: _isHidden ? _l10n.s_show_window : _l10n.s_hide_window, onClick: (_) { _ref .read(desktopWindowStateProvider.notifier) @@ -204,7 +204,7 @@ class _Systray extends TrayListener { ), MenuItem.separator(), MenuItem( - label: _l10n.w_quit, + label: _l10n.s_quit, onClick: (_) { _ref.read(withContextProvider)( (context) async { diff --git a/lib/error_page.dart b/lib/error_page.dart index 0ba2a5f9..7c4bb215 100755 --- a/lib/error_page.dart +++ b/lib/error_page.dart @@ -25,7 +25,7 @@ class ErrorPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(AppLocalizations.of(context)!.l_application_error), + title: Text(AppLocalizations.of(context)!.s_application_error), ), body: Center( child: Column( diff --git a/lib/fido/views/add_fingerprint_dialog.dart b/lib/fido/views/add_fingerprint_dialog.dart index d97533b2..802e89b9 100755 --- a/lib/fido/views/add_fingerprint_dialog.dart +++ b/lib/fido/views/add_fingerprint_dialog.dart @@ -146,7 +146,7 @@ class _AddFingerprintDialogState extends ConsumerState .renameFingerprint(_fingerprint!, _label); if (!mounted) return; Navigator.of(context).pop(true); - showMessage(context, l10n.l_fingerprint_added); + showMessage(context, l10n.s_fingerprint_added); } catch (e) { final String errorMessage; // TODO: Make this cleaner than importing desktop specific RpcError. @@ -169,7 +169,7 @@ class _AddFingerprintDialogState extends ConsumerState final progress = _samples == 0 ? 0.0 : _samples / (_samples + _remaining); return ResponsiveDialog( - title: Text(l10n.l_add_fingerprint), + title: Text(l10n.s_add_fingerprint), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 18.0), child: Column( @@ -208,7 +208,7 @@ class _AddFingerprintDialogState extends ConsumerState decoration: InputDecoration( enabled: _fingerprint != null, border: const OutlineInputBorder(), - labelText: l10n.w_name, + labelText: l10n.s_name, prefixIcon: const Icon(Icons.fingerprint_outlined), ), onChanged: (value) { @@ -234,7 +234,7 @@ class _AddFingerprintDialogState extends ConsumerState actions: [ TextButton( onPressed: _fingerprint != null && _label.isNotEmpty ? _submit : null, - child: Text(l10n.w_save), + child: Text(l10n.s_save), ), ], ); diff --git a/lib/fido/views/delete_credential_dialog.dart b/lib/fido/views/delete_credential_dialog.dart index 46d8d9a7..b1bb30aa 100755 --- a/lib/fido/views/delete_credential_dialog.dart +++ b/lib/fido/views/delete_credential_dialog.dart @@ -38,7 +38,7 @@ class DeleteCredentialDialog extends ConsumerWidget { final label = credential.userName; return ResponsiveDialog( - title: Text(l10n.l_delete_credential), + title: Text(l10n.s_delete_credential), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 18.0), child: Column( @@ -63,11 +63,11 @@ class DeleteCredentialDialog extends ConsumerWidget { await ref.read(withContextProvider)( (context) async { Navigator.of(context).pop(true); - showMessage(context, l10n.l_credential_deleted); + showMessage(context, l10n.s_credential_deleted); }, ); }, - child: Text(l10n.w_delete), + child: Text(l10n.s_delete), ), ], ); diff --git a/lib/fido/views/delete_fingerprint_dialog.dart b/lib/fido/views/delete_fingerprint_dialog.dart index 4660770c..4543b151 100755 --- a/lib/fido/views/delete_fingerprint_dialog.dart +++ b/lib/fido/views/delete_fingerprint_dialog.dart @@ -36,7 +36,7 @@ class DeleteFingerprintDialog extends ConsumerWidget { final label = fingerprint.label; return ResponsiveDialog( - title: Text(l10n.l_delete_fingerprint), + title: Text(l10n.s_delete_fingerprint), actions: [ TextButton( onPressed: () async { @@ -45,10 +45,10 @@ class DeleteFingerprintDialog extends ConsumerWidget { .deleteFingerprint(fingerprint); await ref.read(withContextProvider)((context) async { Navigator.of(context).pop(true); - showMessage(context, l10n.l_fingerprint_deleted); + showMessage(context, l10n.s_fingerprint_deleted); }); }, - child: Text(l10n.w_delete), + child: Text(l10n.s_delete), ), ], child: Padding( diff --git a/lib/fido/views/fido_screen.dart b/lib/fido/views/fido_screen.dart index 73a1d569..e159acac 100755 --- a/lib/fido/views/fido_screen.dart +++ b/lib/fido/views/fido_screen.dart @@ -37,7 +37,7 @@ class FidoScreen extends ConsumerWidget { final l10n = AppLocalizations.of(context)!; return ref.watch(fidoStateProvider(deviceData.node.path)).when( loading: () => AppPage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), centered: true, delayedContent: true, child: const CircularProgressIndicator(), @@ -48,7 +48,7 @@ class FidoScreen extends ConsumerWidget { 0; if (Capability.fido2.value & supported == 0) { return MessagePage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), graphic: manageAccounts, header: l10n.l_ready_to_use, message: l10n.l_register_sk_on_websites, @@ -59,14 +59,14 @@ class FidoScreen extends ConsumerWidget { 0; if (Capability.fido2.value & enabled == 0) { return MessagePage( - title: Text(l10n.w_webauthn), - header: l10n.l_fido_disabled, + title: Text(l10n.s_webauthn), + header: l10n.s_fido_disabled, message: l10n.l_webauthn_req_fido2, ); } return AppFailurePage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), cause: error, ); }, diff --git a/lib/fido/views/key_actions.dart b/lib/fido/views/key_actions.dart index b140fe05..51ab8ac5 100755 --- a/lib/fido/views/key_actions.dart +++ b/lib/fido/views/key_actions.dart @@ -32,11 +32,11 @@ Widget fidoBuildActions( return SimpleDialog( children: [ if (state.bioEnroll != null) ...[ - ListTitle(l10n.w_setup, + ListTitle(l10n.s_setup, textStyle: Theme.of(context).textTheme.bodyLarge), ListTile( leading: const CircleAvatar(child: Icon(Icons.fingerprint_outlined)), - title: Text(l10n.l_add_fingerprint), + title: Text(l10n.s_add_fingerprint), subtitle: state.unlocked ? Text(l10n.l_fingerprints_used(fingerprints)) : Text(state.hasPin @@ -54,13 +54,13 @@ Widget fidoBuildActions( : null, ), ], - ListTitle(l10n.w_manage, + ListTitle(l10n.s_manage, textStyle: Theme.of(context).textTheme.bodyLarge), ListTile( leading: const CircleAvatar(child: Icon(Icons.pin_outlined)), - title: Text(state.hasPin ? l10n.l_change_pin : l10n.l_set_pin), + title: Text(state.hasPin ? l10n.s_change_pin : l10n.s_set_pin), subtitle: Text(state.hasPin - ? l10n.l_fido_pin_protection + ? l10n.s_fido_pin_protection : l10n.l_fido_pin_protection_optional), onTap: () { Navigator.of(context).pop(); @@ -75,7 +75,7 @@ Widget fidoBuildActions( backgroundColor: theme.error, child: const Icon(Icons.delete_outline), ), - title: Text(l10n.l_reset_fido), + title: Text(l10n.s_reset_fido), subtitle: Text(l10n.l_factory_reset_this_app), onTap: () { Navigator.of(context).pop(); diff --git a/lib/fido/views/locked_page.dart b/lib/fido/views/locked_page.dart index 5fcaaf65..2a0fa837 100755 --- a/lib/fido/views/locked_page.dart +++ b/lib/fido/views/locked_page.dart @@ -38,15 +38,15 @@ class FidoLockedPage extends ConsumerWidget { if (!state.hasPin) { if (state.bioEnroll != null) { return MessagePage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), graphic: noFingerprints, - header: l10n.l_no_fingerprints, + header: l10n.s_no_fingerprints, message: l10n.l_set_pin_fingerprints, keyActionsBuilder: _buildActions, ); } else { return MessagePage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), graphic: manageAccounts, header: state.credMgmt ? l10n.l_no_discoverable_accounts @@ -59,7 +59,7 @@ class FidoLockedPage extends ConsumerWidget { if (!state.credMgmt && state.bioEnroll == null) { return MessagePage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), graphic: manageAccounts, header: l10n.l_ready_to_use, message: l10n.l_register_sk_on_websites, @@ -68,7 +68,7 @@ class FidoLockedPage extends ConsumerWidget { } return AppPage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), keyActionsBuilder: _buildActions, child: Column( children: [ @@ -148,7 +148,7 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> { controller: _pinController, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.w_pin, + labelText: l10n.s_pin, helperText: '', // Prevents dialog resizing errorText: _pinIsWrong ? _getErrorText() : null, errorMaxLines: 3, @@ -187,7 +187,7 @@ class _PinEntryFormState extends ConsumerState<_PinEntryForm> { minLeadingWidth: 0, trailing: ElevatedButton.icon( icon: const Icon(Icons.lock_open), - label: Text(l10n.w_unlock), + label: Text(l10n.s_unlock), onPressed: _pinController.text.isNotEmpty && !_blocked ? _submit : null, ), diff --git a/lib/fido/views/pin_dialog.dart b/lib/fido/views/pin_dialog.dart index f78c3b7f..55fcc6af 100755 --- a/lib/fido/views/pin_dialog.dart +++ b/lib/fido/views/pin_dialog.dart @@ -57,11 +57,11 @@ class _FidoPinDialogState extends ConsumerState { final minPinLength = widget.state.minPinLength; return ResponsiveDialog( - title: Text(hasPin ? l10n.l_change_pin : l10n.l_set_pin), + title: Text(hasPin ? l10n.s_change_pin : l10n.s_set_pin), actions: [ TextButton( onPressed: isValid ? _submit : null, - child: Text(l10n.w_save), + child: Text(l10n.s_save), ), ], child: Padding( @@ -77,7 +77,7 @@ class _FidoPinDialogState extends ConsumerState { obscureText: true, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_current_pin, + labelText: l10n.s_current_pin, errorText: _currentIsWrong ? _currentPinError : null, errorMaxLines: 3, prefixIcon: const Icon(Icons.pin_outlined), @@ -98,7 +98,7 @@ class _FidoPinDialogState extends ConsumerState { obscureText: true, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_new_pin, + labelText: l10n.s_new_pin, enabled: !hasPin || _currentPin.isNotEmpty, errorText: _newIsWrong ? _newPinError : null, errorMaxLines: 3, @@ -116,7 +116,7 @@ class _FidoPinDialogState extends ConsumerState { obscureText: true, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_confirm_pin, + labelText: l10n.s_confirm_pin, prefixIcon: const Icon(Icons.pin_outlined), enabled: (!hasPin || _currentPin.isNotEmpty) && _newPin.isNotEmpty, @@ -160,7 +160,7 @@ class _FidoPinDialogState extends ConsumerState { .setPin(_newPin, oldPin: oldPin); result.when(success: () { Navigator.of(context).pop(true); - showMessage(context, l10n.l_pin_set); + showMessage(context, l10n.s_pin_set); }, failed: (retries, authBlocked) { setState(() { if (authBlocked) { diff --git a/lib/fido/views/rename_fingerprint_dialog.dart b/lib/fido/views/rename_fingerprint_dialog.dart index 28966e96..7f3e9712 100755 --- a/lib/fido/views/rename_fingerprint_dialog.dart +++ b/lib/fido/views/rename_fingerprint_dialog.dart @@ -54,7 +54,7 @@ class _RenameAccountDialogState extends ConsumerState { .renameFingerprint(widget.fingerprint, _label); if (!mounted) return; Navigator.of(context).pop(renamed); - showMessage(context, l10n.l_fingerprint_renamed); + showMessage(context, l10n.s_fingerprint_renamed); } catch (e) { final String errorMessage; // TODO: Make this cleaner than importing desktop specific RpcError. @@ -75,11 +75,11 @@ class _RenameAccountDialogState extends ConsumerState { Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return ResponsiveDialog( - title: Text(l10n.l_rename_fp), + title: Text(l10n.s_rename_fp), actions: [ TextButton( onPressed: _label.isNotEmpty ? _submit : null, - child: Text(l10n.w_save), + child: Text(l10n.s_save), ), ], child: Padding( @@ -96,7 +96,7 @@ class _RenameAccountDialogState extends ConsumerState { buildCounter: buildByteCounterFor(_label), decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.w_label, + labelText: l10n.s_label, prefixIcon: const Icon(Icons.fingerprint_outlined), ), onChanged: (value) { diff --git a/lib/fido/views/reset_dialog.dart b/lib/fido/views/reset_dialog.dart index a9f72357..72c3722f 100755 --- a/lib/fido/views/reset_dialog.dart +++ b/lib/fido/views/reset_dialog.dart @@ -63,7 +63,7 @@ class _ResetDialogState extends ConsumerState { Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return ResponsiveDialog( - title: Text(l10n.l_factory_reset), + title: Text(l10n.s_factory_reset), onCancel: () { _subscription?.cancel(); }, @@ -100,7 +100,7 @@ class _ResetDialogState extends ConsumerState { }); } : null, - child: Text(l10n.w_reset), + child: Text(l10n.s_reset), ), ], child: Padding( diff --git a/lib/fido/views/unlocked_page.dart b/lib/fido/views/unlocked_page.dart index a606d94f..b682f745 100755 --- a/lib/fido/views/unlocked_page.dart +++ b/lib/fido/views/unlocked_page.dart @@ -48,7 +48,7 @@ class FidoUnlockedPage extends ConsumerWidget { } final creds = data.value; if (creds.isNotEmpty) { - children.add(ListTitle(l10n.w_credentials)); + children.add(ListTitle(l10n.s_credentials)); children.addAll( creds.map( (cred) => ListTile( @@ -96,7 +96,7 @@ class FidoUnlockedPage extends ConsumerWidget { final fingerprints = data.value; if (fingerprints.isNotEmpty) { nFingerprints = fingerprints.length; - children.add(ListTitle(l10n.w_fingerprints)); + children.add(ListTitle(l10n.s_fingerprints)); children.addAll(fingerprints.map((fp) => ListTile( leading: CircleAvatar( foregroundColor: Theme.of(context).colorScheme.onSecondary, @@ -137,7 +137,7 @@ class FidoUnlockedPage extends ConsumerWidget { if (children.isNotEmpty) { return AppPage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), keyActionsBuilder: (context) => fidoBuildActions(context, node, state, nFingerprints), child: Column( @@ -147,9 +147,9 @@ class FidoUnlockedPage extends ConsumerWidget { if (state.bioEnroll != null) { return MessagePage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), graphic: noFingerprints, - header: l10n.l_no_fingerprints, + header: l10n.s_no_fingerprints, message: l10n.l_add_one_or_more_fps, keyActionsBuilder: (context) => fidoBuildActions(context, node, state, 0), @@ -157,7 +157,7 @@ class FidoUnlockedPage extends ConsumerWidget { } return MessagePage( - title: Text(l10n.w_webauthn), + title: Text(l10n.s_webauthn), graphic: manageAccounts, header: l10n.l_no_discoverable_accounts, message: l10n.l_register_sk_on_websites, @@ -166,7 +166,7 @@ class FidoUnlockedPage extends ConsumerWidget { } Widget _buildLoadingPage(BuildContext context) => AppPage( - title: Text(AppLocalizations.of(context)!.w_webauthn), + title: Text(AppLocalizations.of(context)!.s_webauthn), centered: true, delayedContent: true, child: const CircularProgressIndicator(), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 0e7a3933..06badc3f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -4,31 +4,37 @@ "@_readme": { "notes": [ "All strings start with a Captial letter.", - "Group strings by category, but don't needlessly tie them to a section of the app if they can be re-used between several." + "Group strings by category, but don't needlessly tie them to a section of the app if they can be re-used between several.", + "Run check_strings.py on the .arb file to detect problems, tweak @_lint_rules as needed per language." ], "prefixes": { - "w_": "A single word", - "l_": "A single line. Should not be more than one sentence, and not end with a period.", + "s_": "A single, or few words. Should be short enough to display on a button, or a header.", + "l_": "A single line, can be wrapped. Should not be more than one sentence, and not end with a period.", "p_": "One or more full sentences, with proper punctuation.", "q_": "A question, ending in question mark." } }, + "@_lint_rules": { + "s_max_words": 4, + "s_max_length": 32 + }, + "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", + "s_save": "Save", + "s_cancel": "Cancel", + "s_close": "Close", + "s_delete": "Delete", + "s_quit": "Quit", + "s_unlock": "Unlock", + "s_calculate": "Calculate", + "s_label": "Label", + "s_name": "Name", + "s_usb": "USB", + "s_nfc": "NFC", + "s_show_window": "Show window", + "s_hide_window": "Hide window", "q_rename_target": "Rename {label}?", "@q_rename_target" : { "placeholders": { @@ -36,62 +42,62 @@ } }, - "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", + "s_about": "About", + "s_appearance": "Appearance", + "s_authenticator": "Authenticator", + "s_manage": "Manage", + "s_setup": "Setup", + "s_settings": "Settings", + "s_webauthn": "WebAuthn", + "s_help_and_about": "Help and about", + "s_help_and_feedback": "Help and feedback", + "s_send_feedback": "Send us feedback", + "s_i_need_help": "I need help", + "s_troubleshooting": "Troubleshooting", + "s_terms_of_use": "Terms of use", + "s_privacy_policy": "Privacy policy", + "s_open_src_licenses": "Open source licenses", + "s_configure_yk": "Configure YubiKey", + "s_please_wait": "Please wait\u2026", + "s_secret_key": "Secret key", + "s_invalid_length": "Invalid length", + "s_require_touch": "Require touch", "q_have_account_info": "Have account info?", - "l_run_diagnostics": "Run diagnostics", - "l_log_level": "Log level: {level}", - "@l_log_level": { + "s_run_diagnostics": "Run diagnostics", + "s_log_level": "Log level: {level}", + "@s_log_level": { "placeholders": { "level": {} } }, - "l_character_count": "Character count", - "l_learn_more": "Learn\u00a0more", + "s_character_count": "Character count", + "s_learn_more": "Learn\u00a0more", "@_language": {}, - "w_language": "Language", + "s_language": "Language", "l_enable_community_translations": "Enable community translations", "p_community_translations_desc": "These translations are provided and maintained by the community. They may contain errors or be incomplete.", "@_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", + "s_app_theme": "App theme", + "s_choose_app_theme": "Choose app theme", + "s_system_default": "System default", + "s_light_mode": "Light mode", + "s_dark_mode": "Dark mode", "@_yubikey_selection": {}, - "l_select_yk": "Select YubiKey", - "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" : { + "s_select_yk": "Select YubiKey", + "s_select_to_scan": "Select to scan", + "s_hide_device": "Hide device", + "s_show_hidden_devices": "Show hidden devices", + "s_sn_serial": "S/N: {serial}", + "@s_sn_serial" : { "placeholders": { "serial": {} } }, - "l_fw_version": "F/W: {version}", - "@l_fw_version" : { + "s_fw_version": "F/W: {version}", + "@s_fw_version" : { "placeholders": { "version": {} } @@ -105,18 +111,18 @@ "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", + "p_try_reinsert_yk": "Try to remove and reinsert your YubiKey.", + "s_touch_required": "Touch required", "l_touch_button_now": "Touch the button on your YubiKey now", "l_keep_touching_yk": "Keep touching your YubiKey repeatedly\u2026", "@_app_configuration": {}, - "l_toggle_applications": "Toggle applications", + "s_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", + "s_reconfiguring_yk": "Reconfiguring YubiKey\u2026", + "s_config_updated": "Configuration updated", "l_config_updated_reinsert": "Configuration updated, remove and reinsert your YubiKey", - "l_app_not_supported": "Application not supported", + "s_app_not_supported": "Application not supported", "l_app_not_supported_on_yk": "The used YubiKey does not support '${app}' application", "@l_app_not_supported_on_yk" : { "placeholders": { @@ -124,65 +130,65 @@ } }, "l_app_not_supported_desc": "This application is not supported", - "l_app_disabled": "Application disabled", + "s_app_disabled": "Application disabled", "l_app_disabled_desc": "Enable the '{app}' application on your YubiKey to access", "@l_app_disabled_desc" : { "placeholders": { "app": {} } }, - "l_fido_disabled": "FIDO2 disabled", + "s_fido_disabled": "FIDO2 disabled", "l_webauthn_req_fido2": "WebAuthn requires the FIDO2 application to be enabled on your YubiKey", "@_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", + "s_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", + "s_unknown_type": "Unknown type", + "s_unknown_device": "Unrecognized device", + "s_unsupported_yk": "Unsupported YubiKey", + "s_yk_not_recognized": "Device not recognized", "@_general_errors": {}, "l_error_occured": "An error has occured", - "l_application_error": "Application error", + "s_application_error": "Application error", "l_import_error": "Import error", "l_file_not_found": "File not found", "l_file_too_big": "File size too big", "l_filesystem_error": "File system operation 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", + "s_pin": "PIN", + "s_set_pin": "Set PIN", + "s_change_pin": "Change PIN", + "s_current_pin": "Current PIN", + "s_new_pin": "New PIN", + "s_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", + "s_pin_set": "PIN set", "l_set_pin_failed": "Failed to set PIN: {message}", "@l_set_pin_failed" : { "placeholders": { "message": {} } }, - "l_wrong_pin_attempts_remaining": "Wrong PIN. {retries} attempt(s) remaining.", + "l_wrong_pin_attempts_remaining": "Wrong PIN, {retries} attempt(s) remaining", "@l_wrong_pin_attempts_remaining" : { "placeholders": { "retries": {} } }, - "l_fido_pin_protection": "FIDO PIN protection", + "s_fido_pin_protection": "FIDO PIN protection", "l_fido_pin_protection_optional": "Optional FIDO PIN protection", "l_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", @@ -199,20 +205,20 @@ }, "@_passwords": {}, - "w_password": "Password", - "l_manage_password": "Manage password", - "l_set_password": "Set password", - "l_password_set": "Password set", + "s_password": "Password", + "s_manage_password": "Manage password", + "s_set_password": "Set password", + "s_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", + "s_new_password": "New password", + "s_current_password": "Current password", + "s_confirm_password": "Confirm password", + "s_wrong_password": "Wrong password", + "s_remove_password": "Remove password", + "s_password_removed": "Password removed", + "s_remember_password": "Remember password", + "s_clear_saved_password": "Clear saved password", + "s_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", @@ -227,10 +233,10 @@ "label": {} } }, - "w_accounts": "Accounts", - "l_no_accounts": "No accounts", - "l_add_account": "Add account", - "l_account_added": "Account added", + "s_accounts": "Accounts", + "s_no_accounts": "No accounts", + "s_add_account": "Add account", + "s_account_added": "Account added", "l_account_add_failed": "Failed adding account: {message}", "@l_account_add_failed" : { "placeholders": { @@ -240,19 +246,19 @@ "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", + "s_pinned": "Pinned", + "s_pin_account": "Pin account", + "s_unpin_account": "Unpin account", + "s_no_pinned_accounts": "No pinned accounts", + "s_rename_account": "Rename account", + "s_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", + "s_delete_account": "Delete account", + "s_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", + "s_account_name": "Account name", + "s_search_accounts": "Search accounts", "l_accounts_used": "{used} of {capacity} accounts used", "@l_accounts_used" : { "placeholders": { @@ -260,19 +266,19 @@ "capacity": {} } }, - "l_num_digits": "{num} digits", - "@l_num_digits" : { + "s_num_digits": "{num} digits", + "@s_num_digits" : { "placeholders": { "num": {} } }, - "l_num_sec": "{num} sec", - "@l_num_sec" : { + "s_num_sec": "{num} sec", + "@s_num_sec" : { "placeholders": { "num": {} } }, - "l_issuer_optional": "Issuer (optional)", + "s_issuer_optional": "Issuer (optional)", "@_fido_credentials": {}, "l_credential": "Credential: {label}", @@ -281,12 +287,12 @@ "label": {} } }, - "w_credentials": "Credentials", + "s_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", + "s_delete_credential": "Delete credential", + "s_credential_deleted": "Credential deleted", "p_warning_delete_credential": "This will delete the credential from your YubiKey.", "@_fingerprints": {}, @@ -296,32 +302,32 @@ "label": {} } }, - "w_fingerprints": "Fingerprints", + "s_fingerprints": "Fingerprints", "l_fingerprint_captured": "Fingerprint captured successfully!", - "l_fingerprint_added": "Fingerprint added", + "s_fingerprint_added": "Fingerprint added", "l_setting_name_failed": "Error setting name: {message}", "@l_setting_name_failed" : { "placeholders": { "message": {} } }, - "l_add_fingerprint": "Add fingerprint", + "s_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", + "s_delete_fingerprint": "Delete fingerprint", + "s_fingerprint_deleted": "Fingerprint deleted", "p_warning_delete_fingerprint": "This will delete the fingerprint from your YubiKey.", - "l_no_fingerprints": "No fingerprints", + "s_no_fingerprints": "No fingerprints", "l_set_pin_fingerprints": "Set a PIN to register fingerprints", "l_no_fps_added": "No fingerprints have been added", - "l_fingerprint_renamed": "Fingerprint renamed", + "s_rename_fp": "Rename fingerprint", + "s_fingerprint_renamed": "Fingerprint renamed", "l_rename_fp_failed": "Error renaming: {message}", "@l_rename_fp_failed" : { "placeholders": { "message": {} } }, - "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": { @@ -333,16 +339,16 @@ "p_will_change_label_fp": "This will change the label of the fingerprint.", "@_permissions": {}, - "l_enable_nfc": "Enable NFC", - "l_permission_denied": "Permission denied", + "s_enable_nfc": "Enable NFC", + "s_permission_denied": "Permission denied", "l_elevating_permissions": "Elevating permissions\u2026", - "l_review_permissions": "Review permissions", + "s_review_permissions": "Review permissions", "p_elevated_permissions_required": "Managing this device requires elevated privileges.", "p_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", + "s_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", @@ -355,15 +361,15 @@ "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", + "s_enter_manually": "Enter manually", "@_factory_reset": {}, - "w_reset": "Reset", - "l_factory_reset": "Factory reset", + "s_reset": "Reset", + "s_factory_reset": "Factory reset", "l_factory_reset_this_app": "Factory reset this application", - "l_reset_oath": "Reset OATH", + "s_reset_oath": "Reset OATH", "l_oath_application_reset": "OATH application reset", - "l_reset_fido": "Reset FIDO", + "s_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: {message}", @@ -379,9 +385,9 @@ "@_copy_to_clipboard": {}, "l_copy_to_clipboard": "Copy to clipboard", - "l_code_copied": "Code copied", + "s_code_copied": "Code copied", "l_code_copied_clipboard": "Code copied to clipboard", - "l_copy_log": "Copy log", + "s_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.", @@ -392,16 +398,16 @@ }, "@_custom_icons": {}, - "l_custom_icons": "Custom icons", + "s_custom_icons": "Custom icons", "l_set_icons_for_accounts": "Set icons for accounts", "p_custom_icons_description": "Icon packs can make your accounts more easily distinguishable with familiar logos and colors.", - "l_replace_icon_pack": "Replace icon pack", + "s_replace_icon_pack": "Replace icon pack", "l_loading_icon_pack": "Loading icon pack\u2026", - "l_load_icon_pack": "Load icon pack", - "l_remove_icon_pack": "Remove icon pack", + "s_load_icon_pack": "Load icon pack", + "s_remove_icon_pack": "Remove icon pack", "l_icon_pack_removed": "Icon pack removed", "l_remove_icon_pack_failed": "Error removing icon pack", - "l_choose_icon_pack": "Choose icon pack", + "s_choose_icon_pack": "Choose icon pack", "l_icon_pack_imported": "Icon pack imported", "l_import_icon_pack_failed": "Error importing icon pack: {message}", "@l_import_icon_pack_failed": { @@ -412,24 +418,24 @@ "l_invalid_icon_pack": "Invalid icon pack", "@_android_settings": {}, - "l_nfc_options": "NFC options", + "s_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", + "s_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", + "s_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", + "s_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", + "s_allow_screenshots": "Allow screenshots", "@_eof": {} } \ No newline at end of file diff --git a/lib/management/views/management_screen.dart b/lib/management/views/management_screen.dart index daea80ef..e49d4cb5 100755 --- a/lib/management/views/management_screen.dart +++ b/lib/management/views/management_screen.dart @@ -116,7 +116,7 @@ class _CapabilitiesForm extends StatelessWidget { if (usbCapabilities != 0) ...[ ListTile( leading: const Icon(Icons.usb), - title: Text(l10n.w_usb), + title: Text(l10n.s_usb), contentPadding: const EdgeInsets.only(bottom: 8), horizontalTitleGap: 0, ), @@ -137,7 +137,7 @@ class _CapabilitiesForm extends StatelessWidget { ), ListTile( leading: nfcIcon, - title: Text(l10n.w_nfc), + title: Text(l10n.s_nfc), contentPadding: const EdgeInsets.only(bottom: 8), horizontalTitleGap: 0, ), @@ -212,7 +212,7 @@ class _ManagementScreenState extends ConsumerState { // This will take longer, show a message close = showMessage( context, - l10n.l_reconfiguring_yk, + l10n.s_reconfiguring_yk, duration: const Duration(seconds: 8), ); } @@ -225,7 +225,7 @@ class _ManagementScreenState extends ConsumerState { ); if (!mounted) return; if (!reboot) Navigator.pop(context); - showMessage(context, l10n.l_config_updated); + showMessage(context, l10n.s_config_updated); } finally { close?.call(); } @@ -250,7 +250,7 @@ class _ManagementScreenState extends ConsumerState { showMessage( context, widget.deviceData.node.maybeMap( - nfcReader: (_) => l10n.l_config_updated, + nfcReader: (_) => l10n.s_config_updated, orElse: () => l10n.l_config_updated_reinsert)); Navigator.pop(context); } @@ -318,12 +318,12 @@ class _ManagementScreenState extends ConsumerState { ); return ResponsiveDialog( - title: Text(l10n.l_toggle_applications), + title: Text(l10n.s_toggle_applications), actions: [ TextButton( onPressed: canSave ? _submitForm : null, key: management_keys.saveButtonKey, - child: Text(l10n.w_save), + child: Text(l10n.s_save), ), ], child: child, diff --git a/lib/oath/icon_provider/icon_pack_dialog.dart b/lib/oath/icon_provider/icon_pack_dialog.dart index 67b46917..46e0759e 100644 --- a/lib/oath/icon_provider/icon_pack_dialog.dart +++ b/lib/oath/icon_provider/icon_pack_dialog.dart @@ -34,7 +34,7 @@ class IconPackDialog extends ConsumerWidget { final l10n = AppLocalizations.of(context)!; final iconPack = ref.watch(iconPackProvider); return ResponsiveDialog( - title: Text(l10n.l_custom_icons), + title: Text(l10n.s_custom_icons), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 18.0), child: Column( @@ -66,9 +66,9 @@ class IconPackDialog extends ConsumerWidget { Widget? _action(AsyncValue iconPack, AppLocalizations l10n) => iconPack.when( data: (IconPack? data) => _ImportActionChip( - data != null ? l10n.l_replace_icon_pack : l10n.l_load_icon_pack), + data != null ? l10n.s_replace_icon_pack : l10n.s_load_icon_pack), error: (Object error, StackTrace stackTrace) => - _ImportActionChip(l10n.l_load_icon_pack), + _ImportActionChip(l10n.s_load_icon_pack), loading: () => _ImportActionChip( l10n.l_loading_icon_pack, avatar: const CircularProgressIndicator(), @@ -96,7 +96,7 @@ class _DialogDescription extends ConsumerWidget { TextSpan _createLearnMoreLink(BuildContext context) { final theme = Theme.of(context); return TextSpan( - text: AppLocalizations.of(context)!.l_learn_more, + text: AppLocalizations.of(context)!.s_learn_more, style: theme.textTheme.bodyMedium ?.copyWith(color: theme.colorScheme.primary), recognizer: TapGestureRecognizer() @@ -134,7 +134,7 @@ class _IconPackDescription extends ConsumerWidget { Row( children: [ IconButton( - tooltip: l10n.l_remove_icon_pack, + tooltip: l10n.s_remove_icon_pack, onPressed: () async { final removePackStatus = await ref.read(iconPackProvider.notifier).removePack(); @@ -179,7 +179,7 @@ class _ImportActionChip extends ConsumerWidget { type: FileType.custom, allowMultiple: false, lockParentWindow: true, - dialogTitle: l10n.l_choose_icon_pack); + dialogTitle: l10n.s_choose_icon_pack); if (result != null && result.files.isNotEmpty) { final importStatus = await ref .read(iconPackProvider.notifier) diff --git a/lib/oath/views/account_dialog.dart b/lib/oath/views/account_dialog.dart index 5b73ddc9..d3b4aee9 100755 --- a/lib/oath/views/account_dialog.dart +++ b/lib/oath/views/account_dialog.dart @@ -46,7 +46,7 @@ class AccountDialog extends ConsumerWidget { final copy = actions.firstWhere(((e) => e.text == l10n.l_copy_to_clipboard)); - final delete = actions.firstWhere(((e) => e.text == l10n.l_delete_account)); + final delete = actions.firstWhere(((e) => e.text == l10n.s_delete_account)); final colors = { copy: Pair(theme.primary, theme.onPrimary), delete: Pair(theme.error, theme.onError), @@ -54,7 +54,7 @@ class AccountDialog extends ConsumerWidget { // If we can't copy, but can calculate, highlight that button instead if (copy.intent == null) { - final calculates = actions.where(((e) => e.text == l10n.w_calculate)); + final calculates = actions.where(((e) => e.text == l10n.s_calculate)); if (calculates.isNotEmpty) { colors[calculates.first] = Pair(theme.primary, theme.onPrimary); } diff --git a/lib/oath/views/account_helper.dart b/lib/oath/views/account_helper.dart index 31255d86..283ae3b1 100755 --- a/lib/oath/views/account_helper.dart +++ b/lib/oath/views/account_helper.dart @@ -73,12 +73,12 @@ class AccountHelper { ), if (manual) MenuAction( - text: l10n.w_calculate, + text: l10n.s_calculate, icon: const Icon(Icons.refresh), intent: ready ? const CalculateIntent() : null, ), MenuAction( - text: pinned ? l10n.l_unpin_account : l10n.l_pin_account, + text: pinned ? l10n.s_unpin_account : l10n.s_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.l_rename_account, + text: l10n.s_rename_account, intent: const EditIntent(), ), MenuAction( - text: l10n.l_delete_account, + text: l10n.s_delete_account, icon: const Icon(Icons.delete_outline), intent: const DeleteIntent(), ), diff --git a/lib/oath/views/account_list.dart b/lib/oath/views/account_list.dart index 709cedaa..da84fbe4 100755 --- a/lib/oath/views/account_list.dart +++ b/lib/oath/views/account_list.dart @@ -34,7 +34,7 @@ class AccountList extends ConsumerWidget { final favorites = ref.watch(favoritesProvider); if (credentials.isEmpty) { return Center( - child: Text(l10n.l_no_accounts), + child: Text(l10n.s_no_accounts), ); } @@ -47,13 +47,13 @@ class AccountList extends ConsumerWidget { policy: WidgetOrderTraversalPolicy(), child: Column( children: [ - if (pinnedCreds.isNotEmpty) ListTitle(l10n.w_pinned), + if (pinnedCreds.isNotEmpty) ListTitle(l10n.s_pinned), ...pinnedCreds.map( (entry) => AccountView( entry.credential, ), ), - if (creds.isNotEmpty) ListTitle(l10n.w_accounts), + if (creds.isNotEmpty) ListTitle(l10n.s_accounts), ...creds.map( (entry) => AccountView( entry.credential, diff --git a/lib/oath/views/add_account_page.dart b/lib/oath/views/add_account_page.dart index 64768dd8..72a88a5b 100755 --- a/lib/oath/views/add_account_page.dart +++ b/lib/oath/views/add_account_page.dart @@ -188,7 +188,7 @@ class _OathAddAccountPageState extends ConsumerState { } if (!mounted) return; Navigator.of(context).pop(); - showMessage(context, l10n.l_account_added); + showMessage(context, l10n.s_account_added); } on CancellationException catch (_) { // ignored } catch (e) { @@ -244,7 +244,7 @@ class _OathAddAccountPageState extends ConsumerState { 0) != 0) { if (oathState == null) { - _promptController?.updateContent(title: l10n.l_please_wait); + _promptController?.updateContent(title: l10n.s_please_wait); } else if (oathState.locked) { _promptController?.close(); } else { @@ -256,12 +256,12 @@ class _OathAddAccountPageState extends ConsumerState { )); } } else { - _promptController?.updateContent(title: l10n.l_unsupported_yk); + _promptController?.updateContent(title: l10n.s_unsupported_yk); } }, error: (error, _) { - _promptController?.updateContent(title: l10n.l_unsupported_yk); + _promptController?.updateContent(title: l10n.s_unsupported_yk); }, loading: () { - _promptController?.updateContent(title: l10n.l_please_wait); + _promptController?.updateContent(title: l10n.s_please_wait); }); } @@ -343,7 +343,7 @@ class _OathAddAccountPageState extends ConsumerState { _promptController = promptUserInteraction( context, title: l10n.l_insert_yk, - description: l10n.l_add_account, + description: l10n.s_add_account, icon: const Icon(Icons.usb), onCancel: () { _otpauthUri = null; @@ -358,11 +358,11 @@ class _OathAddAccountPageState extends ConsumerState { } return ResponsiveDialog( - title: Text(l10n.l_add_account), + title: Text(l10n.s_add_account), actions: [ TextButton( onPressed: isValid ? submit : null, - child: Text(l10n.w_save, key: keys.saveButton), + child: Text(l10n.s_save, key: keys.saveButton), ), ], child: FileDropTarget( @@ -402,7 +402,7 @@ class _OathAddAccountPageState extends ConsumerState { buildCounter: buildByteCounterFor(issuerText), decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_issuer_optional, + labelText: l10n.s_issuer_optional, helperText: '', // Prevents dialog resizing when disabled prefixIcon: const Icon(Icons.business_outlined), @@ -431,7 +431,7 @@ class _OathAddAccountPageState extends ConsumerState { decoration: InputDecoration( border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.person_outline), - labelText: l10n.l_account_name, + labelText: l10n.s_account_name, helperText: '', // Prevents dialog resizing when disabled errorText: (byteLength(nameText) > nameMaxLength) @@ -474,9 +474,9 @@ class _OathAddAccountPageState extends ConsumerState { ), border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.key_outlined), - labelText: l10n.l_secret_key, + labelText: l10n.s_secret_key, errorText: _validateSecretLength && !secretLengthValid - ? l10n.l_invalid_length + ? l10n.s_invalid_length : null), readOnly: _qrState == _QrScanState.success, textInputAction: TextInputAction.done, @@ -502,7 +502,7 @@ class _OathAddAccountPageState extends ConsumerState { strokeWidth: 2.0), label: _qrState == _QrScanState.success ? Text(l10n.l_qr_scanned) - : Text(l10n.l_qr_scan), + : Text(l10n.s_qr_scan), onPressed: () { _scanQrCode(qrScanner); }), @@ -515,7 +515,7 @@ class _OathAddAccountPageState extends ConsumerState { children: [ if (oathState?.version.isAtLeast(4, 2) ?? true) FilterChip( - label: Text(l10n.l_require_touch), + label: Text(l10n.s_require_touch), selected: _touch, onSelected: (value) { setState(() { @@ -557,7 +557,7 @@ class _OathAddAccountPageState extends ConsumerState { selected: int.tryParse(_periodController.text) != defaultPeriod, itemBuilder: ((value) => - Text(l10n.l_num_sec(value))), + Text(l10n.s_num_sec(value))), onChanged: _qrState != _QrScanState.success ? (period) { setState(() { @@ -571,7 +571,7 @@ class _OathAddAccountPageState extends ConsumerState { value: _digits, selected: _digits != defaultDigits, itemBuilder: (value) => - Text(l10n.l_num_digits(value)), + Text(l10n.s_num_digits(value)), onChanged: _qrState != _QrScanState.success ? (digits) { setState(() { diff --git a/lib/oath/views/delete_account_dialog.dart b/lib/oath/views/delete_account_dialog.dart index b93a5add..dc355651 100755 --- a/lib/oath/views/delete_account_dialog.dart +++ b/lib/oath/views/delete_account_dialog.dart @@ -37,7 +37,7 @@ class DeleteAccountDialog extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context)!; return ResponsiveDialog( - title: Text(l10n.l_delete_account), + title: Text(l10n.s_delete_account), actions: [ TextButton( key: keys.deleteButton, @@ -49,14 +49,14 @@ class DeleteAccountDialog extends ConsumerWidget { await ref.read(withContextProvider)( (context) async { Navigator.of(context).pop(true); - showMessage(context, l10n.l_account_deleted); + showMessage(context, l10n.s_account_deleted); }, ); } on CancellationException catch (_) { // ignored } }, - child: Text(l10n.w_delete), + child: Text(l10n.s_delete), ), ], child: Padding( diff --git a/lib/oath/views/key_actions.dart b/lib/oath/views/key_actions.dart index 719cae8b..635ef26e 100755 --- a/lib/oath/views/key_actions.dart +++ b/lib/oath/views/key_actions.dart @@ -45,9 +45,9 @@ Widget oathBuildActions( final theme = Theme.of(context).colorScheme; return SimpleDialog( children: [ - ListTitle(l10n.w_setup, textStyle: Theme.of(context).textTheme.bodyLarge), + ListTitle(l10n.s_setup, textStyle: Theme.of(context).textTheme.bodyLarge), ListTile( - title: Text(l10n.l_add_account), + title: Text(l10n.s_add_account), key: keys.addAccountAction, leading: const CircleAvatar(child: Icon(Icons.person_add_alt_1_outlined)), @@ -87,11 +87,11 @@ Widget oathBuildActions( } : null, ), - ListTitle(l10n.w_manage, + ListTitle(l10n.s_manage, textStyle: Theme.of(context).textTheme.bodyLarge), ListTile( key: keys.customIconsAction, - title: Text(l10n.l_custom_icons), + title: Text(l10n.s_custom_icons), subtitle: Text(l10n.l_set_icons_for_accounts), leading: const CircleAvatar( child: Icon(Icons.image_outlined), @@ -108,7 +108,7 @@ Widget oathBuildActions( ListTile( key: keys.setOrManagePasswordAction, title: Text( - oathState.hasKey ? l10n.l_manage_password : l10n.l_set_password), + oathState.hasKey ? l10n.s_manage_password : l10n.s_set_password), subtitle: Text(l10n.l_optional_password_protection), leading: const CircleAvatar(child: Icon(Icons.password_outlined)), onTap: () { @@ -120,7 +120,7 @@ Widget oathBuildActions( }), ListTile( key: keys.resetAction, - title: Text(l10n.l_reset_oath), + title: Text(l10n.s_reset_oath), subtitle: Text(l10n.l_factory_reset_this_app), leading: CircleAvatar( foregroundColor: theme.onError, diff --git a/lib/oath/views/manage_password_dialog.dart b/lib/oath/views/manage_password_dialog.dart index fe0ccb26..5d2c50d2 100755 --- a/lib/oath/views/manage_password_dialog.dart +++ b/lib/oath/views/manage_password_dialog.dart @@ -48,7 +48,7 @@ class _ManagePasswordDialogState extends ConsumerState { if (result) { if (!mounted) return; Navigator.of(context).pop(); - showMessage(context, AppLocalizations.of(context)!.l_password_set); + showMessage(context, AppLocalizations.of(context)!.s_password_set); } else { setState(() { _currentIsWrong = true; @@ -64,12 +64,12 @@ class _ManagePasswordDialogState extends ConsumerState { (!widget.state.hasKey || _currentPassword.isNotEmpty); return ResponsiveDialog( - title: Text(l10n.l_manage_password), + title: Text(l10n.s_manage_password), actions: [ TextButton( onPressed: isValid ? _submit : null, key: keys.savePasswordButton, - child: Text(l10n.w_save), + child: Text(l10n.s_save), ) ], child: Padding( @@ -85,9 +85,9 @@ class _ManagePasswordDialogState extends ConsumerState { key: keys.currentPasswordField, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_current_password, + labelText: l10n.s_current_password, prefixIcon: const Icon(Icons.password_outlined), - errorText: _currentIsWrong ? l10n.l_wrong_password : null, + errorText: _currentIsWrong ? l10n.s_wrong_password : null, errorMaxLines: 3), textInputAction: TextInputAction.next, onChanged: (value) { @@ -111,7 +111,7 @@ class _ManagePasswordDialogState extends ConsumerState { if (result) { if (!mounted) return; Navigator.of(context).pop(); - showMessage(context, l10n.l_password_removed); + showMessage(context, l10n.s_password_removed); } else { setState(() { _currentIsWrong = true; @@ -119,18 +119,18 @@ class _ManagePasswordDialogState extends ConsumerState { } } : null, - child: Text(l10n.l_remove_password), + child: Text(l10n.s_remove_password), ), if (widget.state.remembered) OutlinedButton( - child: Text(l10n.l_clear_saved_password), + child: Text(l10n.s_clear_saved_password), onPressed: () async { await ref .read(oathStateProvider(widget.path).notifier) .forgetPassword(); if (!mounted) return; Navigator.of(context).pop(); - showMessage(context, l10n.l_password_forgotten); + showMessage(context, l10n.s_password_forgotten); }, ), ], @@ -143,7 +143,7 @@ class _ManagePasswordDialogState extends ConsumerState { obscureText: true, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_new_password, + labelText: l10n.s_new_password, prefixIcon: const Icon(Icons.password_outlined), enabled: !widget.state.hasKey || _currentPassword.isNotEmpty, ), @@ -164,7 +164,7 @@ class _ManagePasswordDialogState extends ConsumerState { obscureText: true, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_confirm_password, + labelText: l10n.s_confirm_password, prefixIcon: const Icon(Icons.password_outlined), enabled: (!widget.state.hasKey || _currentPassword.isNotEmpty) && diff --git a/lib/oath/views/oath_screen.dart b/lib/oath/views/oath_screen.dart index 467c4313..d5f4270b 100755 --- a/lib/oath/views/oath_screen.dart +++ b/lib/oath/views/oath_screen.dart @@ -42,12 +42,12 @@ class OathScreen extends ConsumerWidget { final l10n = AppLocalizations.of(context)!; return ref.watch(oathStateProvider(devicePath)).when( loading: () => MessagePage( - title: Text(l10n.w_authenticator), + title: Text(l10n.s_authenticator), graphic: const CircularProgressIndicator(), delayedContent: true, ), error: (error, _) => AppFailurePage( - title: Text(l10n.w_authenticator), + title: Text(l10n.s_authenticator), cause: error, ), data: (oathState) => oathState.locked @@ -66,7 +66,7 @@ class _LockedView extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return AppPage( - title: Text(AppLocalizations.of(context)!.w_authenticator), + title: Text(AppLocalizations.of(context)!.s_authenticator), keyActionsBuilder: (context) => oathBuildActions(context, devicePath, oathState, ref), child: Padding( @@ -116,10 +116,10 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> { .select((value) => value?.length)); if (numCreds == 0) { return MessagePage( - title: Text(l10n.w_authenticator), + title: Text(l10n.s_authenticator), key: keys.noAccountsView, graphic: noAccounts, - header: l10n.l_no_accounts, + header: l10n.s_no_accounts, keyActionsBuilder: (context) => oathBuildActions( context, widget.devicePath, widget.oathState, ref, used: 0), @@ -154,7 +154,7 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> { style: textTheme.titleMedium ?.copyWith(fontSize: textTheme.titleSmall?.fontSize), decoration: InputDecoration( - hintText: l10n.l_search_accounts, + hintText: l10n.s_search_accounts, border: const OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(32)), ), diff --git a/lib/oath/views/rename_account_dialog.dart b/lib/oath/views/rename_account_dialog.dart index 4291ae1d..aa984ce6 100755 --- a/lib/oath/views/rename_account_dialog.dart +++ b/lib/oath/views/rename_account_dialog.dart @@ -73,7 +73,7 @@ class _RenameAccountDialogState extends ConsumerState { if (!mounted) return; Navigator.of(context).pop(renamed); - showMessage(context, l10n.l_account_renamed); + showMessage(context, l10n.s_account_renamed); } on CancellationException catch (_) { // ignored } catch (e) { @@ -127,12 +127,12 @@ class _RenameAccountDialogState extends ConsumerState { final isValid = isUnique && isValidFormat; return ResponsiveDialog( - title: Text(l10n.l_rename_account), + title: Text(l10n.s_rename_account), actions: [ TextButton( onPressed: didChange && isValid ? _submit : null, key: keys.saveButton, - child: Text(l10n.w_save), + child: Text(l10n.s_save), ), ], child: Padding( @@ -151,7 +151,7 @@ class _RenameAccountDialogState extends ConsumerState { key: keys.issuerField, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_issuer_optional, + labelText: l10n.s_issuer_optional, helperText: '', // Prevents dialog resizing when disabled prefixIcon: const Icon(Icons.business_outlined), ), @@ -170,7 +170,7 @@ class _RenameAccountDialogState extends ConsumerState { key: keys.nameField, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.l_account_name, + labelText: l10n.s_account_name, helperText: '', // Prevents dialog resizing when disabled errorText: !isValidFormat ? l10n.l_account_name_required diff --git a/lib/oath/views/reset_dialog.dart b/lib/oath/views/reset_dialog.dart index a615d65e..7f69ea46 100755 --- a/lib/oath/views/reset_dialog.dart +++ b/lib/oath/views/reset_dialog.dart @@ -32,7 +32,7 @@ class ResetDialog extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context)!; return ResponsiveDialog( - title: Text(l10n.l_factory_reset), + title: Text(l10n.s_factory_reset), actions: [ TextButton( onPressed: () async { @@ -42,7 +42,7 @@ class ResetDialog extends ConsumerWidget { showMessage(context, l10n.l_oath_application_reset); }); }, - child: Text(l10n.w_reset), + child: Text(l10n.s_reset), ), ], child: Padding( diff --git a/lib/oath/views/unlock_form.dart b/lib/oath/views/unlock_form.dart index ba89c019..2b04218e 100755 --- a/lib/oath/views/unlock_form.dart +++ b/lib/oath/views/unlock_form.dart @@ -79,8 +79,8 @@ class _UnlockFormState extends ConsumerState { obscureText: _isObscure, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: l10n.w_password, - errorText: _passwordIsWrong ? l10n.l_wrong_password : null, + labelText: l10n.s_password, + errorText: _passwordIsWrong ? l10n.s_wrong_password : null, helperText: '', // Prevents resizing when errorText shown prefixIcon: const Icon(Icons.password_outlined), suffixIcon: IconButton( @@ -111,7 +111,7 @@ class _UnlockFormState extends ConsumerState { minLeadingWidth: 0, ) : CheckboxListTile( - title: Text(l10n.l_remember_password), + title: Text(l10n.s_remember_password), dense: true, controlAffinity: ListTileControlAffinity.leading, value: _remember, @@ -127,7 +127,7 @@ class _UnlockFormState extends ConsumerState { alignment: Alignment.centerRight, child: ElevatedButton.icon( key: keys.unlockButton, - label: Text(l10n.w_unlock), + label: Text(l10n.s_unlock), icon: const Icon(Icons.lock_open), onPressed: _passwordController.text.isNotEmpty ? _submit : null, ), diff --git a/lib/settings_page.dart b/lib/settings_page.dart index d1695757..c8a708d2 100755 --- a/lib/settings_page.dart +++ b/lib/settings_page.dart @@ -39,7 +39,7 @@ class SettingsPage extends ConsumerWidget { final theme = Theme.of(context); final enableTranslations = ref.watch(communityTranslationsProvider); return ResponsiveDialog( - title: Text(l10n.w_settings), + title: Text(l10n.s_settings), child: Theme( // Make the headers use the primary color to pop a bit. // Once M3 is implemented this will probably not be needed. @@ -52,9 +52,9 @@ class SettingsPage extends ConsumerWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - ListTitle(l10n.w_appearance), + ListTitle(l10n.s_appearance), RadioListTile( - title: Text(l10n.l_system_default), + title: Text(l10n.s_system_default), value: ThemeMode.system, groupValue: themeMode, onChanged: (mode) { @@ -63,7 +63,7 @@ class SettingsPage extends ConsumerWidget { }, ), RadioListTile( - title: Text(l10n.l_light_mode), + title: Text(l10n.s_light_mode), value: ThemeMode.light, groupValue: themeMode, onChanged: (mode) { @@ -72,7 +72,7 @@ class SettingsPage extends ConsumerWidget { }, ), RadioListTile( - title: Text(l10n.l_dark_mode), + title: Text(l10n.s_dark_mode), value: ThemeMode.dark, groupValue: themeMode, onChanged: (mode) { @@ -84,7 +84,7 @@ class SettingsPage extends ConsumerWidget { basicLocaleListResolution(window.locales, officialLocales) != basicLocaleListResolution( window.locales, AppLocalizations.supportedLocales)) ...[ - ListTitle(l10n.w_language), + ListTitle(l10n.s_language), SwitchListTile( title: Text(l10n.l_enable_community_translations), subtitle: Text(l10n.p_community_translations_desc), diff --git a/lib/widgets/responsive_dialog.dart b/lib/widgets/responsive_dialog.dart index be8f1199..047ef6af 100755 --- a/lib/widgets/responsive_dialog.dart +++ b/lib/widgets/responsive_dialog.dart @@ -62,8 +62,8 @@ class _ResponsiveDialogState extends State { } else { // Dialog final cancelText = widget.onCancel == null && widget.actions.isEmpty - ? l10n.w_close - : l10n.w_cancel; + ? l10n.s_close + : l10n.s_cancel; return AlertDialog( title: widget.title, titlePadding: const EdgeInsets.only(top: 24, left: 18, right: 18), diff --git a/lib/widgets/utf8_utils.dart b/lib/widgets/utf8_utils.dart index 6c19bbaa..8a062881 100755 --- a/lib/widgets/utf8_utils.dart +++ b/lib/widgets/utf8_utils.dart @@ -38,7 +38,7 @@ InputCounterWidgetBuilder buildByteCounterFor(String currentValue) => return Text( maxLength != null ? '${byteLength(currentValue)}/$maxLength' : '', style: style, - semanticsLabel: AppLocalizations.of(context)!.l_character_count, + semanticsLabel: AppLocalizations.of(context)!.s_character_count, ); };