提交 Nontonki 短剧原型,准备推送到远程仓库。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
VickyandCursor committed 2026-10-13 16:23:08 +08:00
commit b1f6ce4bf9
148 files changed
+11175

No files matched your search

+134
View File
@@ -0,0 +1,134 @@
{
"@@locale": "en",
"appName": "Nontonki",
"demo": "DEMO",
"homeHeadline": "Watch now",
"homeSubtitle": "Free short drama preview.",
"mediaNotice": "User-provided local demo video · Free preview",
"featuredDemo": "FEATURED · TECHNICAL DEMO",
"demoTitle": "The Signal",
"demoSynopsis": "A short local video preview. More episodes can be added when media is available.",
"homeTab": "Home",
"openQuickMenu": "Open quick menu",
"quickAccess": "Quick access",
"currentSeries": "Current series",
"discoverTab": "Discover",
"searchDiscover": "Search dramas, actors, genres...",
"featured": "Featured",
"suspense": "Suspense",
"romance": "Romance",
"actionGenre": "Action",
"filter": "Filter",
"topCharts": "Top Charts",
"newReleases": "New Releases",
"trendingMicroDramas": "Trending Micro-Dramas",
"seeAll": "See All",
"artworkOnly": "Artwork",
"artworkOnlyNotice": "This is a visual catalog item. No video is available yet.",
"videoPending": "Video pending",
"watchNow": "Watch free",
"noSearchResults": "No matching dramas.",
"demoCatalogNotice": "Three demo dramas share the same local video.",
"myTab": "My",
"localViewer": "Local Viewer",
"localDemoProfile": "Local demo profile",
"continueWatching": "Continue Watching",
"watchedPercent": "Watched {percent}%",
"@watchedPercent": {"placeholders": {"percent": {"type": "int"}}},
"resume": "Resume",
"history": "History",
"watchlist": "Watchlist",
"likedTab": "Liked",
"all": "All",
"inProgress": "In Progress",
"completed": "Completed",
"noSavedShows": "No shows here yet.",
"preferences": "Preferences",
"appLanguage": "App Language",
"followingTab": "Following",
"animatedTab": "Animated",
"recommendedTab": "Recommended",
"noCategoryDramas": "No dramas in this category yet.",
"trendingTab": "Trending",
"liveActionTab": "Live Action",
"search": "Search",
"free": "Free",
"mute": "Mute",
"unmute": "Unmute",
"like": "Like",
"save": "Save",
"comments": "Comments",
"share": "Share",
"localOnlyComments": "Only visible on this device",
"noComments": "No comments yet.",
"writeComment": "Write a comment",
"postComment": "Post",
"shareFailed": "Could not open the share sheet.",
"nowPlaying": "Playing now",
"watchFullscreen": "Watch in landscape",
"exitFullscreen": "Exit fullscreen",
"pictureInPicture": "Picture in picture",
"pipUnavailable": "Picture in picture is unavailable on this device",
"originalTag": "Original",
"dramaTag": "Short drama",
"episodeLabel": "Episode {number}",
"@episodeLabel": {"placeholders": {"number": {"type": "int"}}},
"exploreSeries": "Explore series",
"episodeCount": "{count} EPISODES",
"@episodeCount": {"placeholders": {"count": {"type": "int"}}},
"technicalDemoCount": "FREE PREVIEW · {count} EPISODES",
"@technicalDemoCount": {"placeholders": {"count": {"type": "int"}}},
"episodes": "Episodes",
"watchEpisodeOne": "Watch episode 1",
"continueEpisode": "Continue episode {number}",
"@continueEpisode": {"placeholders": {"number": {"type": "int"}}},
"freeTestMedia": "Same demo clip · free",
"lockedStoreUnavailable": "Locked · store unavailable",
"freeTestClip": "Free test clip",
"locked": "Locked",
"freeSamplesNotice": "Two free samples · store setup pending",
"demoTestMedia": "FREE · SAME DEMO CLIP",
"episodeProgress": "EPISODE {number} / {total}",
"@episodeProgress": {"placeholders": {"number": {"type": "int"}, "total": {"type": "int"}}},
"testVideoNotice": "Self-generated technical test video",
"lockedTitle": "Episode {number} is locked",
"@lockedTitle": {"placeholders": {"number": {"type": "int"}}},
"lockedBody": "Unlocking will be available after store and verification setup. This demo does not process payments.",
"playbackError": "This clip could not be played.",
"catalogError": "The catalog could not be loaded.",
"noStories": "No stories available yet.",
"retry": "Retry",
"backToSeries": "Back to series",
"nextEpisode": "Next episode",
"pause": "Pause",
"play": "Play",
"seekVideo": "Seek video",
"seekFailed": "Could not change playback position.",
"captions": "Captions",
"captionsOff": "Captions off",
"englishCaptions": "English captions",
"chineseCaptions": "Chinese captions",
"language": "Language",
"systemLanguage": "System",
"english": "English",
"simplifiedChinese": "简体中文",
"episodeOneTitle": "First Light",
"episodeTwoTitle": "A New Frequency",
"episodeThreeTitle": "Crossing Over",
"episodeFourTitle": "After the Echo",
"dramaSignalTitle": "The Signal",
"dramaSignalSynopsis": "A demo series for vertical playback. Every episode reuses one local clip.",
"dramaCityTitle": "City Lights & Velvet Nights",
"dramaCitySynopsis": "A demo romance series. The same local video is used to try switching and resume.",
"dramaVengeanceTitle": "Vengeance Rising",
"dramaVengeanceSynopsis": "A demo action series. The same local video is used to try switching and resume.",
"dramaEchoesTitle": "Echoes of Fate",
"genreSuspenseMystery": "Suspense · Mystery",
"genreUrbanRomance": "Urban Romance",
"genreActionThriller": "Action · Thriller",
"genreDramaMystery": "Drama · Mystery",
"continueWatchingHeading": "CONTINUE WATCHING",
"preferencesHeading": "PREFERENCES",
"brandMark": "NONTONKI · DEMO",
"shareFooter": "Nontonki demo"
}
+878
View File
@@ -0,0 +1,878 @@
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_zh.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, you’ll need to edit this
/// file.
///
/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file.
/// Then, in the Project Navigator, open the Info.plist file under the Runner
/// project’s 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('zh'),
];
/// No description provided for @appName.
///
/// In en, this message translates to:
/// **'Nontonki'**
String get appName;
/// No description provided for @demo.
///
/// In en, this message translates to:
/// **'DEMO'**
String get demo;
/// No description provided for @homeHeadline.
///
/// In en, this message translates to:
/// **'Watch now'**
String get homeHeadline;
/// No description provided for @homeSubtitle.
///
/// In en, this message translates to:
/// **'Free short drama preview.'**
String get homeSubtitle;
/// No description provided for @mediaNotice.
///
/// In en, this message translates to:
/// **'User-provided local demo video · Free preview'**
String get mediaNotice;
/// No description provided for @featuredDemo.
///
/// In en, this message translates to:
/// **'FEATURED · TECHNICAL DEMO'**
String get featuredDemo;
/// No description provided for @demoTitle.
///
/// In en, this message translates to:
/// **'The Signal'**
String get demoTitle;
/// No description provided for @demoSynopsis.
///
/// In en, this message translates to:
/// **'A short local video preview. More episodes can be added when media is available.'**
String get demoSynopsis;
/// No description provided for @homeTab.
///
/// In en, this message translates to:
/// **'Home'**
String get homeTab;
/// No description provided for @openQuickMenu.
///
/// In en, this message translates to:
/// **'Open quick menu'**
String get openQuickMenu;
/// No description provided for @quickAccess.
///
/// In en, this message translates to:
/// **'Quick access'**
String get quickAccess;
/// No description provided for @currentSeries.
///
/// In en, this message translates to:
/// **'Current series'**
String get currentSeries;
/// No description provided for @discoverTab.
///
/// In en, this message translates to:
/// **'Discover'**
String get discoverTab;
/// No description provided for @searchDiscover.
///
/// In en, this message translates to:
/// **'Search dramas, actors, genres...'**
String get searchDiscover;
/// No description provided for @featured.
///
/// In en, this message translates to:
/// **'Featured'**
String get featured;
/// No description provided for @suspense.
///
/// In en, this message translates to:
/// **'Suspense'**
String get suspense;
/// No description provided for @romance.
///
/// In en, this message translates to:
/// **'Romance'**
String get romance;
/// No description provided for @actionGenre.
///
/// In en, this message translates to:
/// **'Action'**
String get actionGenre;
/// No description provided for @filter.
///
/// In en, this message translates to:
/// **'Filter'**
String get filter;
/// No description provided for @topCharts.
///
/// In en, this message translates to:
/// **'Top Charts'**
String get topCharts;
/// No description provided for @newReleases.
///
/// In en, this message translates to:
/// **'New Releases'**
String get newReleases;
/// No description provided for @trendingMicroDramas.
///
/// In en, this message translates to:
/// **'Trending Micro-Dramas'**
String get trendingMicroDramas;
/// No description provided for @seeAll.
///
/// In en, this message translates to:
/// **'See All'**
String get seeAll;
/// No description provided for @artworkOnly.
///
/// In en, this message translates to:
/// **'Artwork'**
String get artworkOnly;
/// No description provided for @artworkOnlyNotice.
///
/// In en, this message translates to:
/// **'This is a visual catalog item. No video is available yet.'**
String get artworkOnlyNotice;
/// No description provided for @videoPending.
///
/// In en, this message translates to:
/// **'Video pending'**
String get videoPending;
/// No description provided for @watchNow.
///
/// In en, this message translates to:
/// **'Watch free'**
String get watchNow;
/// No description provided for @noSearchResults.
///
/// In en, this message translates to:
/// **'No matching dramas.'**
String get noSearchResults;
/// No description provided for @demoCatalogNotice.
///
/// In en, this message translates to:
/// **'Three demo dramas share the same local video.'**
String get demoCatalogNotice;
/// No description provided for @myTab.
///
/// In en, this message translates to:
/// **'My'**
String get myTab;
/// No description provided for @localViewer.
///
/// In en, this message translates to:
/// **'Local Viewer'**
String get localViewer;
/// No description provided for @localDemoProfile.
///
/// In en, this message translates to:
/// **'Local demo profile'**
String get localDemoProfile;
/// No description provided for @continueWatching.
///
/// In en, this message translates to:
/// **'Continue Watching'**
String get continueWatching;
/// No description provided for @watchedPercent.
///
/// In en, this message translates to:
/// **'Watched {percent}%'**
String watchedPercent(int percent);
/// No description provided for @resume.
///
/// In en, this message translates to:
/// **'Resume'**
String get resume;
/// No description provided for @history.
///
/// In en, this message translates to:
/// **'History'**
String get history;
/// No description provided for @watchlist.
///
/// In en, this message translates to:
/// **'Watchlist'**
String get watchlist;
/// No description provided for @likedTab.
///
/// In en, this message translates to:
/// **'Liked'**
String get likedTab;
/// No description provided for @all.
///
/// In en, this message translates to:
/// **'All'**
String get all;
/// No description provided for @inProgress.
///
/// In en, this message translates to:
/// **'In Progress'**
String get inProgress;
/// No description provided for @completed.
///
/// In en, this message translates to:
/// **'Completed'**
String get completed;
/// No description provided for @noSavedShows.
///
/// In en, this message translates to:
/// **'No shows here yet.'**
String get noSavedShows;
/// No description provided for @preferences.
///
/// In en, this message translates to:
/// **'Preferences'**
String get preferences;
/// No description provided for @appLanguage.
///
/// In en, this message translates to:
/// **'App Language'**
String get appLanguage;
/// No description provided for @followingTab.
///
/// In en, this message translates to:
/// **'Following'**
String get followingTab;
/// No description provided for @animatedTab.
///
/// In en, this message translates to:
/// **'Animated'**
String get animatedTab;
/// No description provided for @recommendedTab.
///
/// In en, this message translates to:
/// **'Recommended'**
String get recommendedTab;
/// No description provided for @noCategoryDramas.
///
/// In en, this message translates to:
/// **'No dramas in this category yet.'**
String get noCategoryDramas;
/// No description provided for @trendingTab.
///
/// In en, this message translates to:
/// **'Trending'**
String get trendingTab;
/// No description provided for @liveActionTab.
///
/// In en, this message translates to:
/// **'Live Action'**
String get liveActionTab;
/// No description provided for @search.
///
/// In en, this message translates to:
/// **'Search'**
String get search;
/// No description provided for @free.
///
/// In en, this message translates to:
/// **'Free'**
String get free;
/// No description provided for @mute.
///
/// In en, this message translates to:
/// **'Mute'**
String get mute;
/// No description provided for @unmute.
///
/// In en, this message translates to:
/// **'Unmute'**
String get unmute;
/// No description provided for @like.
///
/// In en, this message translates to:
/// **'Like'**
String get like;
/// No description provided for @save.
///
/// In en, this message translates to:
/// **'Save'**
String get save;
/// No description provided for @comments.
///
/// In en, this message translates to:
/// **'Comments'**
String get comments;
/// No description provided for @share.
///
/// In en, this message translates to:
/// **'Share'**
String get share;
/// No description provided for @localOnlyComments.
///
/// In en, this message translates to:
/// **'Only visible on this device'**
String get localOnlyComments;
/// No description provided for @noComments.
///
/// In en, this message translates to:
/// **'No comments yet.'**
String get noComments;
/// No description provided for @writeComment.
///
/// In en, this message translates to:
/// **'Write a comment'**
String get writeComment;
/// No description provided for @postComment.
///
/// In en, this message translates to:
/// **'Post'**
String get postComment;
/// No description provided for @shareFailed.
///
/// In en, this message translates to:
/// **'Could not open the share sheet.'**
String get shareFailed;
/// No description provided for @nowPlaying.
///
/// In en, this message translates to:
/// **'Playing now'**
String get nowPlaying;
/// No description provided for @watchFullscreen.
///
/// In en, this message translates to:
/// **'Watch in landscape'**
String get watchFullscreen;
/// No description provided for @exitFullscreen.
///
/// In en, this message translates to:
/// **'Exit fullscreen'**
String get exitFullscreen;
/// No description provided for @pictureInPicture.
///
/// In en, this message translates to:
/// **'Picture in picture'**
String get pictureInPicture;
/// No description provided for @pipUnavailable.
///
/// In en, this message translates to:
/// **'Picture in picture is unavailable on this device'**
String get pipUnavailable;
/// No description provided for @originalTag.
///
/// In en, this message translates to:
/// **'Original'**
String get originalTag;
/// No description provided for @dramaTag.
///
/// In en, this message translates to:
/// **'Short drama'**
String get dramaTag;
/// No description provided for @episodeLabel.
///
/// In en, this message translates to:
/// **'Episode {number}'**
String episodeLabel(int number);
/// No description provided for @exploreSeries.
///
/// In en, this message translates to:
/// **'Explore series'**
String get exploreSeries;
/// No description provided for @episodeCount.
///
/// In en, this message translates to:
/// **'{count} EPISODES'**
String episodeCount(int count);
/// No description provided for @technicalDemoCount.
///
/// In en, this message translates to:
/// **'FREE PREVIEW · {count} EPISODES'**
String technicalDemoCount(int count);
/// No description provided for @episodes.
///
/// In en, this message translates to:
/// **'Episodes'**
String get episodes;
/// No description provided for @watchEpisodeOne.
///
/// In en, this message translates to:
/// **'Watch episode 1'**
String get watchEpisodeOne;
/// No description provided for @continueEpisode.
///
/// In en, this message translates to:
/// **'Continue episode {number}'**
String continueEpisode(int number);
/// No description provided for @freeTestMedia.
///
/// In en, this message translates to:
/// **'Same demo clip · free'**
String get freeTestMedia;
/// No description provided for @lockedStoreUnavailable.
///
/// In en, this message translates to:
/// **'Locked · store unavailable'**
String get lockedStoreUnavailable;
/// No description provided for @freeTestClip.
///
/// In en, this message translates to:
/// **'Free test clip'**
String get freeTestClip;
/// No description provided for @locked.
///
/// In en, this message translates to:
/// **'Locked'**
String get locked;
/// No description provided for @freeSamplesNotice.
///
/// In en, this message translates to:
/// **'Two free samples · store setup pending'**
String get freeSamplesNotice;
/// No description provided for @demoTestMedia.
///
/// In en, this message translates to:
/// **'FREE · SAME DEMO CLIP'**
String get demoTestMedia;
/// No description provided for @episodeProgress.
///
/// In en, this message translates to:
/// **'EPISODE {number} / {total}'**
String episodeProgress(int number, int total);
/// No description provided for @testVideoNotice.
///
/// In en, this message translates to:
/// **'Self-generated technical test video'**
String get testVideoNotice;
/// No description provided for @lockedTitle.
///
/// In en, this message translates to:
/// **'Episode {number} is locked'**
String lockedTitle(int number);
/// No description provided for @lockedBody.
///
/// In en, this message translates to:
/// **'Unlocking will be available after store and verification setup. This demo does not process payments.'**
String get lockedBody;
/// No description provided for @playbackError.
///
/// In en, this message translates to:
/// **'This clip could not be played.'**
String get playbackError;
/// No description provided for @catalogError.
///
/// In en, this message translates to:
/// **'The catalog could not be loaded.'**
String get catalogError;
/// No description provided for @noStories.
///
/// In en, this message translates to:
/// **'No stories available yet.'**
String get noStories;
/// No description provided for @retry.
///
/// In en, this message translates to:
/// **'Retry'**
String get retry;
/// No description provided for @backToSeries.
///
/// In en, this message translates to:
/// **'Back to series'**
String get backToSeries;
/// No description provided for @nextEpisode.
///
/// In en, this message translates to:
/// **'Next episode'**
String get nextEpisode;
/// No description provided for @pause.
///
/// In en, this message translates to:
/// **'Pause'**
String get pause;
/// No description provided for @play.
///
/// In en, this message translates to:
/// **'Play'**
String get play;
/// No description provided for @seekVideo.
///
/// In en, this message translates to:
/// **'Seek video'**
String get seekVideo;
/// No description provided for @seekFailed.
///
/// In en, this message translates to:
/// **'Could not change playback position.'**
String get seekFailed;
/// No description provided for @captions.
///
/// In en, this message translates to:
/// **'Captions'**
String get captions;
/// No description provided for @captionsOff.
///
/// In en, this message translates to:
/// **'Captions off'**
String get captionsOff;
/// No description provided for @englishCaptions.
///
/// In en, this message translates to:
/// **'English captions'**
String get englishCaptions;
/// No description provided for @chineseCaptions.
///
/// In en, this message translates to:
/// **'Chinese captions'**
String get chineseCaptions;
/// No description provided for @language.
///
/// In en, this message translates to:
/// **'Language'**
String get language;
/// No description provided for @systemLanguage.
///
/// In en, this message translates to:
/// **'System'**
String get systemLanguage;
/// No description provided for @english.
///
/// In en, this message translates to:
/// **'English'**
String get english;
/// No description provided for @simplifiedChinese.
///
/// In en, this message translates to:
/// **'简体中文'**
String get simplifiedChinese;
/// No description provided for @episodeOneTitle.
///
/// In en, this message translates to:
/// **'First Light'**
String get episodeOneTitle;
/// No description provided for @episodeTwoTitle.
///
/// In en, this message translates to:
/// **'A New Frequency'**
String get episodeTwoTitle;
/// No description provided for @episodeThreeTitle.
///
/// In en, this message translates to:
/// **'Crossing Over'**
String get episodeThreeTitle;
/// No description provided for @episodeFourTitle.
///
/// In en, this message translates to:
/// **'After the Echo'**
String get episodeFourTitle;
/// No description provided for @dramaSignalTitle.
///
/// In en, this message translates to:
/// **'The Signal'**
String get dramaSignalTitle;
/// No description provided for @dramaSignalSynopsis.
///
/// In en, this message translates to:
/// **'A demo series for vertical playback. Every episode reuses one local clip.'**
String get dramaSignalSynopsis;
/// No description provided for @dramaCityTitle.
///
/// In en, this message translates to:
/// **'City Lights & Velvet Nights'**
String get dramaCityTitle;
/// No description provided for @dramaCitySynopsis.
///
/// In en, this message translates to:
/// **'A demo romance series. The same local video is used to try switching and resume.'**
String get dramaCitySynopsis;
/// No description provided for @dramaVengeanceTitle.
///
/// In en, this message translates to:
/// **'Vengeance Rising'**
String get dramaVengeanceTitle;
/// No description provided for @dramaVengeanceSynopsis.
///
/// In en, this message translates to:
/// **'A demo action series. The same local video is used to try switching and resume.'**
String get dramaVengeanceSynopsis;
/// No description provided for @dramaEchoesTitle.
///
/// In en, this message translates to:
/// **'Echoes of Fate'**
String get dramaEchoesTitle;
/// No description provided for @genreSuspenseMystery.
///
/// In en, this message translates to:
/// **'Suspense · Mystery'**
String get genreSuspenseMystery;
/// No description provided for @genreUrbanRomance.
///
/// In en, this message translates to:
/// **'Urban Romance'**
String get genreUrbanRomance;
/// No description provided for @genreActionThriller.
///
/// In en, this message translates to:
/// **'Action · Thriller'**
String get genreActionThriller;
/// No description provided for @genreDramaMystery.
///
/// In en, this message translates to:
/// **'Drama · Mystery'**
String get genreDramaMystery;
/// No description provided for @continueWatchingHeading.
///
/// In en, this message translates to:
/// **'CONTINUE WATCHING'**
String get continueWatchingHeading;
/// No description provided for @preferencesHeading.
///
/// In en, this message translates to:
/// **'PREFERENCES'**
String get preferencesHeading;
/// No description provided for @brandMark.
///
/// In en, this message translates to:
/// **'NONTONKI · DEMO'**
String get brandMark;
/// No description provided for @shareFooter.
///
/// In en, this message translates to:
/// **'Nontonki demo'**
String get shareFooter;
}
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', 'zh'].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 'zh':
return AppLocalizationsZh();
}
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.',
);
}
+404
View File
@@ -0,0 +1,404 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String get appName => 'Nontonki';
@override
String get demo => 'DEMO';
@override
String get homeHeadline => 'Watch now';
@override
String get homeSubtitle => 'Free short drama preview.';
@override
String get mediaNotice => 'User-provided local demo video · Free preview';
@override
String get featuredDemo => 'FEATURED · TECHNICAL DEMO';
@override
String get demoTitle => 'The Signal';
@override
String get demoSynopsis =>
'A short local video preview. More episodes can be added when media is available.';
@override
String get homeTab => 'Home';
@override
String get openQuickMenu => 'Open quick menu';
@override
String get quickAccess => 'Quick access';
@override
String get currentSeries => 'Current series';
@override
String get discoverTab => 'Discover';
@override
String get searchDiscover => 'Search dramas, actors, genres...';
@override
String get featured => 'Featured';
@override
String get suspense => 'Suspense';
@override
String get romance => 'Romance';
@override
String get actionGenre => 'Action';
@override
String get filter => 'Filter';
@override
String get topCharts => 'Top Charts';
@override
String get newReleases => 'New Releases';
@override
String get trendingMicroDramas => 'Trending Micro-Dramas';
@override
String get seeAll => 'See All';
@override
String get artworkOnly => 'Artwork';
@override
String get artworkOnlyNotice =>
'This is a visual catalog item. No video is available yet.';
@override
String get videoPending => 'Video pending';
@override
String get watchNow => 'Watch free';
@override
String get noSearchResults => 'No matching dramas.';
@override
String get demoCatalogNotice =>
'Three demo dramas share the same local video.';
@override
String get myTab => 'My';
@override
String get localViewer => 'Local Viewer';
@override
String get localDemoProfile => 'Local demo profile';
@override
String get continueWatching => 'Continue Watching';
@override
String watchedPercent(int percent) {
return 'Watched $percent%';
}
@override
String get resume => 'Resume';
@override
String get history => 'History';
@override
String get watchlist => 'Watchlist';
@override
String get likedTab => 'Liked';
@override
String get all => 'All';
@override
String get inProgress => 'In Progress';
@override
String get completed => 'Completed';
@override
String get noSavedShows => 'No shows here yet.';
@override
String get preferences => 'Preferences';
@override
String get appLanguage => 'App Language';
@override
String get followingTab => 'Following';
@override
String get animatedTab => 'Animated';
@override
String get recommendedTab => 'Recommended';
@override
String get noCategoryDramas => 'No dramas in this category yet.';
@override
String get trendingTab => 'Trending';
@override
String get liveActionTab => 'Live Action';
@override
String get search => 'Search';
@override
String get free => 'Free';
@override
String get mute => 'Mute';
@override
String get unmute => 'Unmute';
@override
String get like => 'Like';
@override
String get save => 'Save';
@override
String get comments => 'Comments';
@override
String get share => 'Share';
@override
String get localOnlyComments => 'Only visible on this device';
@override
String get noComments => 'No comments yet.';
@override
String get writeComment => 'Write a comment';
@override
String get postComment => 'Post';
@override
String get shareFailed => 'Could not open the share sheet.';
@override
String get nowPlaying => 'Playing now';
@override
String get watchFullscreen => 'Watch in landscape';
@override
String get exitFullscreen => 'Exit fullscreen';
@override
String get pictureInPicture => 'Picture in picture';
@override
String get pipUnavailable =>
'Picture in picture is unavailable on this device';
@override
String get originalTag => 'Original';
@override
String get dramaTag => 'Short drama';
@override
String episodeLabel(int number) {
return 'Episode $number';
}
@override
String get exploreSeries => 'Explore series';
@override
String episodeCount(int count) {
return '$count EPISODES';
}
@override
String technicalDemoCount(int count) {
return 'FREE PREVIEW · $count EPISODES';
}
@override
String get episodes => 'Episodes';
@override
String get watchEpisodeOne => 'Watch episode 1';
@override
String continueEpisode(int number) {
return 'Continue episode $number';
}
@override
String get freeTestMedia => 'Same demo clip · free';
@override
String get lockedStoreUnavailable => 'Locked · store unavailable';
@override
String get freeTestClip => 'Free test clip';
@override
String get locked => 'Locked';
@override
String get freeSamplesNotice => 'Two free samples · store setup pending';
@override
String get demoTestMedia => 'FREE · SAME DEMO CLIP';
@override
String episodeProgress(int number, int total) {
return 'EPISODE $number / $total';
}
@override
String get testVideoNotice => 'Self-generated technical test video';
@override
String lockedTitle(int number) {
return 'Episode $number is locked';
}
@override
String get lockedBody =>
'Unlocking will be available after store and verification setup. This demo does not process payments.';
@override
String get playbackError => 'This clip could not be played.';
@override
String get catalogError => 'The catalog could not be loaded.';
@override
String get noStories => 'No stories available yet.';
@override
String get retry => 'Retry';
@override
String get backToSeries => 'Back to series';
@override
String get nextEpisode => 'Next episode';
@override
String get pause => 'Pause';
@override
String get play => 'Play';
@override
String get seekVideo => 'Seek video';
@override
String get seekFailed => 'Could not change playback position.';
@override
String get captions => 'Captions';
@override
String get captionsOff => 'Captions off';
@override
String get englishCaptions => 'English captions';
@override
String get chineseCaptions => 'Chinese captions';
@override
String get language => 'Language';
@override
String get systemLanguage => 'System';
@override
String get english => 'English';
@override
String get simplifiedChinese => '简体中文';
@override
String get episodeOneTitle => 'First Light';
@override
String get episodeTwoTitle => 'A New Frequency';
@override
String get episodeThreeTitle => 'Crossing Over';
@override
String get episodeFourTitle => 'After the Echo';
@override
String get dramaSignalTitle => 'The Signal';
@override
String get dramaSignalSynopsis =>
'A demo series for vertical playback. Every episode reuses one local clip.';
@override
String get dramaCityTitle => 'City Lights & Velvet Nights';
@override
String get dramaCitySynopsis =>
'A demo romance series. The same local video is used to try switching and resume.';
@override
String get dramaVengeanceTitle => 'Vengeance Rising';
@override
String get dramaVengeanceSynopsis =>
'A demo action series. The same local video is used to try switching and resume.';
@override
String get dramaEchoesTitle => 'Echoes of Fate';
@override
String get genreSuspenseMystery => 'Suspense · Mystery';
@override
String get genreUrbanRomance => 'Urban Romance';
@override
String get genreActionThriller => 'Action · Thriller';
@override
String get genreDramaMystery => 'Drama · Mystery';
@override
String get continueWatchingHeading => 'CONTINUE WATCHING';
@override
String get preferencesHeading => 'PREFERENCES';
@override
String get brandMark => 'NONTONKI · DEMO';
@override
String get shareFooter => 'Nontonki demo';
}
+396
View File
@@ -0,0 +1,396 @@
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for Chinese (`zh`).
class AppLocalizationsZh extends AppLocalizations {
AppLocalizationsZh([String locale = 'zh']) : super(locale);
@override
String get appName => 'Nontonki';
@override
String get demo => '演示';
@override
String get homeHeadline => '即刻观看';
@override
String get homeSubtitle => '免费短剧预览。';
@override
String get mediaNotice => '用户提供的本地演示视频 · 免费观看';
@override
String get featuredDemo => '精选 · 技术演示';
@override
String get demoTitle => '信号';
@override
String get demoSynopsis => '使用本地视频进行播放预览,后续有素材再增加剧集。';
@override
String get homeTab => '首页';
@override
String get openQuickMenu => '打开快捷菜单';
@override
String get quickAccess => '快捷入口';
@override
String get currentSeries => '当前短剧';
@override
String get discoverTab => '找剧';
@override
String get searchDiscover => '搜索短剧、演员、类型…';
@override
String get featured => '精选';
@override
String get suspense => '悬疑';
@override
String get romance => '都市爱情';
@override
String get actionGenre => '动作';
@override
String get filter => '筛选';
@override
String get topCharts => '排行榜';
@override
String get newReleases => '新剧';
@override
String get trendingMicroDramas => '热门短剧';
@override
String get seeAll => '查看全部';
@override
String get artworkOnly => '海报展示';
@override
String get artworkOnlyNotice => '这张海报仅用于目录展示,暂时没有可播放视频。';
@override
String get videoPending => '视频待提供';
@override
String get watchNow => '免费观看';
@override
String get noSearchResults => '没有匹配的短剧。';
@override
String get demoCatalogNotice => '三部演示短剧共用同一条本地视频。';
@override
String get myTab => '我的';
@override
String get localViewer => '本地观众';
@override
String get localDemoProfile => '本地演示档案';
@override
String get continueWatching => '继续观看';
@override
String watchedPercent(int percent) {
return '已观看 $percent%';
}
@override
String get resume => '继续播放';
@override
String get history => '历史';
@override
String get watchlist => '追剧';
@override
String get likedTab => '喜欢';
@override
String get all => '全部';
@override
String get inProgress => '未看完';
@override
String get completed => '已看完';
@override
String get noSavedShows => '这里还没有剧集。';
@override
String get preferences => '偏好设置';
@override
String get appLanguage => '应用语言';
@override
String get followingTab => '关注';
@override
String get animatedTab => '漫剧';
@override
String get recommendedTab => '推荐';
@override
String get noCategoryDramas => '这个分类暂时没有剧集。';
@override
String get trendingTab => '热门';
@override
String get liveActionTab => '真人剧';
@override
String get search => '搜索';
@override
String get free => '免费';
@override
String get mute => '静音';
@override
String get unmute => '取消静音';
@override
String get like => '喜欢';
@override
String get save => '收藏';
@override
String get comments => '评论';
@override
String get share => '分享';
@override
String get localOnlyComments => '仅在本机可见';
@override
String get noComments => '还没有评论。';
@override
String get writeComment => '写评论';
@override
String get postComment => '发布';
@override
String get shareFailed => '无法打开系统分享面板。';
@override
String get nowPlaying => '正在播放';
@override
String get watchFullscreen => '横屏全屏观看';
@override
String get exitFullscreen => '退出全屏';
@override
String get pictureInPicture => '画中画';
@override
String get pipUnavailable => '此设备无法使用画中画';
@override
String get originalTag => '原创';
@override
String get dramaTag => '短剧';
@override
String episodeLabel(int number) {
return '第 $number 集';
}
@override
String get exploreSeries => '查看剧集';
@override
String episodeCount(int count) {
return '$count 集';
}
@override
String technicalDemoCount(int count) {
return '免费试看 · $count 集';
}
@override
String get episodes => '选集';
@override
String get watchEpisodeOne => '观看第 1 集';
@override
String continueEpisode(int number) {
return '续看第 $number 集';
}
@override
String get freeTestMedia => '复用同一演示视频 · 免费';
@override
String get lockedStoreUnavailable => '已锁定 · 商店未配置';
@override
String get freeTestClip => '免费测试片';
@override
String get locked => '已锁定';
@override
String get freeSamplesNotice => '前两集免费 · 商店配置待完成';
@override
String get demoTestMedia => '免费 · 同一演示视频';
@override
String episodeProgress(int number, int total) {
return '第 $number / $total 集';
}
@override
String get testVideoNotice => '自行生成的技术测试视频';
@override
String lockedTitle(int number) {
return '第 $number 集已锁定';
}
@override
String get lockedBody => '完成商店与服务端验单配置后才能解锁。本演示目前不处理付款。';
@override
String get playbackError => '此视频暂时无法播放。';
@override
String get catalogError => '剧目列表加载失败。';
@override
String get noStories => '暂无剧目。';
@override
String get retry => '重试';
@override
String get backToSeries => '返回剧集详情';
@override
String get nextEpisode => '下一集';
@override
String get pause => '暂停';
@override
String get play => '播放';
@override
String get seekVideo => '拖动播放进度';
@override
String get seekFailed => '无法调整播放进度。';
@override
String get captions => '字幕';
@override
String get captionsOff => '关闭字幕';
@override
String get englishCaptions => '英文字幕';
@override
String get chineseCaptions => '简体中文字幕';
@override
String get language => '界面语言';
@override
String get systemLanguage => '跟随系统';
@override
String get english => 'English';
@override
String get simplifiedChinese => '简体中文';
@override
String get episodeOneTitle => '初见微光';
@override
String get episodeTwoTitle => '新的频率';
@override
String get episodeThreeTitle => '越过边界';
@override
String get episodeFourTitle => '回声之后';
@override
String get dramaSignalTitle => '信号';
@override
String get dramaSignalSynopsis => '一部竖屏连播的演示短剧,每一集都使用同一段本地视频。';
@override
String get dramaCityTitle => '都市灯火与丝绒夜';
@override
String get dramaCitySynopsis => '一部都市爱情演示短剧,用同一段本地视频体验切换和续看。';
@override
String get dramaVengeanceTitle => '复仇崛起';
@override
String get dramaVengeanceSynopsis => '一部动作演示短剧,用同一段本地视频体验切换和续看。';
@override
String get dramaEchoesTitle => '命运回声';
@override
String get genreSuspenseMystery => '悬疑 · 推理';
@override
String get genreUrbanRomance => '都市爱情';
@override
String get genreActionThriller => '动作 · 惊悚';
@override
String get genreDramaMystery => '剧情 · 悬疑';
@override
String get continueWatchingHeading => '继续观看';
@override
String get preferencesHeading => '偏好设置';
@override
String get brandMark => 'NONTONKI · 演示';
@override
String get shareFooter => 'Nontonki 演示';
}
+129
View File
@@ -0,0 +1,129 @@
{
"@@locale": "zh",
"appName": "Nontonki",
"demo": "演示",
"homeHeadline": "即刻观看",
"homeSubtitle": "免费短剧预览。",
"mediaNotice": "用户提供的本地演示视频 · 免费观看",
"featuredDemo": "精选 · 技术演示",
"demoTitle": "信号",
"demoSynopsis": "使用本地视频进行播放预览,后续有素材再增加剧集。",
"homeTab": "首页",
"openQuickMenu": "打开快捷菜单",
"quickAccess": "快捷入口",
"currentSeries": "当前短剧",
"discoverTab": "找剧",
"searchDiscover": "搜索短剧、演员、类型…",
"featured": "精选",
"suspense": "悬疑",
"romance": "都市爱情",
"actionGenre": "动作",
"filter": "筛选",
"topCharts": "排行榜",
"newReleases": "新剧",
"trendingMicroDramas": "热门短剧",
"seeAll": "查看全部",
"artworkOnly": "海报展示",
"artworkOnlyNotice": "这张海报仅用于目录展示,暂时没有可播放视频。",
"videoPending": "视频待提供",
"watchNow": "免费观看",
"noSearchResults": "没有匹配的短剧。",
"demoCatalogNotice": "三部演示短剧共用同一条本地视频。",
"myTab": "我的",
"localViewer": "本地观众",
"localDemoProfile": "本地演示档案",
"continueWatching": "继续观看",
"watchedPercent": "已观看 {percent}%",
"@watchedPercent": {"placeholders": {"percent": {"type": "int"}}},
"resume": "继续播放",
"history": "历史",
"watchlist": "追剧",
"likedTab": "喜欢",
"all": "全部",
"inProgress": "未看完",
"completed": "已看完",
"noSavedShows": "这里还没有剧集。",
"preferences": "偏好设置",
"appLanguage": "应用语言",
"followingTab": "关注",
"animatedTab": "漫剧",
"recommendedTab": "推荐",
"noCategoryDramas": "这个分类暂时没有剧集。",
"trendingTab": "热门",
"liveActionTab": "真人剧",
"search": "搜索",
"free": "免费",
"mute": "静音",
"unmute": "取消静音",
"like": "喜欢",
"save": "收藏",
"comments": "评论",
"share": "分享",
"localOnlyComments": "仅在本机可见",
"noComments": "还没有评论。",
"writeComment": "写评论",
"postComment": "发布",
"shareFailed": "无法打开系统分享面板。",
"nowPlaying": "正在播放",
"watchFullscreen": "横屏全屏观看",
"exitFullscreen": "退出全屏",
"pictureInPicture": "画中画",
"pipUnavailable": "此设备无法使用画中画",
"originalTag": "原创",
"dramaTag": "短剧",
"episodeLabel": "第 {number} 集",
"@episodeLabel": {"placeholders": {"number": {"type": "int"}}},
"exploreSeries": "查看剧集",
"episodeCount": "{count} 集",
"technicalDemoCount": "免费试看 · {count} 集",
"episodes": "选集",
"watchEpisodeOne": "观看第 1 集",
"continueEpisode": "续看第 {number} 集",
"freeTestMedia": "复用同一演示视频 · 免费",
"lockedStoreUnavailable": "已锁定 · 商店未配置",
"freeTestClip": "免费测试片",
"locked": "已锁定",
"freeSamplesNotice": "前两集免费 · 商店配置待完成",
"demoTestMedia": "免费 · 同一演示视频",
"episodeProgress": "第 {number} / {total} 集",
"testVideoNotice": "自行生成的技术测试视频",
"lockedTitle": "第 {number} 集已锁定",
"lockedBody": "完成商店与服务端验单配置后才能解锁。本演示目前不处理付款。",
"playbackError": "此视频暂时无法播放。",
"catalogError": "剧目列表加载失败。",
"noStories": "暂无剧目。",
"retry": "重试",
"backToSeries": "返回剧集详情",
"nextEpisode": "下一集",
"pause": "暂停",
"play": "播放",
"seekVideo": "拖动播放进度",
"seekFailed": "无法调整播放进度。",
"captions": "字幕",
"captionsOff": "关闭字幕",
"englishCaptions": "英文字幕",
"chineseCaptions": "简体中文字幕",
"language": "界面语言",
"systemLanguage": "跟随系统",
"english": "English",
"simplifiedChinese": "简体中文",
"episodeOneTitle": "初见微光",
"episodeTwoTitle": "新的频率",
"episodeThreeTitle": "越过边界",
"episodeFourTitle": "回声之后",
"dramaSignalTitle": "信号",
"dramaSignalSynopsis": "一部竖屏连播的演示短剧,每一集都使用同一段本地视频。",
"dramaCityTitle": "都市灯火与丝绒夜",
"dramaCitySynopsis": "一部都市爱情演示短剧,用同一段本地视频体验切换和续看。",
"dramaVengeanceTitle": "复仇崛起",
"dramaVengeanceSynopsis": "一部动作演示短剧,用同一段本地视频体验切换和续看。",
"dramaEchoesTitle": "命运回声",
"genreSuspenseMystery": "悬疑 · 推理",
"genreUrbanRomance": "都市爱情",
"genreActionThriller": "动作 · 惊悚",
"genreDramaMystery": "剧情 · 悬疑",
"continueWatchingHeading": "继续观看",
"preferencesHeading": "偏好设置",
"brandMark": "NONTONKI · 演示",
"shareFooter": "Nontonki 演示"
}