Browse Source

neon,neon_files,neon_news,neon_notes,neon_notifications: Split localizations

pull/327/head
jld3103 2 years ago
parent
commit
eb479063a4
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 197
      packages/neon/neon/lib/l10n/en.arb
  2. 714
      packages/neon/neon/lib/l10n/localizations.dart
  3. 377
      packages/neon/neon/lib/l10n/localizations_en.dart
  4. 1
      packages/neon/neon/lib/neon.dart
  5. 25
      packages/neon/neon/lib/src/app.dart
  6. 2
      packages/neon/neon/lib/src/utils/app_implementation.dart
  7. 10
      packages/neon/neon_files/lib/dialogs/choose_create.dart
  8. 6
      packages/neon/neon_files/lib/dialogs/choose_folder.dart
  9. 6
      packages/neon/neon_files/lib/dialogs/create_folder.dart
  10. 85
      packages/neon/neon_files/lib/l10n/en.arb
  11. 252
      packages/neon/neon_files/lib/l10n/localizations.dart
  12. 136
      packages/neon/neon_files/lib/l10n/localizations_en.dart
  13. 7
      packages/neon/neon_files/lib/neon_files.dart
  14. 22
      packages/neon/neon_files/lib/options.dart
  15. 15
      packages/neon/neon_files/lib/pages/details.dart
  16. 4
      packages/neon/neon_files/lib/pages/main.dart
  17. 25
      packages/neon/neon_files/lib/widgets/browser_view.dart
  18. 4
      packages/neon/neon_news/lib/dialogs/add_feed.dart
  19. 6
      packages/neon/neon_news/lib/dialogs/create_folder.dart
  20. 4
      packages/neon/neon_news/lib/dialogs/feed_show_url.dart
  21. 4
      packages/neon/neon_news/lib/dialogs/feed_update_error.dart
  22. 4
      packages/neon/neon_news/lib/dialogs/move_feed.dart
  23. 79
      packages/neon/neon_news/lib/l10n/en.arb
  24. 336
      packages/neon/neon_news/lib/l10n/localizations.dart
  25. 174
      packages/neon/neon_news/lib/l10n/localizations_en.dart
  26. 7
      packages/neon/neon_news/lib/neon_news.dart
  27. 66
      packages/neon/neon_news/lib/options.dart
  28. 13
      packages/neon/neon_news/lib/pages/article.dart
  29. 6
      packages/neon/neon_news/lib/pages/main.dart
  30. 11
      packages/neon/neon_news/lib/widgets/articles_view.dart
  31. 2
      packages/neon/neon_news/lib/widgets/feed_floating_action_button.dart
  32. 13
      packages/neon/neon_news/lib/widgets/feeds_view.dart
  33. 2
      packages/neon/neon_news/lib/widgets/folder_floating_action_button.dart
  34. 4
      packages/neon/neon_news/lib/widgets/folder_select.dart
  35. 6
      packages/neon/neon_news/lib/widgets/folders_view.dart
  36. 6
      packages/neon/neon_notes/lib/dialogs/create_note.dart
  37. 4
      packages/neon/neon_notes/lib/dialogs/select_category.dart
  38. 45
      packages/neon/neon_notes/lib/l10n/en.arb
  39. 174
      packages/neon/neon_notes/lib/l10n/localizations.dart
  40. 91
      packages/neon/neon_notes/lib/l10n/localizations_en.dart
  41. 7
      packages/neon/neon_notes/lib/neon_notes.dart
  42. 35
      packages/neon/neon_notes/lib/options.dart
  43. 2
      packages/neon/neon_notes/lib/pages/category.dart
  44. 4
      packages/neon/neon_notes/lib/pages/main.dart
  45. 7
      packages/neon/neon_notes/lib/pages/note.dart
  46. 2
      packages/neon/neon_notes/lib/utils/exception_handler.dart
  47. 4
      packages/neon/neon_notes/lib/widgets/categories_view.dart
  48. 4
      packages/neon/neon_notes/lib/widgets/category_select.dart
  49. 2
      packages/neon/neon_notes/lib/widgets/notes_floating_action_button.dart
  50. 4
      packages/neon/neon_notes/lib/widgets/notes_view.dart
  51. 5
      packages/neon/neon_notifications/lib/l10n/en.arb
  52. 18
      packages/neon/neon_notifications/lib/l10n/localizations.dart
  53. 9
      packages/neon/neon_notifications/lib/l10n/localizations_en.dart
  54. 7
      packages/neon/neon_notifications/lib/neon_notifications.dart
  55. 4
      packages/neon/neon_notifications/lib/pages/main.dart

197
packages/neon/neon/lib/l10n/en.arb

@ -46,18 +46,12 @@
}, },
"errorEmptyField": "This field can not be empty", "errorEmptyField": "This field can not be empty",
"errorInvalidURL": "Invalid URL provided", "errorInvalidURL": "Invalid URL provided",
"delete": "Delete",
"remove": "Remove",
"rename": "Rename",
"move": "Move",
"copy": "Copy",
"yes": "Yes", "yes": "Yes",
"no": "No", "no": "No",
"close": "Close", "close": "Close",
"retry": "Retry", "retry": "Retry",
"showSlashHide": "Show/Hide", "showSlashHide": "Show/Hide",
"exit": "Exit", "exit": "Exit",
"disabled": "Disabled",
"firstLaunchGoToSettingsToEnablePushNotifications": "Go to the settings to enable push notifications", "firstLaunchGoToSettingsToEnablePushNotifications": "Go to the settings to enable push notifications",
"nextPushSupported": "NextPush is supported!", "nextPushSupported": "NextPush is supported!",
"nextPushSupportedText": "NextPush is a FOSS way of receiving push notifications using the UnifiedPush protocol via a Nextcloud instance.\nYou can install NextPush from the F-Droid app store.", "nextPushSupportedText": "NextPush is a FOSS way of receiving push notifications using the UnifiedPush protocol via a Nextcloud instance.\nYou can install NextPush from the F-Droid app store.",
@ -149,194 +143,5 @@
}, },
"accountOptionsInitialApp": "App to show initially", "accountOptionsInitialApp": "App to show initially",
"accountOptionsAutomatic": "Automatic", "accountOptionsAutomatic": "Automatic",
"licenses": "Licenses", "licenses": "Licenses"
"filesUploadFiles": "Upload files",
"filesUploadImages": "Upload images",
"filesUploadCamera": "Upload from camera",
"filesCreateFolder": "Create folder",
"filesFolderName": "Folder name",
"filesRenameFolder": "Rename folder",
"filesRenameFile": "Rename file",
"filesDetails": "Details",
"filesDetailsFileName": "File name",
"filesDetailsFolderName": "Folder name",
"filesDetailsParentFolder": "Parent folder",
"filesDetailsFileSize": "File size",
"filesDetailsFolderSize": "Folder size",
"filesDetailsLastModified": "Last modified",
"filesDetailsIsFavorite": "Is favorite",
"filesSync": "Sync",
"filesDeleteFileConfirm": "Are you sure you want to delete the file '{name}'?",
"@filesDeleteFileConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"filesDeleteFolderConfirm": "Are you sure you want to delete the folder '{name}'?",
"@filesDeleteFolderConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"filesChooseFolder": "Choose folder",
"filesAddToFavorites": "Add to favorites",
"filesRemoveFromFavorites": "Remove from favorites",
"filesConfirmUploadSizeWarning": "Are you sure you want to upload a file that is bigger than {warningSize} ({actualSize})?",
"@filesConfirmUploadSizeWarning": {
"placeholders": {
"warningSize": {
"type": "String"
},
"actualSize": {
"type": "String"
}
}
},
"filesConfirmDownloadSizeWarning": "Are you sure you want to download a file that is bigger than {warningSize} ({actualSize})?",
"@filesConfirmDownloadSizeWarning": {
"placeholders": {
"warningSize": {
"type": "String"
},
"actualSize": {
"type": "String"
}
}
},
"filesGoToPath": "Go to /{path}",
"@filesGoToPath": {
"placeholders": {
"path": {
"type": "String"
}
}
},
"filesOptionsFilesSortPropertyName": "Name",
"filesOptionsFilesSortPropertyModifiedDate": "Last modified",
"filesOptionsFilesSortPropertySize": "Size",
"filesOptionsFilesSortOrder": "Sort order of files",
"filesOptionsShowPreviews": "Show previews for files",
"filesOptionsUploadQueueParallelism": "Upload queue parallelism",
"filesOptionsDownloadQueueParallelism": "Download queue parallelism",
"filesOptionsUploadSizeWarning": "Upload size warning",
"filesOptionsDownloadSizeWarning": "Download size warning",
"newsAddFeed": "Add feed",
"newsFolder": "Folder",
"newsFolderRoot": "Root Folder",
"newsCreateFolder": "Create folder",
"newsCreateFolderName": "Folder name",
"newsDeleteFolderConfirm": "Are you sure you want to delete the folder '{name}'?",
"@newsDeleteFolderConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"newsRenameFolder": "Rename folder",
"newsRemoveFeedConfirm": "Are you sure you want to remove the feed '{name}'?",
"@newsRemoveFeedConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"newsMoveFeed": "Move feed",
"newsRenameFeed": "Rename feed",
"newsArticles": "Articles",
"newsFolders": "Folders",
"newsFeeds": "Feeds",
"newsFilterAll": "All",
"newsFilterUnread": "Unread",
"newsFilterStarred": "Starred",
"newsUnreadArticles": "{count} unread",
"@newsUnreadArticles": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"newsArticleStar": "Star article",
"newsArticleUnstar": "Unstar article",
"newsArticleMarkRead": "Mark article as read",
"newsArticleMarkUnread": "Mark article as unread",
"newsArticleOpenLink": "Open in browser",
"newsArticleShare": "Share",
"newsShowFeedURL": "Show URL",
"newsCopyFeedURL": "Copy URL",
"newsCopiedFeedURL": "URL copied to clipboard",
"newsShowFeedErrorMessage": "Show error message",
"newsCopyFeedErrorMessage": "Copy error message",
"newsCopiedFeedErrorMessage": "Error message copied to clipboard",
"newsOptionsDefaultCategory": "Category to show by default",
"newsOptionsArticleViewType": "How to open article",
"newsOptionsArticleViewTypeDirect": "Show text directly",
"newsOptionsArticleViewTypeInternalBrowser": "Open in internal browser",
"newsOptionsArticleViewTypeExternalBrowser": "Open in external browser",
"newsOptionsArticleDisableMarkAsReadTimeout": "Mark articles as read instantly",
"newsOptionsDefaultArticlesFilter": "Articles to show by default",
"newsOptionsArticlesSortProperty": "How to sort articles",
"newsOptionsArticlesSortPropertyPublishDate": "Publish date",
"newsOptionsArticlesSortPropertyAlphabetical": "Alphabetical",
"newsOptionsArticlesSortPropertyFeed": "Feed",
"newsOptionsArticlesSortOrder": "Sort order of articles",
"newsOptionsFeedsSortProperty": "How to sort feeds",
"newsOptionsFeedsSortPropertyAlphabetical": "Alphabetical",
"newsOptionsFeedsSortPropertyUnreadCount": "Unread count",
"newsOptionsFeedsSortOrder": "Sort order of feeds",
"newsOptionsFoldersSortProperty": "How to sort folders",
"newsOptionsFoldersSortPropertyAlphabetical": "Alphabetical",
"newsOptionsFoldersSortPropertyUnreadCount": "Unread count",
"newsOptionsFoldersSortOrder": "Sort order of folders",
"newsOptionsDefaultFolderViewType": "What should be shown first when opening a folder",
"notesNote": "Note",
"notesNotes": "Notes",
"notesCategories": "Categories",
"notesCreateNote": "Create note",
"notesCategory": "Category",
"notesSetCategory": "Set category",
"notesNoteTitle": "Title",
"notesNoteChangedOnServer": "The note has been changed on the server. Please refresh and try again",
"notesNotesInCategory": "{count} notes",
"@notesNotesInCategory": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"notesUncategorized": "Uncategorized",
"notesShowEditor": "Edit note",
"notesShowPreview": "Preview note",
"notesStar": "Star note",
"notesUnstar": "Unstar note",
"notesChangeCategory": "Change note category",
"notesDeleteNoteConfirm": "Are you sure you want to delete the note '{name}'?",
"@notesDeleteNoteConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"notesOptionsDefaultCategory": "Category to show by default",
"notesOptionsDefaultNoteViewType": "How to show note",
"notesOptionsDefaultNoteViewTypePreview": "Preview",
"notesOptionsDefaultNoteViewTypeEdit": "Editor",
"notesOptionsNotesSortOrder": "Sort order of notes",
"notesOptionsNotesSortProperty": "How to sort notes",
"notesOptionsNotesSortPropertyLastModified": "Last modified",
"notesOptionsNotesSortPropertyAlphabetical": "Alphabetical",
"notesOptionsCategoriesSortOrder": "Sort order of categories",
"notesOptionsCategoriesSortProperty": "How to sort categories",
"notesOptionsCategoriesSortPropertyAlphabetical": "Alphabetical",
"notesOptionsCategoriesSortPropertyNotesCount": "Count of notes",
"notificationsNextcloudAppNotImplementedYet": "Sorry, this Nextcloud app has not been implemented yet",
"notificationsDismissAll": "Dismiss all notifications"
} }

714
packages/neon/neon/lib/l10n/localizations.dart

