worldhopper/lib/l10n/app_localizations.dart
Felipe M. 58a562abe8
feat: refactor server software abstraction with Kavita REST API integration
Rename all OPDS-prefixed models to generic names (Server, Feed, Entry,
Link, StreamLink), expand the ServerSoftware interface to cover all
server interactions, and implement a full Kavita REST API client that
replaces the OPDS delegation.

- Rename OPDS* models to generic names across ~60 files
- Add database migrations 13 (opds_id → entry_id) and 14 (unify credentials)
- Create OPDSServerSoftware wrapping existing OPDS services
- Create KavitaApiClient for direct Kavita REST API calls
- Create KavitaFeedMapper to convert Kavita JSON to Feed/Entry models
- Rewrite KavitaServerSoftware to use native API (no OPDS delegation)
- Unify server credentials (remove softwareUsername/softwarePassword)
- Simplify add/edit server UI to single auth section
- Add test connection button to server add/edit screens
- Add progress indicator to PublicationCard using local and server data
- Eliminate softwareType branching in reader screens
- Add EntryProgress and fetchEntryProgress to ServerSoftware interface
- Fix Entry.acquisitionLink crash on empty links
- Add 59 new tests covering models, services, and providers
2026-04-06 17:46:48 +02:00

1819 lines
52 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart' as intl;
import 'app_localizations_en.dart';
import 'app_localizations_es.dart';
// ignore_for_file: type=lint
/// Callers can lookup localized strings with an instance of AppLocalizations
/// returned by `AppLocalizations.of(context)`.
///
/// Applications need to include `AppLocalizations.delegate()` in their app's
/// `localizationDelegates` list, and the locales they support in the app's
/// `supportedLocales` list. For example:
///
/// ```dart
/// import 'l10n/app_localizations.dart';
///
/// return MaterialApp(
/// localizationsDelegates: AppLocalizations.localizationsDelegates,
/// supportedLocales: AppLocalizations.supportedLocales,
/// home: MyApplicationHome(),
/// );
/// ```
///
/// ## Update pubspec.yaml
///
/// Please make sure to update your pubspec.yaml to include the following
/// packages:
///
/// ```yaml
/// dependencies:
/// # Internationalization support.
/// flutter_localizations:
/// sdk: flutter
/// intl: any # Use the pinned version from flutter_localizations
///
/// # Rest of dependencies
/// ```
///
/// ## iOS Applications
///
/// iOS applications define key application metadata, including supported
/// locales, in an Info.plist file that is built into the application bundle.
/// To configure the locales supported by your app, youll need to edit this
/// file.
///
/// First, open your projects ios/Runner.xcworkspace Xcode workspace file.
/// Then, in the Project Navigator, open the Info.plist file under the Runner
/// projects Runner folder.
///
/// Next, select the Information Property List item, select Add Item from the
/// Editor menu, then select Localizations from the pop-up menu.
///
/// Select and expand the newly-created Localizations item then, for each
/// locale your application supports, add a new item and select the locale
/// you wish to add from the pop-up menu in the Value field. This list should
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
/// property.
abstract class AppLocalizations {
AppLocalizations(String locale)
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
final String localeName;
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations)!;
}
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
/// A list of this localizations delegate along with the default localizations
/// delegates.
///
/// Returns a list of localizations delegates containing this delegate along with
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
/// and GlobalWidgetsLocalizations.delegate.
///
/// Additional delegates can be added by appending to this list in
/// MaterialApp. This list does not have to be used at all if a custom list
/// of delegates is preferred or required.
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
<LocalizationsDelegate<dynamic>>[
delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
];
/// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[
Locale('en'),
Locale('es')
];
/// No description provided for @appName.
///
/// In en, this message translates to:
/// **'Worldhopper'**
String get appName;
/// No description provided for @navLibrary.
///
/// In en, this message translates to:
/// **'Library'**
String get navLibrary;
/// No description provided for @navServers.
///
/// In en, this message translates to:
/// **'Servers'**
String get navServers;
/// No description provided for @navSettings.
///
/// In en, this message translates to:
/// **'Settings'**
String get navSettings;
/// No description provided for @settingsTitle.
///
/// In en, this message translates to:
/// **'Settings'**
String get settingsTitle;
/// No description provided for @settingsAppearance.
///
/// In en, this message translates to:
/// **'Appearance'**
String get settingsAppearance;
/// No description provided for @settingsAppearanceSubtitle.
///
/// In en, this message translates to:
/// **'Display options'**
String get settingsAppearanceSubtitle;
/// No description provided for @settingsLanguage.
///
/// In en, this message translates to:
/// **'Language'**
String get settingsLanguage;
/// No description provided for @settingsLanguageSubtitle.
///
/// In en, this message translates to:
/// **'App language'**
String get settingsLanguageSubtitle;
/// No description provided for @settingsReaders.
///
/// In en, this message translates to:
/// **'Readers'**
String get settingsReaders;
/// No description provided for @settingsReadersSubtitle.
///
/// In en, this message translates to:
/// **'Reader options'**
String get settingsReadersSubtitle;
/// No description provided for @settingsAdvanced.
///
/// In en, this message translates to:
/// **'Advanced'**
String get settingsAdvanced;
/// No description provided for @settingsAdvancedSubtitle.
///
/// In en, this message translates to:
/// **'Developer and debugging'**
String get settingsAdvancedSubtitle;
/// No description provided for @settingsAbout.
///
/// In en, this message translates to:
/// **'About'**
String get settingsAbout;
/// No description provided for @settingsAboutSubtitle.
///
/// In en, this message translates to:
/// **'Worldhopper'**
String get settingsAboutSubtitle;
/// No description provided for @appearanceTitle.
///
/// In en, this message translates to:
/// **'Appearance'**
String get appearanceTitle;
/// No description provided for @appearanceTheme.
///
/// In en, this message translates to:
/// **'Theme'**
String get appearanceTheme;
/// No description provided for @themeLight.
///
/// In en, this message translates to:
/// **'Light'**
String get themeLight;
/// No description provided for @themeDark.
///
/// In en, this message translates to:
/// **'Dark'**
String get themeDark;
/// No description provided for @themeSystem.
///
/// In en, this message translates to:
/// **'System'**
String get themeSystem;
/// No description provided for @themeSystemSubtitle.
///
/// In en, this message translates to:
/// **'Follow device theme'**
String get themeSystemSubtitle;
/// No description provided for @languageTitle.
///
/// In en, this message translates to:
/// **'Language'**
String get languageTitle;
/// No description provided for @languageSystem.
///
/// In en, this message translates to:
/// **'System default'**
String get languageSystem;
/// No description provided for @languageSystemSubtitle.
///
/// In en, this message translates to:
/// **'Use device language'**
String get languageSystemSubtitle;
/// No description provided for @readersTitle.
///
/// In en, this message translates to:
/// **'Readers'**
String get readersTitle;
/// No description provided for @readersGeneralSection.
///
/// In en, this message translates to:
/// **'General'**
String get readersGeneralSection;
/// No description provided for @readersEinkMode.
///
/// In en, this message translates to:
/// **'E-ink mode'**
String get readersEinkMode;
/// No description provided for @readersEinkModeSubtitle.
///
/// In en, this message translates to:
/// **'Disable animations for e-ink displays'**
String get readersEinkModeSubtitle;
/// No description provided for @readersImageReaderSection.
///
/// In en, this message translates to:
/// **'Image Reader'**
String get readersImageReaderSection;
/// No description provided for @readersCachingSection.
///
/// In en, this message translates to:
/// **'Caching'**
String get readersCachingSection;
/// No description provided for @readersReadingDirection.
///
/// In en, this message translates to:
/// **'Reading direction'**
String get readersReadingDirection;
/// No description provided for @readersFilterQuality.
///
/// In en, this message translates to:
/// **'Filter quality'**
String get readersFilterQuality;
/// No description provided for @readersPrecachePages.
///
/// In en, this message translates to:
/// **'Pre-cache pages'**
String get readersPrecachePages;
/// No description provided for @readersTwoPageSpread.
///
/// In en, this message translates to:
/// **'Two-page spread'**
String get readersTwoPageSpread;
/// No description provided for @readersTwoPageSpreadSubtitle.
///
/// In en, this message translates to:
/// **'Show two pages side by side on wide screens'**
String get readersTwoPageSpreadSubtitle;
/// No description provided for @readersFirstPageIsCover.
///
/// In en, this message translates to:
/// **'First page is cover'**
String get readersFirstPageIsCover;
/// No description provided for @readersFirstPageIsCoverSubtitle.
///
/// In en, this message translates to:
/// **'Show the first page alone in two-page spread'**
String get readersFirstPageIsCoverSubtitle;
/// No description provided for @readersSyncProgress.
///
/// In en, this message translates to:
/// **'Sync progress for cached pages'**
String get readersSyncProgress;
/// No description provided for @readersSyncProgressSubtitle.
///
/// In en, this message translates to:
/// **'Re-fetches each page on turn so the server tracks your reading progress. Uses additional data.'**
String get readersSyncProgressSubtitle;
/// No description provided for @readingDirectionTitle.
///
/// In en, this message translates to:
/// **'Reading Direction'**
String get readingDirectionTitle;
/// No description provided for @readingModeLtr.
///
/// In en, this message translates to:
/// **'Left to right'**
String get readingModeLtr;
/// No description provided for @readingModeLtrDescription.
///
/// In en, this message translates to:
/// **'Standard Western reading order'**
String get readingModeLtrDescription;
/// No description provided for @readingModeRtl.
///
/// In en, this message translates to:
/// **'Right to left'**
String get readingModeRtl;
/// No description provided for @readingModeRtlDescription.
///
/// In en, this message translates to:
/// **'Manga-style reading order'**
String get readingModeRtlDescription;
/// No description provided for @readingModeVertical.
///
/// In en, this message translates to:
/// **'Vertical scroll'**
String get readingModeVertical;
/// No description provided for @readingModeVerticalDescription.
///
/// In en, this message translates to:
/// **'Continuous webtoon-style scrolling'**
String get readingModeVerticalDescription;
/// No description provided for @readingDirectionHelp.
///
/// In en, this message translates to:
/// **'Controls the reading direction for the image reader. Left to right is standard for Western comics, right to left for manga, and vertical scroll for webtoons.'**
String get readingDirectionHelp;
/// No description provided for @readingModeShortLtr.
///
/// In en, this message translates to:
/// **'LTR'**
String get readingModeShortLtr;
/// No description provided for @readingModeShortRtl.
///
/// In en, this message translates to:
/// **'RTL'**
String get readingModeShortRtl;
/// No description provided for @readingModeShortVertical.
///
/// In en, this message translates to:
/// **'Vertical'**
String get readingModeShortVertical;
/// No description provided for @filterQualityTitle.
///
/// In en, this message translates to:
/// **'Filter Quality'**
String get filterQualityTitle;
/// No description provided for @filterQualityNone.
///
/// In en, this message translates to:
/// **'None'**
String get filterQualityNone;
/// No description provided for @filterQualityNoneDescription.
///
/// In en, this message translates to:
/// **'Fastest, may look pixelated'**
String get filterQualityNoneDescription;
/// No description provided for @filterQualityLow.
///
/// In en, this message translates to:
/// **'Low'**
String get filterQualityLow;
/// No description provided for @filterQualityLowDescription.
///
/// In en, this message translates to:
/// **'Bilinear interpolation'**
String get filterQualityLowDescription;
/// No description provided for @filterQualityMedium.
///
/// In en, this message translates to:
/// **'Medium'**
String get filterQualityMedium;
/// No description provided for @filterQualityMediumDescription.
///
/// In en, this message translates to:
/// **'Bilinear with mipmaps, good balance'**
String get filterQualityMediumDescription;
/// No description provided for @filterQualityHigh.
///
/// In en, this message translates to:
/// **'High'**
String get filterQualityHigh;
/// No description provided for @filterQualityHighDescription.
///
/// In en, this message translates to:
/// **'Bicubic interpolation, best quality'**
String get filterQualityHighDescription;
/// No description provided for @filterQualityHelp.
///
/// In en, this message translates to:
/// **'Controls how images are scaled when a page is zoomed out to fit the screen. Higher quality makes text and fine details sharper but uses more GPU resources. Medium is recommended for most devices.'**
String get filterQualityHelp;
/// No description provided for @precachePagesTitle.
///
/// In en, this message translates to:
/// **'Pre-cache Pages'**
String get precachePagesTitle;
/// No description provided for @precachePagesOff.
///
/// In en, this message translates to:
/// **'Off'**
String get precachePagesOff;
/// No description provided for @precachePagesOffDescription.
///
/// In en, this message translates to:
/// **'Pages load on demand'**
String get precachePagesOffDescription;
/// No description provided for @precachePages1.
///
/// In en, this message translates to:
/// **'1 page'**
String get precachePages1;
/// No description provided for @precachePages1Description.
///
/// In en, this message translates to:
/// **'Minimal pre-loading'**
String get precachePages1Description;
/// No description provided for @precachePages2.
///
/// In en, this message translates to:
/// **'2 pages'**
String get precachePages2;
/// No description provided for @precachePages2Description.
///
/// In en, this message translates to:
/// **'Light pre-loading'**
String get precachePages2Description;
/// No description provided for @precachePages3.
///
/// In en, this message translates to:
/// **'3 pages'**
String get precachePages3;
/// No description provided for @precachePages3Description.
///
/// In en, this message translates to:
/// **'Balanced, recommended'**
String get precachePages3Description;
/// No description provided for @precachePages4.
///
/// In en, this message translates to:
/// **'4 pages'**
String get precachePages4;
/// No description provided for @precachePages4Description.
///
/// In en, this message translates to:
/// **'Aggressive pre-loading'**
String get precachePages4Description;
/// No description provided for @precachePages5.
///
/// In en, this message translates to:
/// **'5 pages'**
String get precachePages5;
/// No description provided for @precachePages5Description.
///
/// In en, this message translates to:
/// **'Maximum pre-loading, uses more bandwidth'**
String get precachePages5Description;
/// No description provided for @precachePagesHelp.
///
/// In en, this message translates to:
/// **'Controls how many upcoming pages are pre-loaded in the background while reading. Higher values make swiping feel more seamless but use more bandwidth and memory.\n\nNote: Pre-fetching pages may mark them as read on the server. Your local reading progress will not be affected.'**
String get precachePagesHelp;
/// No description provided for @advancedTitle.
///
/// In en, this message translates to:
/// **'Advanced'**
String get advancedTitle;
/// No description provided for @advancedDeveloperMode.
///
/// In en, this message translates to:
/// **'Developer mode'**
String get advancedDeveloperMode;
/// No description provided for @advancedDeveloperModeSubtitle.
///
/// In en, this message translates to:
/// **'Enable debugging tools'**
String get advancedDeveloperModeSubtitle;
/// No description provided for @advancedTests.
///
/// In en, this message translates to:
/// **'Tests'**
String get advancedTests;
/// No description provided for @advancedTestsSubtitle.
///
/// In en, this message translates to:
/// **'Preview UI components'**
String get advancedTestsSubtitle;
/// No description provided for @advancedDebuggingInfo.
///
/// In en, this message translates to:
/// **'Debugging info'**
String get advancedDebuggingInfo;
/// No description provided for @advancedVersion.
///
/// In en, this message translates to:
/// **'Version'**
String get advancedVersion;
/// No description provided for @advancedBuildNumber.
///
/// In en, this message translates to:
/// **'Build number'**
String get advancedBuildNumber;
/// No description provided for @advancedPackageName.
///
/// In en, this message translates to:
/// **'Package name'**
String get advancedPackageName;
/// No description provided for @advancedDatabaseVersion.
///
/// In en, this message translates to:
/// **'Database version'**
String get advancedDatabaseVersion;
/// No description provided for @advancedPlatform.
///
/// In en, this message translates to:
/// **'Platform'**
String get advancedPlatform;
/// No description provided for @advancedCopyToClipboard.
///
/// In en, this message translates to:
/// **'Copy to clipboard'**
String get advancedCopyToClipboard;
/// No description provided for @advancedCopyToClipboardSubtitle.
///
/// In en, this message translates to:
/// **'Copy all debug info for bug reports'**
String get advancedCopyToClipboardSubtitle;
/// No description provided for @advancedDebugInfoCopied.
///
/// In en, this message translates to:
/// **'Debug info copied to clipboard'**
String get advancedDebugInfoCopied;
/// No description provided for @advancedFailedToLoadInfo.
///
/// In en, this message translates to:
/// **'Failed to load info'**
String get advancedFailedToLoadInfo;
/// No description provided for @aboutTitle.
///
/// In en, this message translates to:
/// **'About'**
String get aboutTitle;
/// No description provided for @aboutVersion.
///
/// In en, this message translates to:
/// **'Version'**
String get aboutVersion;
/// No description provided for @aboutVersionUnknown.
///
/// In en, this message translates to:
/// **'unknown'**
String get aboutVersionUnknown;
/// No description provided for @aboutSourceCode.
///
/// In en, this message translates to:
/// **'Source code'**
String get aboutSourceCode;
/// No description provided for @aboutReportIssue.
///
/// In en, this message translates to:
/// **'Report an issue'**
String get aboutReportIssue;
/// No description provided for @aboutReportIssueSubtitle.
///
/// In en, this message translates to:
/// **'Open an issue on the repository'**
String get aboutReportIssueSubtitle;
/// No description provided for @devTestsTitle.
///
/// In en, this message translates to:
/// **'Dev Tests'**
String get devTestsTitle;
/// No description provided for @devTestsSnackBars.
///
/// In en, this message translates to:
/// **'Snack Bars'**
String get devTestsSnackBars;
/// No description provided for @devTestsSuccess.
///
/// In en, this message translates to:
/// **'Success'**
String get devTestsSuccess;
/// No description provided for @devTestsError.
///
/// In en, this message translates to:
/// **'Error'**
String get devTestsError;
/// No description provided for @devTestsWarning.
///
/// In en, this message translates to:
/// **'Warning'**
String get devTestsWarning;
/// No description provided for @devTestsInfo.
///
/// In en, this message translates to:
/// **'Info'**
String get devTestsInfo;
/// No description provided for @devTestsSuccessMessage.
///
/// In en, this message translates to:
/// **'This is a success message'**
String get devTestsSuccessMessage;
/// No description provided for @devTestsErrorMessage.
///
/// In en, this message translates to:
/// **'This is an error message'**
String get devTestsErrorMessage;
/// No description provided for @devTestsWarningMessage.
///
/// In en, this message translates to:
/// **'This is a warning message'**
String get devTestsWarningMessage;
/// No description provided for @devTestsInfoMessage.
///
/// In en, this message translates to:
/// **'This is an info message'**
String get devTestsInfoMessage;
/// No description provided for @serverListTitle.
///
/// In en, this message translates to:
/// **'My Servers'**
String get serverListTitle;
/// No description provided for @serverListEmpty.
///
/// In en, this message translates to:
/// **'No Servers Yet'**
String get serverListEmpty;
/// No description provided for @serverListEmptySubtitle.
///
/// In en, this message translates to:
/// **'Add your first OPDS server to start browsing and reading'**
String get serverListEmptySubtitle;
/// No description provided for @serverListOffline.
///
/// In en, this message translates to:
/// **'You are offline. Connect to the internet to browse servers.'**
String get serverListOffline;
/// No description provided for @serverListErrorLoading.
///
/// In en, this message translates to:
/// **'Error loading servers: {error}'**
String serverListErrorLoading(String error);
/// No description provided for @serverListRetry.
///
/// In en, this message translates to:
/// **'Retry'**
String get serverListRetry;
/// No description provided for @serverListAddServer.
///
/// In en, this message translates to:
/// **'Add Server'**
String get serverListAddServer;
/// No description provided for @serverDeleteTitle.
///
/// In en, this message translates to:
/// **'Delete Server'**
String get serverDeleteTitle;
/// No description provided for @serverDeleteConfirmation.
///
/// In en, this message translates to:
/// **'Are you sure you want to delete \"{name}\"?'**
String serverDeleteConfirmation(String name);
/// No description provided for @serverDeleted.
///
/// In en, this message translates to:
/// **'{name} deleted'**
String serverDeleted(String name);
/// No description provided for @addServerTitle.
///
/// In en, this message translates to:
/// **'Add Server'**
String get addServerTitle;
/// No description provided for @addServerNameLabel.
///
/// In en, this message translates to:
/// **'Server Name'**
String get addServerNameLabel;
/// No description provided for @addServerNameHint.
///
/// In en, this message translates to:
/// **'My Library'**
String get addServerNameHint;
/// No description provided for @addServerUrlLabel.
///
/// In en, this message translates to:
/// **'Server URL'**
String get addServerUrlLabel;
/// No description provided for @addServerUrlHint.
///
/// In en, this message translates to:
/// **'https://example.com/opds'**
String get addServerUrlHint;
/// No description provided for @addServerUrlHintKavita.
///
/// In en, this message translates to:
/// **'https://kavita.example.com'**
String get addServerUrlHintKavita;
/// No description provided for @addServerServerType.
///
/// In en, this message translates to:
/// **'Server Type'**
String get addServerServerType;
/// No description provided for @addServerServerTypeSubtitle.
///
/// In en, this message translates to:
/// **'Auto-detected from URL. Change if needed.'**
String get addServerServerTypeSubtitle;
/// No description provided for @serverTypeGeneric.
///
/// In en, this message translates to:
/// **'Generic OPDS'**
String get serverTypeGeneric;
/// No description provided for @serverTypeKavita.
///
/// In en, this message translates to:
/// **'Kavita'**
String get serverTypeKavita;
/// No description provided for @addServerAuth.
///
/// In en, this message translates to:
/// **'Authentication'**
String get addServerAuth;
/// No description provided for @addServerAuthSubtitle.
///
/// In en, this message translates to:
/// **'Credentials for server access'**
String get addServerAuthSubtitle;
/// No description provided for @addServerRequiresAuth.
///
/// In en, this message translates to:
/// **'Requires Authentication'**
String get addServerRequiresAuth;
/// No description provided for @addServerRequiresAuthSubtitle.
///
/// In en, this message translates to:
/// **'Enable if server requires login'**
String get addServerRequiresAuthSubtitle;
/// No description provided for @addServerUsername.
///
/// In en, this message translates to:
/// **'Username'**
String get addServerUsername;
/// No description provided for @addServerPassword.
///
/// In en, this message translates to:
/// **'Password'**
String get addServerPassword;
/// No description provided for @addServerValidationNameRequired.
///
/// In en, this message translates to:
/// **'Please enter a server name'**
String get addServerValidationNameRequired;
/// No description provided for @addServerValidationUrlRequired.
///
/// In en, this message translates to:
/// **'Please enter a server URL'**
String get addServerValidationUrlRequired;
/// No description provided for @addServerValidationUrlInvalid.
///
/// In en, this message translates to:
/// **'Please enter a valid URL'**
String get addServerValidationUrlInvalid;
/// No description provided for @addServerValidationUrlScheme.
///
/// In en, this message translates to:
/// **'URL must start with http:// or https://'**
String get addServerValidationUrlScheme;
/// No description provided for @addServerValidationUsernameRequired.
///
/// In en, this message translates to:
/// **'Please enter a username'**
String get addServerValidationUsernameRequired;
/// No description provided for @addServerValidationPasswordRequired.
///
/// In en, this message translates to:
/// **'Please enter a password'**
String get addServerValidationPasswordRequired;
/// No description provided for @addServerHelp.
///
/// In en, this message translates to:
/// **'Enter the root URL of your OPDS server. Credentials will be securely stored on your device.'**
String get addServerHelp;
/// No description provided for @testConnectionButton.
///
/// In en, this message translates to:
/// **'Test Connection'**
String get testConnectionButton;
/// No description provided for @testConnectionTesting.
///
/// In en, this message translates to:
/// **'Testing...'**
String get testConnectionTesting;
/// No description provided for @testConnectionSuccess.
///
/// In en, this message translates to:
/// **'Connection successful!'**
String get testConnectionSuccess;
/// No description provided for @testConnectionError.
///
/// In en, this message translates to:
/// **'Connection failed: {error}'**
String testConnectionError(String error);
/// No description provided for @addServerButton.
///
/// In en, this message translates to:
/// **'Add Server'**
String get addServerButton;
/// No description provided for @addServerDuplicate.
///
/// In en, this message translates to:
/// **'A server with this URL already exists'**
String get addServerDuplicate;
/// No description provided for @addServerSuccess.
///
/// In en, this message translates to:
/// **'{name} added successfully'**
String addServerSuccess(String name);
/// No description provided for @addServerError.
///
/// In en, this message translates to:
/// **'Error adding server: {error}'**
String addServerError(String error);
/// No description provided for @editServerTitle.
///
/// In en, this message translates to:
/// **'Edit Server'**
String get editServerTitle;
/// No description provided for @editServerNotFound.
///
/// In en, this message translates to:
/// **'Server not found'**
String get editServerNotFound;
/// No description provided for @editServerInfo.
///
/// In en, this message translates to:
/// **'Server Information'**
String get editServerInfo;
/// No description provided for @editServerAdded.
///
/// In en, this message translates to:
/// **'Added'**
String get editServerAdded;
/// No description provided for @editServerLastSynced.
///
/// In en, this message translates to:
/// **'Last Synced'**
String get editServerLastSynced;
/// No description provided for @editServerSaveButton.
///
/// In en, this message translates to:
/// **'Save Changes'**
String get editServerSaveButton;
/// No description provided for @editServerSuccess.
///
/// In en, this message translates to:
/// **'{name} updated successfully'**
String editServerSuccess(String name);
/// No description provided for @editServerError.
///
/// In en, this message translates to:
/// **'Error updating server: {error}'**
String editServerError(String error);
/// No description provided for @editServerErrorLoading.
///
/// In en, this message translates to:
/// **'Error loading server: {error}'**
String editServerErrorLoading(String error);
/// No description provided for @readerError.
///
/// In en, this message translates to:
/// **'Error'**
String get readerError;
/// No description provided for @readerNoStreamLink.
///
/// In en, this message translates to:
/// **'This publication cannot be read (no stream link)'**
String get readerNoStreamLink;
/// No description provided for @readerServerNotFound.
///
/// In en, this message translates to:
/// **'Server not found'**
String get readerServerNotFound;
/// No description provided for @readerErrorLoadingServer.
///
/// In en, this message translates to:
/// **'Error loading server: {error}'**
String readerErrorLoadingServer(String error);
/// No description provided for @readerReadingDirectionWithMode.
///
/// In en, this message translates to:
/// **'Reading direction ({mode})'**
String readerReadingDirectionWithMode(String mode);
/// No description provided for @readerPageOf.
///
/// In en, this message translates to:
/// **'Page {current} of {total}'**
String readerPageOf(int current, int total);
/// No description provided for @readerPagesOf.
///
/// In en, this message translates to:
/// **'Pages {start}-{end} of {total}'**
String readerPagesOf(int start, int end, int total);
/// No description provided for @epubPreparing.
///
/// In en, this message translates to:
/// **'Preparing...'**
String get epubPreparing;
/// No description provided for @epubLoadingFromCache.
///
/// In en, this message translates to:
/// **'Loading from cache...'**
String get epubLoadingFromCache;
/// No description provided for @epubDownloading.
///
/// In en, this message translates to:
/// **'Downloading... {percent}%'**
String epubDownloading(int percent);
/// No description provided for @epubProcessing.
///
/// In en, this message translates to:
/// **'Processing EPUB...'**
String get epubProcessing;
/// No description provided for @epubOpeningReader.
///
/// In en, this message translates to:
/// **'Opening reader...'**
String get epubOpeningReader;
/// No description provided for @epubErrorLoading.
///
/// In en, this message translates to:
/// **'Error loading EPUB: {error}'**
String epubErrorLoading(String error);
/// No description provided for @epubGoBack.
///
/// In en, this message translates to:
/// **'Go Back'**
String get epubGoBack;
/// No description provided for @epubSearch.
///
/// In en, this message translates to:
/// **'Search'**
String get epubSearch;
/// No description provided for @epubSearchHint.
///
/// In en, this message translates to:
/// **'Enter search term...'**
String get epubSearchHint;
/// No description provided for @epubNoResults.
///
/// In en, this message translates to:
/// **'No results found'**
String get epubNoResults;
/// No description provided for @epubSearchResults.
///
/// In en, this message translates to:
/// **'{count} results for \"{query}\"'**
String epubSearchResults(int count, String query);
/// No description provided for @epubSearchFailed.
///
/// In en, this message translates to:
/// **'Search failed: {error}'**
String epubSearchFailed(String error);
/// No description provided for @epubChapters.
///
/// In en, this message translates to:
/// **'Chapters'**
String get epubChapters;
/// No description provided for @epubBack.
///
/// In en, this message translates to:
/// **'Back'**
String get epubBack;
/// No description provided for @epubSettings.
///
/// In en, this message translates to:
/// **'Settings'**
String get epubSettings;
/// No description provided for @epubFontSize.
///
/// In en, this message translates to:
/// **'Font Size'**
String get epubFontSize;
/// No description provided for @epubFontSizeReset.
///
/// In en, this message translates to:
/// **'Reset'**
String get epubFontSizeReset;
/// No description provided for @libraryTitle.
///
/// In en, this message translates to:
/// **'Library'**
String get libraryTitle;
/// No description provided for @libraryRecentlyRead.
///
/// In en, this message translates to:
/// **'Recently Read'**
String get libraryRecentlyRead;
/// No description provided for @libraryNoServers.
///
/// In en, this message translates to:
/// **'No Servers Configured'**
String get libraryNoServers;
/// No description provided for @libraryNoServersSubtitle.
///
/// In en, this message translates to:
/// **'Add an OPDS server to start reading books'**
String get libraryNoServersSubtitle;
/// No description provided for @libraryAddServer.
///
/// In en, this message translates to:
/// **'Add Server'**
String get libraryAddServer;
/// No description provided for @libraryNoHistory.
///
/// In en, this message translates to:
/// **'No Reading History'**
String get libraryNoHistory;
/// No description provided for @libraryNoHistorySubtitle.
///
/// In en, this message translates to:
/// **'Start reading a book to see it here'**
String get libraryNoHistorySubtitle;
/// No description provided for @libraryBrowseServers.
///
/// In en, this message translates to:
/// **'Browse Servers'**
String get libraryBrowseServers;
/// No description provided for @libraryErrorLoading.
///
/// In en, this message translates to:
/// **'Error Loading Library'**
String get libraryErrorLoading;
/// No description provided for @browserLoading.
///
/// In en, this message translates to:
/// **'Loading...'**
String get browserLoading;
/// No description provided for @browserLibrary.
///
/// In en, this message translates to:
/// **'Library'**
String get browserLibrary;
/// No description provided for @browserNoContent.
///
/// In en, this message translates to:
/// **'No Content Available'**
String get browserNoContent;
/// No description provided for @browserLibraryEmpty.
///
/// In en, this message translates to:
/// **'This library appears to be empty'**
String get browserLibraryEmpty;
/// No description provided for @browserCollectionEmpty.
///
/// In en, this message translates to:
/// **'This collection appears to be empty'**
String get browserCollectionEmpty;
/// No description provided for @browserFailedToLoadLibrary.
///
/// In en, this message translates to:
/// **'Failed to Load Library'**
String get browserFailedToLoadLibrary;
/// No description provided for @browserFailedToLoadFeed.
///
/// In en, this message translates to:
/// **'Failed to Load Feed'**
String get browserFailedToLoadFeed;
/// No description provided for @browserRetry.
///
/// In en, this message translates to:
/// **'Retry'**
String get browserRetry;
/// No description provided for @browserFailedToLoadMore.
///
/// In en, this message translates to:
/// **'Failed to load more: {error}'**
String browserFailedToLoadMore(String error);
/// No description provided for @browserOfflineEpubNotCached.
///
/// In en, this message translates to:
/// **'This EPUB is not cached. You may not be able to read it offline.'**
String get browserOfflineEpubNotCached;
/// No description provided for @browserOfflinePagesWarning.
///
/// In en, this message translates to:
/// **'You are offline. Pages may not load properly.'**
String get browserOfflinePagesWarning;
/// No description provided for @publicationPages.
///
/// In en, this message translates to:
/// **'{count} pages'**
String publicationPages(int count);
/// No description provided for @publicationReadingProgress.
///
/// In en, this message translates to:
/// **'Reading Progress'**
String get publicationReadingProgress;
/// No description provided for @publicationPageOfTotal.
///
/// In en, this message translates to:
/// **'Page {current} of {total}'**
String publicationPageOfTotal(int current, int total);
/// No description provided for @publicationLastRead.
///
/// In en, this message translates to:
/// **'Last read: {time}'**
String publicationLastRead(String time);
/// No description provided for @publicationCannotRead.
///
/// In en, this message translates to:
/// **'This publication cannot be read in the app'**
String get publicationCannotRead;
/// No description provided for @publicationContinueFromPage.
///
/// In en, this message translates to:
/// **'Continue reading from page {page}'**
String publicationContinueFromPage(int page);
/// No description provided for @publicationStartReading.
///
/// In en, this message translates to:
/// **'Start Reading'**
String get publicationStartReading;
/// No description provided for @publicationContinueReading.
///
/// In en, this message translates to:
/// **'Continue Reading'**
String get publicationContinueReading;
/// No description provided for @publicationReadAgain.
///
/// In en, this message translates to:
/// **'Read Again'**
String get publicationReadAgain;
/// No description provided for @publicationStartFromBeginning.
///
/// In en, this message translates to:
/// **'Start from Beginning'**
String get publicationStartFromBeginning;
/// No description provided for @publicationCollection.
///
/// In en, this message translates to:
/// **'Collection'**
String get publicationCollection;
/// No description provided for @recentlyReadPublicationNotFound.
///
/// In en, this message translates to:
/// **'Publication not found'**
String get recentlyReadPublicationNotFound;
/// No description provided for @recentlyReadErrorLoading.
///
/// In en, this message translates to:
/// **'Error loading publication'**
String get recentlyReadErrorLoading;
/// No description provided for @recentlyReadViewRawData.
///
/// In en, this message translates to:
/// **'View raw data'**
String get recentlyReadViewRawData;
/// No description provided for @recentlyReadRemove.
///
/// In en, this message translates to:
/// **'Remove from Recently Read'**
String get recentlyReadRemove;
/// No description provided for @recentlyReadRemoveTitle.
///
/// In en, this message translates to:
/// **'Remove from Recently Read'**
String get recentlyReadRemoveTitle;
/// No description provided for @recentlyReadRemoveConfirmation.
///
/// In en, this message translates to:
/// **'Remove \"{title}\" from your reading history?\n\nThis will not delete the book from your library.'**
String recentlyReadRemoveConfirmation(String title);
/// No description provided for @recentlyReadRemoved.
///
/// In en, this message translates to:
/// **'Removed from Recently Read'**
String get recentlyReadRemoved;
/// No description provided for @recentlyReadRemoveFailed.
///
/// In en, this message translates to:
/// **'Failed to remove: {error}'**
String recentlyReadRemoveFailed(String error);
/// No description provided for @recentlyReadRawData.
///
/// In en, this message translates to:
/// **'Raw Data'**
String get recentlyReadRawData;
/// No description provided for @recentlyReadOfflineEpubNotCached.
///
/// In en, this message translates to:
/// **'This EPUB is not cached. Connect to internet to download.'**
String get recentlyReadOfflineEpubNotCached;
/// No description provided for @recentlyReadOfflinePagesWarning.
///
/// In en, this message translates to:
/// **'You are offline. Pages may not load.'**
String get recentlyReadOfflinePagesWarning;
/// No description provided for @recentlyReadUnsupportedFormat.
///
/// In en, this message translates to:
/// **'Unsupported format'**
String get recentlyReadUnsupportedFormat;
/// No description provided for @serverCardEdit.
///
/// In en, this message translates to:
/// **'Edit'**
String get serverCardEdit;
/// No description provided for @serverCardDelete.
///
/// In en, this message translates to:
/// **'Delete'**
String get serverCardDelete;
/// No description provided for @serverCardAuthenticated.
///
/// In en, this message translates to:
/// **'Authenticated'**
String get serverCardAuthenticated;
/// No description provided for @serverCardLastSynced.
///
/// In en, this message translates to:
/// **'Last synced: {time}'**
String serverCardLastSynced(String time);
/// No description provided for @offlineSemanticLabel.
///
/// In en, this message translates to:
/// **'Offline'**
String get offlineSemanticLabel;
/// No description provided for @nextInSeriesNext.
///
/// In en, this message translates to:
/// **'Next'**
String get nextInSeriesNext;
/// No description provided for @nextInSeriesFinished.
///
/// In en, this message translates to:
/// **'Finished'**
String get nextInSeriesFinished;
/// No description provided for @nextInSeriesBackToDetails.
///
/// In en, this message translates to:
/// **'Back to details'**
String get nextInSeriesBackToDetails;
/// No description provided for @nextInSeriesBackToLibrary.
///
/// In en, this message translates to:
/// **'Back to library'**
String get nextInSeriesBackToLibrary;
/// No description provided for @routeNotFound.
///
/// In en, this message translates to:
/// **'Page not found: {uri}'**
String routeNotFound(String uri);
/// No description provided for @commonCancel.
///
/// In en, this message translates to:
/// **'Cancel'**
String get commonCancel;
/// No description provided for @commonDelete.
///
/// In en, this message translates to:
/// **'Delete'**
String get commonDelete;
/// No description provided for @commonRemove.
///
/// In en, this message translates to:
/// **'Remove'**
String get commonRemove;
/// No description provided for @timeJustNow.
///
/// In en, this message translates to:
/// **'just now'**
String get timeJustNow;
/// No description provided for @timeMinutesAgo.
///
/// In en, this message translates to:
/// **'{minutes}m ago'**
String timeMinutesAgo(int minutes);
/// No description provided for @timeHoursAgo.
///
/// In en, this message translates to:
/// **'{hours}h ago'**
String timeHoursAgo(int hours);
/// No description provided for @timeDaysAgo.
///
/// In en, this message translates to:
/// **'{days}d ago'**
String timeDaysAgo(int days);
/// No description provided for @timeWeeksAgo.
///
/// In en, this message translates to:
/// **'{weeks}w ago'**
String timeWeeksAgo(int weeks);
/// No description provided for @timeMonthsAgo.
///
/// In en, this message translates to:
/// **'{months}mo ago'**
String timeMonthsAgo(int months);
/// No description provided for @timeYearsAgo.
///
/// In en, this message translates to:
/// **'{years}y ago'**
String timeYearsAgo(int years);
/// No description provided for @timeToday.
///
/// In en, this message translates to:
/// **'Today'**
String get timeToday;
/// No description provided for @timeYesterday.
///
/// In en, this message translates to:
/// **'Yesterday'**
String get timeYesterday;
/// No description provided for @timeMinAgo.
///
/// In en, this message translates to:
/// **'{minutes} min ago'**
String timeMinAgo(int minutes);
/// No description provided for @timeHoursAgoLong.
///
/// In en, this message translates to:
/// **'{count} {count, plural, =1{hour} other{hours}} ago'**
String timeHoursAgoLong(int count);
/// No description provided for @timeDaysAgoLong.
///
/// In en, this message translates to:
/// **'{days} days ago'**
String timeDaysAgoLong(int days);
/// No description provided for @downloadAll.
///
/// In en, this message translates to:
/// **'Download All'**
String get downloadAll;
/// No description provided for @downloadChapter.
///
/// In en, this message translates to:
/// **'Download Chapter'**
String get downloadChapter;
/// No description provided for @downloadCancel.
///
/// In en, this message translates to:
/// **'Cancel Download'**
String get downloadCancel;
/// No description provided for @downloadDelete.
///
/// In en, this message translates to:
/// **'Delete Download'**
String get downloadDelete;
/// No description provided for @downloadDeleteSeries.
///
/// In en, this message translates to:
/// **'Delete Downloaded Series'**
String get downloadDeleteSeries;
/// No description provided for @downloadDeleteSeriesConfirmation.
///
/// In en, this message translates to:
/// **'Delete \"{title}\" and all its downloaded files? This cannot be undone.'**
String downloadDeleteSeriesConfirmation(String title);
/// No description provided for @downloadDeleteChapterConfirmation.
///
/// In en, this message translates to:
/// **'Delete the downloaded file for \"{title}\"?'**
String downloadDeleteChapterConfirmation(String title);
/// No description provided for @downloadStarting.
///
/// In en, this message translates to:
/// **'Starting download...'**
String get downloadStarting;
/// No description provided for @downloadComplete.
///
/// In en, this message translates to:
/// **'Download complete'**
String get downloadComplete;
/// No description provided for @downloadFailed.
///
/// In en, this message translates to:
/// **'Download failed'**
String get downloadFailed;
/// No description provided for @downloadCancelled.
///
/// In en, this message translates to:
/// **'Download cancelled'**
String get downloadCancelled;
/// No description provided for @downloadInProgress.
///
/// In en, this message translates to:
/// **'Downloading...'**
String get downloadInProgress;
/// No description provided for @downloadChaptersCount.
///
/// In en, this message translates to:
/// **'{downloaded}/{total} chapters'**
String downloadChaptersCount(int downloaded, int total);
/// No description provided for @downloadConfirmTitle.
///
/// In en, this message translates to:
/// **'Download Series'**
String get downloadConfirmTitle;
/// No description provided for @downloadConfirmMessage.
///
/// In en, this message translates to:
/// **'Download {count} chapters for offline reading?'**
String downloadConfirmMessage(int count);
/// No description provided for @downloadConfirmStart.
///
/// In en, this message translates to:
/// **'Download'**
String get downloadConfirmStart;
/// No description provided for @libraryDownloaded.
///
/// In en, this message translates to:
/// **'Downloaded'**
String get libraryDownloaded;
/// No description provided for @libraryNoDownloads.
///
/// In en, this message translates to:
/// **'No Downloads'**
String get libraryNoDownloads;
/// No description provided for @libraryNoDownloadsSubtitle.
///
/// In en, this message translates to:
/// **'Download series from the browse screen for offline reading'**
String get libraryNoDownloadsSubtitle;
/// No description provided for @downloadedSeriesDetailTitle.
///
/// In en, this message translates to:
/// **'Downloaded Series'**
String get downloadedSeriesDetailTitle;
/// No description provided for @downloadedSeriesChapters.
///
/// In en, this message translates to:
/// **'{count} chapters'**
String downloadedSeriesChapters(int count);
/// No description provided for @downloadedChapterReady.
///
/// In en, this message translates to:
/// **'Ready to read'**
String get downloadedChapterReady;
/// No description provided for @downloadedChapterPending.
///
/// In en, this message translates to:
/// **'Pending'**
String get downloadedChapterPending;
/// No description provided for @downloadedChapterFailed.
///
/// In en, this message translates to:
/// **'Failed'**
String get downloadedChapterFailed;
/// No description provided for @downloadRetryAll.
///
/// In en, this message translates to:
/// **'Retry all failed'**
String get downloadRetryAll;
/// No description provided for @downloadRetryFailed.
///
/// In en, this message translates to:
/// **'Failed - tap to retry'**
String get downloadRetryFailed;
/// No description provided for @downloadingPages.
///
/// In en, this message translates to:
/// **'Page {downloaded}/{total}'**
String downloadingPages(int downloaded, int total);
/// No description provided for @downloadFailedCount.
///
/// In en, this message translates to:
/// **'{count} failed'**
String downloadFailedCount(int count);
/// No description provided for @settingsDownloadedContent.
///
/// In en, this message translates to:
/// **'Downloaded content'**
String get settingsDownloadedContent;
/// No description provided for @settingsDownloadedContentSubtitle.
///
/// In en, this message translates to:
/// **'Manage offline downloads'**
String get settingsDownloadedContentSubtitle;
/// No description provided for @settingsClearAllDownloads.
///
/// In en, this message translates to:
/// **'Clear all downloads'**
String get settingsClearAllDownloads;
/// No description provided for @settingsClearAllDownloadsConfirmation.
///
/// In en, this message translates to:
/// **'Delete all downloaded content? This cannot be undone.'**
String get settingsClearAllDownloadsConfirmation;
/// No description provided for @settingsDownloadSize.
///
/// In en, this message translates to:
/// **'Using {size}'**
String settingsDownloadSize(String size);
/// No description provided for @settingsDownloadsCleared.
///
/// In en, this message translates to:
/// **'All downloads cleared'**
String get settingsDownloadsCleared;
}
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
@override
Future<AppLocalizations> load(Locale locale) {
return SynchronousFuture<AppLocalizations>(lookupAppLocalizations(locale));
}
@override
bool isSupported(Locale locale) =>
<String>['en', 'es'].contains(locale.languageCode);
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
AppLocalizations lookupAppLocalizations(Locale locale) {
// Lookup logic when only language code is specified.
switch (locale.languageCode) {
case 'en':
return AppLocalizationsEn();
case 'es':
return AppLocalizationsEs();
}
throw FlutterError(
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.');
}