From 520e0673e0fcf021fd01be66f1ec6e4dcedbe644 Mon Sep 17 00:00:00 2001 From: MuZhou233 Date: Fri, 26 Jan 2024 00:11:30 +0000 Subject: [PATCH] fix: improve l10n --- l10n_arb/intl_en.arb | 98 +++- l10n_arb/intl_zh_CN.arb | 5 - lib/bloc/chesed/chesed_bloc.dart | 8 +- lib/bloc/gebura/gebura_bloc.dart | 26 +- lib/bloc/yesod/yesod_bloc.dart | 3 +- lib/l10n/intl/messages_en.dart | 147 +++++- lib/l10n/l10n.dart | 644 +++++++++++++++++++++--- lib/repo/grpc/api_helper.dart | 14 +- lib/view/components/toast.dart | 3 +- lib/view/helper/duration_format.dart | 12 +- lib/view/pages/init_page.dart | 11 +- lib/view/pages/login_page.dart | 71 ++- lib/view/pages/settings/about_page.dart | 3 +- lib/view/specialized/title_bar.dart | 13 +- pubspec.yaml | 2 +- 15 files changed, 901 insertions(+), 159 deletions(-) diff --git a/l10n_arb/intl_en.arb b/l10n_arb/intl_en.arb index 3b0e613..5cff613 100644 --- a/l10n_arb/intl_en.arb +++ b/l10n_arb/intl_en.arb @@ -1,9 +1,97 @@ { "@@locale":"en", "title": "TuiHub", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - } + "buttonConfirm": "Confirm", + "buttonClose": "Close", + "parseFailed": "Parse failed", + "unknownErrorOccurred": "Unknown error occurred", + "areYouSureToClose": "Are you sure to close?", + "buttonExit": "Exit", + "buttonMinimizeToTray": "Minimize to tray", + "buttonCancel": "Cancel", + "webVersionFunctionLimited": "Web version has limited functionality, for evaluation use only", + + "durationJustNow": "Just now", + "durationSeconds": "{number} seconds ago", + "durationMinutes": "{number} minutes ago", + "durationHours": "{number} hours ago", + "durationDays": "{number} days ago", + "durationWeeks": "{number} weeks ago", + "durationMonths": "{number} months ago", + "durationYears": "{number} years ago", + + "welcomeHeader": "\uD83C\uDF89Welcome!", + "welcome": "Welcome", + "welcomeBack": "Welcome back", + "login": "Login", + "clickLoginToStart": "CLICK LOGIN TO START", + "serverSetup": "Server setup", + "address": "Address", + "pleaseInputServerAddress": "Please input server address", + "port": "Port", + "pleaseInputServerPort": "Please input server port", + "tls": "TLS", + "buttonCheck": "Check", + "loginFailed": "Login failed, {reason}", + "buttonRetry": "Retry", + "loggingInTo": "Logging in to {server}", + "buttonBackward": "Backward", + "username": "Username", + "password": "Password", + "buttonLogin": "Login", + + "chesed": "Chesed", + "updateImageUserCanceledPick": "User canceled pick", + "updateImageUserCanceledCapture": "User canceled capture", + "uploadImageFailed": "Upload image failed", + + "gebura": "Gebura", + "pleaseSetupApplicationPath": "Please setup application path", + "pleaseDontReRunApplication": "Please don't re-run application", + "applicationExitAbnormally": "Application exit abnormally", + "launcherError": "Launcher error", + "scanningLocalFiles": "Scanning local files", + "newApplicationFound": "{number} new applications found", + "importingSteamApplications": "Importing steam applications", + "importSteamApplicationFinished": "Import steam application finished, {success} success, {failed} failed", + + "grpc": "gRPC", + "USER_TYPE": "Type", + "USER_TYPE_UNSPECIFIED": "Unspecified", + "USER_TYPE_ADMIN": "Admin", + "USER_TYPE_NORMAL": "Normal", + "USER_TYPE_SENTINEL": "Sentinel", + "USER_STATUS": "Status", + "USER_STATUS_UNSPECIFIED": "Unspecified", + "USER_STATUS_ACTIVE": "Active", + "USER_STATUS_BLOCKED": "Blocked", + "ACCOUNT_PLATFORM": "Platform", + "ACCOUNT_PLATFORM_UNSPECIFIED": "Unspecified", + "ACCOUNT_PLATFORM_STEAM": "Steam", + "APP_SOURCE": "Source", + "APP_SOURCE_UNSPECIFIED": "Unspecified", + "APP_SOURCE_INTERNAL": "Internal", + "APP_SOURCE_STEAM": "Steam", + "APP_TYPE": "Type", + "APP_TYPE_UNSPECIFIED": "Unspecified", + "APP_TYPE_GAME": "Game", + "APP_PACKAGE_SOURCE": "Source", + "APP_PACKAGE_SOURCE_UNSPECIFIED": "Unspecified", + "APP_PACKAGE_SOURCE_MANUAL": "Manual", + "APP_PACKAGE_SOURCE_SENTINEL": "Sentinel", + "FEED_CONFIG_STATUS": "Status", + "FEED_CONFIG_STATUS_UNSPECIFIED": "Unspecified", + "FEED_CONFIG_STATUS_ACTIVE": "Active", + "FEED_CONFIG_STATUS_SUSPEND": "Suspend", + "NOTIFY_TARGET_STATUS": "Status", + "NOTIFY_TARGET_STATUS_UNSPECIFIED": "Unspecified", + "NOTIFY_TARGET_STATUS_ACTIVE": "Active", + "NOTIFY_TARGET_STATUS_SUSPEND": "Suspend", + "NOTIFY_TARGET_TYPE": "Type", + "NOTIFY_TARGET_TYPE_UNSPECIFIED": "Unspecified", + "NOTIFY_TARGET_TYPE_TELEGRAM": "Telegram", + "NOTIFY_FLOW_STATUS": "Status", + "NOTIFY_FLOW_STATUS_UNSPECIFIED": "Unspecified", + "NOTIFY_FLOW_STATUS_ACTIVE": "Active", + "NOTIFY_FLOW_STATUS_SUSPEND": "Suspend" } \ No newline at end of file diff --git a/l10n_arb/intl_zh_CN.arb b/l10n_arb/intl_zh_CN.arb index 3fdcfcb..b768744 100644 --- a/l10n_arb/intl_zh_CN.arb +++ b/l10n_arb/intl_zh_CN.arb @@ -1,11 +1,6 @@ { "@@locale":"zh_CN", "title": "TuiHub", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, "USER_TYPE": "类型", "USER_TYPE_UNSPECIFIED": "未知", "USER_TYPE_ADMIN": "管理员", diff --git a/lib/bloc/chesed/chesed_bloc.dart b/lib/bloc/chesed/chesed_bloc.dart index 0d88f54..5598c68 100644 --- a/lib/bloc/chesed/chesed_bloc.dart +++ b/lib/bloc/chesed/chesed_bloc.dart @@ -14,6 +14,7 @@ import 'package:tuihub_protos/librarian/v1/common.pb.dart'; import 'package:universal_io/io.dart'; import '../../common/bloc_event_status_mixin.dart'; +import '../../l10n/l10n.dart'; import '../../repo/grpc/api_helper.dart'; part 'chesed_event.dart'; @@ -89,7 +90,7 @@ class ChesedBloc extends Bloc { extension = pick.extension!; } else { emit(ChesedUploadImageState(state, EventStatus.failed, - msg: 'User canceled pick')); + msg: S.current.updateImageUserCanceledPick)); return; } } @@ -119,7 +120,7 @@ class ChesedBloc extends Bloc { extension = 'png'; } else { emit(ChesedUploadImageState(state, EventStatus.failed, - msg: 'User canceled capture')); + msg: S.current.updateImageUserCanceledCapture)); return; } } @@ -145,7 +146,8 @@ class ChesedBloc extends Bloc { body: await file.readAsBytes(), ); if (uploadResponse.statusCode != 200) { - throw Exception('文件上传失败: ${uploadResponse.reasonPhrase}'); + throw Exception( + '${S.current.uploadImageFailed} ${uploadResponse.reasonPhrase}'); } await _api.doRequestWithOptions( (client) => client.presignedUploadFileStatus, diff --git a/lib/bloc/gebura/gebura_bloc.dart b/lib/bloc/gebura/gebura_bloc.dart index cd5d06e..c986ee0 100644 --- a/lib/bloc/gebura/gebura_bloc.dart +++ b/lib/bloc/gebura/gebura_bloc.dart @@ -12,6 +12,7 @@ import '../../common/platform.dart'; import '../../common/steam/local_library.dart'; import '../../ffi/ffi.dart'; import '../../ffi/ffi_model.dart'; +import '../../l10n/l10n.dart'; import '../../model/gebura_model.dart'; import '../../repo/grpc/api_helper.dart'; import '../../repo/local/gebura.dart'; @@ -191,13 +192,13 @@ class GeburaBloc extends Bloc { final setting = _repo.getAppLauncherSetting(event.appID.id.toInt()); if (setting == null || setting.path.isEmpty) { emit(GeburaRunAppState(state, event.appID, EventStatus.failed, - msg: '请先设置应用路径')); + msg: S.current.pleaseSetupApplicationPath)); return; } if (state.runState![event.appID] != null && state.runState![event.appID]!.running) { emit(GeburaRunAppState(state, event.appID, EventStatus.failed, - msg: '请勿重复运行')); + msg: S.current.pleaseDontReRunApplication)); return; } state.runState![event.appID] = @@ -216,7 +217,7 @@ class GeburaBloc extends Bloc { state.runState![event.appID] = state.runState![event.appID]!.copyWith(running: false); emit(GeburaRunAppState(state, event.appID, EventStatus.failed, - msg: '应用未正常退出')); + msg: S.current.applicationExitAbnormally)); return; } state.runState![event.appID] = AppRunState( @@ -233,7 +234,8 @@ class GeburaBloc extends Bloc { state.runState![event.appID] = state.runState![event.appID]!.copyWith(running: false); emit(GeburaRunAppState(state, event.appID, EventStatus.failed, - msg: '启动器错误 ${e is FrbAnyhowException ? e.anyhow : e}')); + msg: + '${S.current.launcherError} ${e is FrbAnyhowException ? e.anyhow : e}')); return; } }); @@ -242,15 +244,16 @@ class GeburaBloc extends Bloc { if (!PlatformHelper.isWindowsApp()) { return; } - emit(state.copyWith(localLibraryState: '正在扫描本地文件')); + emit(state.copyWith(localLibraryState: S.current.scanningLocalFiles)); final (apps, result) = await scanLocalLibrary(); final folders = await getSteamLibraryFolders(); final imported = _repo.getImportedSteamApps(); final unImported = apps.where((element) => !imported.any((imported) => imported.steamAppID == element.appId)); emit(state.copyWith( - localLibraryState: - unImported.isNotEmpty ? '发现${unImported.length}个本地游戏' : '', + localLibraryState: unImported.isNotEmpty + ? S.current.newApplicationFound(unImported.length) + : '', localSteamScanResult: result, localSteamApps: apps, importedSteamApps: imported, @@ -263,7 +266,8 @@ class GeburaBloc extends Bloc { return; } emit(GeburaImportSteamAppsState( - state.copyWith(localLibraryState: '正在导入Steam应用'), + state.copyWith( + localLibraryState: S.current.importingSteamApplications), EventStatus.processing)); var processCount = 0; var failedCount = 0; @@ -273,7 +277,7 @@ class GeburaBloc extends Bloc { emit(GeburaImportSteamAppsState( state.copyWith( localLibraryState: - '正在导入Steam应用 $processCount ( $failedCount ) / ${event.appIDs.length}', + '${S.current.importingSteamApplications} $processCount ( $failedCount ) / ${event.appIDs.length}', ), EventStatus.processing)); if (importedSteamApps.any((element) => element.steamAppID == app)) { @@ -331,8 +335,8 @@ class GeburaBloc extends Bloc { add(GeburaPurchasedAppsLoadEvent()); emit(GeburaImportSteamAppsState( state.copyWith( - localLibraryState: - 'Steam应用导入完成,${processCount - failedCount}成功,$failedCount失败', + localLibraryState: S.current.importSteamApplicationFinished( + processCount - failedCount, failedCount), importedSteamApps: importedSteamApps, ), EventStatus.success)); diff --git a/lib/bloc/yesod/yesod_bloc.dart b/lib/bloc/yesod/yesod_bloc.dart index 317d0eb..334aa7b 100644 --- a/lib/bloc/yesod/yesod_bloc.dart +++ b/lib/bloc/yesod/yesod_bloc.dart @@ -9,6 +9,7 @@ import 'package:tuihub_protos/librarian/v1/common.pb.dart'; import 'package:webfeed_revised/domain/rss_feed.dart'; import '../../common/bloc_event_status_mixin.dart'; +import '../../l10n/l10n.dart'; import '../../model/yesod_model.dart'; import '../../repo/grpc/api_helper.dart'; import '../../repo/local/yesod.dart'; @@ -138,7 +139,7 @@ class YesodBloc extends Bloc { title: '', link: '', iconUrl: '', description: '')), ), EventStatus.failed, - msg: '解析失败, $e', + msg: '${S.current.parseFailed} $e', )); } }, transformer: droppable()); diff --git a/lib/l10n/intl/messages_en.dart b/lib/l10n/intl/messages_en.dart index 24e1638..6e52794 100644 --- a/lib/l10n/intl/messages_en.dart +++ b/lib/l10n/intl/messages_en.dart @@ -20,8 +20,153 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'en'; + static String m0(number) => "${number} days ago"; + + static String m1(number) => "${number} hours ago"; + + static String m2(number) => "${number} minutes ago"; + + static String m3(number) => "${number} months ago"; + + static String m4(number) => "${number} seconds ago"; + + static String m5(number) => "${number} weeks ago"; + + static String m6(number) => "${number} years ago"; + + static String m7(success, failed) => + "Import steam application finished, ${success} success, ${failed} failed"; + + static String m8(server) => "Logging in to ${server}"; + + static String m9(reason) => "Login failed, ${reason}"; + + static String m10(number) => "${number} new applications found"; + final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { - "title": MessageLookupByLibrary.simpleMessage("TuiHub") + "ACCOUNT_PLATFORM": MessageLookupByLibrary.simpleMessage("Platform"), + "ACCOUNT_PLATFORM_STEAM": MessageLookupByLibrary.simpleMessage("Steam"), + "ACCOUNT_PLATFORM_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "APP_PACKAGE_SOURCE": MessageLookupByLibrary.simpleMessage("Source"), + "APP_PACKAGE_SOURCE_MANUAL": + MessageLookupByLibrary.simpleMessage("Manual"), + "APP_PACKAGE_SOURCE_SENTINEL": + MessageLookupByLibrary.simpleMessage("Sentinel"), + "APP_PACKAGE_SOURCE_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "APP_SOURCE": MessageLookupByLibrary.simpleMessage("Source"), + "APP_SOURCE_INTERNAL": MessageLookupByLibrary.simpleMessage("Internal"), + "APP_SOURCE_STEAM": MessageLookupByLibrary.simpleMessage("Steam"), + "APP_SOURCE_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "APP_TYPE": MessageLookupByLibrary.simpleMessage("Type"), + "APP_TYPE_GAME": MessageLookupByLibrary.simpleMessage("Game"), + "APP_TYPE_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "FEED_CONFIG_STATUS": MessageLookupByLibrary.simpleMessage("Status"), + "FEED_CONFIG_STATUS_ACTIVE": + MessageLookupByLibrary.simpleMessage("Active"), + "FEED_CONFIG_STATUS_SUSPEND": + MessageLookupByLibrary.simpleMessage("Suspend"), + "FEED_CONFIG_STATUS_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "NOTIFY_FLOW_STATUS": MessageLookupByLibrary.simpleMessage("Status"), + "NOTIFY_FLOW_STATUS_ACTIVE": + MessageLookupByLibrary.simpleMessage("Active"), + "NOTIFY_FLOW_STATUS_SUSPEND": + MessageLookupByLibrary.simpleMessage("Suspend"), + "NOTIFY_FLOW_STATUS_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "NOTIFY_TARGET_STATUS": MessageLookupByLibrary.simpleMessage("Status"), + "NOTIFY_TARGET_STATUS_ACTIVE": + MessageLookupByLibrary.simpleMessage("Active"), + "NOTIFY_TARGET_STATUS_SUSPEND": + MessageLookupByLibrary.simpleMessage("Suspend"), + "NOTIFY_TARGET_STATUS_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "NOTIFY_TARGET_TYPE": MessageLookupByLibrary.simpleMessage("Type"), + "NOTIFY_TARGET_TYPE_TELEGRAM": + MessageLookupByLibrary.simpleMessage("Telegram"), + "NOTIFY_TARGET_TYPE_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "USER_STATUS": MessageLookupByLibrary.simpleMessage("Status"), + "USER_STATUS_ACTIVE": MessageLookupByLibrary.simpleMessage("Active"), + "USER_STATUS_BLOCKED": MessageLookupByLibrary.simpleMessage("Blocked"), + "USER_STATUS_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "USER_TYPE": MessageLookupByLibrary.simpleMessage("Type"), + "USER_TYPE_ADMIN": MessageLookupByLibrary.simpleMessage("Admin"), + "USER_TYPE_NORMAL": MessageLookupByLibrary.simpleMessage("Normal"), + "USER_TYPE_SENTINEL": MessageLookupByLibrary.simpleMessage("Sentinel"), + "USER_TYPE_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("Unspecified"), + "address": MessageLookupByLibrary.simpleMessage("Address"), + "applicationExitAbnormally": + MessageLookupByLibrary.simpleMessage("Application exit abnormally"), + "areYouSureToClose": + MessageLookupByLibrary.simpleMessage("Are you sure to close?"), + "buttonBackward": MessageLookupByLibrary.simpleMessage("Backward"), + "buttonCancel": MessageLookupByLibrary.simpleMessage("Cancel"), + "buttonCheck": MessageLookupByLibrary.simpleMessage("Check"), + "buttonClose": MessageLookupByLibrary.simpleMessage("Close"), + "buttonConfirm": MessageLookupByLibrary.simpleMessage("Confirm"), + "buttonExit": MessageLookupByLibrary.simpleMessage("Exit"), + "buttonLogin": MessageLookupByLibrary.simpleMessage("Login"), + "buttonMinimizeToTray": + MessageLookupByLibrary.simpleMessage("Minimize to tray"), + "buttonRetry": MessageLookupByLibrary.simpleMessage("Retry"), + "chesed": MessageLookupByLibrary.simpleMessage("Chesed"), + "clickLoginToStart": + MessageLookupByLibrary.simpleMessage("CLICK LOGIN TO START"), + "durationDays": m0, + "durationHours": m1, + "durationJustNow": MessageLookupByLibrary.simpleMessage("Just now"), + "durationMinutes": m2, + "durationMonths": m3, + "durationSeconds": m4, + "durationWeeks": m5, + "durationYears": m6, + "gebura": MessageLookupByLibrary.simpleMessage("Gebura"), + "grpc": MessageLookupByLibrary.simpleMessage("gRPC"), + "importSteamApplicationFinished": m7, + "importingSteamApplications": MessageLookupByLibrary.simpleMessage( + "Importing steam applications"), + "launcherError": MessageLookupByLibrary.simpleMessage("Launcher error"), + "loggingInTo": m8, + "login": MessageLookupByLibrary.simpleMessage("Login"), + "loginFailed": m9, + "newApplicationFound": m10, + "parseFailed": MessageLookupByLibrary.simpleMessage("Parse failed"), + "password": MessageLookupByLibrary.simpleMessage("Password"), + "pleaseDontReRunApplication": MessageLookupByLibrary.simpleMessage( + "Please don\'t re-run application"), + "pleaseInputServerAddress": + MessageLookupByLibrary.simpleMessage("Please input server address"), + "pleaseInputServerPort": + MessageLookupByLibrary.simpleMessage("Please input server port"), + "pleaseSetupApplicationPath": MessageLookupByLibrary.simpleMessage( + "Please setup application path"), + "port": MessageLookupByLibrary.simpleMessage("Port"), + "scanningLocalFiles": + MessageLookupByLibrary.simpleMessage("Scanning local files"), + "serverSetup": MessageLookupByLibrary.simpleMessage("Server setup"), + "title": MessageLookupByLibrary.simpleMessage("TuiHub"), + "tls": MessageLookupByLibrary.simpleMessage("TLS"), + "unknownErrorOccurred": + MessageLookupByLibrary.simpleMessage("Unknown error occurred"), + "updateImageUserCanceledCapture": + MessageLookupByLibrary.simpleMessage("User canceled capture"), + "updateImageUserCanceledPick": + MessageLookupByLibrary.simpleMessage("User canceled pick"), + "uploadImageFailed": + MessageLookupByLibrary.simpleMessage("Upload image failed"), + "username": MessageLookupByLibrary.simpleMessage("Username"), + "webVersionFunctionLimited": MessageLookupByLibrary.simpleMessage( + "Web version has limited functionality, for evaluation use only"), + "welcome": MessageLookupByLibrary.simpleMessage("Welcome"), + "welcomeBack": MessageLookupByLibrary.simpleMessage("Welcome back"), + "welcomeHeader": MessageLookupByLibrary.simpleMessage("🎉Welcome!") }; } diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart index 241207f..cd67604 100644 --- a/lib/l10n/l10n.dart +++ b/lib/l10n/l10n.dart @@ -55,115 +55,615 @@ class S { return Intl.message( 'TuiHub', name: 'title', - desc: 'Title for the application', + desc: '', + args: [], + ); + } + + /// `Confirm` + String get buttonConfirm { + return Intl.message( + 'Confirm', + name: 'buttonConfirm', + desc: '', + args: [], + ); + } + + /// `Close` + String get buttonClose { + return Intl.message( + 'Close', + name: 'buttonClose', + desc: '', + args: [], + ); + } + + /// `Parse failed` + String get parseFailed { + return Intl.message( + 'Parse failed', + name: 'parseFailed', + desc: '', + args: [], + ); + } + + /// `Unknown error occurred` + String get unknownErrorOccurred { + return Intl.message( + 'Unknown error occurred', + name: 'unknownErrorOccurred', + desc: '', + args: [], + ); + } + + /// `Are you sure to close?` + String get areYouSureToClose { + return Intl.message( + 'Are you sure to close?', + name: 'areYouSureToClose', + desc: '', + args: [], + ); + } + + /// `Exit` + String get buttonExit { + return Intl.message( + 'Exit', + name: 'buttonExit', + desc: '', + args: [], + ); + } + + /// `Minimize to tray` + String get buttonMinimizeToTray { + return Intl.message( + 'Minimize to tray', + name: 'buttonMinimizeToTray', + desc: '', + args: [], + ); + } + + /// `Cancel` + String get buttonCancel { + return Intl.message( + 'Cancel', + name: 'buttonCancel', + desc: '', + args: [], + ); + } + + /// `Web version has limited functionality, for evaluation use only` + String get webVersionFunctionLimited { + return Intl.message( + 'Web version has limited functionality, for evaluation use only', + name: 'webVersionFunctionLimited', + desc: '', + args: [], + ); + } + + /// `Just now` + String get durationJustNow { + return Intl.message( + 'Just now', + name: 'durationJustNow', + desc: '', + args: [], + ); + } + + /// `{number} seconds ago` + String durationSeconds(Object number) { + return Intl.message( + '$number seconds ago', + name: 'durationSeconds', + desc: '', + args: [number], + ); + } + + /// `{number} minutes ago` + String durationMinutes(Object number) { + return Intl.message( + '$number minutes ago', + name: 'durationMinutes', + desc: '', + args: [number], + ); + } + + /// `{number} hours ago` + String durationHours(Object number) { + return Intl.message( + '$number hours ago', + name: 'durationHours', + desc: '', + args: [number], + ); + } + + /// `{number} days ago` + String durationDays(Object number) { + return Intl.message( + '$number days ago', + name: 'durationDays', + desc: '', + args: [number], + ); + } + + /// `{number} weeks ago` + String durationWeeks(Object number) { + return Intl.message( + '$number weeks ago', + name: 'durationWeeks', + desc: '', + args: [number], + ); + } + + /// `{number} months ago` + String durationMonths(Object number) { + return Intl.message( + '$number months ago', + name: 'durationMonths', + desc: '', + args: [number], + ); + } + + /// `{number} years ago` + String durationYears(Object number) { + return Intl.message( + '$number years ago', + name: 'durationYears', + desc: '', + args: [number], + ); + } + + /// `🎉Welcome!` + String get welcomeHeader { + return Intl.message( + '🎉Welcome!', + name: 'welcomeHeader', + desc: '', + args: [], + ); + } + + /// `Welcome` + String get welcome { + return Intl.message( + 'Welcome', + name: 'welcome', + desc: '', + args: [], + ); + } + + /// `Welcome back` + String get welcomeBack { + return Intl.message( + 'Welcome back', + name: 'welcomeBack', + desc: '', + args: [], + ); + } + + /// `Login` + String get login { + return Intl.message( + 'Login', + name: 'login', + desc: '', + args: [], + ); + } + + /// `CLICK LOGIN TO START` + String get clickLoginToStart { + return Intl.message( + 'CLICK LOGIN TO START', + name: 'clickLoginToStart', + desc: '', + args: [], + ); + } + + /// `Server setup` + String get serverSetup { + return Intl.message( + 'Server setup', + name: 'serverSetup', + desc: '', + args: [], + ); + } + + /// `Address` + String get address { + return Intl.message( + 'Address', + name: 'address', + desc: '', + args: [], + ); + } + + /// `Please input server address` + String get pleaseInputServerAddress { + return Intl.message( + 'Please input server address', + name: 'pleaseInputServerAddress', + desc: '', + args: [], + ); + } + + /// `Port` + String get port { + return Intl.message( + 'Port', + name: 'port', + desc: '', + args: [], + ); + } + + /// `Please input server port` + String get pleaseInputServerPort { + return Intl.message( + 'Please input server port', + name: 'pleaseInputServerPort', + desc: '', + args: [], + ); + } + + /// `TLS` + String get tls { + return Intl.message( + 'TLS', + name: 'tls', + desc: '', + args: [], + ); + } + + /// `Check` + String get buttonCheck { + return Intl.message( + 'Check', + name: 'buttonCheck', + desc: '', + args: [], + ); + } + + /// `Login failed, {reason}` + String loginFailed(Object reason) { + return Intl.message( + 'Login failed, $reason', + name: 'loginFailed', + desc: '', + args: [reason], + ); + } + + /// `Retry` + String get buttonRetry { + return Intl.message( + 'Retry', + name: 'buttonRetry', + desc: '', + args: [], + ); + } + + /// `Logging in to {server}` + String loggingInTo(Object server) { + return Intl.message( + 'Logging in to $server', + name: 'loggingInTo', + desc: '', + args: [server], + ); + } + + /// `Backward` + String get buttonBackward { + return Intl.message( + 'Backward', + name: 'buttonBackward', + desc: '', + args: [], + ); + } + + /// `Username` + String get username { + return Intl.message( + 'Username', + name: 'username', + desc: '', + args: [], + ); + } + + /// `Password` + String get password { + return Intl.message( + 'Password', + name: 'password', + desc: '', + args: [], + ); + } + + /// `Login` + String get buttonLogin { + return Intl.message( + 'Login', + name: 'buttonLogin', + desc: '', + args: [], + ); + } + + /// `Chesed` + String get chesed { + return Intl.message( + 'Chesed', + name: 'chesed', + desc: '', + args: [], + ); + } + + /// `User canceled pick` + String get updateImageUserCanceledPick { + return Intl.message( + 'User canceled pick', + name: 'updateImageUserCanceledPick', + desc: '', + args: [], + ); + } + + /// `User canceled capture` + String get updateImageUserCanceledCapture { + return Intl.message( + 'User canceled capture', + name: 'updateImageUserCanceledCapture', + desc: '', + args: [], + ); + } + + /// `Upload image failed` + String get uploadImageFailed { + return Intl.message( + 'Upload image failed', + name: 'uploadImageFailed', + desc: '', + args: [], + ); + } + + /// `Gebura` + String get gebura { + return Intl.message( + 'Gebura', + name: 'gebura', + desc: '', + args: [], + ); + } + + /// `Please setup application path` + String get pleaseSetupApplicationPath { + return Intl.message( + 'Please setup application path', + name: 'pleaseSetupApplicationPath', + desc: '', + args: [], + ); + } + + /// `Please don't re-run application` + String get pleaseDontReRunApplication { + return Intl.message( + 'Please don\'t re-run application', + name: 'pleaseDontReRunApplication', + desc: '', + args: [], + ); + } + + /// `Application exit abnormally` + String get applicationExitAbnormally { + return Intl.message( + 'Application exit abnormally', + name: 'applicationExitAbnormally', + desc: '', args: [], ); } - /// `类型` + /// `Launcher error` + String get launcherError { + return Intl.message( + 'Launcher error', + name: 'launcherError', + desc: '', + args: [], + ); + } + + /// `Scanning local files` + String get scanningLocalFiles { + return Intl.message( + 'Scanning local files', + name: 'scanningLocalFiles', + desc: '', + args: [], + ); + } + + /// `{number} new applications found` + String newApplicationFound(Object number) { + return Intl.message( + '$number new applications found', + name: 'newApplicationFound', + desc: '', + args: [number], + ); + } + + /// `Importing steam applications` + String get importingSteamApplications { + return Intl.message( + 'Importing steam applications', + name: 'importingSteamApplications', + desc: '', + args: [], + ); + } + + /// `Import steam application finished, {success} success, {failed} failed` + String importSteamApplicationFinished(Object success, Object failed) { + return Intl.message( + 'Import steam application finished, $success success, $failed failed', + name: 'importSteamApplicationFinished', + desc: '', + args: [success, failed], + ); + } + + /// `gRPC` + String get grpc { + return Intl.message( + 'gRPC', + name: 'grpc', + desc: '', + args: [], + ); + } + + /// `Type` String get USER_TYPE { return Intl.message( - '类型', + 'Type', name: 'USER_TYPE', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get USER_TYPE_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'USER_TYPE_UNSPECIFIED', desc: '', args: [], ); } - /// `管理员` + /// `Admin` String get USER_TYPE_ADMIN { return Intl.message( - '管理员', + 'Admin', name: 'USER_TYPE_ADMIN', desc: '', args: [], ); } - /// `普通` + /// `Normal` String get USER_TYPE_NORMAL { return Intl.message( - '普通', + 'Normal', name: 'USER_TYPE_NORMAL', desc: '', args: [], ); } - /// `扫描器` + /// `Sentinel` String get USER_TYPE_SENTINEL { return Intl.message( - '扫描器', + 'Sentinel', name: 'USER_TYPE_SENTINEL', desc: '', args: [], ); } - /// `状态` + /// `Status` String get USER_STATUS { return Intl.message( - '状态', + 'Status', name: 'USER_STATUS', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get USER_STATUS_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'USER_STATUS_UNSPECIFIED', desc: '', args: [], ); } - /// `正常` + /// `Active` String get USER_STATUS_ACTIVE { return Intl.message( - '正常', + 'Active', name: 'USER_STATUS_ACTIVE', desc: '', args: [], ); } - /// `禁用` + /// `Blocked` String get USER_STATUS_BLOCKED { return Intl.message( - '禁用', + 'Blocked', name: 'USER_STATUS_BLOCKED', desc: '', args: [], ); } - /// `平台` + /// `Platform` String get ACCOUNT_PLATFORM { return Intl.message( - '平台', + 'Platform', name: 'ACCOUNT_PLATFORM', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get ACCOUNT_PLATFORM_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'ACCOUNT_PLATFORM_UNSPECIFIED', desc: '', args: [], @@ -180,30 +680,30 @@ class S { ); } - /// `来源` + /// `Source` String get APP_SOURCE { return Intl.message( - '来源', + 'Source', name: 'APP_SOURCE', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get APP_SOURCE_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'APP_SOURCE_UNSPECIFIED', desc: '', args: [], ); } - /// `内置` + /// `Internal` String get APP_SOURCE_INTERNAL { return Intl.message( - '内置', + 'Internal', name: 'APP_SOURCE_INTERNAL', desc: '', args: [], @@ -220,170 +720,170 @@ class S { ); } - /// `类型` + /// `Type` String get APP_TYPE { return Intl.message( - '类型', + 'Type', name: 'APP_TYPE', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get APP_TYPE_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'APP_TYPE_UNSPECIFIED', desc: '', args: [], ); } - /// `游戏` + /// `Game` String get APP_TYPE_GAME { return Intl.message( - '游戏', + 'Game', name: 'APP_TYPE_GAME', desc: '', args: [], ); } - /// `来源` + /// `Source` String get APP_PACKAGE_SOURCE { return Intl.message( - '来源', + 'Source', name: 'APP_PACKAGE_SOURCE', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get APP_PACKAGE_SOURCE_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'APP_PACKAGE_SOURCE_UNSPECIFIED', desc: '', args: [], ); } - /// `手动` + /// `Manual` String get APP_PACKAGE_SOURCE_MANUAL { return Intl.message( - '手动', + 'Manual', name: 'APP_PACKAGE_SOURCE_MANUAL', desc: '', args: [], ); } - /// `扫描` + /// `Sentinel` String get APP_PACKAGE_SOURCE_SENTINEL { return Intl.message( - '扫描', + 'Sentinel', name: 'APP_PACKAGE_SOURCE_SENTINEL', desc: '', args: [], ); } - /// `状态` + /// `Status` String get FEED_CONFIG_STATUS { return Intl.message( - '状态', + 'Status', name: 'FEED_CONFIG_STATUS', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get FEED_CONFIG_STATUS_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'FEED_CONFIG_STATUS_UNSPECIFIED', desc: '', args: [], ); } - /// `启用` + /// `Active` String get FEED_CONFIG_STATUS_ACTIVE { return Intl.message( - '启用', + 'Active', name: 'FEED_CONFIG_STATUS_ACTIVE', desc: '', args: [], ); } - /// `停止` + /// `Suspend` String get FEED_CONFIG_STATUS_SUSPEND { return Intl.message( - '停止', + 'Suspend', name: 'FEED_CONFIG_STATUS_SUSPEND', desc: '', args: [], ); } - /// `状态` + /// `Status` String get NOTIFY_TARGET_STATUS { return Intl.message( - '状态', + 'Status', name: 'NOTIFY_TARGET_STATUS', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get NOTIFY_TARGET_STATUS_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'NOTIFY_TARGET_STATUS_UNSPECIFIED', desc: '', args: [], ); } - /// `启用` + /// `Active` String get NOTIFY_TARGET_STATUS_ACTIVE { return Intl.message( - '启用', + 'Active', name: 'NOTIFY_TARGET_STATUS_ACTIVE', desc: '', args: [], ); } - /// `停止` + /// `Suspend` String get NOTIFY_TARGET_STATUS_SUSPEND { return Intl.message( - '停止', + 'Suspend', name: 'NOTIFY_TARGET_STATUS_SUSPEND', desc: '', args: [], ); } - /// `类型` + /// `Type` String get NOTIFY_TARGET_TYPE { return Intl.message( - '类型', + 'Type', name: 'NOTIFY_TARGET_TYPE', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get NOTIFY_TARGET_TYPE_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'NOTIFY_TARGET_TYPE_UNSPECIFIED', desc: '', args: [], @@ -400,40 +900,40 @@ class S { ); } - /// `状态` + /// `Status` String get NOTIFY_FLOW_STATUS { return Intl.message( - '状态', + 'Status', name: 'NOTIFY_FLOW_STATUS', desc: '', args: [], ); } - /// `未知` + /// `Unspecified` String get NOTIFY_FLOW_STATUS_UNSPECIFIED { return Intl.message( - '未知', + 'Unspecified', name: 'NOTIFY_FLOW_STATUS_UNSPECIFIED', desc: '', args: [], ); } - /// `启用` + /// `Active` String get NOTIFY_FLOW_STATUS_ACTIVE { return Intl.message( - '启用', + 'Active', name: 'NOTIFY_FLOW_STATUS_ACTIVE', desc: '', args: [], ); } - /// `停止` + /// `Suspend` String get NOTIFY_FLOW_STATUS_SUSPEND { return Intl.message( - '停止', + 'Suspend', name: 'NOTIFY_FLOW_STATUS_SUSPEND', desc: '', args: [], @@ -446,8 +946,8 @@ class AppLocalizationDelegate extends LocalizationsDelegate { List get supportedLocales { return const [ - Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'), Locale.fromSubtags(languageCode: 'en'), + Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'), ]; } diff --git a/lib/repo/grpc/api_helper.dart b/lib/repo/grpc/api_helper.dart index 5fc04c3..09417d1 100644 --- a/lib/repo/grpc/api_helper.dart +++ b/lib/repo/grpc/api_helper.dart @@ -3,6 +3,8 @@ import 'package:grpc/grpc.dart'; import 'package:tuihub_protos/librarian/sephirah/v1/sephirah.pbgrpc.dart'; import 'package:tuihub_protos/librarian/sephirah/v1/tiphereth.pb.dart'; +import '../../l10n/l10n.dart'; + enum ApiStatus { success, error } class ApiResponse { @@ -62,14 +64,16 @@ class ApiHelper { return ApiResponse(resp, ApiStatus.success, null); } catch (e) { if (e is GrpcError) { - return ApiResponse(null, ApiStatus.error, e.message ?? '发生未知错误'); + return ApiResponse(null, ApiStatus.error, + e.message ?? S.current.unknownErrorOccurred); } return ApiResponse(null, ApiStatus.error, e.toString()); } } debugPrint(e.toString()); if (e is GrpcError) { - return ApiResponse(null, ApiStatus.error, e.message ?? '发生未知错误'); + return ApiResponse( + null, ApiStatus.error, e.message ?? S.current.unknownErrorOccurred); } return ApiResponse(null, ApiStatus.error, e.toString()); } @@ -100,14 +104,16 @@ class ApiHelper { return ApiResponse(resp, ApiStatus.success, null); } catch (e) { if (e is GrpcError) { - return ApiResponse(null, ApiStatus.error, e.message ?? '发生未知错误'); + return ApiResponse(null, ApiStatus.error, + e.message ?? S.current.unknownErrorOccurred); } return ApiResponse(null, ApiStatus.error, e.toString()); } } debugPrint(e.toString()); if (e is GrpcError) { - return ApiResponse(null, ApiStatus.error, e.message ?? '发生未知错误'); + return ApiResponse( + null, ApiStatus.error, e.message ?? S.current.unknownErrorOccurred); } return ApiResponse(null, ApiStatus.error, e.toString()); } diff --git a/lib/view/components/toast.dart b/lib/view/components/toast.dart index cd039ec..2c9c3c0 100644 --- a/lib/view/components/toast.dart +++ b/lib/view/components/toast.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import '../../l10n/l10n.dart'; import '../layout/bootstrap_container.dart'; class Toast { @@ -55,7 +56,7 @@ class Toast { child: TextButton( onPressed: () => ScaffoldMessenger.of(context) .hideCurrentSnackBar(reason: SnackBarClosedReason.dismiss), - child: const Text('关闭'), + child: Text(S.of(context).buttonClose), ), ), ), diff --git a/lib/view/helper/duration_format.dart b/lib/view/helper/duration_format.dart index fc1dae3..dc13568 100644 --- a/lib/view/helper/duration_format.dart +++ b/lib/view/helper/duration_format.dart @@ -1,3 +1,5 @@ +import '../../l10n/l10n.dart'; + class DurationHelper { static String recentString(DateTime dateTime) { final duration = DateTime.now().difference(dateTime); @@ -14,15 +16,15 @@ class DurationHelper { const maxDays = 30; if (minutes <= 1) { - return '刚刚'; + return S.current.durationJustNow; } else if (minutes < maxMinutes) { - return '$minutes 分钟前'; + return S.current.durationMinutes(minutes); } else if (hours < maxHours) { - return '$hours 小时前'; + return S.current.durationHours(hours); } else if (days < maxDays) { - return '$days 天前'; + return S.current.durationDays(days); } else { - return '$months 个月前'; + return S.current.durationMonths(months); } } } diff --git a/lib/view/pages/init_page.dart b/lib/view/pages/init_page.dart index 0f6ecfd..0b12135 100644 --- a/lib/view/pages/init_page.dart +++ b/lib/view/pages/init_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../bloc/main_bloc.dart'; +import '../../l10n/l10n.dart'; import '../../route.dart'; import '../components/toast.dart'; import '../layout/bootstrap_container.dart'; @@ -31,7 +32,7 @@ class _InitPageState extends State { listener: (context, state) { if (state is MainAutoLoginState && state.success) { AppRoutes.tiphereth.go(context); - const Toast(title: '', message: '欢迎回来').show(context); + Toast(title: '', message: S.of(context).welcomeBack).show(context); } }, builder: (context, state) { @@ -54,7 +55,7 @@ class _InitPageState extends State { AppRoutes.login.go(context); }, icon: const Icon(Icons.arrow_forward), - label: const Text('登录'), + label: Text(S.of(context).login), ) : Container(), ); @@ -121,11 +122,11 @@ class InitWidget extends StatelessWidget { ), ) else - const SizedBox( + SizedBox( height: 24, child: Text( - 'CLICK LOGIN TO START', - style: TextStyle(fontSize: 16), + S.of(context).clickLoginToStart, + style: const TextStyle(fontSize: 16), ), ), ], diff --git a/lib/view/pages/login_page.dart b/lib/view/pages/login_page.dart index 39761ae..55b1379 100644 --- a/lib/view/pages/login_page.dart +++ b/lib/view/pages/login_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../bloc/main_bloc.dart'; +import '../../l10n/l10n.dart'; import '../../model/common_model.dart'; import '../../route.dart'; import '../components/toast.dart'; @@ -23,7 +24,7 @@ class LoginPage extends StatelessWidget { listener: (context, state) { if (state.currentUser != null) { AppRoutes.tiphereth.go(context); - const Toast(title: '', message: '欢迎').show(context); + Toast(title: '', message: S.of(context).welcome).show(context); } }, builder: (context, state) { @@ -85,7 +86,7 @@ class _ServerSelectWidgetState extends State backgroundColor: Colors.transparent, appBar: AppBar( toolbarHeight: 96, - title: const Center(child: Text('连接服务器')), + title: Center(child: Text(S.of(context).serverSetup)), backgroundColor: Colors.transparent, ), body: ServerSelectForm(callback: () {})); @@ -106,7 +107,7 @@ class _ServerSelectFormState extends State { String host = ''; int port = 0; bool tls = false; - final String name = '确定'; + final String name = '确定'; // TODO: what is this? ServerConfig server = const ServerConfig('', 0, true, ''); void submit() { @@ -130,13 +131,13 @@ class _ServerSelectFormState extends State { children: [ TextFormField( onSaved: (newValue) => host = newValue!, - decoration: const InputDecoration( - border: OutlineInputBorder(), - labelText: '地址', + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: S.of(context).address, ), validator: (value) { if (value == null || value.isEmpty) { - return '请输入地址'; + return S.of(context).pleaseInputServerAddress; } return null; }, @@ -146,14 +147,14 @@ class _ServerSelectFormState extends State { ), TextFormField( onSaved: (newValue) => port = int.parse(newValue!), - decoration: const InputDecoration( - border: OutlineInputBorder(), - labelText: '端口', + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: S.of(context).port, ), validator: (value) { final p = int.tryParse(value!) ?? 0; if (p <= 0) { - return '请输入端口'; + return S.of(context).pleaseInputServerPort; } return null; }, @@ -165,7 +166,7 @@ class _ServerSelectFormState extends State { ), SwitchFormField( onSaved: (newValue) => tls = newValue!, - title: const Text('TLS'), + title: Text(S.of(context).tls), initialValue: tls, ), const SizedBox( @@ -176,7 +177,7 @@ class _ServerSelectFormState extends State { minimumSize: const Size(128, 32), ), onPressed: submit, - child: const Text('检查'), + child: Text(S.of(context).buttonCheck), ), ServerConnectivityWidget( config: server, @@ -218,17 +219,13 @@ class _LoginWidgetState extends State { super.dispose(); } - void submitUrl() { + void login() { final username = _usernameController.text.trim(); final password = _passwordController.text.trim(); - if (username.isEmpty || password.isEmpty) { - const Toast(title: '', message: '用户名或密码为空, 请修改后重试').show(context); - } else { - context.read().add( - MainManualLoginEvent(username, password), - ); - } + context.read().add( + MainManualLoginEvent(username, password), + ); } bool hidePassword = true; @@ -240,10 +237,10 @@ class _LoginWidgetState extends State { if (state is MainManualLoginState && state.failed) { Toast( title: '', - message: '登录失败,${state.msg}', + message: S.of(context).loginFailed(state.msg ?? ''), action: SnackBarAction( - label: '重试', - onPressed: submitUrl, + label: S.of(context).buttonRetry, + onPressed: login, ), ).show(context); } @@ -257,7 +254,7 @@ class _LoginWidgetState extends State { Expanded( child: Center( child: Text( - '🎉欢迎!', + S.of(context).welcomeHeader, style: Theme.of(context) .textTheme .titleLarge @@ -265,8 +262,8 @@ class _LoginWidgetState extends State { ), ), ), - Text( - '登录至 ${state.serverConfig?.host}:${state.serverConfig?.port}'), + Text(S.of(context).loggingInTo( + '${state.serverConfig?.host}:${state.serverConfig?.port}')), Align( alignment: Alignment.centerLeft, child: Padding( @@ -275,17 +272,17 @@ class _LoginWidgetState extends State { onPressed: () { context.read().add(MainLogoutEvent()); }, - child: const Text('< 返回'), + child: Text('< ${S.of(context).buttonBackward}'), ), ), ), TextField( - decoration: const InputDecoration( - labelText: '用户名', + decoration: InputDecoration( + labelText: S.of(context).username, ), controller: _usernameController, onSubmitted: (value) { - submitUrl(); + login(); }, ), const SizedBox( @@ -294,7 +291,7 @@ class _LoginWidgetState extends State { TextField( obscureText: hidePassword, decoration: InputDecoration( - labelText: '密码', + labelText: S.of(context).password, suffixIcon: IconButton( onPressed: () { setState(() { @@ -308,7 +305,7 @@ class _LoginWidgetState extends State { ), controller: _passwordController, onSubmitted: (value) { - submitUrl(); + login(); }, obscuringCharacter: '*', ), @@ -316,7 +313,7 @@ class _LoginWidgetState extends State { height: 16, ), ElevatedButton( - onPressed: submitUrl, + onPressed: login, style: const ButtonStyle( fixedSize: MaterialStatePropertyAll( Size(144, 36), @@ -331,9 +328,9 @@ class _LoginWidgetState extends State { color: Colors.black, ), ) - : const Text( - '登录', - style: TextStyle( + : Text( + S.of(context).buttonLogin, + style: const TextStyle( fontSize: 16, ), ), diff --git a/lib/view/pages/settings/about_page.dart b/lib/view/pages/settings/about_page.dart index b28cd39..80e1891 100644 --- a/lib/view/pages/settings/about_page.dart +++ b/lib/view/pages/settings/about_page.dart @@ -82,8 +82,7 @@ class AboutPage extends StatelessWidget { (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData) { return Markdown( - shrinkWrap: true, - data: snapshot.data ?? ''); + shrinkWrap: true, data: snapshot.data ?? ''); } return const Center( child: CircularProgressIndicator(), diff --git a/lib/view/specialized/title_bar.dart b/lib/view/specialized/title_bar.dart index 40ff021..311381f 100644 --- a/lib/view/specialized/title_bar.dart +++ b/lib/view/specialized/title_bar.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:system_tray/system_tray.dart'; import '../../common/platform.dart'; +import '../../l10n/l10n.dart'; class TitleBar extends StatelessWidget { const TitleBar({super.key, this.actions = const []}); @@ -44,7 +45,7 @@ class TitleBar extends StatelessWidget { child: MoveWindow(), ) : PlatformHelper.isWeb() - ? const Align(child: Text('网页版功能受限,仅供评估使用')) + ? Align(child: Text(S.of(context).webVersionFunctionLimited)) : const SizedBox(), ), for (final action in actions) action, @@ -61,11 +62,11 @@ class TitleBar extends StatelessWidget { context: context, builder: (BuildContext context) { return AlertDialog( - title: const Text('关闭'), - content: const Text('确定要关闭吗?'), + title: Text(S.of(context).buttonClose), + content: Text(S.of(context).areYouSureToClose), actions: [ TextButton( - child: const Text('退出应用'), + child: Text(S.of(context).buttonExit), onPressed: () { final SystemTray systemTray = SystemTray(); systemTray.destroy(); @@ -73,14 +74,14 @@ class TitleBar extends StatelessWidget { }, ), TextButton( - child: const Text('最小化到托盘'), + child: Text(S.of(context).buttonMinimizeToTray), onPressed: () { Navigator.of(context).pop(); appWindow.hide(); }, ), TextButton( - child: const Text('取消'), + child: Text(S.of(context).buttonCancel), onPressed: () { Navigator.of(context).pop(); }, diff --git a/pubspec.yaml b/pubspec.yaml index 9a038f3..fe97564 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -177,7 +177,7 @@ flutter: flutter_intl: enabled: true class_name: S # Optional. Sets the name for the generated localization class. Default: S - main_locale: zh_CN # Optional. Sets the main locale used for generating localization files. Provided value should consist of language code and optional script and country codes separated with underscore (e.g. 'en', 'en_GB', 'zh_Hans', 'zh_Hans_CN'). Default: en + main_locale: en # Optional. Sets the main locale used for generating localization files. Provided value should consist of language code and optional script and country codes separated with underscore (e.g. 'en', 'en_GB', 'zh_Hans', 'zh_Hans_CN'). Default: en arb_dir: l10n_arb/ # Optional. Sets the directory of your ARB resource files. Provided value should be a valid path on your system. Default: lib/l10n output_dir: lib/l10n # Optional. Sets the directory of generated localization files. Provided value should be a valid path on your system. Default: lib/generated