From b8ce9b9afb880f28427c045d9af69423582b8218 Mon Sep 17 00:00:00 2001 From: Irfan Backer Date: Tue, 7 Dec 2021 22:58:50 +0530 Subject: [PATCH 1/2] Setup basic i18n configs --- frontend/app_flowy/ios/Runner/Info.plist | 4 + frontend/app_flowy/lib/main.dart | 6 +- .../lib/startup/tasks/application_widget.dart | 13 +++- frontend/app_flowy/pubspec.lock | 77 ++++++++++++++++++- frontend/app_flowy/pubspec.yaml | 7 ++ 5 files changed, 104 insertions(+), 3 deletions(-) diff --git a/frontend/app_flowy/ios/Runner/Info.plist b/frontend/app_flowy/ios/Runner/Info.plist index 607d5e00cd..848c264d70 100644 --- a/frontend/app_flowy/ios/Runner/Info.plist +++ b/frontend/app_flowy/ios/Runner/Info.plist @@ -41,5 +41,9 @@ UIViewControllerBasedStatusBarAppearance + CFBundleLocalizations + + en + diff --git a/frontend/app_flowy/lib/main.dart b/frontend/app_flowy/lib/main.dart index 49a024173d..3c17924567 100644 --- a/frontend/app_flowy/lib/main.dart +++ b/frontend/app_flowy/lib/main.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/user/presentation/splash_screen.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class FlowyApp implements EntryPoint { @@ -9,6 +10,9 @@ class FlowyApp implements EntryPoint { } } -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await EasyLocalization.ensureInitialized(); + System.run(FlowyApp()); } diff --git a/frontend/app_flowy/lib/startup/tasks/application_widget.dart b/frontend/app_flowy/lib/startup/tasks/application_widget.dart index c0e68ba8ee..3e4bd8857a 100644 --- a/frontend/app_flowy/lib/startup/tasks/application_widget.dart +++ b/frontend/app_flowy/lib/startup/tasks/application_widget.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; @@ -17,7 +18,14 @@ class AppWidgetTask extends LaunchTask { final widget = context.getIt().create(); final app = ApplicationWidget(child: widget); Bloc.observer = ApplicationBlocObserver(); - runApp(app); + + runApp( + EasyLocalization( + supportedLocales: const [Locale('en')], + path: 'assets/translations', + fallbackLocale: const Locale('en'), + child: app), + ); return Future(() => {}); } @@ -45,6 +53,9 @@ class ApplicationWidget extends StatelessWidget { builder: overlayManagerBuilder(), debugShowCheckedModeBanner: false, theme: theme.themeData, + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, + locale: context.locale, navigatorKey: AppGlobals.rootNavKey, home: child, ), diff --git a/frontend/app_flowy/pubspec.lock b/frontend/app_flowy/pubspec.lock index d3330a7e75..7d1c411e1d 100644 --- a/frontend/app_flowy/pubspec.lock +++ b/frontend/app_flowy/pubspec.lock @@ -267,6 +267,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.1" + easy_localization: + dependency: "direct main" + description: + name: easy_localization + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + easy_logger: + dependency: transitive + description: + name: easy_logger + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2" equatable: dependency: "direct main" description: @@ -405,6 +419,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -544,7 +563,7 @@ packages: source: hosted version: "2.4.1" intl: - dependency: transitive + dependency: "direct main" description: name: intl url: "https://pub.dartlang.org" @@ -851,6 +870,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.1+1" + shared_preferences: + dependency: transitive + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" shelf: dependency: transitive description: diff --git a/frontend/app_flowy/pubspec.yaml b/frontend/app_flowy/pubspec.yaml index f91bdeddaf..8ad85a6066 100644 --- a/frontend/app_flowy/pubspec.yaml +++ b/frontend/app_flowy/pubspec.yaml @@ -29,6 +29,8 @@ environment: dependencies: flutter: sdk: flutter + flutter_localizations: + sdk: flutter flowy_sdk: path: packages/flowy_sdk flowy_infra_ui: @@ -43,6 +45,7 @@ dependencies: ref: develop # third party packages + intl: ^0.17.0 time: '^2.0.0' equatable: '^2.0.3' freezed_annotation: @@ -65,6 +68,7 @@ dependencies: # file_picker: ^4.2.1 clipboard: ^0.1.3 connectivity_plus: ^2.1.0 + easy_localization: ^3.0.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -89,6 +93,8 @@ dev_dependencies: # The following section is specific to Flutter. flutter: + # Automatic code generation for l10n and i18n + generate: true # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in @@ -105,6 +111,7 @@ flutter: - assets/images/ - assets/images/home/ - assets/images/editor/ + - assets/translations/ # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see From 2aaa076592ee69e59edcd725298dc03f420ae596 Mon Sep 17 00:00:00 2001 From: Irfan Backer Date: Tue, 7 Dec 2021 23:01:23 +0530 Subject: [PATCH 2/2] Add default en translation for i18n --- .../app_flowy/assets/translations/en.json | 122 +++++++++++++++ .../lib/generated/codegen_loader.g.dart | 140 ++++++++++++++++++ .../lib/generated/locale_keys.g.dart | 108 ++++++++++++++ .../lib/user/application/sign_up_bloc.dart | 8 +- .../lib/user/presentation/sign_in_screen.dart | 20 +-- .../lib/user/presentation/sign_up_screen.dart | 20 +-- .../user/presentation/skip_log_in_screen.dart | 24 +-- .../lib/user/presentation/welcome_screen.dart | 6 +- .../domain/edit_action/app_edit.dart | 6 +- .../domain/edit_action/view_edit.dart | 8 +- .../infrastructure/repos/workspace_repo.dart | 4 +- .../stack_page/blank/blank_page.dart | 4 +- .../stack_page/doc/doc_stack_page.dart | 10 +- .../stack_page/doc/widget/banner.dart | 9 +- .../doc/widget/toolbar/tool_bar.dart | 24 +-- .../stack_page/trash/trash_page.dart | 10 +- .../stack_page/trash/widget/trash_header.dart | 8 +- .../presentation/widgets/dialogs.dart | 9 +- .../widgets/edit_pannel/edit_pannel.dart | 12 +- .../widgets/float_bubble/question_bubble.dart | 8 +- .../menu/widget/app/create_button.dart | 6 +- .../menu/widget/app/header/header.dart | 10 +- .../widgets/menu/widget/app/section/item.dart | 4 +- .../widgets/menu/widget/menu_trash.dart | 4 +- 24 files changed, 497 insertions(+), 87 deletions(-) create mode 100644 frontend/app_flowy/assets/translations/en.json create mode 100644 frontend/app_flowy/lib/generated/codegen_loader.g.dart create mode 100644 frontend/app_flowy/lib/generated/locale_keys.g.dart diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json new file mode 100644 index 0000000000..57d02b3967 --- /dev/null +++ b/frontend/app_flowy/assets/translations/en.json @@ -0,0 +1,122 @@ +{ + "appName": "Appflowy", + "defaultUsername": "Me", + "welcomeText": "Welcome to @:appName", + "githubStarText": "Star on GitHub", + "subscribeNewsletterText": "Subscribe to Newsletter", + "letsGoButtonText": "Let's Go", + "title": "Title", + "signUp": { + "buttonText": "Sign Up", + "title": "Sign Up to @:appName", + "getStartedText": "Get Started", + "emptyPasswordError": "Password can't be empty", + "repeatPasswordEmptyError": "Repeat password can't be empty", + "unmatchedPasswordError": "Repeat password is not the same as password", + "alreadyHaveAnAccount": "Already have an account?", + "emailHint": "Email", + "passwordHint": "Password", + "repeatPasswordHint": "Repeat password" + }, + "signIn": { + "loginTitle": "Login to @:appName", + "loginButtonText": "Login", + "buttonText": "Sign In", + "forgotPassword": "Forgot Password?", + "emailHint": "Email", + "passwordHint": "Password", + "dontHaveAnAccount": "Don't have an account?", + "repeatPasswordEmptyError": "Repeat password can't be empty", + "unmatchedPasswordError": "Repeat password is not the same as password" + }, + "workspace": { + "create": "Create workspace", + "hint": "workspace", + "notFoundError": "Workspace not found" + }, + "shareAction": { + "buttonText": "Share", + "workInProgress": "Work in progress", + "markdown": "Markdown", + "copyLink": "Copy Link" + }, + "disclosureAction": { + "rename": "Rename", + "delete": "Delete", + "duplicate": "Duplicate" + }, + "blankPageTitle": "Blank page", + "newPageText": "New page", + "trash": { + "text": "Trash", + "restoreAll": "Restore All", + "deleteAll": "Delete All", + "pageHeader": { + "fileName": "File name", + "lastModified": "Last Modified", + "created": "Created" + } + }, + "deletePagePrompt": { + "text": "This page is in Trash", + "restore": "Restore page", + "deletePermanent": "Delete permanently" + }, + "dialogCreatePageNameHint": "Page name", + "questionBubble": { + "whatsNew": "What's new?", + "help": "Help & Support" + }, + "menuAppHeader": { + "addPageTooltip": "Quickly add a page inside", + "defaultNewPageName": "Untitles", + "renameDialog": "Rename" + }, + "toolbar": { + "undo": "Undo", + "redo": "Redo", + "bold": "Bold", + "italic": "Italic", + "underline": "Underline", + "strike": "Strikethrough", + "numList": "Numbered List", + "bulletList": "Bulleted List", + "checkList": "Check List", + "inlineCode": "Inline Code", + "quote": "Quote Block" + }, + "contactsPage": { + "title": "Contacts", + "whatsHappening": "What's happening this week?", + "addContact": "Add Contact", + "editContact": "Edit Contact" + }, + "button": { + "OK": "OK", + "Cancel": "Cancel", + "signIn": "Sign In", + "signOut": "Sign Out", + "complete": "Complete", + "save": "Save" + }, + "label": { + "welcome": "Welcome!", + "firstName": "First Name", + "middleName": "Middle Name", + "lastName": "Last Name", + "stepX": "Step {X}" + }, + "oAuth": { + "err": { + "failedTitle": "Unable to connect to your account.", + "failedMsg": "Please make sure you've completed the sign-in process in your browser." + }, + "google": { + "title": "GOOGLE SIGN-IN", + "instruction1": "In order to import your Google Contacts, you'll need to authorize this application using your web browser.", + "instruction2": "Copy this code to your clipboard by clicking the icon or selecting the text:", + "instruction3": "Navigate to the following link in your web browser, and enter the above code:", + "instruction4": "Press the button below when you've completed signup:" + } + } +} \ No newline at end of file diff --git a/frontend/app_flowy/lib/generated/codegen_loader.g.dart b/frontend/app_flowy/lib/generated/codegen_loader.g.dart new file mode 100644 index 0000000000..b150ffcbc4 --- /dev/null +++ b/frontend/app_flowy/lib/generated/codegen_loader.g.dart @@ -0,0 +1,140 @@ +// DO NOT EDIT. This is code generated via package:easy_localization/generate.dart + +// ignore_for_file: prefer_single_quotes + +import 'dart:ui'; + +import 'package:easy_localization/easy_localization.dart' show AssetLoader; + +class CodegenLoader extends AssetLoader{ + const CodegenLoader(); + + @override + Future> load(String fullPath, Locale locale ) { + return Future.value(mapLocales[locale.toString()]); + } + + static const Map en = { + "appName": "Appflowy", + "defaultUsername": "Me", + "welcomeText": "Welcome to @:appName", + "githubStarText": "Star on GitHub", + "subscribeNewsletterText": "Subscribe to Newsletter", + "letsGoButtonText": "Let's Go", + "title": "Title", + "signUp": { + "buttonText": "Sign Up", + "title": "Sign Up to @:appName", + "getStartedText": "Get Started", + "emptyPasswordError": "Password can't be empty", + "repeatPasswordEmptyError": "Repeat password can't be empty", + "unmatchedPasswordError": "Repeat password is not the same as password", + "alreadyHaveAnAccount": "Already have an account?", + "emailHint": "Email", + "passwordHint": "Password", + "repeatPasswordHint": "Repeat password" + }, + "signIn": { + "loginTitle": "Login to @:appName", + "loginButtonText": "Login", + "buttonText": "Sign In", + "forgotPassword": "Forgot Password?", + "emailHint": "Email", + "passwordHint": "Password", + "dontHaveAnAccount": "Don't have an account?", + "repeatPasswordEmptyError": "Repeat password can't be empty", + "unmatchedPasswordError": "Repeat password is not the same as password" + }, + "workspace": { + "create": "Create workspace", + "hint": "workspace", + "notFoundError": "Workspace not found" + }, + "shareAction": { + "buttonText": "Share", + "workInProgress": "Work in progress", + "markdown": "Markdown", + "copyLink": "Copy Link" + }, + "disclosureAction": { + "rename": "Rename", + "delete": "Delete", + "duplicate": "Duplicate" + }, + "blankPageTitle": "Blank page", + "newPageText": "New page", + "trash": { + "text": "Trash", + "restoreAll": "Restore All", + "deleteAll": "Delete All", + "pageHeader": { + "fileName": "File name", + "lastModified": "Last Modified", + "created": "Created" + } + }, + "deletePagePrompt": { + "text": "This page is in Trash", + "restore": "Restore page", + "deletePermanent": "Delete permanently" + }, + "dialogCreatePageNameHint": "Page name", + "questionBubble": { + "whatsNew": "What's new?", + "help": "Help & Support" + }, + "menuAppHeader": { + "addPageTooltip": "Quickly add a page inside", + "defaultNewPageName": "Untitles", + "renameDialog": "Rename" + }, + "toolbar": { + "undo": "Undo", + "redo": "Redo", + "bold": "Bold", + "italic": "Italic", + "underline": "Underline", + "strike": "Strikethrough", + "numList": "Numbered List", + "bulletList": "Bulleted List", + "checkList": "Check List", + "inlineCode": "Inline Code", + "quote": "Quote Block" + }, + "contactsPage": { + "title": "Contacts", + "whatsHappening": "What's happening this week?", + "addContact": "Add Contact", + "editContact": "Edit Contact" + }, + "button": { + "OK": "OK", + "Cancel": "Cancel", + "signIn": "Sign In", + "signOut": "Sign Out", + "complete": "Complete", + "save": "Save" + }, + "label": { + "welcome": "Welcome!", + "firstName": "First Name", + "middleName": "Middle Name", + "lastName": "Last Name", + "stepX": "Step {X}" + }, + "oAuth": { + "err": { + "failedTitle": "Unable to connect to your account.", + "failedMsg": "Please make sure you've completed the sign-in process in your browser." + }, + "google": { + "title": "GOOGLE SIGN-IN", + "instruction1": "In order to import your Google Contacts, you'll need to authorize this application using your web browser.", + "instruction2": "Copy this code to your clipboard by clicking the icon or selecting the text:", + "instruction3": "Navigate to the following link in your web browser, and enter the above code:", + "instruction4": "Press the button below when you've completed signup:" + } + } +}; +static const Map> mapLocales = {"en": en}; +} diff --git a/frontend/app_flowy/lib/generated/locale_keys.g.dart b/frontend/app_flowy/lib/generated/locale_keys.g.dart new file mode 100644 index 0000000000..28888ad277 --- /dev/null +++ b/frontend/app_flowy/lib/generated/locale_keys.g.dart @@ -0,0 +1,108 @@ +// DO NOT EDIT. This is code generated via package:easy_localization/generate.dart + +abstract class LocaleKeys { + static const appName = 'appName'; + static const defaultUsername = 'defaultUsername'; + static const welcomeText = 'welcomeText'; + static const githubStarText = 'githubStarText'; + static const subscribeNewsletterText = 'subscribeNewsletterText'; + static const letsGoButtonText = 'letsGoButtonText'; + static const title = 'title'; + static const signUp_buttonText = 'signUp.buttonText'; + static const signUp_title = 'signUp.title'; + static const signUp_getStartedText = 'signUp.getStartedText'; + static const signUp_emptyPasswordError = 'signUp.emptyPasswordError'; + static const signUp_repeatPasswordEmptyError = 'signUp.repeatPasswordEmptyError'; + static const signUp_unmatchedPasswordError = 'signUp.unmatchedPasswordError'; + static const signUp_alreadyHaveAnAccount = 'signUp.alreadyHaveAnAccount'; + static const signUp_emailHint = 'signUp.emailHint'; + static const signUp_passwordHint = 'signUp.passwordHint'; + static const signUp_repeatPasswordHint = 'signUp.repeatPasswordHint'; + static const signUp = 'signUp'; + static const signIn_loginTitle = 'signIn.loginTitle'; + static const signIn_loginButtonText = 'signIn.loginButtonText'; + static const signIn_buttonText = 'signIn.buttonText'; + static const signIn_forgotPassword = 'signIn.forgotPassword'; + static const signIn_emailHint = 'signIn.emailHint'; + static const signIn_passwordHint = 'signIn.passwordHint'; + static const signIn_dontHaveAnAccount = 'signIn.dontHaveAnAccount'; + static const signIn_repeatPasswordEmptyError = 'signIn.repeatPasswordEmptyError'; + static const signIn_unmatchedPasswordError = 'signIn.unmatchedPasswordError'; + static const signIn = 'signIn'; + static const workspace_create = 'workspace.create'; + static const workspace_hint = 'workspace.hint'; + static const workspace_notFoundError = 'workspace.notFoundError'; + static const workspace = 'workspace'; + static const shareAction_buttonText = 'shareAction.buttonText'; + static const shareAction_workInProgress = 'shareAction.workInProgress'; + static const shareAction_markdown = 'shareAction.markdown'; + static const shareAction_copyLink = 'shareAction.copyLink'; + static const shareAction = 'shareAction'; + static const disclosureAction_rename = 'disclosureAction.rename'; + static const disclosureAction_delete = 'disclosureAction.delete'; + static const disclosureAction_duplicate = 'disclosureAction.duplicate'; + static const disclosureAction = 'disclosureAction'; + static const blankPageTitle = 'blankPageTitle'; + static const newPageText = 'newPageText'; + static const trash_text = 'trash.text'; + static const trash_restoreAll = 'trash.restoreAll'; + static const trash_deleteAll = 'trash.deleteAll'; + static const trash_pageHeader_fileName = 'trash.pageHeader.fileName'; + static const trash_pageHeader_lastModified = 'trash.pageHeader.lastModified'; + static const trash_pageHeader_created = 'trash.pageHeader.created'; + static const trash_pageHeader = 'trash.pageHeader'; + static const trash = 'trash'; + static const deletePagePrompt_text = 'deletePagePrompt.text'; + static const deletePagePrompt_restore = 'deletePagePrompt.restore'; + static const deletePagePrompt_deletePermanent = 'deletePagePrompt.deletePermanent'; + static const deletePagePrompt = 'deletePagePrompt'; + static const dialogCreatePageNameHint = 'dialogCreatePageNameHint'; + static const questionBubble_whatsNew = 'questionBubble.whatsNew'; + static const questionBubble_help = 'questionBubble.help'; + static const questionBubble = 'questionBubble'; + static const menuAppHeader_addPageTooltip = 'menuAppHeader.addPageTooltip'; + static const menuAppHeader_defaultNewPageName = 'menuAppHeader.defaultNewPageName'; + static const menuAppHeader_renameDialog = 'menuAppHeader.renameDialog'; + static const menuAppHeader = 'menuAppHeader'; + static const toolbar_undo = 'toolbar.undo'; + static const toolbar_redo = 'toolbar.redo'; + static const toolbar_bold = 'toolbar.bold'; + static const toolbar_italic = 'toolbar.italic'; + static const toolbar_underline = 'toolbar.underline'; + static const toolbar_strike = 'toolbar.strike'; + static const toolbar_numList = 'toolbar.numList'; + static const toolbar_bulletList = 'toolbar.bulletList'; + static const toolbar_checkList = 'toolbar.checkList'; + static const toolbar_inlineCode = 'toolbar.inlineCode'; + static const toolbar_quote = 'toolbar.quote'; + static const toolbar = 'toolbar'; + static const contactsPage_title = 'contactsPage.title'; + static const contactsPage_whatsHappening = 'contactsPage.whatsHappening'; + static const contactsPage_addContact = 'contactsPage.addContact'; + static const contactsPage_editContact = 'contactsPage.editContact'; + static const contactsPage = 'contactsPage'; + static const button_OK = 'button.OK'; + static const button_Cancel = 'button.Cancel'; + static const button_signIn = 'button.signIn'; + static const button_signOut = 'button.signOut'; + static const button_complete = 'button.complete'; + static const button_save = 'button.save'; + static const button = 'button'; + static const label_welcome = 'label.welcome'; + static const label_firstName = 'label.firstName'; + static const label_middleName = 'label.middleName'; + static const label_lastName = 'label.lastName'; + static const label_stepX = 'label.stepX'; + static const label = 'label'; + static const oAuth_err_failedTitle = 'oAuth.err.failedTitle'; + static const oAuth_err_failedMsg = 'oAuth.err.failedMsg'; + static const oAuth_err = 'oAuth.err'; + static const oAuth_google_title = 'oAuth.google.title'; + static const oAuth_google_instruction1 = 'oAuth.google.instruction1'; + static const oAuth_google_instruction2 = 'oAuth.google.instruction2'; + static const oAuth_google_instruction3 = 'oAuth.google.instruction3'; + static const oAuth_google_instruction4 = 'oAuth.google.instruction4'; + static const oAuth_google = 'oAuth.google'; + static const oAuth = 'oAuth'; + +} diff --git a/frontend/app_flowy/lib/user/application/sign_up_bloc.dart b/frontend/app_flowy/lib/user/application/sign_up_bloc.dart index 2d926ba489..0271de7309 100644 --- a/frontend/app_flowy/lib/user/application/sign_up_bloc.dart +++ b/frontend/app_flowy/lib/user/application/sign_up_bloc.dart @@ -1,9 +1,11 @@ import 'package:app_flowy/user/domain/i_auth.dart'; import 'package:dartz/dartz.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile, ErrorCode; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; part 'sign_up_bloc.freezed.dart'; @@ -37,7 +39,7 @@ class SignUpBloc extends Bloc { if (password == null) { yield state.copyWith( isSubmitting: false, - passwordError: some("Password can't be empty"), + passwordError: some(LocaleKeys.signUp_emptyPasswordError.tr()), ); return; } @@ -45,7 +47,7 @@ class SignUpBloc extends Bloc { if (repeatedPassword == null) { yield state.copyWith( isSubmitting: false, - repeatPasswordError: some("Repeat password can't be empty"), + repeatPasswordError: some(LocaleKeys.signUp_repeatPasswordEmptyError.tr()), ); return; } @@ -53,7 +55,7 @@ class SignUpBloc extends Bloc { if (password != repeatedPassword) { yield state.copyWith( isSubmitting: false, - repeatPasswordError: some("Repeat password is not the same as password"), + repeatPasswordError: some(LocaleKeys.signUp_unmatchedPasswordError.tr()), ); return; } diff --git a/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart b/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart index c0f5588913..869c55e715 100644 --- a/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart @@ -2,6 +2,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/user/application/sign_in_bloc.dart'; import 'package:app_flowy/user/domain/i_auth.dart'; import 'package:app_flowy/user/presentation/widgets/background.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; @@ -14,6 +15,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_infra/image.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class SignInScreen extends StatelessWidget { final IAuthRouter router; @@ -58,9 +60,9 @@ class SignInForm extends StatelessWidget { alignment: Alignment.center, child: AuthFormContainer( children: [ - const FlowyLogoTitle( - title: 'Login to Appflowy', - logoSize: Size(60, 60), + FlowyLogoTitle( + title: LocaleKeys.signIn_loginTitle.tr(), + logoSize: const Size(60, 60), ), const VSpace(30), const EmailTextField(), @@ -93,14 +95,14 @@ class SignUpPrompt extends StatelessWidget { final theme = context.watch(); return Row( children: [ - Text("Dont't have an account", style: TextStyle(color: theme.shader3, fontSize: 12)), + Text(LocaleKeys.signIn_dontHaveAnAccount.tr(), style: TextStyle(color: theme.shader3, fontSize: 12)), TextButton( style: TextButton.styleFrom( textStyle: const TextStyle(fontSize: 12), ), onPressed: () => router.pushSignUpScreen(context), child: Text( - 'Sign Up', + LocaleKeys.signUp_buttonText.tr(), style: TextStyle(color: theme.main1), ), ), @@ -119,7 +121,7 @@ class LoginButton extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); return RoundedTextButton( - title: 'Login', + title: LocaleKeys.signIn_loginButtonText.tr(), height: 48, borderRadius: Corners.s10Border, color: theme.main1, @@ -147,7 +149,7 @@ class ForgetPasswordButton extends StatelessWidget { ), onPressed: () => router.pushForgetPasswordScreen(context), child: Text( - 'Forgot Password?', + LocaleKeys.signIn_forgotPassword.tr(), style: TextStyle(color: theme.main1), ), ); @@ -170,7 +172,7 @@ class PasswordTextField extends StatelessWidget { style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), obscureIcon: svg("home/hide"), obscureHideIcon: svg("home/show"), - hintText: 'Password', + hintText: LocaleKeys.signIn_passwordHint.tr(), normalBorderColor: theme.shader4, highlightBorderColor: theme.red, cursorColor: theme.main1, @@ -194,7 +196,7 @@ class EmailTextField extends StatelessWidget { buildWhen: (previous, current) => previous.emailError != current.emailError, builder: (context, state) { return RoundedInputField( - hintText: 'Email', + hintText: LocaleKeys.signIn_emailHint.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), normalBorderColor: theme.shader4, highlightBorderColor: theme.red, diff --git a/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart b/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart index 97b73a43c1..40aa18ef25 100644 --- a/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart @@ -2,6 +2,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/user/application/sign_up_bloc.dart'; import 'package:app_flowy/user/domain/i_auth.dart'; import 'package:app_flowy/user/presentation/widgets/background.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; @@ -13,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_infra/image.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class SignUpScreen extends StatelessWidget { final IAuthRouter router; @@ -53,9 +55,9 @@ class SignUpForm extends StatelessWidget { alignment: Alignment.center, child: AuthFormContainer( children: [ - const FlowyLogoTitle( - title: 'Sign Up to Appflowy', - logoSize: Size(60, 60), + FlowyLogoTitle( + title: LocaleKeys.signUp_title.tr(), + logoSize: const Size(60, 60), ), const VSpace(30), const EmailTextField(), @@ -86,13 +88,13 @@ class SignUpPrompt extends StatelessWidget { return Row( children: [ Text( - "Already have an account?", + LocaleKeys.signUp_alreadyHaveAnAccount.tr(), style: TextStyle(color: theme.shader3, fontSize: 12), ), TextButton( style: TextButton.styleFrom(textStyle: const TextStyle(fontSize: 12)), onPressed: () => Navigator.pop(context), - child: Text('Sign In', style: TextStyle(color: theme.main1)), + child: Text(LocaleKeys.signIn_buttonText.tr(), style: TextStyle(color: theme.main1)), ), ], mainAxisAlignment: MainAxisAlignment.center, @@ -109,7 +111,7 @@ class SignUpButton extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); return RoundedTextButton( - title: 'Get Started', + title: LocaleKeys.signUp_getStartedText.tr(), height: 48, color: theme.main1, onPressed: () { @@ -135,7 +137,7 @@ class PasswordTextField extends StatelessWidget { obscureIcon: svg("home/hide"), obscureHideIcon: svg("home/show"), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), - hintText: "Password", + hintText: LocaleKeys.signUp_passwordHint.tr(), normalBorderColor: theme.shader4, highlightBorderColor: theme.red, cursorColor: theme.main1, @@ -163,7 +165,7 @@ class RepeatPasswordTextField extends StatelessWidget { obscureIcon: svg("home/hide"), obscureHideIcon: svg("home/show"), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), - hintText: "Repeate password", + hintText: LocaleKeys.signUp_repeatPasswordHint.tr(), normalBorderColor: theme.shader4, highlightBorderColor: theme.red, cursorColor: theme.main1, @@ -187,7 +189,7 @@ class EmailTextField extends StatelessWidget { buildWhen: (previous, current) => previous.emailError != current.emailError, builder: (context, state) { return RoundedInputField( - hintText: 'Email', + hintText: LocaleKeys.signUp_emailHint.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), normalBorderColor: theme.shader4, highlightBorderColor: theme.red, diff --git a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart index e384fbc8c5..2cd490baf9 100644 --- a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart @@ -1,6 +1,7 @@ import 'package:app_flowy/user/domain/i_auth.dart'; import 'package:app_flowy/user/presentation/widgets/background.dart'; import 'package:app_flowy/workspace/domain/i_user.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/uuid.dart'; @@ -15,6 +16,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:dartz/dartz.dart' as dartz; +import 'package:app_flowy/generated/locale_keys.g.dart'; class SkipLogInScreen extends StatefulWidget { final IAuthRouter router; @@ -50,9 +52,9 @@ class _SkipLogInScreenState extends State { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const FlowyLogoTitle( - title: 'Welcome to AppFlowy', - logoSize: Size.square(60), + FlowyLogoTitle( + title: LocaleKeys.welcomeText.tr(), + logoSize: const Size.square(60), ), const VSpace(80), GoButton(onPressed: () => _autoRegister(context)), @@ -61,18 +63,18 @@ class _SkipLogInScreenState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ InkWell( - child: const Text( - 'Star on Github', - style: TextStyle(decoration: TextDecoration.underline, color: Colors.blue), + child: Text( + LocaleKeys.githubStarText.tr(), + style: const TextStyle(decoration: TextDecoration.underline, color: Colors.blue), ), onTap: () { _launchURL('https://github.com/AppFlowy-IO/appflowy'); }, ), InkWell( - child: const Text( - 'Subscribe to Newsletter', - style: TextStyle(decoration: TextDecoration.underline, color: Colors.blue), + child: Text( + LocaleKeys.subscribeNewsletterText.tr(), + style: const TextStyle(decoration: TextDecoration.underline, color: Colors.blue), ), onTap: () { _launchURL('https://www.appflowy.io/blog'); @@ -96,7 +98,7 @@ class _SkipLogInScreenState extends State { const password = "AppFlowy123@"; final uid = uuid(); final userEmail = "$uid@appflowy.io"; - final result = await widget.authManager.signUp("Me", password, userEmail); + final result = await widget.authManager.signUp(LocaleKeys.defaultUsername.tr(), password, userEmail); result.fold( (user) { WorkspaceEventReadCurWorkspace().send().then((result) { @@ -136,7 +138,7 @@ class GoButton extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); return RoundedTextButton( - title: 'Let\'s Go', + title: LocaleKeys.letsGoButtonText.tr(), height: 50, borderRadius: Corners.s10Border, color: theme.main1, diff --git a/frontend/app_flowy/lib/user/presentation/welcome_screen.dart b/frontend/app_flowy/lib/user/presentation/welcome_screen.dart index 19d3b68181..16e95e3b67 100644 --- a/frontend/app_flowy/lib/user/presentation/welcome_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/welcome_screen.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/workspace/welcome_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -8,6 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dar import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class WelcomeScreen extends StatelessWidget { final UserRepo repo; @@ -53,11 +55,11 @@ class WelcomeScreen extends StatelessWidget { width: 200, height: 40, child: FlowyTextButton( - "Create workspace", + LocaleKeys.workspace_create.tr(), fontSize: 14, hoverColor: theme.bg3, onPressed: () { - context.read().add(const WelcomeEvent.createWorkspace("workspace", "")); + context.read().add(WelcomeEvent.createWorkspace(LocaleKeys.workspace_hint.tr(), "")); }, ), ); diff --git a/frontend/app_flowy/lib/workspace/domain/edit_action/app_edit.dart b/frontend/app_flowy/lib/workspace/domain/edit_action/app_edit.dart index 9efce138c6..bca476e956 100644 --- a/frontend/app_flowy/lib/workspace/domain/edit_action/app_edit.dart +++ b/frontend/app_flowy/lib/workspace/domain/edit_action/app_edit.dart @@ -1,5 +1,7 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flutter/material.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; enum AppDisclosureAction { rename, @@ -10,9 +12,9 @@ extension AppDisclosureExtension on AppDisclosureAction { String get name { switch (this) { case AppDisclosureAction.rename: - return 'rename'; + return LocaleKeys.disclosureAction_rename.tr(); case AppDisclosureAction.delete: - return 'delete'; + return LocaleKeys.disclosureAction_delete.tr(); } } diff --git a/frontend/app_flowy/lib/workspace/domain/edit_action/view_edit.dart b/frontend/app_flowy/lib/workspace/domain/edit_action/view_edit.dart index 05e4672baa..39a0b44aac 100644 --- a/frontend/app_flowy/lib/workspace/domain/edit_action/view_edit.dart +++ b/frontend/app_flowy/lib/workspace/domain/edit_action/view_edit.dart @@ -1,5 +1,7 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flutter/material.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; enum ViewDisclosureAction { rename, @@ -11,11 +13,11 @@ extension ViewDisclosureExtension on ViewDisclosureAction { String get name { switch (this) { case ViewDisclosureAction.rename: - return 'Rename'; + return LocaleKeys.disclosureAction_rename.tr(); case ViewDisclosureAction.delete: - return 'Delete'; + return LocaleKeys.disclosureAction_delete.tr(); case ViewDisclosureAction.duplicate: - return 'Duplicate'; + return LocaleKeys.disclosureAction_duplicate.tr(); } } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart index f95c8bac63..59f0e5b482 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:dartz/dartz.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.pb.dart'; @@ -13,6 +14,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/workspace/domain/i_workspace.dart'; import 'helper.dart'; @@ -41,7 +43,7 @@ class WorkspaceRepo { assert(workspaces.items.length == 1); if (workspaces.items.isEmpty) { - return right(WorkspaceError.create()..msg = "Workspace not found"); + return right(WorkspaceError.create()..msg = LocaleKeys.workspace_notFoundError.tr()); } else { return left(workspaces.items[0]); } diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart index a769c49980..6f32b0f671 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart @@ -1,6 +1,8 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class BlankStackContext extends HomeStackContext { final ValueNotifier _isUpdated = ValueNotifier(false); @@ -9,7 +11,7 @@ class BlankStackContext extends HomeStackContext { String get identifier => "1"; @override - Widget get leftBarItem => const FlowyText.medium('Blank page', fontSize: 12); + Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12); @override Widget? get rightBarItem => null; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 170fdf09a3..024b02d8e1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -6,6 +6,7 @@ import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -18,6 +19,7 @@ import 'package:flutter/material.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:clipboard/clipboard.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; import 'doc_page.dart'; @@ -170,7 +172,7 @@ class DocShareButton extends StatelessWidget { child: BlocBuilder( builder: (context, state) { return RoundedTextButton( - title: 'Share', + title: 'shareAction.buttonText'.tr(), height: 30, width: buttonWidth, fontSize: 12, @@ -222,7 +224,7 @@ class DocShareButton extends StatelessWidget { } void showWorkInProgressDialog(BuildContext context) { - const FlowyAlertDialog(title: "Work in progress").show(context); + FlowyAlertDialog(title: LocaleKeys.shareAction_workInProgress.tr()).show(context); } } @@ -279,9 +281,9 @@ extension QuestionBubbleExtension on ShareAction { String get name { switch (this) { case ShareAction.markdown: - return "Markdown"; + return LocaleKeys.shareAction_markdown.tr(); case ShareAction.copyLink: - return "Copy Link"; + return LocaleKeys.shareAction_copyLink.tr(); } } } diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/banner.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/banner.dart index 114d000445..89cb0e713a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/banner.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/banner.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -5,6 +6,7 @@ import 'package:flowy_infra_ui/widget/buttons/base_styled_button.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class DocBanner extends StatelessWidget { final void Function() onRestore; @@ -22,7 +24,7 @@ class DocBanner extends StatelessWidget { color: theme.main1, child: Row( children: [ - const FlowyText.medium('This page is in Trash', color: Colors.white), + FlowyText.medium(LocaleKeys.deletePagePrompt_text.tr(), color: Colors.white), const HSpace(20), BaseStyledButton( minWidth: 160, @@ -33,7 +35,7 @@ class DocBanner extends StatelessWidget { downColor: theme.main1, outlineColor: Colors.white, borderRadius: Corners.s8Border, - child: const FlowyText.medium('Restore page', color: Colors.white, fontSize: 14), + child: FlowyText.medium(LocaleKeys.deletePagePrompt_restore.tr(), color: Colors.white, fontSize: 14), onPressed: onRestore), const HSpace(20), BaseStyledButton( @@ -45,7 +47,8 @@ class DocBanner extends StatelessWidget { downColor: theme.main1, outlineColor: Colors.white, borderRadius: Corners.s8Border, - child: const FlowyText.medium('Delete permanently', color: Colors.white, fontSize: 14), + child: FlowyText.medium(LocaleKeys.deletePagePrompt_deletePermanent.tr(), + color: Colors.white, fontSize: 14), onPressed: onDelete), ], crossAxisAlignment: CrossAxisAlignment.center, diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/tool_bar.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/tool_bar.dart index 0e3038360c..54d6c12ea1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/tool_bar.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/tool_bar.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:math'; import 'package:app_flowy/workspace/presentation/stack_page/doc/widget/toolbar/history_button.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter/material.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -11,6 +12,7 @@ import 'header_button.dart'; import 'link_button.dart'; import 'toggle_button.dart'; import 'toolbar_icon_button.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class EditorToolbar extends StatelessWidget implements PreferredSizeWidget { final List children; @@ -56,42 +58,42 @@ class EditorToolbar extends StatelessWidget implements PreferredSizeWidget { iconSize: toolbarIconSize, controller: controller, undo: true, - tooltipText: 'Undo', + tooltipText: LocaleKeys.toolbar_undo.tr(), ), FlowyHistoryButton( icon: Icons.redo_outlined, iconSize: toolbarIconSize, controller: controller, undo: false, - tooltipText: 'Redo', + tooltipText: LocaleKeys.toolbar_redo.tr(), ), FlowyToggleStyleButton( attribute: Attribute.bold, normalIcon: 'editor/bold', iconSize: toolbarIconSize, controller: controller, - tooltipText: 'Bold', + tooltipText: LocaleKeys.toolbar_bold.tr(), ), FlowyToggleStyleButton( attribute: Attribute.italic, normalIcon: 'editor/italic', iconSize: toolbarIconSize, controller: controller, - tooltipText: 'Italic', + tooltipText: LocaleKeys.toolbar_italic.tr(), ), FlowyToggleStyleButton( attribute: Attribute.underline, normalIcon: 'editor/underline', iconSize: toolbarIconSize, controller: controller, - tooltipText: 'Underline', + tooltipText: LocaleKeys.toolbar_underline.tr(), ), FlowyToggleStyleButton( attribute: Attribute.strikeThrough, normalIcon: 'editor/strikethrough', iconSize: toolbarIconSize, controller: controller, - tooltipText: 'Strikethrough', + tooltipText: LocaleKeys.toolbar_strike.tr(), ), FlowyColorButton( icon: Icons.format_color_fill, @@ -116,34 +118,34 @@ class EditorToolbar extends StatelessWidget implements PreferredSizeWidget { controller: controller, normalIcon: 'editor/numbers', iconSize: toolbarIconSize, - tooltipText: 'Numbered List', + tooltipText: LocaleKeys.toolbar_numList.tr(), ), FlowyToggleStyleButton( attribute: Attribute.ul, controller: controller, normalIcon: 'editor/bullet_list', iconSize: toolbarIconSize, - tooltipText: 'Bulleted List', + tooltipText: LocaleKeys.toolbar_bulletList.tr(), ), FlowyCheckListButton( attribute: Attribute.unchecked, controller: controller, iconSize: toolbarIconSize, - tooltipText: 'Check List', + tooltipText: LocaleKeys.toolbar_checkList.tr(), ), FlowyToggleStyleButton( attribute: Attribute.inlineCode, controller: controller, normalIcon: 'editor/inline_block', iconSize: toolbarIconSize, - tooltipText: 'Inline Code', + tooltipText: LocaleKeys.toolbar_inlineCode.tr(), ), FlowyToggleStyleButton( attribute: Attribute.blockQuote, controller: controller, normalIcon: 'editor/quote', iconSize: toolbarIconSize, - tooltipText: 'Quote Block', + tooltipText: LocaleKeys.toolbar_quote.tr(), ), FlowyLinkStyleButton( controller: controller, diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart index 4df08f110e..bd8c0c03b4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart @@ -3,6 +3,7 @@ import 'package:app_flowy/workspace/application/trash/trash_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/sizes.dart'; import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/trash_cell.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; @@ -15,6 +16,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; import 'widget/trash_header.dart'; @@ -25,7 +27,7 @@ class TrashStackContext extends HomeStackContext { String get identifier => "TrashStackContext"; @override - Widget get leftBarItem => const FlowyText.medium('Trash', fontSize: 12); + Widget get leftBarItem => FlowyText.medium(LocaleKeys.trash_text.tr(), fontSize: 12); @override Widget? get rightBarItem => null; @@ -117,12 +119,12 @@ class _TrashStackPageState extends State { height: 36, child: Row( children: [ - const FlowyText.semibold('Trash'), + FlowyText.semibold(LocaleKeys.trash_text.tr()), const Spacer(), SizedBox.fromSize( size: const Size(102, 30), child: FlowyButton( - text: const FlowyText.medium('Restore all', fontSize: 12), + text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr(), fontSize: 12), icon: svg('editor/restore'), hoverColor: theme.hover, onTap: () => context.read().add(const TrashEvent.restoreAll()), @@ -132,7 +134,7 @@ class _TrashStackPageState extends State { SizedBox.fromSize( size: const Size(102, 30), child: FlowyButton( - text: const FlowyText.medium('Delete all', fontSize: 12), + text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr(), fontSize: 12), icon: svg('editor/delete'), hoverColor: theme.hover, onTap: () => context.read().add(const TrashEvent.deleteAll()), diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart index f3f7a57a0c..6b31ce185c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart @@ -1,7 +1,9 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; import 'sizes.dart'; @@ -34,9 +36,9 @@ class TrashHeaderItem { class TrashHeader extends StatelessWidget { final List items = [ - TrashHeaderItem(title: 'File name', width: TrashSizes.fileNameWidth), - TrashHeaderItem(title: 'Last modified', width: TrashSizes.lashModifyWidth), - TrashHeaderItem(title: 'Created', width: TrashSizes.createTimeWidth), + TrashHeaderItem(title: LocaleKeys.trash_pageHeader_fileName.tr(), width: TrashSizes.fileNameWidth), + TrashHeaderItem(title: LocaleKeys.trash_pageHeader_lastModified.tr(), width: TrashSizes.lashModifyWidth), + TrashHeaderItem(title: LocaleKeys.trash_pageHeader_created.tr(), width: TrashSizes.createTimeWidth), ]; TrashHeader({Key? key}) : super(key: key); diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/dialogs.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/dialogs.dart index 6923dc58d0..3141568272 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/dialogs.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/dialogs.dart @@ -1,4 +1,4 @@ -import 'package:flowy_infra/strings.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/text_style.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -13,6 +13,7 @@ import 'package:flowy_infra_ui/style_widget/text_input.dart'; import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart'; import 'package:textstyle_extensions/textstyle_extensions.dart'; export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class TextFieldDialog extends StatefulWidget { final String value; @@ -53,7 +54,7 @@ class _CreateTextFieldDialog extends State { VSpace(Insets.sm * 1.5), ], FlowyFormTextInput( - hintText: "Page name", + hintText: LocaleKeys.dialogCreatePageNameHint.tr(), initialValue: widget.value, textStyle: const TextStyle(fontSize: 24, fontWeight: FontWeight.w400), autoFocus: true, @@ -196,7 +197,7 @@ class OkCancelButton extends StatelessWidget { children: [ if (onCancelPressed != null) SecondaryTextButton( - cancelTitle ?? S.BTN_CANCEL, + cancelTitle ?? LocaleKeys.button_Cancel.tr(), onPressed: () { onCancelPressed!(); AppGlobals.nav.pop(); @@ -206,7 +207,7 @@ class OkCancelButton extends StatelessWidget { HSpace(Insets.m), if (onOkPressed != null) PrimaryTextButton( - okTitle ?? S.BTN_OK, + okTitle ?? LocaleKeys.button_OK.tr(), onPressed: () { onOkPressed!(); AppGlobals.nav.pop(); diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart index 716b32f5e9..e4b0b9646c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart @@ -3,19 +3,17 @@ import 'package:app_flowy/workspace/domain/edit_context.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:dartz/dartz.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/bar_title.dart'; import 'package:flowy_infra_ui/style_widget/close_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class EditPannel extends StatelessWidget { late final EditPannelContext editContext; final VoidCallback onEndEdit; - EditPannel( - {Key? key, - required Option context, - required this.onEndEdit}) - : super(key: key) { + EditPannel({Key? key, required Option context, required this.onEndEdit}) : super(key: key) { editContext = context.fold(() => const BlankEditPannelContext(), (c) => c); } @@ -54,8 +52,8 @@ class EditPannelTopBar extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: Row( children: [ - const FlowyBarTitle( - title: 'Title', + FlowyBarTitle( + title: LocaleKeys.title.tr(), ), const Spacer(), FlowyCloseButton(onPressed: onClose), diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart index b9e66558fc..a2e1012583 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -10,6 +11,7 @@ import 'package:dartz/dartz.dart' as dartz; import 'package:styled_widget/styled_widget.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class QuestionBubble extends StatelessWidget { const QuestionBubble({Key? key}) : super(key: key); @@ -22,7 +24,7 @@ class QuestionBubble extends StatelessWidget { height: 30, child: FlowyTextButton( '?', - tooltip: 'Help and Support', + tooltip: LocaleKeys.questionBubble_help.tr(), fontSize: 12, fontWeight: FontWeight.w600, fillColor: theme.selector, @@ -163,9 +165,9 @@ extension QuestionBubbleExtension on BubbleAction { String get name { switch (this) { case BubbleAction.whatsNews: - return "What's new?"; + return LocaleKeys.questionBubble_whatsNew.tr(); case BubbleAction.help: - return "Help & Support"; + return LocaleKeys.questionBubble_help.tr(); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart index 2641839302..ef75be0232 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart @@ -1,11 +1,13 @@ import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; // ignore: implementation_imports class NewAppButton extends StatelessWidget { @@ -15,7 +17,7 @@ class NewAppButton extends StatelessWidget { @override Widget build(BuildContext context) { final child = FlowyTextButton( - 'New page', + LocaleKeys.newPageText.tr(), fontSize: 12, onPressed: () async => await _showCreateAppDialog(context), heading: svgWithSize("home/new_app", const Size(16, 16)), @@ -30,7 +32,7 @@ class NewAppButton extends StatelessWidget { Future _showCreateAppDialog(BuildContext context) async { return TextFieldDialog( - title: 'New page', + title: LocaleKeys.newPageText.tr(), value: "", confirm: (newValue) { if (newValue.isNotEmpty && press != null) { diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart index 59037dd9f9..71396a1f7d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/workspace/domain/edit_action/app_edit.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:expandable/expandable.dart'; import 'package:flowy_infra/flowy_icon_data_icons.dart'; import 'package:flowy_infra/theme.dart'; @@ -12,6 +13,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/workspace/application/app/app_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:dartz/dartz.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; import '../menu_app.dart'; import 'add_button.dart'; @@ -99,10 +101,12 @@ class MenuAppHeader extends StatelessWidget { Widget _renderAddButton(BuildContext context) { return Tooltip( - message: "Quickly add a page inside", + message: LocaleKeys.menuAppHeader_addPageTooltip.tr(), child: AddButton( onSelected: (viewType) { - context.read().add(AppEvent.createView("Untitled", "", viewType)); + context + .read() + .add(AppEvent.createView(LocaleKeys.menuAppHeader_defaultNewPageName.tr(), "", viewType)); }, ).padding(right: MenuAppSizes.headerPadding), ); @@ -113,7 +117,7 @@ class MenuAppHeader extends StatelessWidget { switch (action) { case AppDisclosureAction.rename: TextFieldDialog( - title: 'Rename', + title: LocaleKeys.menuAppHeader_renameDialog.tr(), value: context.read().state.app.name, confirm: (newValue) { context.read().add(AppEvent.rename(newValue)); diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart index 4a0575e529..e361bce174 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart @@ -3,6 +3,7 @@ import 'package:app_flowy/workspace/application/view/view_bloc.dart'; import 'package:app_flowy/workspace/domain/edit_action/view_edit.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:dartz/dartz.dart' as dartz; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -14,6 +15,7 @@ import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:app_flowy/workspace/domain/image.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_app.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; import 'disclosure_action.dart'; @@ -85,7 +87,7 @@ class ViewSectionItem extends StatelessWidget { switch (action) { case ViewDisclosureAction.rename: TextFieldDialog( - title: 'Rename', + title: LocaleKeys.disclosureAction_rename.tr(), value: context.read().state.view.name, confirm: (newValue) { context.read().add(ViewEvent.rename(newValue)); diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart index a4de334e12..7f6b094777 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart @@ -2,12 +2,14 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/stack_page/trash/trash_page.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class MenuTrash extends StatelessWidget { const MenuTrash({Key? key}) : super(key: key); @@ -30,7 +32,7 @@ class MenuTrash extends StatelessWidget { return Row(children: [ SizedBox(width: 16, height: 16, child: svg("home/trash")), const HSpace(6), - const FlowyText.medium('Trash', fontSize: 12), + FlowyText.medium(LocaleKeys.trash_text.tr(), fontSize: 12), ]); } }