@ -209,36 +209,6 @@ abstract class AppLocalizations {
/// **'Invalid URL provided'** /// **'Invalid URL provided'**
String get errorInvalidURL; String get errorInvalidURL;
/// No description provided for @delete.
///
/// In en, this message translates to:
/// **'Delete'**
String get delete;
/// No description provided for @remove.
///
/// In en, this message translates to:
/// **'Remove'**
String get remove;
/// No description provided for @rename.
///
/// In en, this message translates to:
/// **'Rename'**
String get rename;
/// No description provided for @move.
///
/// In en, this message translates to:
/// **'Move'**
String get move;
/// No description provided for @copy.
///
/// In en, this message translates to:
/// **'Copy'**
String get copy;
/// No description provided for @yes. /// No description provided for @yes.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@ -275,12 +245,6 @@ abstract class AppLocalizations {
/// **'Exit'** /// **'Exit'**
String get exit; String get exit;
/// No description provided for @disabled.
///
/// In en, this message translates to:
/// **'Disabled'**
String get disabled;
/// No description provided for @firstLaunchGoToSettingsToEnablePushNotifications. /// No description provided for @firstLaunchGoToSettingsToEnablePushNotifications.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@ -628,684 +592,6 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'Licenses'** /// **'Licenses'**
String get licenses; String get licenses;
/// No description provided for @filesUploadFiles.
///
/// In en, this message translates to:
/// **'Upload files'**
String get filesUploadFiles;
/// No description provided for @filesUploadImages.
///
/// In en, this message translates to:
/// **'Upload images'**
String get filesUploadImages;
/// No description provided for @filesUploadCamera.
///
/// In en, this message translates to:
/// **'Upload from camera'**
String get filesUploadCamera;
/// No description provided for @filesCreateFolder.
///
/// In en, this message translates to:
/// **'Create folder'**
String get filesCreateFolder;
/// No description provided for @filesFolderName.
///
/// In en, this message translates to:
/// **'Folder name'**
String get filesFolderName;
/// No description provided for @filesRenameFolder.
///
/// In en, this message translates to:
/// **'Rename folder'**
String get filesRenameFolder;
/// No description provided for @filesRenameFile.
///
/// In en, this message translates to:
/// **'Rename file'**
String get filesRenameFile;
/// No description provided for @filesDetails.
///
/// In en, this message translates to:
/// **'Details'**
String get filesDetails;
/// No description provided for @filesDetailsFileName.
///
/// In en, this message translates to:
/// **'File name'**
String get filesDetailsFileName;
/// No description provided for @filesDetailsFolderName.
///
/// In en, this message translates to:
/// **'Folder name'**
String get filesDetailsFolderName;
/// No description provided for @filesDetailsParentFolder.
///
/// In en, this message translates to:
/// **'Parent folder'**
String get filesDetailsParentFolder;
/// No description provided for @filesDetailsFileSize.
///
/// In en, this message translates to:
/// **'File size'**
String get filesDetailsFileSize;
/// No description provided for @filesDetailsFolderSize.
///
/// In en, this message translates to:
/// **'Folder size'**
String get filesDetailsFolderSize;
/// No description provided for @filesDetailsLastModified.
///
/// In en, this message translates to:
/// **'Last modified'**
String get filesDetailsLastModified;
/// No description provided for @filesDetailsIsFavorite.
///
/// In en, this message translates to:
/// **'Is favorite'**
String get filesDetailsIsFavorite;
/// No description provided for @filesSync.
///
/// In en, this message translates to:
/// **'Sync'**
String get filesSync;
/// No description provided for @filesDeleteFileConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete the file \'{name}\'?'**
String filesDeleteFileConfirm(String name);
/// No description provided for @filesDeleteFolderConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete the folder \'{name}\'?'**
String filesDeleteFolderConfirm(String name);
/// No description provided for @filesChooseFolder.
///
/// In en, this message translates to:
/// **'Choose folder'**
String get filesChooseFolder;
/// No description provided for @filesAddToFavorites.
///
/// In en, this message translates to:
/// **'Add to favorites'**
String get filesAddToFavorites;
/// No description provided for @filesRemoveFromFavorites.
///
/// In en, this message translates to:
/// **'Remove from favorites'**
String get filesRemoveFromFavorites;
/// No description provided for @filesConfirmUploadSizeWarning.
///
/// In en, this message translates to:
/// **'Are you sure you want to upload a file that is bigger than {warningSize} ({actualSize})?'**
String filesConfirmUploadSizeWarning(String warningSize, String actualSize);
/// No description provided for @filesConfirmDownloadSizeWarning.
///
/// In en, this message translates to:
/// **'Are you sure you want to download a file that is bigger than {warningSize} ({actualSize})?'**
String filesConfirmDownloadSizeWarning(String warningSize, String actualSize);
/// No description provided for @filesGoToPath.
///
/// In en, this message translates to:
/// **'Go to /{path}'**
String filesGoToPath(String path);
/// No description provided for @filesOptionsFilesSortPropertyName.
///
/// In en, this message translates to:
/// **'Name'**
String get filesOptionsFilesSortPropertyName;
/// No description provided for @filesOptionsFilesSortPropertyModifiedDate.
///
/// In en, this message translates to:
/// **'Last modified'**
String get filesOptionsFilesSortPropertyModifiedDate;
/// No description provided for @filesOptionsFilesSortPropertySize.
///
/// In en, this message translates to:
/// **'Size'**
String get filesOptionsFilesSortPropertySize;
/// No description provided for @filesOptionsFilesSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of files'**
String get filesOptionsFilesSortOrder;
/// No description provided for @filesOptionsShowPreviews.
///
/// In en, this message translates to:
/// **'Show previews for files'**
String get filesOptionsShowPreviews;
/// No description provided for @filesOptionsUploadQueueParallelism.
///
/// In en, this message translates to:
/// **'Upload queue parallelism'**
String get filesOptionsUploadQueueParallelism;
/// No description provided for @filesOptionsDownloadQueueParallelism.
///
/// In en, this message translates to:
/// **'Download queue parallelism'**
String get filesOptionsDownloadQueueParallelism;
/// No description provided for @filesOptionsUploadSizeWarning.
///
/// In en, this message translates to:
/// **'Upload size warning'**
String get filesOptionsUploadSizeWarning;
/// No description provided for @filesOptionsDownloadSizeWarning.
///
/// In en, this message translates to:
/// **'Download size warning'**
String get filesOptionsDownloadSizeWarning;
/// No description provided for @newsAddFeed.
///
/// In en, this message translates to:
/// **'Add feed'**
String get newsAddFeed;
/// No description provided for @newsFolder.
///
/// In en, this message translates to:
/// **'Folder'**
String get newsFolder;
/// No description provided for @newsFolderRoot.
///
/// In en, this message translates to:
/// **'Root Folder'**
String get newsFolderRoot;
/// No description provided for @newsCreateFolder.
///
/// In en, this message translates to:
/// **'Create folder'**
String get newsCreateFolder;
/// No description provided for @newsCreateFolderName.
///
/// In en, this message translates to:
/// **'Folder name'**
String get newsCreateFolderName;
/// No description provided for @newsDeleteFolderConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete the folder \'{name}\'?'**
String newsDeleteFolderConfirm(String name);
/// No description provided for @newsRenameFolder.
///
/// In en, this message translates to:
/// **'Rename folder'**
String get newsRenameFolder;
/// No description provided for @newsRemoveFeedConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to remove the feed \'{name}\'?'**
String newsRemoveFeedConfirm(String name);
/// No description provided for @newsMoveFeed.
///
/// In en, this message translates to:
/// **'Move feed'**
String get newsMoveFeed;
/// No description provided for @newsRenameFeed.
///
/// In en, this message translates to:
/// **'Rename feed'**
String get newsRenameFeed;
/// No description provided for @newsArticles.
///
/// In en, this message translates to:
/// **'Articles'**
String get newsArticles;
/// No description provided for @newsFolders.
///
/// In en, this message translates to:
/// **'Folders'**
String get newsFolders;
/// No description provided for @newsFeeds.
///
/// In en, this message translates to:
/// **'Feeds'**
String get newsFeeds;
/// No description provided for @newsFilterAll.
///
/// In en, this message translates to:
/// **'All'**
String get newsFilterAll;
/// No description provided for @newsFilterUnread.
///
/// In en, this message translates to:
/// **'Unread'**
String get newsFilterUnread;
/// No description provided for @newsFilterStarred.
///
/// In en, this message translates to:
/// **'Starred'**
String get newsFilterStarred;
/// No description provided for @newsUnreadArticles.
///
/// In en, this message translates to:
/// **'{count} unread'**
String newsUnreadArticles(int count);
/// No description provided for @newsArticleStar.
///
/// In en, this message translates to:
/// **'Star article'**
String get newsArticleStar;
/// No description provided for @newsArticleUnstar.
///
/// In en, this message translates to:
/// **'Unstar article'**
String get newsArticleUnstar;
/// No description provided for @newsArticleMarkRead.
///
/// In en, this message translates to:
/// **'Mark article as read'**
String get newsArticleMarkRead;
/// No description provided for @newsArticleMarkUnread.
///
/// In en, this message translates to:
/// **'Mark article as unread'**
String get newsArticleMarkUnread;
/// No description provided for @newsArticleOpenLink.
///
/// In en, this message translates to:
/// **'Open in browser'**
String get newsArticleOpenLink;
/// No description provided for @newsArticleShare.
///
/// In en, this message translates to:
/// **'Share'**
String get newsArticleShare;
/// No description provided for @newsShowFeedURL.
///
/// In en, this message translates to:
/// **'Show URL'**
String get newsShowFeedURL;
/// No description provided for @newsCopyFeedURL.
///
/// In en, this message translates to:
/// **'Copy URL'**
String get newsCopyFeedURL;
/// No description provided for @newsCopiedFeedURL.
///
/// In en, this message translates to:
/// **'URL copied to clipboard'**
String get newsCopiedFeedURL;
/// No description provided for @newsShowFeedErrorMessage.
///
/// In en, this message translates to:
/// **'Show error message'**
String get newsShowFeedErrorMessage;
/// No description provided for @newsCopyFeedErrorMessage.
///
/// In en, this message translates to:
/// **'Copy error message'**
String get newsCopyFeedErrorMessage;
/// No description provided for @newsCopiedFeedErrorMessage.
///
/// In en, this message translates to:
/// **'Error message copied to clipboard'**
String get newsCopiedFeedErrorMessage;
/// No description provided for @newsOptionsDefaultCategory.
///
/// In en, this message translates to:
/// **'Category to show by default'**
String get newsOptionsDefaultCategory;
/// No description provided for @newsOptionsArticleViewType.
///
/// In en, this message translates to:
/// **'How to open article'**
String get newsOptionsArticleViewType;
/// No description provided for @newsOptionsArticleViewTypeDirect.
///
/// In en, this message translates to:
/// **'Show text directly'**
String get newsOptionsArticleViewTypeDirect;
/// No description provided for @newsOptionsArticleViewTypeInternalBrowser.
///
/// In en, this message translates to:
/// **'Open in internal browser'**
String get newsOptionsArticleViewTypeInternalBrowser;
/// No description provided for @newsOptionsArticleViewTypeExternalBrowser.
///
/// In en, this message translates to:
/// **'Open in external browser'**
String get newsOptionsArticleViewTypeExternalBrowser;
/// No description provided for @newsOptionsArticleDisableMarkAsReadTimeout.
///
/// In en, this message translates to:
/// **'Mark articles as read instantly'**
String get newsOptionsArticleDisableMarkAsReadTimeout;
/// No description provided for @newsOptionsDefaultArticlesFilter.
///
/// In en, this message translates to:
/// **'Articles to show by default'**
String get newsOptionsDefaultArticlesFilter;
/// No description provided for @newsOptionsArticlesSortProperty.
///
/// In en, this message translates to:
/// **'How to sort articles'**
String get newsOptionsArticlesSortProperty;
/// No description provided for @newsOptionsArticlesSortPropertyPublishDate.
///
/// In en, this message translates to:
/// **'Publish date'**
String get newsOptionsArticlesSortPropertyPublishDate;
/// No description provided for @newsOptionsArticlesSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get newsOptionsArticlesSortPropertyAlphabetical;
/// No description provided for @newsOptionsArticlesSortPropertyFeed.
///
/// In en, this message translates to:
/// **'Feed'**
String get newsOptionsArticlesSortPropertyFeed;
/// No description provided for @newsOptionsArticlesSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of articles'**
String get newsOptionsArticlesSortOrder;
/// No description provided for @newsOptionsFeedsSortProperty.
///
/// In en, this message translates to:
/// **'How to sort feeds'**
String get newsOptionsFeedsSortProperty;
/// No description provided for @newsOptionsFeedsSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get newsOptionsFeedsSortPropertyAlphabetical;
/// No description provided for @newsOptionsFeedsSortPropertyUnreadCount.
///
/// In en, this message translates to:
/// **'Unread count'**
String get newsOptionsFeedsSortPropertyUnreadCount;
/// No description provided for @newsOptionsFeedsSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of feeds'**
String get newsOptionsFeedsSortOrder;
/// No description provided for @newsOptionsFoldersSortProperty.
///
/// In en, this message translates to:
/// **'How to sort folders'**
String get newsOptionsFoldersSortProperty;
/// No description provided for @newsOptionsFoldersSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get newsOptionsFoldersSortPropertyAlphabetical;
/// No description provided for @newsOptionsFoldersSortPropertyUnreadCount.
///
/// In en, this message translates to:
/// **'Unread count'**
String get newsOptionsFoldersSortPropertyUnreadCount;
/// No description provided for @newsOptionsFoldersSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of folders'**
String get newsOptionsFoldersSortOrder;
/// No description provided for @newsOptionsDefaultFolderViewType.
///
/// In en, this message translates to:
/// **'What should be shown first when opening a folder'**
String get newsOptionsDefaultFolderViewType;
/// No description provided for @notesNote.
///
/// In en, this message translates to:
/// **'Note'**
String get notesNote;
/// No description provided for @notesNotes.
///
/// In en, this message translates to:
/// **'Notes'**
String get notesNotes;
/// No description provided for @notesCategories.
///
/// In en, this message translates to:
/// **'Categories'**
String get notesCategories;
/// No description provided for @notesCreateNote.
///
/// In en, this message translates to:
/// **'Create note'**
String get notesCreateNote;
/// No description provided for @notesCategory.
///
/// In en, this message translates to:
/// **'Category'**
String get notesCategory;
/// No description provided for @notesSetCategory.
///
/// In en, this message translates to:
/// **'Set category'**
String get notesSetCategory;
/// No description provided for @notesNoteTitle.
///
/// In en, this message translates to:
/// **'Title'**
String get notesNoteTitle;
/// No description provided for @notesNoteChangedOnServer.
///
/// In en, this message translates to:
/// **'The note has been changed on the server. Please refresh and try again'**
String get notesNoteChangedOnServer;
/// No description provided for @notesNotesInCategory.
///
/// In en, this message translates to:
/// **'{count} notes'**
String notesNotesInCategory(int count);
/// No description provided for @notesUncategorized.
///
/// In en, this message translates to:
/// **'Uncategorized'**
String get notesUncategorized;
/// No description provided for @notesShowEditor.
///
/// In en, this message translates to:
/// **'Edit note'**
String get notesShowEditor;
/// No description provided for @notesShowPreview.
///
/// In en, this message translates to:
/// **'Preview note'**
String get notesShowPreview;
/// No description provided for @notesStar.
///
/// In en, this message translates to:
/// **'Star note'**
String get notesStar;
/// No description provided for @notesUnstar.
///
/// In en, this message translates to:
/// **'Unstar note'**
String get notesUnstar;
/// No description provided for @notesChangeCategory.
///
/// In en, this message translates to:
/// **'Change note category'**
String get notesChangeCategory;
/// No description provided for @notesDeleteNoteConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete the note \'{name}\'?'**
String notesDeleteNoteConfirm(String name);
/// No description provided for @notesOptionsDefaultCategory.
///
/// In en, this message translates to:
/// **'Category to show by default'**
String get notesOptionsDefaultCategory;
/// No description provided for @notesOptionsDefaultNoteViewType.
///
/// In en, this message translates to:
/// **'How to show note'**
String get notesOptionsDefaultNoteViewType;
/// No description provided for @notesOptionsDefaultNoteViewTypePreview.
///
/// In en, this message translates to:
/// **'Preview'**
String get notesOptionsDefaultNoteViewTypePreview;
/// No description provided for @notesOptionsDefaultNoteViewTypeEdit.
///
/// In en, this message translates to:
/// **'Editor'**
String get notesOptionsDefaultNoteViewTypeEdit;
/// No description provided for @notesOptionsNotesSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of notes'**
String get notesOptionsNotesSortOrder;
/// No description provided for @notesOptionsNotesSortProperty.
///
/// In en, this message translates to:
/// **'How to sort notes'**
String get notesOptionsNotesSortProperty;
/// No description provided for @notesOptionsNotesSortPropertyLastModified.
///
/// In en, this message translates to:
/// **'Last modified'**
String get notesOptionsNotesSortPropertyLastModified;
/// No description provided for @notesOptionsNotesSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get notesOptionsNotesSortPropertyAlphabetical;
/// No description provided for @notesOptionsCategoriesSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of categories'**
String get notesOptionsCategoriesSortOrder;
/// No description provided for @notesOptionsCategoriesSortProperty.
///
/// In en, this message translates to:
/// **'How to sort categories'**
String get notesOptionsCategoriesSortProperty;
/// No description provided for @notesOptionsCategoriesSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get notesOptionsCategoriesSortPropertyAlphabetical;
/// No description provided for @notesOptionsCategoriesSortPropertyNotesCount.
///
/// In en, this message translates to:
/// **'Count of notes'**
String get notesOptionsCategoriesSortPropertyNotesCount;
/// No description provided for @notificationsNextcloudAppNotImplementedYet.
///
/// In en, this message translates to:
/// **'Sorry, this Nextcloud app has not been implemented yet'**
String get notificationsNextcloudAppNotImplementedYet;
/// No description provided for @notificationsDismissAll.
///
/// In en, this message translates to:
/// **'Dismiss all notifications'**
String get notificationsDismissAll;
} }
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> { class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {

377
packages/neon/neon/lib/l10n/localizations_en.dart

@ -89,21 +89,6 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get errorInvalidURL => 'Invalid URL provided'; String get errorInvalidURL => 'Invalid URL provided';
@override
String get delete => 'Delete';
@override
String get remove => 'Remove';
@override
String get rename => 'Rename';
@override
String get move => 'Move';
@override
String get copy => 'Copy';
@override @override
String get yes => 'Yes'; String get yes => 'Yes';
@ -122,9 +107,6 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get exit => 'Exit'; String get exit => 'Exit';
@override
String get disabled => 'Disabled';
@override @override
String get firstLaunchGoToSettingsToEnablePushNotifications => 'Go to the settings to enable push notifications'; String get firstLaunchGoToSettingsToEnablePushNotifications => 'Go to the settings to enable push notifications';
@ -308,363 +290,4 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get licenses => 'Licenses'; String get licenses => 'Licenses';
@override
String get filesUploadFiles => 'Upload files';
@override
String get filesUploadImages => 'Upload images';
@override
String get filesUploadCamera => 'Upload from camera';
@override
String get filesCreateFolder => 'Create folder';
@override
String get filesFolderName => 'Folder name';
@override
String get filesRenameFolder => 'Rename folder';
@override
String get filesRenameFile => 'Rename file';
@override
String get filesDetails => 'Details';
@override
String get filesDetailsFileName => 'File name';
@override
String get filesDetailsFolderName => 'Folder name';
@override
String get filesDetailsParentFolder => 'Parent folder';
@override
String get filesDetailsFileSize => 'File size';
@override
String get filesDetailsFolderSize => 'Folder size';
@override
String get filesDetailsLastModified => 'Last modified';
@override
String get filesDetailsIsFavorite => 'Is favorite';
@override
String get filesSync => 'Sync';
@override
String filesDeleteFileConfirm(String name) {
return 'Are you sure you want to delete the file \'$name\'?';
}
@override
String filesDeleteFolderConfirm(String name) {
return 'Are you sure you want to delete the folder \'$name\'?';
}
@override
String get filesChooseFolder => 'Choose folder';
@override
String get filesAddToFavorites => 'Add to favorites';
@override
String get filesRemoveFromFavorites => 'Remove from favorites';
@override
String filesConfirmUploadSizeWarning(String warningSize, String actualSize) {
return 'Are you sure you want to upload a file that is bigger than $warningSize ($actualSize)?';
}
@override
String filesConfirmDownloadSizeWarning(String warningSize, String actualSize) {
return 'Are you sure you want to download a file that is bigger than $warningSize ($actualSize)?';
}
@override
String filesGoToPath(String path) {
return 'Go to /$path';
}
@override
String get filesOptionsFilesSortPropertyName => 'Name';
@override
String get filesOptionsFilesSortPropertyModifiedDate => 'Last modified';
@override
String get filesOptionsFilesSortPropertySize => 'Size';
@override
String get filesOptionsFilesSortOrder => 'Sort order of files';
@override
String get filesOptionsShowPreviews => 'Show previews for files';
@override
String get filesOptionsUploadQueueParallelism => 'Upload queue parallelism';
@override
String get filesOptionsDownloadQueueParallelism => 'Download queue parallelism';
@override
String get filesOptionsUploadSizeWarning => 'Upload size warning';
@override
String get filesOptionsDownloadSizeWarning => 'Download size warning';
@override
String get newsAddFeed => 'Add feed';
@override
String get newsFolder => 'Folder';
@override
String get newsFolderRoot => 'Root Folder';
@override
String get newsCreateFolder => 'Create folder';
@override
String get newsCreateFolderName => 'Folder name';
@override
String newsDeleteFolderConfirm(String name) {
return 'Are you sure you want to delete the folder \'$name\'?';
}
@override
String get newsRenameFolder => 'Rename folder';
@override
String newsRemoveFeedConfirm(String name) {
return 'Are you sure you want to remove the feed \'$name\'?';
}
@override
String get newsMoveFeed => 'Move feed';
@override
String get newsRenameFeed => 'Rename feed';
@override
String get newsArticles => 'Articles';
@override
String get newsFolders => 'Folders';
@override
String get newsFeeds => 'Feeds';
@override
String get newsFilterAll => 'All';
@override
String get newsFilterUnread => 'Unread';
@override
String get newsFilterStarred => 'Starred';
@override
String newsUnreadArticles(int count) {
return '$count unread';
}
@override
String get newsArticleStar => 'Star article';
@override
String get newsArticleUnstar => 'Unstar article';
@override
String get newsArticleMarkRead => 'Mark article as read';
@override
String get newsArticleMarkUnread => 'Mark article as unread';
@override
String get newsArticleOpenLink => 'Open in browser';
@override
String get newsArticleShare => 'Share';
@override
String get newsShowFeedURL => 'Show URL';
@override
String get newsCopyFeedURL => 'Copy URL';
@override
String get newsCopiedFeedURL => 'URL copied to clipboard';
@override
String get newsShowFeedErrorMessage => 'Show error message';
@override
String get newsCopyFeedErrorMessage => 'Copy error message';
@override
String get newsCopiedFeedErrorMessage => 'Error message copied to clipboard';
@override
String get newsOptionsDefaultCategory => 'Category to show by default';
@override
String get newsOptionsArticleViewType => 'How to open article';
@override
String get newsOptionsArticleViewTypeDirect => 'Show text directly';
@override
String get newsOptionsArticleViewTypeInternalBrowser => 'Open in internal browser';
@override
String get newsOptionsArticleViewTypeExternalBrowser => 'Open in external browser';
@override
String get newsOptionsArticleDisableMarkAsReadTimeout => 'Mark articles as read instantly';
@override
String get newsOptionsDefaultArticlesFilter => 'Articles to show by default';
@override
String get newsOptionsArticlesSortProperty => 'How to sort articles';
@override
String get newsOptionsArticlesSortPropertyPublishDate => 'Publish date';
@override
String get newsOptionsArticlesSortPropertyAlphabetical => 'Alphabetical';
@override
String get newsOptionsArticlesSortPropertyFeed => 'Feed';
@override
String get newsOptionsArticlesSortOrder => 'Sort order of articles';
@override
String get newsOptionsFeedsSortProperty => 'How to sort feeds';
@override
String get newsOptionsFeedsSortPropertyAlphabetical => 'Alphabetical';
@override
String get newsOptionsFeedsSortPropertyUnreadCount => 'Unread count';
@override
String get newsOptionsFeedsSortOrder => 'Sort order of feeds';
@override
String get newsOptionsFoldersSortProperty => 'How to sort folders';
@override
String get newsOptionsFoldersSortPropertyAlphabetical => 'Alphabetical';
@override
String get newsOptionsFoldersSortPropertyUnreadCount => 'Unread count';
@override
String get newsOptionsFoldersSortOrder => 'Sort order of folders';
@override
String get newsOptionsDefaultFolderViewType => 'What should be shown first when opening a folder';
@override
String get notesNote => 'Note';
@override
String get notesNotes => 'Notes';
@override
String get notesCategories => 'Categories';
@override
String get notesCreateNote => 'Create note';
@override
String get notesCategory => 'Category';
@override
String get notesSetCategory => 'Set category';
@override
String get notesNoteTitle => 'Title';
@override
String get notesNoteChangedOnServer => 'The note has been changed on the server. Please refresh and try again';
@override
String notesNotesInCategory(int count) {
return '$count notes';
}
@override
String get notesUncategorized => 'Uncategorized';
@override
String get notesShowEditor => 'Edit note';
@override
String get notesShowPreview => 'Preview note';
@override
String get notesStar => 'Star note';
@override
String get notesUnstar => 'Unstar note';
@override
String get notesChangeCategory => 'Change note category';
@override
String notesDeleteNoteConfirm(String name) {
return 'Are you sure you want to delete the note \'$name\'?';
}
@override
String get notesOptionsDefaultCategory => 'Category to show by default';
@override
String get notesOptionsDefaultNoteViewType => 'How to show note';
@override
String get notesOptionsDefaultNoteViewTypePreview => 'Preview';
@override
String get notesOptionsDefaultNoteViewTypeEdit => 'Editor';
@override
String get notesOptionsNotesSortOrder => 'Sort order of notes';
@override
String get notesOptionsNotesSortProperty => 'How to sort notes';
@override
String get notesOptionsNotesSortPropertyLastModified => 'Last modified';
@override
String get notesOptionsNotesSortPropertyAlphabetical => 'Alphabetical';
@override
String get notesOptionsCategoriesSortOrder => 'Sort order of categories';
@override
String get notesOptionsCategoriesSortProperty => 'How to sort categories';
@override
String get notesOptionsCategoriesSortPropertyAlphabetical => 'Alphabetical';
@override
String get notesOptionsCategoriesSortPropertyNotesCount => 'Count of notes';
@override
String get notificationsNextcloudAppNotImplementedYet => 'Sorry, this Nextcloud app has not been implemented yet';
@override
String get notificationsDismissAll => 'Dismiss all notifications';
} }

1
packages/neon/neon/lib/neon.dart

@ -42,7 +42,6 @@ import 'package:window_manager/window_manager.dart';
import 'package:xdg_directories/xdg_directories.dart' as xdg; import 'package:xdg_directories/xdg_directories.dart' as xdg;
import 'package:xml/xml.dart' as xml; import 'package:xml/xml.dart' as xml;
export 'l10n/localizations.dart';
export 'src/models/account.dart'; export 'src/models/account.dart';
export 'src/models/push_notification.dart'; export 'src/models/push_notification.dart';

25
packages/neon/neon/lib/src/app.dart

@ -22,9 +22,10 @@ class NeonApp extends StatefulWidget {
class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.TrayListener, WindowListener { class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.TrayListener, WindowListener {
final _appRegex = RegExp(r'^app_([a-z]+)$', multiLine: true); final _appRegex = RegExp(r'^app_([a-z]+)$', multiLine: true);
final _navigatorKey = GlobalKey<NavigatorState>(); final _navigatorKey = GlobalKey<NavigatorState>();
late NeonPlatform _platform; late final List<AppImplementation> _appImplementations;
late GlobalOptions _globalOptions; late final NeonPlatform _platform;
late AccountsBloc _accountsBloc; late final GlobalOptions _globalOptions;
late final AccountsBloc _accountsBloc;
late final _routerDelegate = AppRouter( late final _routerDelegate = AppRouter(
navigatorKey: _navigatorKey, navigatorKey: _navigatorKey,
accountsBloc: _accountsBloc, accountsBloc: _accountsBloc,
@ -36,6 +37,7 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
void initState() { void initState() {
super.initState(); super.initState();
_appImplementations = Provider.of<List<AppImplementation>>(context, listen: false);
_platform = Provider.of<NeonPlatform>(context, listen: false); _platform = Provider.of<NeonPlatform>(context, listen: false);
_globalOptions = Provider.of<GlobalOptions>(context, listen: false); _globalOptions = Provider.of<GlobalOptions>(context, listen: false);
_accountsBloc = Provider.of<AccountsBloc>(context, listen: false); _accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
@ -54,11 +56,10 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
if (!mounted) { if (!mounted) {
return; return;
} }
final appImplementations = Provider.of<List<AppImplementation>>(context, listen: false);
if (_platform.canUseQuickActions) { if (_platform.canUseQuickActions) {
const quickActions = QuickActions(); const quickActions = QuickActions();
await quickActions.setShortcutItems( await quickActions.setShortcutItems(
appImplementations _appImplementations
.map( .map(
(final app) => ShortcutItem( (final app) => ShortcutItem(
type: 'app_${app.id}', type: 'app_${app.id}',
@ -88,7 +89,7 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
await tray.trayManager.setContextMenu( await tray.trayManager.setContextMenu(
tray.Menu( tray.Menu(
items: [ items: [
for (final app in appImplementations) ...[ for (final app in _appImplementations) ...[
tray.MenuItem( tray.MenuItem(
key: 'app_${app.id}', key: 'app_${app.id}',
label: app.nameFromLocalization(localizations), label: app.nameFromLocalization(localizations),
@ -272,8 +273,16 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
builder: (final context, final capabilitiesSnapshot) { builder: (final context, final capabilitiesSnapshot) {
final nextcloudTheme = capabilitiesSnapshot.data?.capabilities.theming; final nextcloudTheme = capabilitiesSnapshot.data?.capabilities.theming;
return MaterialApp.router( return MaterialApp.router(
localizationsDelegates: AppLocalizations.localizationsDelegates, localizationsDelegates: [
supportedLocales: AppLocalizations.supportedLocales, ..._appImplementations.map((final app) => app.localizationsDelegate),
...AppLocalizations.localizationsDelegates,
],
supportedLocales: {
..._appImplementations
.map((final app) => app.supportedLocales)
.reduce((final value, final element) => [...value, ...element]),
...AppLocalizations.supportedLocales,
},
themeMode: themeMode, themeMode: themeMode,
theme: getThemeFromNextcloudTheme( theme: getThemeFromNextcloudTheme(
nextcloudTheme, nextcloudTheme,

2
packages/neon/neon/lib/src/utils/app_implementation.dart

@ -11,6 +11,8 @@ abstract class AppImplementation<T extends Bloc, R extends NextcloudAppSpecificO
} }
String get id; String get id;
LocalizationsDelegate get localizationsDelegate;
List<Locale> get supportedLocales;
final RequestManager requestManager; final RequestManager requestManager;
final NeonPlatform platform; final NeonPlatform platform;

10
packages/neon/neon_files/lib/dialogs/choose_create.dart

@ -36,7 +36,7 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
if (!(await showConfirmationDialog( if (!(await showConfirmationDialog(
context, context,
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
AppLocalizations.of(context).filesConfirmUploadSizeWarning( AppLocalizations.of(context).confirmUploadSizeWarning(
filesize(sizeWarning), filesize(sizeWarning),
filesize(stat.size), filesize(stat.size),
), ),
@ -56,7 +56,7 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
MdiIcons.filePlus, MdiIcons.filePlus,
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
), ),
title: Text(AppLocalizations.of(context).filesUploadFiles), title: Text(AppLocalizations.of(context).uploadFiles),
onTap: () async { onTap: () async {
await uploadFromPick(FileType.any); await uploadFromPick(FileType.any);
@ -70,7 +70,7 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
MdiIcons.fileImagePlus, MdiIcons.fileImagePlus,
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
), ),
title: Text(AppLocalizations.of(context).filesUploadImages), title: Text(AppLocalizations.of(context).uploadImages),
onTap: () async { onTap: () async {
await uploadFromPick(FileType.image); await uploadFromPick(FileType.image);
@ -85,7 +85,7 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
MdiIcons.cameraPlus, MdiIcons.cameraPlus,
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
), ),
title: Text(AppLocalizations.of(context).filesUploadCamera), title: Text(AppLocalizations.of(context).uploadCamera),
onTap: () async { onTap: () async {
Navigator.of(context).pop(); Navigator.of(context).pop();
@ -102,7 +102,7 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
MdiIcons.folderPlus, MdiIcons.folderPlus,
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
), ),
title: Text(AppLocalizations.of(context).filesCreateFolder), title: Text(AppLocalizations.of(context).createFolder),
onTap: () async { onTap: () async {
Navigator.of(context).pop(); Navigator.of(context).pop();

6
packages/neon/neon_files/lib/dialogs/choose_folder.dart

@ -15,7 +15,7 @@ class FilesChooseFolderDialog extends StatelessWidget {
@override @override
Widget build(final BuildContext context) => AlertDialog( Widget build(final BuildContext context) => AlertDialog(
title: Text(AppLocalizations.of(context).filesChooseFolder), title: Text(AppLocalizations.of(context).chooseFolder),
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
content: SizedBox( content: SizedBox(
width: double.maxFinite, width: double.maxFinite,
@ -47,13 +47,13 @@ class FilesChooseFolderDialog extends StatelessWidget {
bloc.createFolder([...pathSnapshot.data!, ...result]); bloc.createFolder([...pathSnapshot.data!, ...result]);
} }
}, },
child: Text(AppLocalizations.of(context).filesCreateFolder), child: Text(AppLocalizations.of(context).createFolder),
), ),
ElevatedButton( ElevatedButton(
onPressed: !(const ListEquality().equals(originalPath, pathSnapshot.data)) onPressed: !(const ListEquality().equals(originalPath, pathSnapshot.data))
? () => Navigator.of(context).pop(pathSnapshot.data) ? () => Navigator.of(context).pop(pathSnapshot.data)
: null, : null,
child: Text(AppLocalizations.of(context).filesChooseFolder), child: Text(AppLocalizations.of(context).chooseFolder),
), ),
], ],
), ),

6
packages/neon/neon_files/lib/dialogs/create_folder.dart

@ -22,7 +22,7 @@ class _FilesCreateFolderDialogState extends State<FilesCreateFolderDialog> {
@override @override
Widget build(final BuildContext context) => NeonDialog( Widget build(final BuildContext context) => NeonDialog(
title: Text(AppLocalizations.of(context).filesCreateFolder), title: Text(AppLocalizations.of(context).createFolder),
children: [ children: [
Form( Form(
key: formKey, key: formKey,
@ -32,7 +32,7 @@ class _FilesCreateFolderDialogState extends State<FilesCreateFolderDialog> {
TextFormField( TextFormField(
controller: controller, controller: controller,
decoration: InputDecoration( decoration: InputDecoration(
hintText: AppLocalizations.of(context).filesFolderName, hintText: AppLocalizations.of(context).folderName,
), ),
autofocus: true, autofocus: true,
validator: (final input) => validateNotEmpty(context, input), validator: (final input) => validateNotEmpty(context, input),
@ -42,7 +42,7 @@ class _FilesCreateFolderDialogState extends State<FilesCreateFolderDialog> {
), ),
ElevatedButton( ElevatedButton(
onPressed: submit, onPressed: submit,
child: Text(AppLocalizations.of(context).filesCreateFolder), child: Text(AppLocalizations.of(context).createFolder),
), ),
], ],
), ),

85
packages/neon/neon_files/lib/l10n/en.arb

@ -1,3 +1,86 @@
{ {
"@@locale": "en" "@@locale": "en",
"yes": "Yes",
"no": "No",
"delete": "Delete",
"rename": "Rename",
"move": "Move",
"copy": "Copy",
"disabled": "Disabled",
"general": "General",
"uploadFiles": "Upload files",
"uploadImages": "Upload images",
"uploadCamera": "Upload from camera",
"createFolder": "Create folder",
"folderName": "Folder name",
"renameFolder": "Rename folder",
"renameFile": "Rename file",
"details": "Details",
"detailsFileName": "File name",
"detailsFolderName": "Folder name",
"detailsParentFolder": "Parent folder",
"detailsFileSize": "File size",
"detailsFolderSize": "Folder size",
"detailsLastModified": "Last modified",
"detailsIsFavorite": "Is favorite",
"sync": "Sync",
"deleteFileConfirm": "Are you sure you want to delete the file '{name}'?",
"@deleteFileConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"deleteFolderConfirm": "Are you sure you want to delete the folder '{name}'?",
"@deleteFolderConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"chooseFolder": "Choose folder",
"addToFavorites": "Add to favorites",
"removeFromFavorites": "Remove from favorites",
"confirmUploadSizeWarning": "Are you sure you want to upload a file that is bigger than {warningSize} ({actualSize})?",
"@confirmUploadSizeWarning": {
"placeholders": {
"warningSize": {
"type": "String"
},
"actualSize": {
"type": "String"
}
}
},
"confirmDownloadSizeWarning": "Are you sure you want to download a file that is bigger than {warningSize} ({actualSize})?",
"@confirmDownloadSizeWarning": {
"placeholders": {
"warningSize": {
"type": "String"
},
"actualSize": {
"type": "String"
}
}
},
"goToPath": "Go to /{path}",
"@goToPath": {
"placeholders": {
"path": {
"type": "String"
}
}
},
"optionsFilesSortProperty": "How to sort files",
"optionsFilesSortPropertyName": "Name",
"optionsFilesSortPropertyModifiedDate": "Last modified",
"optionsFilesSortPropertySize": "Size",
"optionsFilesSortOrder": "Sort order of files",
"optionsShowPreviews": "Show previews for files",
"optionsUploadQueueParallelism": "Upload queue parallelism",
"optionsDownloadQueueParallelism": "Download queue parallelism",
"optionsUploadSizeWarning": "Upload size warning",
"optionsDownloadSizeWarning": "Download size warning"
} }

252
packages/neon/neon_files/lib/l10n/localizations.dart

@ -88,6 +88,258 @@ abstract class AppLocalizations {
/// A list of this localizations delegate's supported locales. /// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[Locale('en')]; static const List<Locale> supportedLocales = <Locale>[Locale('en')];
/// No description provided for @yes.
///
/// In en, this message translates to:
/// **'Yes'**
String get yes;
/// No description provided for @no.
///
/// In en, this message translates to:
/// **'No'**
String get no;
/// No description provided for @delete.
///
/// In en, this message translates to:
/// **'Delete'**
String get delete;
/// No description provided for @rename.
///
/// In en, this message translates to:
/// **'Rename'**
String get rename;
/// No description provided for @move.
///
/// In en, this message translates to:
/// **'Move'**
String get move;
/// No description provided for @copy.
///
/// In en, this message translates to:
/// **'Copy'**
String get copy;
/// No description provided for @disabled.
///
/// In en, this message translates to:
/// **'Disabled'**
String get disabled;
/// No description provided for @general.
///
/// In en, this message translates to:
/// **'General'**
String get general;
/// No description provided for @uploadFiles.
///
/// In en, this message translates to:
/// **'Upload files'**
String get uploadFiles;
/// No description provided for @uploadImages.
///
/// In en, this message translates to:
/// **'Upload images'**
String get uploadImages;
/// No description provided for @uploadCamera.
///
/// In en, this message translates to:
/// **'Upload from camera'**
String get uploadCamera;
/// No description provided for @createFolder.
///
/// In en, this message translates to:
/// **'Create folder'**
String get createFolder;
/// No description provided for @folderName.
///
/// In en, this message translates to:
/// **'Folder name'**
String get folderName;
/// No description provided for @renameFolder.
///
/// In en, this message translates to:
/// **'Rename folder'**
String get renameFolder;
/// No description provided for @renameFile.
///
/// In en, this message translates to:
/// **'Rename file'**
String get renameFile;
/// No description provided for @details.
///
/// In en, this message translates to:
/// **'Details'**
String get details;
/// No description provided for @detailsFileName.
///
/// In en, this message translates to:
/// **'File name'**
String get detailsFileName;
/// No description provided for @detailsFolderName.
///
/// In en, this message translates to:
/// **'Folder name'**
String get detailsFolderName;
/// No description provided for @detailsParentFolder.
///
/// In en, this message translates to:
/// **'Parent folder'**
String get detailsParentFolder;
/// No description provided for @detailsFileSize.
///
/// In en, this message translates to:
/// **'File size'**
String get detailsFileSize;
/// No description provided for @detailsFolderSize.
///
/// In en, this message translates to:
/// **'Folder size'**
String get detailsFolderSize;
/// No description provided for @detailsLastModified.
///
/// In en, this message translates to:
/// **'Last modified'**
String get detailsLastModified;
/// No description provided for @detailsIsFavorite.
///
/// In en, this message translates to:
/// **'Is favorite'**
String get detailsIsFavorite;
/// No description provided for @sync.
///
/// In en, this message translates to:
/// **'Sync'**
String get sync;
/// No description provided for @deleteFileConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete the file \'{name}\'?'**
String deleteFileConfirm(String name);
/// No description provided for @deleteFolderConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete the folder \'{name}\'?'**
String deleteFolderConfirm(String name);
/// No description provided for @chooseFolder.
///
/// In en, this message translates to:
/// **'Choose folder'**
String get chooseFolder;
/// No description provided for @addToFavorites.
///
/// In en, this message translates to:
/// **'Add to favorites'**
String get addToFavorites;
/// No description provided for @removeFromFavorites.
///
/// In en, this message translates to:
/// **'Remove from favorites'**
String get removeFromFavorites;
/// No description provided for @confirmUploadSizeWarning.
///
/// In en, this message translates to:
/// **'Are you sure you want to upload a file that is bigger than {warningSize} ({actualSize})?'**
String confirmUploadSizeWarning(String warningSize, String actualSize);
/// No description provided for @confirmDownloadSizeWarning.
///
/// In en, this message translates to:
/// **'Are you sure you want to download a file that is bigger than {warningSize} ({actualSize})?'**
String confirmDownloadSizeWarning(String warningSize, String actualSize);
/// No description provided for @goToPath.
///
/// In en, this message translates to:
/// **'Go to /{path}'**
String goToPath(String path);
/// No description provided for @optionsFilesSortProperty.
///
/// In en, this message translates to:
/// **'How to sort files'**
String get optionsFilesSortProperty;
/// No description provided for @optionsFilesSortPropertyName.
///
/// In en, this message translates to:
/// **'Name'**
String get optionsFilesSortPropertyName;
/// No description provided for @optionsFilesSortPropertyModifiedDate.
///
/// In en, this message translates to:
/// **'Last modified'**
String get optionsFilesSortPropertyModifiedDate;
/// No description provided for @optionsFilesSortPropertySize.
///
/// In en, this message translates to:
/// **'Size'**
String get optionsFilesSortPropertySize;
/// No description provided for @optionsFilesSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of files'**
String get optionsFilesSortOrder;
/// No description provided for @optionsShowPreviews.
///
/// In en, this message translates to:
/// **'Show previews for files'**
String get optionsShowPreviews;
/// No description provided for @optionsUploadQueueParallelism.
///
/// In en, this message translates to:
/// **'Upload queue parallelism'**
String get optionsUploadQueueParallelism;
/// No description provided for @optionsDownloadQueueParallelism.
///
/// In en, this message translates to:
/// **'Download queue parallelism'**
String get optionsDownloadQueueParallelism;
/// No description provided for @optionsUploadSizeWarning.
///
/// In en, this message translates to:
/// **'Upload size warning'**
String get optionsUploadSizeWarning;
/// No description provided for @optionsDownloadSizeWarning.
///
/// In en, this message translates to:
/// **'Download size warning'**
String get optionsDownloadSizeWarning;
} }
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> { class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {

136
packages/neon/neon_files/lib/l10n/localizations_en.dart

@ -3,4 +3,140 @@ import 'localizations.dart';
/// The translations for English (`en`). /// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations { class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale); AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String get yes => 'Yes';
@override
String get no => 'No';
@override
String get delete => 'Delete';
@override
String get rename => 'Rename';
@override
String get move => 'Move';
@override
String get copy => 'Copy';
@override
String get disabled => 'Disabled';
@override
String get general => 'General';
@override
String get uploadFiles => 'Upload files';
@override
String get uploadImages => 'Upload images';
@override
String get uploadCamera => 'Upload from camera';
@override
String get createFolder => 'Create folder';
@override
String get folderName => 'Folder name';
@override
String get renameFolder => 'Rename folder';
@override
String get renameFile => 'Rename file';
@override
String get details => 'Details';
@override
String get detailsFileName => 'File name';
@override
String get detailsFolderName => 'Folder name';
@override
String get detailsParentFolder => 'Parent folder';
@override
String get detailsFileSize => 'File size';
@override
String get detailsFolderSize => 'Folder size';
@override
String get detailsLastModified => 'Last modified';
@override
String get detailsIsFavorite => 'Is favorite';
@override
String get sync => 'Sync';
@override
String deleteFileConfirm(String name) {
return 'Are you sure you want to delete the file \'$name\'?';
}
@override
String deleteFolderConfirm(String name) {
return 'Are you sure you want to delete the folder \'$name\'?';
}
@override
String get chooseFolder => 'Choose folder';
@override
String get addToFavorites => 'Add to favorites';
@override
String get removeFromFavorites => 'Remove from favorites';
@override
String confirmUploadSizeWarning(String warningSize, String actualSize) {
return 'Are you sure you want to upload a file that is bigger than $warningSize ($actualSize)?';
}
@override
String confirmDownloadSizeWarning(String warningSize, String actualSize) {
return 'Are you sure you want to download a file that is bigger than $warningSize ($actualSize)?';
}
@override
String goToPath(String path) {
return 'Go to /$path';
}
@override
String get optionsFilesSortProperty => 'How to sort files';
@override
String get optionsFilesSortPropertyName => 'Name';
@override
String get optionsFilesSortPropertyModifiedDate => 'Last modified';
@override
String get optionsFilesSortPropertySize => 'Size';
@override
String get optionsFilesSortOrder => 'Sort order of files';
@override
String get optionsShowPreviews => 'Show previews for files';
@override
String get optionsUploadQueueParallelism => 'Upload queue parallelism';
@override
String get optionsDownloadQueueParallelism => 'Download queue parallelism';
@override
String get optionsUploadSizeWarning => 'Upload size warning';
@override
String get optionsDownloadSizeWarning => 'Download size warning';
} }

7
packages/neon/neon_files/lib/neon_files.dart

@ -13,6 +13,7 @@ import 'package:image_picker/image_picker.dart';
import 'package:intersperse/intersperse.dart'; import 'package:intersperse/intersperse.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:neon/neon.dart'; import 'package:neon/neon.dart';
import 'package:neon_files/l10n/localizations.dart';
import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/nextcloud.dart';
import 'package:open_file/open_file.dart'; import 'package:open_file/open_file.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
@ -43,6 +44,12 @@ class FilesApp extends AppImplementation<FilesBloc, FilesAppSpecificOptions> {
@override @override
String id = 'files'; String id = 'files';
@override
LocalizationsDelegate localizationsDelegate = AppLocalizations.delegate;
@override
List<Locale> supportedLocales = AppLocalizations.supportedLocales;
@override @override
FilesAppSpecificOptions buildOptions(final AppStorage storage) => FilesAppSpecificOptions(storage); FilesAppSpecificOptions buildOptions(final AppStorage storage) => FilesAppSpecificOptions(storage);

22
packages/neon/neon_files/lib/options.dart

@ -17,20 +17,20 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
} }
final generalCategory = OptionsCategory( final generalCategory = OptionsCategory(
name: (final context) => AppLocalizations.of(context).optionsCategoryGeneral, name: (final context) => AppLocalizations.of(context).general,
); );
late final filesSortPropertyOption = SelectOption<FilesSortProperty>( late final filesSortPropertyOption = SelectOption<FilesSortProperty>(
storage: super.storage, storage: super.storage,
category: generalCategory, category: generalCategory,
key: 'files-sort-property', key: 'files-sort-property',
label: (final context) => AppLocalizations.of(context).newsOptionsArticlesSortProperty, label: (final context) => AppLocalizations.of(context).optionsFilesSortProperty,
defaultValue: BehaviorSubject.seeded(FilesSortProperty.name), defaultValue: BehaviorSubject.seeded(FilesSortProperty.name),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
FilesSortProperty.name: (final context) => AppLocalizations.of(context).filesOptionsFilesSortPropertyName, FilesSortProperty.name: (final context) => AppLocalizations.of(context).optionsFilesSortPropertyName,
FilesSortProperty.modifiedDate: (final context) => FilesSortProperty.modifiedDate: (final context) =>
AppLocalizations.of(context).filesOptionsFilesSortPropertyModifiedDate, AppLocalizations.of(context).optionsFilesSortPropertyModifiedDate,
FilesSortProperty.size: (final context) => AppLocalizations.of(context).filesOptionsFilesSortPropertySize, FilesSortProperty.size: (final context) => AppLocalizations.of(context).optionsFilesSortPropertySize,
}), }),
); );
@ -38,7 +38,7 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: generalCategory, category: generalCategory,
key: 'files-sort-box-order', key: 'files-sort-box-order',
label: (final context) => AppLocalizations.of(context).filesOptionsFilesSortOrder, label: (final context) => AppLocalizations.of(context).optionsFilesSortOrder,
defaultValue: BehaviorSubject.seeded(SortBoxOrder.ascending), defaultValue: BehaviorSubject.seeded(SortBoxOrder.ascending),
values: BehaviorSubject.seeded(sortBoxOrderOptionValues), values: BehaviorSubject.seeded(sortBoxOrderOptionValues),
); );
@ -47,7 +47,7 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: generalCategory, category: generalCategory,
key: 'show-previews', key: 'show-previews',
label: (final context) => AppLocalizations.of(context).filesOptionsShowPreviews, label: (final context) => AppLocalizations.of(context).optionsShowPreviews,
defaultValue: BehaviorSubject.seeded(true), defaultValue: BehaviorSubject.seeded(true),
); );
@ -55,7 +55,7 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: storage, storage: storage,
category: generalCategory, category: generalCategory,
key: 'upload-queue-parallelism', key: 'upload-queue-parallelism',
label: (final context) => AppLocalizations.of(context).filesOptionsUploadQueueParallelism, label: (final context) => AppLocalizations.of(context).optionsUploadQueueParallelism,
defaultValue: BehaviorSubject.seeded(4), defaultValue: BehaviorSubject.seeded(4),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
for (var i = 1; i <= 16; i = i * 2) ...{ for (var i = 1; i <= 16; i = i * 2) ...{
@ -68,7 +68,7 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: storage, storage: storage,
category: generalCategory, category: generalCategory,
key: 'download-queue-parallelism', key: 'download-queue-parallelism',
label: (final context) => AppLocalizations.of(context).filesOptionsDownloadQueueParallelism, label: (final context) => AppLocalizations.of(context).optionsDownloadQueueParallelism,
defaultValue: BehaviorSubject.seeded(4), defaultValue: BehaviorSubject.seeded(4),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
for (var i = 1; i <= 16; i = i * 2) ...{ for (var i = 1; i <= 16; i = i * 2) ...{
@ -98,7 +98,7 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: storage, storage: storage,
category: generalCategory, category: generalCategory,
key: 'upload-size-warning', key: 'upload-size-warning',
label: (final context) => AppLocalizations.of(context).filesOptionsUploadSizeWarning, label: (final context) => AppLocalizations.of(context).optionsUploadSizeWarning,
defaultValue: BehaviorSubject.seeded(_mb(10)), defaultValue: BehaviorSubject.seeded(_mb(10)),
values: BehaviorSubject.seeded(_sizeWarningValues), values: BehaviorSubject.seeded(_sizeWarningValues),
); );
@ -107,7 +107,7 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: storage, storage: storage,
category: generalCategory, category: generalCategory,
key: 'download-size-warning', key: 'download-size-warning',
label: (final context) => AppLocalizations.of(context).filesOptionsDownloadSizeWarning, label: (final context) => AppLocalizations.of(context).optionsDownloadSizeWarning,
defaultValue: BehaviorSubject.seeded(_mb(10)), defaultValue: BehaviorSubject.seeded(_mb(10)),
values: BehaviorSubject.seeded(_sizeWarningValues), values: BehaviorSubject.seeded(_sizeWarningValues),
); );

15
packages/neon/neon_files/lib/pages/details.dart

@ -42,17 +42,16 @@ class FilesDetailsPage extends StatelessWidget {
rows: [ rows: [
for (final entry in { for (final entry in {
details.isDirectory details.isDirectory
? AppLocalizations.of(context).filesDetailsFolderName ? AppLocalizations.of(context).detailsFolderName
: AppLocalizations.of(context).filesDetailsFileName: details.name, : AppLocalizations.of(context).detailsFileName: details.name,
AppLocalizations.of(context).filesDetailsParentFolder: AppLocalizations.of(context).detailsParentFolder:
details.path.length == 1 ? '/' : details.path.sublist(0, details.path.length - 1).join('/'), details.path.length == 1 ? '/' : details.path.sublist(0, details.path.length - 1).join('/'),
details.isDirectory details.isDirectory
? AppLocalizations.of(context).filesDetailsFolderSize ? AppLocalizations.of(context).detailsFolderSize
: AppLocalizations.of(context).filesDetailsFileSize: filesize(details.size, 1), : AppLocalizations.of(context).detailsFileSize: filesize(details.size, 1),
AppLocalizations.of(context).filesDetailsLastModified: AppLocalizations.of(context).detailsLastModified: details.lastModified.toLocal().toIso8601String(),
details.lastModified.toLocal().toIso8601String(),
if (details.isFavorite != null) ...{ if (details.isFavorite != null) ...{
AppLocalizations.of(context).filesDetailsIsFavorite: AppLocalizations.of(context).detailsIsFavorite:
details.isFavorite! ? AppLocalizations.of(context).yes : AppLocalizations.of(context).no, details.isFavorite! ? AppLocalizations.of(context).yes : AppLocalizations.of(context).no,
}, },
}.entries) ...[ }.entries) ...[

4
packages/neon/neon_files/lib/pages/main.dart

@ -34,7 +34,7 @@ class _FilesMainPageState extends State<FilesMainPage> {
if (!(await showConfirmationDialog( if (!(await showConfirmationDialog(
context, context,
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
AppLocalizations.of(context).filesConfirmDownloadSizeWarning( AppLocalizations.of(context).confirmDownloadSizeWarning(
filesize(sizeWarning), filesize(sizeWarning),
filesize(details.size), filesize(details.size),
), ),
@ -55,7 +55,7 @@ class _FilesMainPageState extends State<FilesMainPage> {
), ),
); );
}, },
tooltip: AppLocalizations.of(context).filesUploadFiles, tooltip: AppLocalizations.of(context).uploadFiles,
child: const Icon(Icons.add), child: const Icon(Icons.add),
), ),
); );

25
packages/neon/neon_files/lib/widgets/browser_view.dart

@ -156,7 +156,7 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
horizontal: VisualDensity.minimumDensity, horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity, vertical: VisualDensity.minimumDensity,
), ),
tooltip: AppLocalizations.of(context).filesGoToPath(''), tooltip: AppLocalizations.of(context).goToPath(''),
icon: const Icon( icon: const Icon(
Icons.house, Icons.house,
size: 30, size: 30,
@ -170,7 +170,7 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
builder: (final context) { builder: (final context) {
final path = pathSnapshot.data!.sublist(0, i + 1); final path = pathSnapshot.data!.sublist(0, i + 1);
return Tooltip( return Tooltip(
message: AppLocalizations.of(context).filesGoToPath(path.join('/')), message: AppLocalizations.of(context).goToPath(path.join('/')),
excludeFromSemantics: true, excludeFromSemantics: true,
child: TextButton( child: TextButton(
onPressed: () { onPressed: () {
@ -178,8 +178,7 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
}, },
child: Text( child: Text(
pathSnapshot.data![i], pathSnapshot.data![i],
semanticsLabel: semanticsLabel: AppLocalizations.of(context).goToPath(path.join('/')),
AppLocalizations.of(context).filesGoToPath(path.join('/')),
), ),
), ),
); );
@ -297,14 +296,14 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
value: FilesFileAction.toggleFavorite, value: FilesFileAction.toggleFavorite,
child: Text( child: Text(
details.isFavorite! details.isFavorite!
? AppLocalizations.of(context).filesRemoveFromFavorites ? AppLocalizations.of(context).removeFromFavorites
: AppLocalizations.of(context).filesAddToFavorites, : AppLocalizations.of(context).addToFavorites,
), ),
), ),
], ],
PopupMenuItem( PopupMenuItem(
value: FilesFileAction.details, value: FilesFileAction.details,
child: Text(AppLocalizations.of(context).filesDetails), child: Text(AppLocalizations.of(context).details),
), ),
PopupMenuItem( PopupMenuItem(
value: FilesFileAction.rename, value: FilesFileAction.rename,
@ -322,7 +321,7 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
if (!details.isDirectory) ...[ if (!details.isDirectory) ...[
PopupMenuItem( PopupMenuItem(
value: FilesFileAction.sync, value: FilesFileAction.sync,
child: Text(AppLocalizations.of(context).filesSync), child: Text(AppLocalizations.of(context).sync),
), ),
], ],
PopupMenuItem( PopupMenuItem(
@ -353,8 +352,8 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
final result = await showRenameDialog( final result = await showRenameDialog(
context: context, context: context,
title: details.isDirectory title: details.isDirectory
? AppLocalizations.of(context).filesRenameFolder ? AppLocalizations.of(context).renameFolder
: AppLocalizations.of(context).filesRenameFile, : AppLocalizations.of(context).renameFile,
value: details.name, value: details.name,
); );
if (result != null) { if (result != null) {
@ -402,7 +401,7 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
if (!(await showConfirmationDialog( if (!(await showConfirmationDialog(
context, context,
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
AppLocalizations.of(context).filesConfirmDownloadSizeWarning( AppLocalizations.of(context).confirmDownloadSizeWarning(
filesize(sizeWarning), filesize(sizeWarning),
filesize(details.size), filesize(details.size),
), ),
@ -418,9 +417,9 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
context, context,
details.isDirectory details.isDirectory
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
? AppLocalizations.of(context).filesDeleteFolderConfirm(details.name) ? AppLocalizations.of(context).deleteFolderConfirm(details.name)
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
: AppLocalizations.of(context).filesDeleteFileConfirm(details.name), : AppLocalizations.of(context).deleteFileConfirm(details.name),
)) { )) {
widget.filesBloc.delete(details.path); widget.filesBloc.delete(details.path);
} }

4
packages/neon/neon_news/lib/dialogs/add_feed.dart

@ -46,7 +46,7 @@ class _NewsAddFeedDialogState extends State<NewsAddFeedDialog> {
Widget build(final BuildContext context) => ResultBuilder<List<NextcloudNewsFolder>>( Widget build(final BuildContext context) => ResultBuilder<List<NextcloudNewsFolder>>(
stream: widget.bloc.folders, stream: widget.bloc.folders,
builder: (final context, final folders) => NeonDialog( builder: (final context, final folders) => NeonDialog(
title: Text(AppLocalizations.of(context).newsAddFeed), title: Text(AppLocalizations.of(context).addFeed),
children: [ children: [
Form( Form(
key: formKey, key: formKey,
@ -91,7 +91,7 @@ class _NewsAddFeedDialogState extends State<NewsAddFeedDialog> {
], ],
ElevatedButton( ElevatedButton(
onPressed: folders.data != null ? submit : null, onPressed: folders.data != null ? submit : null,
child: Text(AppLocalizations.of(context).newsAddFeed), child: Text(AppLocalizations.of(context).addFeed),
), ),
], ],
), ),

6
packages/neon/neon_news/lib/dialogs/create_folder.dart

@ -22,7 +22,7 @@ class _NewsCreateFolderDialogState extends State<NewsCreateFolderDialog> {
@override @override
Widget build(final BuildContext context) => NeonDialog( Widget build(final BuildContext context) => NeonDialog(
title: Text(AppLocalizations.of(context).newsCreateFolder), title: Text(AppLocalizations.of(context).createFolder),
children: [ children: [
Form( Form(
key: formKey, key: formKey,
@ -33,7 +33,7 @@ class _NewsCreateFolderDialogState extends State<NewsCreateFolderDialog> {
autofocus: true, autofocus: true,
controller: controller, controller: controller,
decoration: InputDecoration( decoration: InputDecoration(
hintText: AppLocalizations.of(context).newsCreateFolderName, hintText: AppLocalizations.of(context).createFolderName,
), ),
validator: (final input) => validateNotEmpty(context, input), validator: (final input) => validateNotEmpty(context, input),
onFieldSubmitted: (final _) { onFieldSubmitted: (final _) {
@ -42,7 +42,7 @@ class _NewsCreateFolderDialogState extends State<NewsCreateFolderDialog> {
), ),
ElevatedButton( ElevatedButton(
onPressed: submit, onPressed: submit,
child: Text(AppLocalizations.of(context).newsCreateFolder), child: Text(AppLocalizations.of(context).createFolder),
), ),
], ],
), ),

4
packages/neon/neon_news/lib/dialogs/feed_show_url.dart

@ -27,13 +27,13 @@ class _NewsFeedShowURLDialogState extends State<NewsFeedShowURLDialog> {
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text(AppLocalizations.of(context).newsCopiedFeedURL), content: Text(AppLocalizations.of(context).copiedFeedURL),
), ),
); );
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
}, },
child: Text(AppLocalizations.of(context).newsCopyFeedURL), child: Text(AppLocalizations.of(context).copyFeedURL),
), ),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {

4
packages/neon/neon_news/lib/dialogs/feed_update_error.dart

@ -27,13 +27,13 @@ class _NewsFeedUpdateErrorDialogState extends State<NewsFeedUpdateErrorDialog> {
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text(AppLocalizations.of(context).newsCopiedFeedErrorMessage), content: Text(AppLocalizations.of(context).copiedFeedErrorMessage),
), ),
); );
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
}, },
child: Text(AppLocalizations.of(context).newsCopyFeedErrorMessage), child: Text(AppLocalizations.of(context).copyFeedErrorMessage),
), ),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {

4
packages/neon/neon_news/lib/dialogs/move_feed.dart

@ -27,7 +27,7 @@ class _NewsMoveFeedDialogState extends State<NewsMoveFeedDialog> {
@override @override
Widget build(final BuildContext context) => NeonDialog( Widget build(final BuildContext context) => NeonDialog(
title: Text(AppLocalizations.of(context).newsMoveFeed), title: Text(AppLocalizations.of(context).moveFeed),
children: [ children: [
Form( Form(
key: formKey, key: formKey,
@ -47,7 +47,7 @@ class _NewsMoveFeedDialogState extends State<NewsMoveFeedDialog> {
), ),
ElevatedButton( ElevatedButton(
onPressed: submit, onPressed: submit,
child: Text(AppLocalizations.of(context).newsMoveFeed), child: Text(AppLocalizations.of(context).moveFeed),
), ),
], ],
), ),

79
packages/neon/neon_news/lib/l10n/en.arb

@ -1,3 +1,80 @@
{ {
"@@locale": "en" "@@locale": "en",
"close": "Close",
"delete": "Delete",
"remove": "Remove",
"rename": "Rename",
"move": "Move",
"general": "General",
"addFeed": "Add feed",
"folder": "Folder",
"folderRoot": "Root Folder",
"createFolder": "Create folder",
"createFolderName": "Folder name",
"deleteFolderConfirm": "Are you sure you want to delete the folder '{name}'?",
"@deleteFolderConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"renameFolder": "Rename folder",
"removeFeedConfirm": "Are you sure you want to remove the feed '{name}'?",
"@removeFeedConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"moveFeed": "Move feed",
"renameFeed": "Rename feed",
"articles": "Articles",
"folders": "Folders",
"feeds": "Feeds",
"filterAll": "All",
"filterUnread": "Unread",
"filterStarred": "Starred",
"unreadArticles": "{count} unread",
"@unreadArticles": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"articleStar": "Star article",
"articleUnstar": "Unstar article",
"articleMarkRead": "Mark article as read",
"articleMarkUnread": "Mark article as unread",
"articleOpenLink": "Open in browser",
"articleShare": "Share",
"showFeedURL": "Show URL",
"copyFeedURL": "Copy URL",
"copiedFeedURL": "URL copied to clipboard",
"showFeedErrorMessage": "Show error message",
"copyFeedErrorMessage": "Copy error message",
"copiedFeedErrorMessage": "Error message copied to clipboard",
"optionsDefaultCategory": "Category to show by default",
"optionsArticleViewType": "How to open article",
"optionsArticleViewTypeDirect": "Show text directly",
"optionsArticleViewTypeInternalBrowser": "Open in internal browser",
"optionsArticleViewTypeExternalBrowser": "Open in external browser",
"optionsArticleDisableMarkAsReadTimeout": "Mark articles as read instantly",
"optionsDefaultArticlesFilter": "Articles to show by default",
"optionsArticlesSortProperty": "How to sort articles",
"optionsArticlesSortPropertyPublishDate": "Publish date",
"optionsArticlesSortPropertyAlphabetical": "Alphabetical",
"optionsArticlesSortPropertyFeed": "Feed",
"optionsArticlesSortOrder": "Sort order of articles",
"optionsFeedsSortProperty": "How to sort feeds",
"optionsFeedsSortPropertyAlphabetical": "Alphabetical",
"optionsFeedsSortPropertyUnreadCount": "Unread count",
"optionsFeedsSortOrder": "Sort order of feeds",
"optionsFoldersSortProperty": "How to sort folders",
"optionsFoldersSortPropertyAlphabetical": "Alphabetical",
"optionsFoldersSortPropertyUnreadCount": "Unread count",
"optionsFoldersSortOrder": "Sort order of folders",
"optionsDefaultFolderViewType": "What should be shown first when opening a folder"
} }

336
packages/neon/neon_news/lib/l10n/localizations.dart

@ -88,6 +88,342 @@ abstract class AppLocalizations {
/// A list of this localizations delegate's supported locales. /// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[Locale('en')]; static const List<Locale> supportedLocales = <Locale>[Locale('en')];
/// No description provided for @close.
///
/// In en, this message translates to:
/// **'Close'**
String get close;
/// No description provided for @delete.
///
/// In en, this message translates to:
/// **'Delete'**
String get delete;
/// No description provided for @remove.
///
/// In en, this message translates to:
/// **'Remove'**
String get remove;
/// No description provided for @rename.
///
/// In en, this message translates to:
/// **'Rename'**
String get rename;
/// No description provided for @move.
///
/// In en, this message translates to:
/// **'Move'**
String get move;
/// No description provided for @general.
///
/// In en, this message translates to:
/// **'General'**
String get general;
/// No description provided for @addFeed.
///
/// In en, this message translates to:
/// **'Add feed'**
String get addFeed;
/// No description provided for @folder.
///
/// In en, this message translates to:
/// **'Folder'**
String get folder;
/// No description provided for @folderRoot.
///
/// In en, this message translates to:
/// **'Root Folder'**
String get folderRoot;
/// No description provided for @createFolder.
///
/// In en, this message translates to:
/// **'Create folder'**
String get createFolder;
/// No description provided for @createFolderName.
///
/// In en, this message translates to:
/// **'Folder name'**
String get createFolderName;
/// No description provided for @deleteFolderConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete the folder \'{name}\'?'**
String deleteFolderConfirm(String name);
/// No description provided for @renameFolder.
///
/// In en, this message translates to:
/// **'Rename folder'**
String get renameFolder;
/// No description provided for @removeFeedConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to remove the feed \'{name}\'?'**
String removeFeedConfirm(String name);
/// No description provided for @moveFeed.
///
/// In en, this message translates to:
/// **'Move feed'**
String get moveFeed;
/// No description provided for @renameFeed.
///
/// In en, this message translates to:
/// **'Rename feed'**
String get renameFeed;
/// No description provided for @articles.
///
/// In en, this message translates to:
/// **'Articles'**
String get articles;
/// No description provided for @folders.
///
/// In en, this message translates to:
/// **'Folders'**
String get folders;
/// No description provided for @feeds.
///
/// In en, this message translates to:
/// **'Feeds'**
String get feeds;
/// No description provided for @filterAll.
///
/// In en, this message translates to:
/// **'All'**
String get filterAll;
/// No description provided for @filterUnread.
///
/// In en, this message translates to:
/// **'Unread'**
String get filterUnread;
/// No description provided for @filterStarred.
///
/// In en, this message translates to:
/// **'Starred'**
String get filterStarred;
/// No description provided for @unreadArticles.
///
/// In en, this message translates to:
/// **'{count} unread'**
String unreadArticles(int count);
/// No description provided for @articleStar.
///
/// In en, this message translates to:
/// **'Star article'**
String get articleStar;
/// No description provided for @articleUnstar.
///
/// In en, this message translates to:
/// **'Unstar article'**
String get articleUnstar;
/// No description provided for @articleMarkRead.
///
/// In en, this message translates to:
/// **'Mark article as read'**
String get articleMarkRead;
/// No description provided for @articleMarkUnread.
///
/// In en, this message translates to:
/// **'Mark article as unread'**
String get articleMarkUnread;
/// No description provided for @articleOpenLink.
///
/// In en, this message translates to:
/// **'Open in browser'**
String get articleOpenLink;
/// No description provided for @articleShare.
///
/// In en, this message translates to:
/// **'Share'**
String get articleShare;
/// No description provided for @showFeedURL.
///
/// In en, this message translates to:
/// **'Show URL'**
String get showFeedURL;
/// No description provided for @copyFeedURL.
///
/// In en, this message translates to:
/// **'Copy URL'**
String get copyFeedURL;
/// No description provided for @copiedFeedURL.
///
/// In en, this message translates to:
/// **'URL copied to clipboard'**
String get copiedFeedURL;
/// No description provided for @showFeedErrorMessage.
///
/// In en, this message translates to:
/// **'Show error message'**
String get showFeedErrorMessage;
/// No description provided for @copyFeedErrorMessage.
///
/// In en, this message translates to:
/// **'Copy error message'**
String get copyFeedErrorMessage;
/// No description provided for @copiedFeedErrorMessage.
///
/// In en, this message translates to:
/// **'Error message copied to clipboard'**
String get copiedFeedErrorMessage;
/// No description provided for @optionsDefaultCategory.
///
/// In en, this message translates to:
/// **'Category to show by default'**
String get optionsDefaultCategory;
/// No description provided for @optionsArticleViewType.
///
/// In en, this message translates to:
/// **'How to open article'**
String get optionsArticleViewType;
/// No description provided for @optionsArticleViewTypeDirect.
///
/// In en, this message translates to:
/// **'Show text directly'**
String get optionsArticleViewTypeDirect;
/// No description provided for @optionsArticleViewTypeInternalBrowser.
///
/// In en, this message translates to:
/// **'Open in internal browser'**
String get optionsArticleViewTypeInternalBrowser;
/// No description provided for @optionsArticleViewTypeExternalBrowser.
///
/// In en, this message translates to:
/// **'Open in external browser'**
String get optionsArticleViewTypeExternalBrowser;
/// No description provided for @optionsArticleDisableMarkAsReadTimeout.
///
/// In en, this message translates to:
/// **'Mark articles as read instantly'**
String get optionsArticleDisableMarkAsReadTimeout;
/// No description provided for @optionsDefaultArticlesFilter.
///
/// In en, this message translates to:
/// **'Articles to show by default'**
String get optionsDefaultArticlesFilter;
/// No description provided for @optionsArticlesSortProperty.
///
/// In en, this message translates to:
/// **'How to sort articles'**
String get optionsArticlesSortProperty;
/// No description provided for @optionsArticlesSortPropertyPublishDate.
///
/// In en, this message translates to:
/// **'Publish date'**
String get optionsArticlesSortPropertyPublishDate;
/// No description provided for @optionsArticlesSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get optionsArticlesSortPropertyAlphabetical;
/// No description provided for @optionsArticlesSortPropertyFeed.
///
/// In en, this message translates to:
/// **'Feed'**
String get optionsArticlesSortPropertyFeed;
/// No description provided for @optionsArticlesSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of articles'**
String get optionsArticlesSortOrder;
/// No description provided for @optionsFeedsSortProperty.
///
/// In en, this message translates to:
/// **'How to sort feeds'**
String get optionsFeedsSortProperty;
/// No description provided for @optionsFeedsSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get optionsFeedsSortPropertyAlphabetical;
/// No description provided for @optionsFeedsSortPropertyUnreadCount.
///
/// In en, this message translates to:
/// **'Unread count'**
String get optionsFeedsSortPropertyUnreadCount;
/// No description provided for @optionsFeedsSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of feeds'**
String get optionsFeedsSortOrder;
/// No description provided for @optionsFoldersSortProperty.
///
/// In en, this message translates to:
/// **'How to sort folders'**
String get optionsFoldersSortProperty;
/// No description provided for @optionsFoldersSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get optionsFoldersSortPropertyAlphabetical;
/// No description provided for @optionsFoldersSortPropertyUnreadCount.
///
/// In en, this message translates to:
/// **'Unread count'**
String get optionsFoldersSortPropertyUnreadCount;
/// No description provided for @optionsFoldersSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of folders'**
String get optionsFoldersSortOrder;
/// No description provided for @optionsDefaultFolderViewType.
///
/// In en, this message translates to:
/// **'What should be shown first when opening a folder'**
String get optionsDefaultFolderViewType;
} }
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> { class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {

174
packages/neon/neon_news/lib/l10n/localizations_en.dart

@ -3,4 +3,178 @@ import 'localizations.dart';
/// The translations for English (`en`). /// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations { class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale); AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String get close => 'Close';
@override
String get delete => 'Delete';
@override
String get remove => 'Remove';
@override
String get rename => 'Rename';
@override
String get move => 'Move';
@override
String get general => 'General';
@override
String get addFeed => 'Add feed';
@override
String get folder => 'Folder';
@override
String get folderRoot => 'Root Folder';
@override
String get createFolder => 'Create folder';
@override
String get createFolderName => 'Folder name';
@override
String deleteFolderConfirm(String name) {
return 'Are you sure you want to delete the folder \'$name\'?';
}
@override
String get renameFolder => 'Rename folder';
@override
String removeFeedConfirm(String name) {
return 'Are you sure you want to remove the feed \'$name\'?';
}
@override
String get moveFeed => 'Move feed';
@override
String get renameFeed => 'Rename feed';
@override
String get articles => 'Articles';
@override
String get folders => 'Folders';
@override
String get feeds => 'Feeds';
@override
String get filterAll => 'All';
@override
String get filterUnread => 'Unread';
@override
String get filterStarred => 'Starred';
@override
String unreadArticles(int count) {
return '$count unread';
}
@override
String get articleStar => 'Star article';
@override
String get articleUnstar => 'Unstar article';
@override
String get articleMarkRead => 'Mark article as read';
@override
String get articleMarkUnread => 'Mark article as unread';
@override
String get articleOpenLink => 'Open in browser';
@override
String get articleShare => 'Share';
@override
String get showFeedURL => 'Show URL';
@override
String get copyFeedURL => 'Copy URL';
@override
String get copiedFeedURL => 'URL copied to clipboard';
@override
String get showFeedErrorMessage => 'Show error message';
@override
String get copyFeedErrorMessage => 'Copy error message';
@override
String get copiedFeedErrorMessage => 'Error message copied to clipboard';
@override
String get optionsDefaultCategory => 'Category to show by default';
@override
String get optionsArticleViewType => 'How to open article';
@override
String get optionsArticleViewTypeDirect => 'Show text directly';
@override
String get optionsArticleViewTypeInternalBrowser => 'Open in internal browser';
@override
String get optionsArticleViewTypeExternalBrowser => 'Open in external browser';
@override
String get optionsArticleDisableMarkAsReadTimeout => 'Mark articles as read instantly';
@override
String get optionsDefaultArticlesFilter => 'Articles to show by default';
@override
String get optionsArticlesSortProperty => 'How to sort articles';
@override
String get optionsArticlesSortPropertyPublishDate => 'Publish date';
@override
String get optionsArticlesSortPropertyAlphabetical => 'Alphabetical';
@override
String get optionsArticlesSortPropertyFeed => 'Feed';
@override
String get optionsArticlesSortOrder => 'Sort order of articles';
@override
String get optionsFeedsSortProperty => 'How to sort feeds';
@override
String get optionsFeedsSortPropertyAlphabetical => 'Alphabetical';
@override
String get optionsFeedsSortPropertyUnreadCount => 'Unread count';
@override
String get optionsFeedsSortOrder => 'Sort order of feeds';
@override
String get optionsFoldersSortProperty => 'How to sort folders';
@override
String get optionsFoldersSortPropertyAlphabetical => 'Alphabetical';
@override
String get optionsFoldersSortPropertyUnreadCount => 'Unread count';
@override
String get optionsFoldersSortOrder => 'Sort order of folders';
@override
String get optionsDefaultFolderViewType => 'What should be shown first when opening a folder';
} }

7
packages/neon/neon_news/lib/neon_news.dart

@ -9,6 +9,7 @@ import 'package:html/dom.dart' as html_dom;
import 'package:html/parser.dart' as html_parser; import 'package:html/parser.dart' as html_parser;
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:neon/neon.dart'; import 'package:neon/neon.dart';
import 'package:neon_news/l10n/localizations.dart';
import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
@ -50,6 +51,12 @@ class NewsApp extends AppImplementation<NewsBloc, NewsAppSpecificOptions> {
@override @override
String id = 'news'; String id = 'news';
@override
LocalizationsDelegate localizationsDelegate = AppLocalizations.delegate;
@override
List<Locale> supportedLocales = AppLocalizations.supportedLocales;
@override @override
NewsAppSpecificOptions buildOptions(final AppStorage storage) => NewsAppSpecificOptions(storage, platform); NewsAppSpecificOptions buildOptions(final AppStorage storage) => NewsAppSpecificOptions(storage, platform);

66
packages/neon/neon_news/lib/options.dart

@ -23,44 +23,44 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
]; ];
_articleViewTypeValuesSubject.add({ _articleViewTypeValuesSubject.add({
ArticleViewType.direct: (final context) => AppLocalizations.of(context).newsOptionsArticleViewTypeDirect, ArticleViewType.direct: (final context) => AppLocalizations.of(context).optionsArticleViewTypeDirect,
if (platform.canUseWebView) ...{ if (platform.canUseWebView) ...{
ArticleViewType.internalBrowser: (final context) => ArticleViewType.internalBrowser: (final context) =>
AppLocalizations.of(context).newsOptionsArticleViewTypeInternalBrowser, AppLocalizations.of(context).optionsArticleViewTypeInternalBrowser,
}, },
ArticleViewType.externalBrowser: (final context) => ArticleViewType.externalBrowser: (final context) =>
AppLocalizations.of(context).newsOptionsArticleViewTypeExternalBrowser, AppLocalizations.of(context).optionsArticleViewTypeExternalBrowser,
}); });
} }
final _articleViewTypeValuesSubject = BehaviorSubject<Map<ArticleViewType, String Function(BuildContext)>>(); final _articleViewTypeValuesSubject = BehaviorSubject<Map<ArticleViewType, String Function(BuildContext)>>();
final generalCategory = OptionsCategory( final generalCategory = OptionsCategory(
name: (final context) => AppLocalizations.of(context).optionsCategoryGeneral, name: (final context) => AppLocalizations.of(context).general,
); );
final articlesCategory = OptionsCategory( final articlesCategory = OptionsCategory(
name: (final context) => AppLocalizations.of(context).newsArticles, name: (final context) => AppLocalizations.of(context).articles,
); );
final foldersCategory = OptionsCategory( final foldersCategory = OptionsCategory(
name: (final context) => AppLocalizations.of(context).newsFolders, name: (final context) => AppLocalizations.of(context).folders,
); );
final feedsCategory = OptionsCategory( final feedsCategory = OptionsCategory(
name: (final context) => AppLocalizations.of(context).newsFeeds, name: (final context) => AppLocalizations.of(context).feeds,
); );
late final defaultCategoryOption = SelectOption<DefaultCategory>( late final defaultCategoryOption = SelectOption<DefaultCategory>(
storage: super.storage, storage: super.storage,
category: generalCategory, category: generalCategory,
key: 'default-category', key: 'default-category',
label: (final context) => AppLocalizations.of(context).newsOptionsDefaultCategory, label: (final context) => AppLocalizations.of(context).optionsDefaultCategory,
defaultValue: BehaviorSubject.seeded(DefaultCategory.articles), defaultValue: BehaviorSubject.seeded(DefaultCategory.articles),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
DefaultCategory.articles: (final context) => AppLocalizations.of(context).newsArticles, DefaultCategory.articles: (final context) => AppLocalizations.of(context).articles,
DefaultCategory.folders: (final context) => AppLocalizations.of(context).newsFolders, DefaultCategory.folders: (final context) => AppLocalizations.of(context).folders,
DefaultCategory.feeds: (final context) => AppLocalizations.of(context).newsFeeds, DefaultCategory.feeds: (final context) => AppLocalizations.of(context).feeds,
}), }),
); );
@ -68,7 +68,7 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: articlesCategory, category: articlesCategory,
key: 'article-view-type', key: 'article-view-type',
label: (final context) => AppLocalizations.of(context).newsOptionsArticleViewType, label: (final context) => AppLocalizations.of(context).optionsArticleViewType,
defaultValue: BehaviorSubject.seeded(ArticleViewType.direct), defaultValue: BehaviorSubject.seeded(ArticleViewType.direct),
values: _articleViewTypeValuesSubject, values: _articleViewTypeValuesSubject,
); );
@ -77,7 +77,7 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: articlesCategory, category: articlesCategory,
key: 'article-disable-mark-as-read-timeout', key: 'article-disable-mark-as-read-timeout',
label: (final context) => AppLocalizations.of(context).newsOptionsArticleDisableMarkAsReadTimeout, label: (final context) => AppLocalizations.of(context).optionsArticleDisableMarkAsReadTimeout,
defaultValue: BehaviorSubject.seeded(false), defaultValue: BehaviorSubject.seeded(false),
); );
@ -85,12 +85,12 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: articlesCategory, category: articlesCategory,
key: 'default-articles-filter', key: 'default-articles-filter',
label: (final context) => AppLocalizations.of(context).newsOptionsDefaultArticlesFilter, label: (final context) => AppLocalizations.of(context).optionsDefaultArticlesFilter,
defaultValue: BehaviorSubject.seeded(FilterType.unread), defaultValue: BehaviorSubject.seeded(FilterType.unread),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
FilterType.all: (final context) => AppLocalizations.of(context).newsFilterAll, FilterType.all: (final context) => AppLocalizations.of(context).filterAll,
FilterType.unread: (final context) => AppLocalizations.of(context).newsFilterUnread, FilterType.unread: (final context) => AppLocalizations.of(context).filterUnread,
FilterType.starred: (final context) => AppLocalizations.of(context).newsFilterStarred, FilterType.starred: (final context) => AppLocalizations.of(context).filterStarred,
}), }),
); );
@ -98,14 +98,14 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: articlesCategory, category: articlesCategory,
key: 'articles-sort-property', key: 'articles-sort-property',
label: (final context) => AppLocalizations.of(context).newsOptionsArticlesSortProperty, label: (final context) => AppLocalizations.of(context).optionsArticlesSortProperty,
defaultValue: BehaviorSubject.seeded(ArticlesSortProperty.publishDate), defaultValue: BehaviorSubject.seeded(ArticlesSortProperty.publishDate),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
ArticlesSortProperty.publishDate: (final context) => ArticlesSortProperty.publishDate: (final context) =>
AppLocalizations.of(context).newsOptionsArticlesSortPropertyPublishDate, AppLocalizations.of(context).optionsArticlesSortPropertyPublishDate,
ArticlesSortProperty.alphabetical: (final context) => ArticlesSortProperty.alphabetical: (final context) =>
AppLocalizations.of(context).newsOptionsArticlesSortPropertyAlphabetical, AppLocalizations.of(context).optionsArticlesSortPropertyAlphabetical,
ArticlesSortProperty.byFeed: (final context) => AppLocalizations.of(context).newsOptionsArticlesSortPropertyFeed, ArticlesSortProperty.byFeed: (final context) => AppLocalizations.of(context).optionsArticlesSortPropertyFeed,
}), }),
); );
@ -113,7 +113,7 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: articlesCategory, category: articlesCategory,
key: 'articles-sort-box-order', key: 'articles-sort-box-order',
label: (final context) => AppLocalizations.of(context).newsOptionsArticlesSortOrder, label: (final context) => AppLocalizations.of(context).optionsArticlesSortOrder,
defaultValue: BehaviorSubject.seeded(SortBoxOrder.descending), defaultValue: BehaviorSubject.seeded(SortBoxOrder.descending),
values: BehaviorSubject.seeded(sortBoxOrderOptionValues), values: BehaviorSubject.seeded(sortBoxOrderOptionValues),
); );
@ -122,13 +122,13 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: foldersCategory, category: foldersCategory,
key: 'folders-sort-property', key: 'folders-sort-property',
label: (final context) => AppLocalizations.of(context).newsOptionsFoldersSortProperty, label: (final context) => AppLocalizations.of(context).optionsFoldersSortProperty,
defaultValue: BehaviorSubject.seeded(FoldersSortProperty.alphabetical), defaultValue: BehaviorSubject.seeded(FoldersSortProperty.alphabetical),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
FoldersSortProperty.alphabetical: (final context) => FoldersSortProperty.alphabetical: (final context) =>
AppLocalizations.of(context).newsOptionsFoldersSortPropertyAlphabetical, AppLocalizations.of(context).optionsFoldersSortPropertyAlphabetical,
FoldersSortProperty.unreadCount: (final context) => FoldersSortProperty.unreadCount: (final context) =>
AppLocalizations.of(context).newsOptionsFoldersSortPropertyUnreadCount, AppLocalizations.of(context).optionsFoldersSortPropertyUnreadCount,
}), }),
); );
@ -136,7 +136,7 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: foldersCategory, category: foldersCategory,
key: 'folders-sort-box-order', key: 'folders-sort-box-order',
label: (final context) => AppLocalizations.of(context).newsOptionsFoldersSortOrder, label: (final context) => AppLocalizations.of(context).optionsFoldersSortOrder,
defaultValue: BehaviorSubject.seeded(SortBoxOrder.ascending), defaultValue: BehaviorSubject.seeded(SortBoxOrder.ascending),
values: BehaviorSubject.seeded(sortBoxOrderOptionValues), values: BehaviorSubject.seeded(sortBoxOrderOptionValues),
); );
@ -145,11 +145,11 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: foldersCategory, category: foldersCategory,
key: 'default-folder-view-type', key: 'default-folder-view-type',
label: (final context) => AppLocalizations.of(context).newsOptionsDefaultFolderViewType, label: (final context) => AppLocalizations.of(context).optionsDefaultFolderViewType,
defaultValue: BehaviorSubject.seeded(DefaultFolderViewType.articles), defaultValue: BehaviorSubject.seeded(DefaultFolderViewType.articles),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
DefaultFolderViewType.articles: (final context) => AppLocalizations.of(context).newsArticles, DefaultFolderViewType.articles: (final context) => AppLocalizations.of(context).articles,
DefaultFolderViewType.feeds: (final context) => AppLocalizations.of(context).newsFeeds, DefaultFolderViewType.feeds: (final context) => AppLocalizations.of(context).feeds,
}), }),
); );
@ -157,13 +157,13 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: feedsCategory, category: feedsCategory,
key: 'feeds-sort-property', key: 'feeds-sort-property',
label: (final context) => AppLocalizations.of(context).newsOptionsFeedsSortProperty, label: (final context) => AppLocalizations.of(context).optionsFeedsSortProperty,
defaultValue: BehaviorSubject.seeded(FeedsSortProperty.alphabetical), defaultValue: BehaviorSubject.seeded(FeedsSortProperty.alphabetical),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
FeedsSortProperty.alphabetical: (final context) => FeedsSortProperty.alphabetical: (final context) =>
AppLocalizations.of(context).newsOptionsFeedsSortPropertyAlphabetical, AppLocalizations.of(context).optionsFeedsSortPropertyAlphabetical,
FeedsSortProperty.unreadCount: (final context) => FeedsSortProperty.unreadCount: (final context) =>
AppLocalizations.of(context).newsOptionsFeedsSortPropertyUnreadCount, AppLocalizations.of(context).optionsFeedsSortPropertyUnreadCount,
}), }),
); );
@ -171,7 +171,7 @@ class NewsAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: feedsCategory, category: feedsCategory,
key: 'feeds-sort-box-order', key: 'feeds-sort-box-order',
label: (final context) => AppLocalizations.of(context).newsOptionsFeedsSortOrder, label: (final context) => AppLocalizations.of(context).optionsFeedsSortOrder,
defaultValue: BehaviorSubject.seeded(SortBoxOrder.ascending), defaultValue: BehaviorSubject.seeded(SortBoxOrder.ascending),
values: BehaviorSubject.seeded(sortBoxOrderOptionValues), values: BehaviorSubject.seeded(sortBoxOrderOptionValues),
); );

13
packages/neon/neon_news/lib/pages/article.dart

@ -123,9 +123,8 @@ class _NewsArticlePageState extends State<NewsArticlePage> {
widget.bloc.starArticle(); widget.bloc.starArticle();
} }
}, },
tooltip: starred tooltip:
? AppLocalizations.of(context).newsArticleUnstar starred ? AppLocalizations.of(context).articleUnstar : AppLocalizations.of(context).articleStar,
: AppLocalizations.of(context).newsArticleStar,
icon: Icon(starred ? Icons.star : Icons.star_outline), icon: Icon(starred ? Icons.star : Icons.star_outline),
); );
}, },
@ -143,8 +142,8 @@ class _NewsArticlePageState extends State<NewsArticlePage> {
} }
}, },
tooltip: unread tooltip: unread
? AppLocalizations.of(context).newsArticleMarkRead ? AppLocalizations.of(context).articleMarkRead
: AppLocalizations.of(context).newsArticleMarkUnread, : AppLocalizations.of(context).articleMarkUnread,
icon: Icon(unread ? MdiIcons.email : MdiIcons.emailMarkAsUnread), icon: Icon(unread ? MdiIcons.email : MdiIcons.emailMarkAsUnread),
); );
}, },
@ -157,14 +156,14 @@ class _NewsArticlePageState extends State<NewsArticlePage> {
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
); );
}, },
tooltip: AppLocalizations.of(context).newsArticleOpenLink, tooltip: AppLocalizations.of(context).articleOpenLink,
icon: const Icon(Icons.open_in_new), icon: const Icon(Icons.open_in_new),
), ),
IconButton( IconButton(
onPressed: () async { onPressed: () async {
await Share.share(await _getURL()); await Share.share(await _getURL());
}, },
tooltip: AppLocalizations.of(context).newsArticleShare, tooltip: AppLocalizations.of(context).articleShare,
icon: const Icon(Icons.share), icon: const Icon(Icons.share),
), ),
], ],

6
packages/neon/neon_news/lib/pages/main.dart

@ -57,15 +57,15 @@ class _NewsMainPageState extends State<NewsMainPage> {
items: [ items: [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: const Icon(Icons.newspaper), icon: const Icon(Icons.newspaper),
label: AppLocalizations.of(context).newsArticles, label: AppLocalizations.of(context).articles,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: const Icon(Icons.folder), icon: const Icon(Icons.folder),
label: AppLocalizations.of(context).newsFolders, label: AppLocalizations.of(context).folders,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: const Icon(Icons.rss_feed), icon: const Icon(Icons.rss_feed),
label: AppLocalizations.of(context).newsFeeds, label: AppLocalizations.of(context).feeds,
), ),
], ],
), ),

11
packages/neon/neon_news/lib/widgets/articles_view.dart

@ -69,13 +69,13 @@ class _NewsArticlesViewState extends State<NewsArticlesView> {
late final String label; late final String label;
switch (a) { switch (a) {
case FilterType.all: case FilterType.all:
label = AppLocalizations.of(context).newsFilterAll; label = AppLocalizations.of(context).filterAll;
break; break;
case FilterType.unread: case FilterType.unread:
label = AppLocalizations.of(context).newsFilterUnread; label = AppLocalizations.of(context).filterUnread;
break; break;
case FilterType.starred: case FilterType.starred:
label = AppLocalizations.of(context).newsFilterStarred; label = AppLocalizations.of(context).filterStarred;
break; break;
default: default:
throw Exception('FilterType $a should not be shown'); throw Exception('FilterType $a should not be shown');
@ -165,9 +165,8 @@ class _NewsArticlesViewState extends State<NewsArticlesView> {
widget.bloc.starArticle(article); widget.bloc.starArticle(article);
} }
}, },
tooltip: article.starred tooltip:
? AppLocalizations.of(context).newsArticleUnstar article.starred ? AppLocalizations.of(context).articleUnstar : AppLocalizations.of(context).articleStar,
: AppLocalizations.of(context).newsArticleStar,
icon: Icon( icon: Icon(
article.starred ? Icons.star : Icons.star_outline, article.starred ? Icons.star : Icons.star_outline,
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,

2
packages/neon/neon_news/lib/widgets/feed_floating_action_button.dart

@ -24,7 +24,7 @@ class NewsFeedFloatingActionButton extends StatelessWidget {
bloc.addFeed(result[0] as String, result[1] as int?); bloc.addFeed(result[0] as String, result[1] as int?);
} }
}, },
tooltip: AppLocalizations.of(context).newsAddFeed, tooltip: AppLocalizations.of(context).addFeed,
child: const Icon(Icons.add), child: const Icon(Icons.add),
); );
} }

13
packages/neon/neon_news/lib/widgets/feeds_view.dart

@ -51,9 +51,8 @@ class NewsFeedsView extends StatelessWidget {
? Theme.of(context).textTheme.titleMedium!.copyWith(color: Theme.of(context).disabledColor) ? Theme.of(context).textTheme.titleMedium!.copyWith(color: Theme.of(context).disabledColor)
: null, : null,
), ),
subtitle: feed.unreadCount! > 0 subtitle:
? Text(AppLocalizations.of(context).newsUnreadArticles(feed.unreadCount!)) feed.unreadCount! > 0 ? Text(AppLocalizations.of(context).unreadArticles(feed.unreadCount!)) : Container(),
: Container(),
leading: NewsFeedIcon( leading: NewsFeedIcon(
feed: feed, feed: feed,
borderRadius: const BorderRadius.all(Radius.circular(8)), borderRadius: const BorderRadius.all(Radius.circular(8)),
@ -71,7 +70,7 @@ class NewsFeedsView extends StatelessWidget {
), ),
); );
}, },
tooltip: AppLocalizations.of(context).newsShowFeedErrorMessage, tooltip: AppLocalizations.of(context).showFeedErrorMessage,
iconSize: 30, iconSize: 30,
icon: Text( icon: Text(
feed.updateErrorCount.toString(), feed.updateErrorCount.toString(),
@ -85,7 +84,7 @@ class NewsFeedsView extends StatelessWidget {
itemBuilder: (final context) => [ itemBuilder: (final context) => [
PopupMenuItem( PopupMenuItem(
value: NewsFeedAction.showURL, value: NewsFeedAction.showURL,
child: Text(AppLocalizations.of(context).newsShowFeedURL), child: Text(AppLocalizations.of(context).showFeedURL),
), ),
PopupMenuItem( PopupMenuItem(
value: NewsFeedAction.delete, value: NewsFeedAction.delete,
@ -117,7 +116,7 @@ class NewsFeedsView extends StatelessWidget {
if (await showConfirmationDialog( if (await showConfirmationDialog(
context, context,
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
AppLocalizations.of(context).newsRemoveFeedConfirm(feed.title), AppLocalizations.of(context).removeFeedConfirm(feed.title),
)) { )) {
bloc.removeFeed(feed.id); bloc.removeFeed(feed.id);
} }
@ -125,7 +124,7 @@ class NewsFeedsView extends StatelessWidget {
case NewsFeedAction.rename: case NewsFeedAction.rename:
final result = await showRenameDialog( final result = await showRenameDialog(
context: context, context: context,
title: AppLocalizations.of(context).newsRenameFeed, title: AppLocalizations.of(context).renameFeed,
value: feed.title, value: feed.title,
); );
if (result != null) { if (result != null) {

2
packages/neon/neon_news/lib/widgets/folder_floating_action_button.dart

@ -19,7 +19,7 @@ class NewsFolderFloatingActionButton extends StatelessWidget {
bloc.createFolder(result); bloc.createFolder(result);
} }
}, },
tooltip: AppLocalizations.of(context).filesCreateFolder, tooltip: AppLocalizations.of(context).createFolder,
child: const Icon(Icons.add), child: const Icon(Icons.add),
); );
} }

4
packages/neon/neon_news/lib/widgets/folder_select.dart

@ -15,12 +15,12 @@ class NewsFolderSelect extends StatelessWidget {
@override @override
Widget build(final BuildContext context) => DropdownButtonFormField<NextcloudNewsFolder>( Widget build(final BuildContext context) => DropdownButtonFormField<NextcloudNewsFolder>(
decoration: InputDecoration( decoration: InputDecoration(
hintText: AppLocalizations.of(context).newsFolder, hintText: AppLocalizations.of(context).folder,
), ),
value: value, value: value,
items: [ items: [
DropdownMenuItem( DropdownMenuItem(
child: Text(AppLocalizations.of(context).newsFolderRoot), child: Text(AppLocalizations.of(context).folderRoot),
), ),
...folders.map( ...folders.map(
(final f) => DropdownMenuItem<NextcloudNewsFolder>( (final f) => DropdownMenuItem<NextcloudNewsFolder>(

6
packages/neon/neon_news/lib/widgets/folders_view.dart

@ -54,7 +54,7 @@ class NewsFoldersView extends StatelessWidget {
), ),
subtitle: unreadCount > 0 subtitle: unreadCount > 0
? Text( ? Text(
AppLocalizations.of(context).newsUnreadArticles(unreadCount), AppLocalizations.of(context).unreadArticles(unreadCount),
) )
: Container(), : Container(),
leading: SizedBox.square( leading: SizedBox.square(
@ -95,7 +95,7 @@ class NewsFoldersView extends StatelessWidget {
if (await showConfirmationDialog( if (await showConfirmationDialog(
context, context,
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
AppLocalizations.of(context).newsDeleteFolderConfirm(folderFeedsWrapper.folder.name), AppLocalizations.of(context).deleteFolderConfirm(folderFeedsWrapper.folder.name),
)) { )) {
bloc.deleteFolder(folderFeedsWrapper.folder.id); bloc.deleteFolder(folderFeedsWrapper.folder.id);
} }
@ -103,7 +103,7 @@ class NewsFoldersView extends StatelessWidget {
case NewsFolderAction.rename: case NewsFolderAction.rename:
final result = await showRenameDialog( final result = await showRenameDialog(
context: context, context: context,
title: AppLocalizations.of(context).newsRenameFolder, title: AppLocalizations.of(context).renameFolder,
value: folderFeedsWrapper.folder.name, value: folderFeedsWrapper.folder.name,
); );
if (result != null) { if (result != null) {

6
packages/neon/neon_notes/lib/dialogs/create_note.dart

@ -29,7 +29,7 @@ class _NotesCreateNoteDialogState extends State<NotesCreateNoteDialog> {
Widget build(final BuildContext context) => ResultBuilder<List<NextcloudNotesNote>>( Widget build(final BuildContext context) => ResultBuilder<List<NextcloudNotesNote>>(
stream: widget.bloc.notes, stream: widget.bloc.notes,
builder: (final context, final notes) => NeonDialog( builder: (final context, final notes) => NeonDialog(
title: Text(AppLocalizations.of(context).notesCreateNote), title: Text(AppLocalizations.of(context).createNote),
children: [ children: [
Form( Form(
key: formKey, key: formKey,
@ -40,7 +40,7 @@ class _NotesCreateNoteDialogState extends State<NotesCreateNoteDialog> {
autofocus: true, autofocus: true,
controller: controller, controller: controller,
decoration: InputDecoration( decoration: InputDecoration(
hintText: AppLocalizations.of(context).notesNoteTitle, hintText: AppLocalizations.of(context).noteTitle,
), ),
validator: (final input) => validateNotEmpty(context, input), validator: (final input) => validateNotEmpty(context, input),
onFieldSubmitted: (final _) { onFieldSubmitted: (final _) {
@ -71,7 +71,7 @@ class _NotesCreateNoteDialogState extends State<NotesCreateNoteDialog> {
], ],
ElevatedButton( ElevatedButton(
onPressed: submit, onPressed: submit,
child: Text(AppLocalizations.of(context).notesCreateNote), child: Text(AppLocalizations.of(context).createNote),
), ),
], ],
), ),

4
packages/neon/neon_notes/lib/dialogs/select_category.dart

@ -29,7 +29,7 @@ class _NotesSelectCategoryDialogState extends State<NotesSelectCategoryDialog> {
Widget build(final BuildContext context) => ResultBuilder<List<NextcloudNotesNote>>( Widget build(final BuildContext context) => ResultBuilder<List<NextcloudNotesNote>>(
stream: widget.bloc.notes, stream: widget.bloc.notes,
builder: (final context, final notes) => NeonDialog( builder: (final context, final notes) => NeonDialog(
title: Text(AppLocalizations.of(context).notesCategory), title: Text(AppLocalizations.of(context).category),
children: [ children: [
Form( Form(
key: formKey, key: formKey,
@ -59,7 +59,7 @@ class _NotesSelectCategoryDialogState extends State<NotesSelectCategoryDialog> {
], ],
ElevatedButton( ElevatedButton(
onPressed: submit, onPressed: submit,
child: Text(AppLocalizations.of(context).notesSetCategory), child: Text(AppLocalizations.of(context).setCategory),
), ),
], ],
), ),

45
packages/neon/neon_notes/lib/l10n/en.arb

@ -1,3 +1,46 @@
{ {
"@@locale": "en" "@@locale": "en",
"general": "General",
"note": "Note",
"notes": "Notes",
"categories": "Categories",
"createNote": "Create note",
"category": "Category",
"setCategory": "Set category",
"noteTitle": "Title",
"noteChangedOnServer": "The note has been changed on the server. Please refresh and try again",
"notesInCategory": "{count} notes",
"@notesInCategory": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"uncategorized": "Uncategorized",
"showEditor": "Edit note",
"showPreview": "Preview note",
"star": "Star note",
"unstar": "Unstar note",
"changeCategory": "Change note category",
"deleteNoteConfirm": "Are you sure you want to delete the note '{name}'?",
"@deleteNoteConfirm": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"optionsDefaultCategory": "Category to show by default",
"optionsDefaultNoteViewType": "How to show note",
"optionsDefaultNoteViewTypePreview": "Preview",
"optionsDefaultNoteViewTypeEdit": "Editor",
"optionsNotesSortOrder": "Sort order of notes",
"optionsNotesSortProperty": "How to sort notes",
"optionsNotesSortPropertyLastModified": "Last modified",
"optionsNotesSortPropertyAlphabetical": "Alphabetical",
"optionsCategoriesSortOrder": "Sort order of categories",
"optionsCategoriesSortProperty": "How to sort categories",
"optionsCategoriesSortPropertyAlphabetical": "Alphabetical",
"optionsCategoriesSortPropertyNotesCount": "Count of notes"
} }

174
packages/neon/neon_notes/lib/l10n/localizations.dart

@ -88,6 +88,180 @@ abstract class AppLocalizations {
/// A list of this localizations delegate's supported locales. /// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[Locale('en')]; static const List<Locale> supportedLocales = <Locale>[Locale('en')];
/// No description provided for @general.
///
/// In en, this message translates to:
/// **'General'**
String get general;
/// No description provided for @note.
///
/// In en, this message translates to:
/// **'Note'**
String get note;
/// No description provided for @notes.
///
/// In en, this message translates to:
/// **'Notes'**
String get notes;
/// No description provided for @categories.
///
/// In en, this message translates to:
/// **'Categories'**
String get categories;
/// No description provided for @createNote.
///
/// In en, this message translates to:
/// **'Create note'**
String get createNote;
/// No description provided for @category.
///
/// In en, this message translates to:
/// **'Category'**
String get category;
/// No description provided for @setCategory.
///
/// In en, this message translates to:
/// **'Set category'**
String get setCategory;
/// No description provided for @noteTitle.
///
/// In en, this message translates to:
/// **'Title'**
String get noteTitle;
/// No description provided for @noteChangedOnServer.
///
/// In en, this message translates to:
/// **'The note has been changed on the server. Please refresh and try again'**
String get noteChangedOnServer;
/// No description provided for @notesInCategory.
///
/// In en, this message translates to:
/// **'{count} notes'**
String notesInCategory(int count);
/// No description provided for @uncategorized.
///
/// In en, this message translates to:
/// **'Uncategorized'**
String get uncategorized;
/// No description provided for @showEditor.
///
/// In en, this message translates to:
/// **'Edit note'**
String get showEditor;
/// No description provided for @showPreview.
///
/// In en, this message translates to:
/// **'Preview note'**
String get showPreview;
/// No description provided for @star.
///
/// In en, this message translates to:
/// **'Star note'**
String get star;
/// No description provided for @unstar.
///
/// In en, this message translates to:
/// **'Unstar note'**
String get unstar;
/// No description provided for @changeCategory.
///
/// In en, this message translates to:
/// **'Change note category'**
String get changeCategory;
/// No description provided for @deleteNoteConfirm.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete the note \'{name}\'?'**
String deleteNoteConfirm(String name);
/// No description provided for @optionsDefaultCategory.
///
/// In en, this message translates to:
/// **'Category to show by default'**
String get optionsDefaultCategory;
/// No description provided for @optionsDefaultNoteViewType.
///
/// In en, this message translates to:
/// **'How to show note'**
String get optionsDefaultNoteViewType;
/// No description provided for @optionsDefaultNoteViewTypePreview.
///
/// In en, this message translates to:
/// **'Preview'**
String get optionsDefaultNoteViewTypePreview;
/// No description provided for @optionsDefaultNoteViewTypeEdit.
///
/// In en, this message translates to:
/// **'Editor'**
String get optionsDefaultNoteViewTypeEdit;
/// No description provided for @optionsNotesSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of notes'**
String get optionsNotesSortOrder;
/// No description provided for @optionsNotesSortProperty.
///
/// In en, this message translates to:
/// **'How to sort notes'**
String get optionsNotesSortProperty;
/// No description provided for @optionsNotesSortPropertyLastModified.
///
/// In en, this message translates to:
/// **'Last modified'**
String get optionsNotesSortPropertyLastModified;
/// No description provided for @optionsNotesSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get optionsNotesSortPropertyAlphabetical;
/// No description provided for @optionsCategoriesSortOrder.
///
/// In en, this message translates to:
/// **'Sort order of categories'**
String get optionsCategoriesSortOrder;
/// No description provided for @optionsCategoriesSortProperty.
///
/// In en, this message translates to:
/// **'How to sort categories'**
String get optionsCategoriesSortProperty;
/// No description provided for @optionsCategoriesSortPropertyAlphabetical.
///
/// In en, this message translates to:
/// **'Alphabetical'**
String get optionsCategoriesSortPropertyAlphabetical;
/// No description provided for @optionsCategoriesSortPropertyNotesCount.
///
/// In en, this message translates to:
/// **'Count of notes'**
String get optionsCategoriesSortPropertyNotesCount;
} }
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> { class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {

91
packages/neon/neon_notes/lib/l10n/localizations_en.dart

@ -3,4 +3,95 @@ import 'localizations.dart';
/// The translations for English (`en`). /// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations { class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale); AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String get general => 'General';
@override
String get note => 'Note';
@override
String get notes => 'Notes';
@override
String get categories => 'Categories';
@override
String get createNote => 'Create note';
@override
String get category => 'Category';
@override
String get setCategory => 'Set category';
@override
String get noteTitle => 'Title';
@override
String get noteChangedOnServer => 'The note has been changed on the server. Please refresh and try again';
@override
String notesInCategory(int count) {
return '$count notes';
}
@override
String get uncategorized => 'Uncategorized';
@override
String get showEditor => 'Edit note';
@override
String get showPreview => 'Preview note';
@override
String get star => 'Star note';
@override
String get unstar => 'Unstar note';
@override
String get changeCategory => 'Change note category';
@override
String deleteNoteConfirm(String name) {
return 'Are you sure you want to delete the note \'$name\'?';
}
@override
String get optionsDefaultCategory => 'Category to show by default';
@override
String get optionsDefaultNoteViewType => 'How to show note';
@override
String get optionsDefaultNoteViewTypePreview => 'Preview';
@override
String get optionsDefaultNoteViewTypeEdit => 'Editor';
@override
String get optionsNotesSortOrder => 'Sort order of notes';
@override
String get optionsNotesSortProperty => 'How to sort notes';
@override
String get optionsNotesSortPropertyLastModified => 'Last modified';
@override
String get optionsNotesSortPropertyAlphabetical => 'Alphabetical';
@override
String get optionsCategoriesSortOrder => 'Sort order of categories';
@override
String get optionsCategoriesSortProperty => 'How to sort categories';
@override
String get optionsCategoriesSortPropertyAlphabetical => 'Alphabetical';
@override
String get optionsCategoriesSortPropertyNotesCount => 'Count of notes';
} }

7
packages/neon/neon_notes/lib/neon_notes.dart

@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:neon/neon.dart'; import 'package:neon/neon.dart';
import 'package:neon_notes/l10n/localizations.dart';
import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:queue/queue.dart'; import 'package:queue/queue.dart';
@ -40,6 +41,12 @@ class NotesApp extends AppImplementation<NotesBloc, NotesAppSpecificOptions> {
@override @override
String id = 'notes'; String id = 'notes';
@override
List<Locale> supportedLocales = AppLocalizations.supportedLocales;
@override
LocalizationsDelegate localizationsDelegate = AppLocalizations.delegate;
@override @override
NotesAppSpecificOptions buildOptions(final AppStorage storage) => NotesAppSpecificOptions(storage); NotesAppSpecificOptions buildOptions(final AppStorage storage) => NotesAppSpecificOptions(storage);

35
packages/neon/neon_notes/lib/options.dart

@ -18,26 +18,26 @@ class NotesAppSpecificOptions extends NextcloudAppSpecificOptions {
} }
final generalCategory = OptionsCategory( final generalCategory = OptionsCategory(
name: (final context) => AppLocalizations.of(context).optionsCategoryGeneral, name: (final context) => AppLocalizations.of(context).general,
); );
final notesCategory = OptionsCategory( final notesCategory = OptionsCategory(
name: (final context) => AppLocalizations.of(context).notesNotes, name: (final context) => AppLocalizations.of(context).notes,
); );
final categoriesCategory = OptionsCategory( final categoriesCategory = OptionsCategory(
name: (final context) => AppLocalizations.of(context).notesCategories, name: (final context) => AppLocalizations.of(context).categories,
); );
late final defaultCategoryOption = SelectOption<DefaultCategory>( late final defaultCategoryOption = SelectOption<DefaultCategory>(
storage: super.storage, storage: super.storage,
category: generalCategory, category: generalCategory,
key: 'default-category', key: 'default-category',
label: (final context) => AppLocalizations.of(context).notesOptionsDefaultCategory, label: (final context) => AppLocalizations.of(context).optionsDefaultCategory,
defaultValue: BehaviorSubject.seeded(DefaultCategory.notes), defaultValue: BehaviorSubject.seeded(DefaultCategory.notes),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
DefaultCategory.notes: (final context) => AppLocalizations.of(context).notesNotes, DefaultCategory.notes: (final context) => AppLocalizations.of(context).notes,
DefaultCategory.categories: (final context) => AppLocalizations.of(context).notesCategories, DefaultCategory.categories: (final context) => AppLocalizations.of(context).categories,
}), }),
); );
@ -45,12 +45,11 @@ class NotesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: generalCategory, category: generalCategory,
key: 'default-note-view-type', key: 'default-note-view-type',
label: (final context) => AppLocalizations.of(context).notesOptionsDefaultNoteViewType, label: (final context) => AppLocalizations.of(context).optionsDefaultNoteViewType,
defaultValue: BehaviorSubject.seeded(DefaultNoteViewType.preview), defaultValue: BehaviorSubject.seeded(DefaultNoteViewType.preview),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
DefaultNoteViewType.preview: (final context) => DefaultNoteViewType.preview: (final context) => AppLocalizations.of(context).optionsDefaultNoteViewTypePreview,
AppLocalizations.of(context).notesOptionsDefaultNoteViewTypePreview, DefaultNoteViewType.edit: (final context) => AppLocalizations.of(context).optionsDefaultNoteViewTypeEdit,
DefaultNoteViewType.edit: (final context) => AppLocalizations.of(context).notesOptionsDefaultNoteViewTypeEdit,
}), }),
); );
@ -58,13 +57,13 @@ class NotesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: notesCategory, category: notesCategory,
key: 'notes-sort-property', key: 'notes-sort-property',
label: (final context) => AppLocalizations.of(context).notesOptionsNotesSortProperty, label: (final context) => AppLocalizations.of(context).optionsNotesSortProperty,
defaultValue: BehaviorSubject.seeded(NotesSortProperty.lastModified), defaultValue: BehaviorSubject.seeded(NotesSortProperty.lastModified),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
NotesSortProperty.lastModified: (final context) => NotesSortProperty.lastModified: (final context) =>
AppLocalizations.of(context).notesOptionsNotesSortPropertyLastModified, AppLocalizations.of(context).optionsNotesSortPropertyLastModified,
NotesSortProperty.alphabetical: (final context) => NotesSortProperty.alphabetical: (final context) =>
AppLocalizations.of(context).notesOptionsNotesSortPropertyAlphabetical, AppLocalizations.of(context).optionsNotesSortPropertyAlphabetical,
}), }),
); );
@ -72,7 +71,7 @@ class NotesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: notesCategory, category: notesCategory,
key: 'notes-sort-box-order', key: 'notes-sort-box-order',
label: (final context) => AppLocalizations.of(context).notesOptionsNotesSortOrder, label: (final context) => AppLocalizations.of(context).optionsNotesSortOrder,
defaultValue: BehaviorSubject.seeded(SortBoxOrder.descending), defaultValue: BehaviorSubject.seeded(SortBoxOrder.descending),
values: BehaviorSubject.seeded(sortBoxOrderOptionValues), values: BehaviorSubject.seeded(sortBoxOrderOptionValues),
); );
@ -81,13 +80,13 @@ class NotesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: categoriesCategory, category: categoriesCategory,
key: 'categories-sort-property', key: 'categories-sort-property',
label: (final context) => AppLocalizations.of(context).notesOptionsCategoriesSortProperty, label: (final context) => AppLocalizations.of(context).optionsCategoriesSortProperty,
defaultValue: BehaviorSubject.seeded(CategoriesSortProperty.alphabetical), defaultValue: BehaviorSubject.seeded(CategoriesSortProperty.alphabetical),
values: BehaviorSubject.seeded({ values: BehaviorSubject.seeded({
CategoriesSortProperty.alphabetical: (final context) => CategoriesSortProperty.alphabetical: (final context) =>
AppLocalizations.of(context).notesOptionsCategoriesSortPropertyAlphabetical, AppLocalizations.of(context).optionsCategoriesSortPropertyAlphabetical,
CategoriesSortProperty.notesCount: (final context) => CategoriesSortProperty.notesCount: (final context) =>
AppLocalizations.of(context).notesOptionsCategoriesSortPropertyNotesCount, AppLocalizations.of(context).optionsCategoriesSortPropertyNotesCount,
}), }),
); );
@ -95,7 +94,7 @@ class NotesAppSpecificOptions extends NextcloudAppSpecificOptions {
storage: super.storage, storage: super.storage,
category: categoriesCategory, category: categoriesCategory,
key: 'categories-sort-box-order', key: 'categories-sort-box-order',
label: (final context) => AppLocalizations.of(context).notesOptionsCategoriesSortOrder, label: (final context) => AppLocalizations.of(context).optionsCategoriesSortOrder,
defaultValue: BehaviorSubject.seeded(SortBoxOrder.ascending), defaultValue: BehaviorSubject.seeded(SortBoxOrder.ascending),
values: BehaviorSubject.seeded(sortBoxOrderOptionValues), values: BehaviorSubject.seeded(sortBoxOrderOptionValues),
); );

2
packages/neon/neon_notes/lib/pages/category.dart

@ -14,7 +14,7 @@ class NotesCategoryPage extends StatelessWidget {
Widget build(final BuildContext context) => Scaffold( Widget build(final BuildContext context) => Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
title: Text(category.name != '' ? category.name : AppLocalizations.of(context).notesUncategorized), title: Text(category.name != '' ? category.name : AppLocalizations.of(context).uncategorized),
), ),
body: NotesView( body: NotesView(
bloc: bloc, bloc: bloc,

4
packages/neon/neon_notes/lib/pages/main.dart

@ -52,11 +52,11 @@ class _NotesMainPageState extends State<NotesMainPage> {
items: [ items: [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: const Icon(Icons.note), icon: const Icon(Icons.note),
label: AppLocalizations.of(context).notesNotes, label: AppLocalizations.of(context).notes,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: const Icon(MdiIcons.tag), icon: const Icon(MdiIcons.tag),
label: AppLocalizations.of(context).notesCategories, label: AppLocalizations.of(context).categories,
), ),
], ],
), ),

7
packages/neon/neon_notes/lib/pages/note.dart

@ -101,9 +101,8 @@ class _NotesNotePageState extends State<NotesNotePage> {
_titleFocusNode.unfocus(); _titleFocusNode.unfocus();
} }
}, },
tooltip: _showEditor tooltip:
? AppLocalizations.of(context).notesShowPreview _showEditor ? AppLocalizations.of(context).showPreview : AppLocalizations.of(context).showEditor,
: AppLocalizations.of(context).notesShowEditor,
icon: Icon( icon: Icon(
_showEditor ? Icons.visibility : Icons.edit, _showEditor ? Icons.visibility : Icons.edit,
), ),
@ -126,7 +125,7 @@ class _NotesNotePageState extends State<NotesNotePage> {
widget.bloc.updateCategory(result); widget.bloc.updateCategory(result);
} }
}, },
tooltip: AppLocalizations.of(context).notesChangeCategory, tooltip: AppLocalizations.of(context).changeCategory,
icon: Icon( icon: Icon(
MdiIcons.tag, MdiIcons.tag,
color: category.isNotEmpty ? NotesCategoryColor.compute(category) : null, color: category.isNotEmpty ? NotesCategoryColor.compute(category) : null,

2
packages/neon/neon_notes/lib/utils/exception_handler.dart

@ -2,7 +2,7 @@ part of '../neon_notes.dart';
void handleNotesException(final BuildContext context, final Object error) { void handleNotesException(final BuildContext context, final Object error) {
if (error is NextcloudApiException && error.statusCode == 412) { if (error is NextcloudApiException && error.statusCode == 412) {
NeonException.showSnackbar(context, AppLocalizations.of(context).notesNoteChangedOnServer); NeonException.showSnackbar(context, AppLocalizations.of(context).noteChangedOnServer);
} else { } else {
NeonException.showSnackbar(context, error); NeonException.showSnackbar(context, error);
} }

4
packages/neon/neon_notes/lib/widgets/categories_view.dart

@ -41,8 +41,8 @@ class NotesCategoriesView extends StatelessWidget {
final NoteCategory category, final NoteCategory category,
) => ) =>
ListTile( ListTile(
title: Text(category.name != '' ? category.name : AppLocalizations.of(context).notesUncategorized), title: Text(category.name != '' ? category.name : AppLocalizations.of(context).uncategorized),
subtitle: Text(AppLocalizations.of(context).notesNotesInCategory(category.count)), subtitle: Text(AppLocalizations.of(context).notesInCategory(category.count)),
leading: category.name != '' leading: category.name != ''
? Icon( ? Icon(
MdiIcons.tag, MdiIcons.tag,

4
packages/neon/neon_notes/lib/widgets/category_select.dart

@ -50,7 +50,7 @@ class NotesCategorySelect extends StatelessWidget {
controller: textEditingController, controller: textEditingController,
focusNode: focusNode, focusNode: focusNode,
decoration: InputDecoration( decoration: InputDecoration(
hintText: AppLocalizations.of(context).notesCategory, hintText: AppLocalizations.of(context).category,
), ),
onFieldSubmitted: (final value) { onFieldSubmitted: (final value) {
onChanged(value); onChanged(value);
@ -77,7 +77,7 @@ class NotesCategorySelect extends StatelessWidget {
color: option != '' ? NotesCategoryColor.compute(option) : null, color: option != '' ? NotesCategoryColor.compute(option) : null,
), ),
title: Text( title: Text(
option != '' ? option : AppLocalizations.of(context).notesUncategorized, option != '' ? option : AppLocalizations.of(context).uncategorized,
), ),
onTap: () { onTap: () {
onSelected(option); onSelected(option);

2
packages/neon/neon_notes/lib/widgets/notes_floating_action_button.dart

@ -27,7 +27,7 @@ class NotesFloatingActionButton extends StatelessWidget {
); );
} }
}, },
tooltip: AppLocalizations.of(context).notesCreateNote, tooltip: AppLocalizations.of(context).createNote,
child: const Icon(Icons.add), child: const Icon(Icons.add),
); );
} }

4
packages/neon/neon_notes/lib/widgets/notes_view.dart

@ -78,7 +78,7 @@ class NotesView extends StatelessWidget {
favorite: !note.favorite, favorite: !note.favorite,
); );
}, },
tooltip: note.favorite ? AppLocalizations.of(context).notesUnstar : AppLocalizations.of(context).notesStar, tooltip: note.favorite ? AppLocalizations.of(context).unstar : AppLocalizations.of(context).star,
icon: Icon( icon: Icon(
note.favorite ? Icons.star : Icons.star_outline, note.favorite ? Icons.star : Icons.star_outline,
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
@ -102,7 +102,7 @@ class NotesView extends StatelessWidget {
onLongPress: () async { onLongPress: () async {
final result = await showConfirmationDialog( final result = await showConfirmationDialog(
context, context,
AppLocalizations.of(context).notesDeleteNoteConfirm(note.title), AppLocalizations.of(context).deleteNoteConfirm(note.title),
); );
if (result) { if (result) {
bloc.deleteNote(note.id); bloc.deleteNote(note.id);

5
packages/neon/neon_notifications/lib/l10n/en.arb

@ -1,3 +1,6 @@
{ {
"@@locale": "en" "@@locale": "en",
"close": "Close",
"nextcloudAppNotImplementedYet": "Sorry, this Nextcloud app has not been implemented yet",
"dismissAll": "Dismiss all notifications"
} }

18
packages/neon/neon_notifications/lib/l10n/localizations.dart

@ -88,6 +88,24 @@ abstract class AppLocalizations {
/// A list of this localizations delegate's supported locales. /// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[Locale('en')]; static const List<Locale> supportedLocales = <Locale>[Locale('en')];
/// No description provided for @close.
///
/// In en, this message translates to:
/// **'Close'**
String get close;
/// No description provided for @nextcloudAppNotImplementedYet.
///
/// In en, this message translates to:
/// **'Sorry, this Nextcloud app has not been implemented yet'**
String get nextcloudAppNotImplementedYet;
/// No description provided for @dismissAll.
///
/// In en, this message translates to:
/// **'Dismiss all notifications'**
String get dismissAll;
} }
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> { class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {

9
packages/neon/neon_notifications/lib/l10n/localizations_en.dart

@ -3,4 +3,13 @@ import 'localizations.dart';
/// The translations for English (`en`). /// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations { class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale); AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String get close => 'Close';
@override
String get nextcloudAppNotImplementedYet => 'Sorry, this Nextcloud app has not been implemented yet';
@override
String get dismissAll => 'Dismiss all notifications';
} }

7
packages/neon/neon_notifications/lib/neon_notifications.dart

@ -5,6 +5,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:neon/neon.dart'; import 'package:neon/neon.dart';
import 'package:neon_notifications/l10n/localizations.dart';
import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/nextcloud.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
@ -19,6 +20,12 @@ class NotificationsApp extends NotificationsAppInterface {
@override @override
String id = 'notifications'; String id = 'notifications';
@override
LocalizationsDelegate localizationsDelegate = AppLocalizations.delegate;
@override
List<Locale> supportedLocales = AppLocalizations.supportedLocales;
@override @override
NotificationsAppSpecificOptions buildOptions(final AppStorage storage) => NotificationsAppSpecificOptions(storage); NotificationsAppSpecificOptions buildOptions(final AppStorage storage) => NotificationsAppSpecificOptions(storage);

4
packages/neon/neon_notifications/lib/pages/main.dart

@ -31,7 +31,7 @@ class _NotificationsMainPageState extends State<NotificationsMainPage> {
onPressed: () async { onPressed: () async {
widget.bloc.deleteAllNotifications(); widget.bloc.deleteAllNotifications();
}, },
tooltip: AppLocalizations.of(context).notificationsDismissAll, tooltip: AppLocalizations.of(context).dismissAll,
child: const Icon(MdiIcons.checkAll), child: const Icon(MdiIcons.checkAll),
), ),
body: NeonListView<NextcloudNotificationsNotification>( body: NeonListView<NextcloudNotificationsNotification>(
@ -95,7 +95,7 @@ class _NotificationsMainPageState extends State<NotificationsMainPage> {
await showDialog( await showDialog(
context: context, context: context,
builder: (final context) => AlertDialog( builder: (final context) => AlertDialog(
title: Text(AppLocalizations.of(context).notificationsNextcloudAppNotImplementedYet), title: Text(AppLocalizations.of(context).nextcloudAppNotImplementedYet),
actions: [ actions: [
ElevatedButton( ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(

Loading…
Cancel
Save