diff --git a/lib/gen/strings.g.dart b/lib/gen/strings.g.dart index 1c66178..9823edc 100644 --- a/lib/gen/strings.g.dart +++ b/lib/gen/strings.g.dart @@ -3,10 +3,10 @@ /// Original: res/i18n /// To regenerate, run: `dart run slang` /// -/// Locales: 3 -/// Strings: 1818 (606 per locale) +/// Locales: 1 +/// Strings: 690 /// -/// Built on 2024-11-21 at 21:18 UTC +/// Built on 2024-11-28 at 20:31 UTC // coverage:ignore-file // ignore_for_file: type=lint @@ -25,9 +25,7 @@ const AppLocale _baseLocale = AppLocale.en; /// - Locale locale = AppLocale.en.flutterLocale // get flutter locale from enum /// - if (LocaleSettings.currentLocale == AppLocale.en) // locale check enum AppLocale with BaseAppLocale { - en(languageCode: 'en', build: Translations.build), - ru(languageCode: 'ru', build: _StringsRu.build), - zhCn(languageCode: 'zh', countryCode: 'CN', build: _StringsZhCn.build); + en(languageCode: 'en', build: Translations.build); const AppLocale({required this.languageCode, this.scriptCode, this.countryCode, required this.build}); // ignore: unused_element @@ -154,247 +152,86 @@ class Translations implements BaseTranslations { 'ru': 'Russian (Русский)', 'zh-CN': 'Simplified Chinese (简体中文)', }; - String get tetraLeague => 'Tetra League'; - String get tlRecords => 'TL Records'; - String get history => 'History'; - String get sprint => '40 Lines'; - String get blitz => 'Blitz'; - String get recent => 'Recent'; - String get recentRuns => 'Recent runs'; - String blitzScore({required Object p}) => '${p} points'; - String get openSPreplay => 'Open replay in TETR.IO'; - String get downloadSPreplay => 'Download replay'; - String get other => 'Other'; - String get distinguishment => 'Distinguishment'; - String get zen => 'Zen'; - String get bio => 'Bio'; - String get news => 'News'; - late final _StringsNewsPartsEn newsParts = _StringsNewsPartsEn._(_root); - String get openSearch => 'Search player'; - String get closeSearch => 'Close search'; - String get searchHint => 'Nickname, ID or Discord userID (with "ds:" prefix)'; - String get refresh => 'Refresh'; - String get fetchAndsaveTLHistory => 'Get player history'; - String get fetchAndSaveOldTLmatches => 'Get Tetra League matches history'; - String fetchAndsaveTLHistoryResult({required Object number}) => '${number} states was found'; - String fetchAndSaveOldTLmatchesResult({required Object number}) => '${number} matches was found'; - String get showStoredData => 'Show stored data'; - String get statsCalc => 'Stats Calculator'; - String get settings => 'Settings'; - String get track => 'Track'; - String get stopTracking => 'Stop\ntracking'; - String get becameTracked => 'Added to tracking list!'; - String get compare => 'Compare'; - String get stoppedBeingTracked => 'Removed from tracking list!'; - String get tlLeaderboard => 'Tetra League leaderboard'; - String get noRecords => 'No records'; - String noOldRecords({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: 'No records', - one: 'Only ${n} record', - two: 'Only ${n} records', - few: 'Only ${n} records', - many: 'Only ${n} records', - other: 'Only ${n} records', - ); - String get noRecord => 'No record'; - String get botRecord => 'Bots are not allowed to set records'; - String get anonRecord => 'Guests are not allowed to set records'; - String get notEnoughData => 'Not enough data'; - String get noHistorySaved => 'No history saved'; - String get pseudoTooltipHeaderInit => 'Hover over point'; - String get pseudoTooltipFooterInit => 'to see detailed data'; - String obtainDate({required Object date}) => 'Obtained ${date}'; - String fetchDate({required Object date}) => 'Fetched ${date}'; - String get exactGametime => 'Exact gametime'; - String get bigRedBanned => 'BANNED'; - String get normalBanned => 'Banned'; - String get bigRedBadStanding => 'BAD STANDING'; - String get copiedToClipboard => 'Copied to clipboard!'; - String get playerRoleAccount => ' account '; - String get wasFromBeginning => 'that was from very beginning'; - String get created => 'created'; - String get botCreatedBy => 'by'; - String get notSupporter => 'Not a supporter'; - String get assignedManualy => 'That badge was assigned manualy by TETR.IO admins'; - String supporter({required Object tier}) => 'Supporter tier ${tier}'; - String comparingWith({required Object newDate, required Object oldDate}) => 'Data from ${newDate} comparing with ${oldDate}'; - String get top => 'Top'; - String get topRank => 'Top rank'; - String verdictGeneral({required Object n, required Object verdict, required Object rank}) => '${n} ${verdict} ${rank} rank avg'; - String get verdictBetter => 'better'; - String get verdictWorse => 'worse'; - String get smooth => 'Smooth'; - String get postSeason => 'Off-season'; - String get seasonStarts => 'Season starts in:'; + Map get gamemodes => { + 'league': 'Tetra League', + 'zenith': 'Quick Play', + 'zenithex': 'Quick Play Expert', + '40l': '40 Lines', + 'blitz': 'Blitz', + '5mblast': '5,000,000 Blast', + 'zen': 'Zen', + }; + late final _StringsDestinationsEn destinations = _StringsDestinationsEn._(_root); + String get goBackButton => 'Go Back'; String get nanow => 'Not avaliable for now...'; String seasonEnds({required Object countdown}) => 'Season ends in ${countdown}'; String get seasonEnded => 'Season has ended'; + String overallPB({required Object pb}) => 'Overall PB: ${pb}'; String gamesUntilRanked({required Object left}) => '${left} games until being ranked'; String numOfVictories({required Object wins}) => '~${wins} victories'; String get promotionOnNextWin => 'Promotion on next win'; String numOfdefeats({required Object losses}) => '~${losses} defeats'; String get demotionOnNextLoss => 'Demotion on next loss'; + String get records => 'Records'; String get nerdStats => 'Nerd Stats'; - String get playersYouTrack => 'Players you track'; - String get formula => 'Formula'; - String get exactValue => 'Exact value'; - String get neverPlayedTL => 'That user never played Tetra League'; - String get botTL => 'Bots are not allowed to play Tetra League'; - String get anonTL => 'Guests are not allowed to play Tetra League'; - String get quickPlay => 'Quick Play'; - String get expert => 'Expert'; - String get withMods => 'With mods'; - String withModsPlural({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: 'with ${n} mods', - one: 'with ${n} mod', - two: 'with ${n} mods', - few: 'with ${n} mods', - many: 'with ${n} mods', - other: 'with ${n} mods', - ); - String get exportDB => 'Export local database'; - String get exportDBDescription => 'It contains states and Tetra League records of the tracked players and list of tracked players.'; - String get desktopExportAlertTitle => 'Desktop export'; - String get desktopExportText => 'It seems like you using this app on desktop. Check your documents folder, you should find "TetraStats.db". Copy it somewhere'; - String get androidExportAlertTitle => 'Android export'; - String androidExportText({required Object exportedDB}) => 'Exported.\n${exportedDB}'; - String get importDB => 'Import local database'; - String get importDBDescription => 'Restore your backup. Notice that already stored database will be overwritten.'; - String get importWrongFileType => 'Wrong file type'; - String get importCancelled => 'Operation was cancelled'; - String get importSuccess => 'Import successful'; - String get yourID => 'Your TETR.IO account'; - String get yourIDAlertTitle => 'Your nickname in TETR.IO'; - String get yourIDText => 'When app loads, it will retrieve data for this account'; - String get language => 'Language'; - String get updateInBackground => 'Update stats in the background'; - String get updateInBackgroundDescription => 'While Tetra Stats is running, it can update stats of the current player when cache expires'; - String get customization => 'Customization'; - String get customizationDescription => 'Change appearance of different things in Tetra Stats UI'; - String get oskKagari => 'Osk Kagari gimmick'; - String get oskKagariDescription => 'If on, osk\'s rank on main view will be rendered as :kagari:'; - String get AccentColor => 'Accent color'; - String get AccentColorDescription => 'Almost all interactive UI elements highlighted with this color'; - String get timestamps => 'Timestamps'; - String get timestampsDescription => 'You can choose, in which way timestamps shows time'; - String get timestampsAbsoluteGMT => 'Absolute (GMT)'; - String get timestampsAbsoluteLocalTime => 'Absolute (Your timezone)'; - String get timestampsRelative => 'Relative'; - String get rating => 'Main representation of rating'; - String get ratingDescription => 'TR is not linear, while Glicko does not have boundaries and percentile is volatile'; - String get ratingLBposition => 'LB position'; - String get sheetbotGraphs => 'Sheetbot-like behavior for radar graphs'; - String get sheetbotGraphsDescription => 'If on, points on the graphs can appear on the opposite half of the graph if value is negative'; - String get lbStats => 'Show leaderboard based stats'; - String get lbStatsDescription => 'That will impact on loading times, but will allow you to see position on LB by stats and comparison with average values'; - String get aboutApp => 'About app'; - String aboutAppText({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) Version ${version} Build ${buildNumber}\n\nDeveloped by dan63047\nFormulas provided by kerrmunism\nHistory provided by p1nkl0bst3r\nTETR.IO replay grabber API by szy'; - String stateViewTitle({required Object nickname, required Object date}) => '${nickname} account on ${date}'; - String statesViewTitle({required Object number, required Object nickname}) => '${number} states of ${nickname} account'; - String matchesViewTitle({required Object nickname}) => '${nickname} TL matches'; - String statesViewEntry({required Object level, required Object glicko, required Object rd, required Object games}) => '${level} TR, ${glicko}±${rd} Glicko, ${games} игр сыграно'; - String stateRemoved({required Object date}) => '${date} state was removed from database!'; - String matchRemoved({required Object date}) => '${date} match was removed from database!'; - String get viewAllMatches => 'View all matches'; - String get trackedPlayersViewTitle => 'Stored data'; - String get trackedPlayersZeroEntrys => 'Empty list. Press "Track" button in previous view to add current player here'; - String get trackedPlayersOneEntry => 'There is only one player'; - String trackedPlayersManyEntrys({required Object numberOfPlayers}) => 'There are ${numberOfPlayers} players'; - String trackedPlayersEntry({required Object nickname, required Object numberOfStates}) => '${nickname}: ${numberOfStates} states'; - String trackedPlayersDescription({required Object firstStateDate, required Object lastStateDate}) => 'From ${firstStateDate} until ${lastStateDate}'; - String trackedPlayersStatesDeleted({required Object nickname}) => '${nickname} states was removed from database!'; - String get duplicatedFix => 'Remove duplicated TL mathces'; - String get compressDB => 'Compress DB'; - String SpaceSaved({required Object size}) => 'Space saved: ${size}'; - String averageXrank({required Object rankLetter}) => 'Average ${rankLetter} rank'; - String get vs => 'vs'; - String get inTLmatch => 'in TL match'; - String get downloadReplay => 'Download .ttrm replay'; - String get openReplay => 'Open replay in TETR.IO'; - String replaySaved({required Object path}) => 'Replay saved to ${path}'; - String get match => 'Match'; - String get timeWeightedmatch => 'Match (time-weighted)'; - String roundNumber({required Object n}) => 'Round ${n}'; - String get statsFor => 'Stats for'; - String get numberOfRounds => 'Number of rounds'; - String get matchLength => 'Match Length'; - String get roundLength => 'Round Length'; - String get matchStats => 'Match stats'; - String get timeWeightedmatchStats => 'Time-weighted match stats'; - String get replayIssue => 'Can\'t process replay'; - String get matchIsTooOld => 'Replay is not available'; - String get winner => 'Winner'; - String get registred => 'Registred'; - String get playedTL => 'Played Tetra League'; - String get winChance => 'Win Chance'; - String get byGlicko => 'By Glicko'; - String get byEstTR => 'By Est. TR'; - String compareViewNoValues({required Object avgR}) => 'Please, enter username, user ID, APM-PPS-VS values (divider doesn\'t matter, only order matter) or ${avgR} (where R is rank) to both fields'; - String compareViewWrongValue({required Object value}) => 'Falied to assign ${value}'; - String get mostRecentOne => 'Most recent one'; - String get yes => 'Yes'; - String get no => 'No'; - String get daysLater => 'days later'; - String get dayseBefore => 'days before'; - String get fromBeginning => 'From beginning'; - String get calc => 'Calc'; - String get calcViewNoValues => 'Enter values to calculate the stats'; - String get rankAveragesViewTitle => 'Ranks cutoffs'; - String get sprintAndBlitsViewTitle => '40 lines and Blitz averages'; - String sprintAndBlitsRelevance({required Object date}) => 'Relevance: ${date}'; + String get playstyles => 'Playstyles'; + String get horoscopes => 'Horoscopes'; + String get season => 'Season'; + String get smooth => 'Smooth'; + String get dateAndTime => 'Date & Time'; + String get TLfullLBnote => 'Heavy, but allows you to sort players by their stats and filter them by ranks'; String get rank => 'Rank'; - String get averages => 'Averages'; - String get lbViewZeroEntrys => 'Empty list'; - String get lbViewOneEntry => 'There is only one player'; - String lbViewManyEntrys({required Object numberOfPlayers}) => 'There are ${numberOfPlayers}'; - String get everyoneAverages => 'Values for leaderboard'; - String get sortBy => 'Sort by'; - String get reversed => 'Reversed'; - String get country => 'Country'; - String rankAverages({required Object rank}) => 'Values for ${rank} rank'; - String players({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} players', - one: '${n} player', - two: '${n} players', - few: '${n} players', - many: '${n} players', - other: '${n} players', - ); - String games({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} games', - one: '${n} game', - two: '${n} games', - few: '${n} games', - many: '${n} games', - other: '${n} games', - ); - String gamesPlayed({required Object games}) => '${games} played'; - String get chart => 'Chart'; - String get entries => 'Entries'; - String get minimums => 'Minimums'; - String get maximums => 'Maximums'; - String get lowestValues => 'Lowest Values'; - String get averageValues => 'Average Values'; - String get highestValues => 'Highest Values'; - String forPlayer({required Object username}) => 'for player ${username}'; - String currentAxis({required Object axis}) => '${axis} axis:'; - String get p1nkl0bst3rAlert => 'That data was retrived from third party API maintained by p1nkl0bst3r'; - String get notForWeb => 'Function is not available for web version'; - late final _StringsGraphsEn graphs = _StringsGraphsEn._(_root); - late final _StringsStatCellNumEn statCellNum = _StringsStatCellNumEn._(_root); - Map get playerRole => { - 'user': 'User', - 'banned': 'Banned', - 'bot': 'Bot', - 'sysop': 'System operator', - 'admin': 'Admin', - 'mod': 'Moderator', - 'halfmod': 'Community moderator', - 'anon': 'Anonymous', - }; - late final _StringsNumOfGameActionsEn numOfGameActions = _StringsNumOfGameActionsEn._(_root); - late final _StringsPopupActionsEn popupActions = _StringsPopupActionsEn._(_root); + String verdictGeneral({required Object n, required Object verdict, required Object rank}) => '${n} ${verdict} of ${rank} rank avg'; + String get verdictBetter => 'ahead'; + String get verdictWorse => 'behind'; + String get localStanding => 'local'; + late final _StringsXpEn xp = _StringsXpEn._(_root); + late final _StringsGametimeEn gametime = _StringsGametimeEn._(_root); + String get track => 'Track'; + String get stopTracking => 'Stop tracking'; + String supporter({required Object tier}) => 'Supporter tier ${tier}'; + String comparingWith({required Object newDate, required Object oldDate}) => 'Data from ${newDate} comparing with ${oldDate}'; + String get compare => 'Compare'; + String get comparison => 'Comparison'; + String get general => 'General'; + String get badges => 'Badges'; + String obtainDate({required Object date}) => 'Obtained ${date}'; + String get assignedManualy => 'That badge was assigned manualy by TETR.IO admins'; + String get distinguishment => 'Distinguishment'; + String get bigRedBanned => 'BANNED'; + String get normalBanned => 'Banned'; + String get bigRedBadStanding => 'BAD STANDING'; + String get copiedToClipboard => 'Copied to clipboard!'; + String get bio => 'Bio'; + String get news => 'News'; + late final _StringsNewsPartsEn newsParts = _StringsNewsPartsEn._(_root); + String get copyUserID => 'Click to copy user ID'; + String get searchHint => 'Username or ID'; + String get searchButton => 'Search'; + String get trackedPlayers => 'Tracked Players'; + String get standing => 'Standing'; + String get previousSeasons => 'Previous Seasons'; + String get recent => 'Recent'; + String get top => 'Top'; + String get noRecord => 'No record'; + String sprintAndBlitsRelevance({required Object date}) => 'Relevance: ${date}'; + late final _StringsSnackBarMessagesEn snackBarMessages = _StringsSnackBarMessagesEn._(_root); late final _StringsErrorsEn errors = _StringsErrorsEn._(_root); + late final _StringsActionsEn actions = _StringsActionsEn._(_root); + late final _StringsGraphsDestinationEn graphsDestination = _StringsGraphsDestinationEn._(_root); + late final _StringsFilterModaleEn filterModale = _StringsFilterModaleEn._(_root); + late final _StringsCutoffsDestinationEn cutoffsDestination = _StringsCutoffsDestinationEn._(_root); + late final _StringsRankViewEn rankView = _StringsRankViewEn._(_root); + late final _StringsTlMatchViewEn tlMatchView = _StringsTlMatchViewEn._(_root); + late final _StringsCalcDestinationEn calcDestination = _StringsCalcDestinationEn._(_root); + late final _StringsInfoDestinationEn infoDestination = _StringsInfoDestinationEn._(_root); + late final _StringsLeaderboardsDestinationEn leaderboardsDestination = _StringsLeaderboardsDestinationEn._(_root); + late final _StringsSettingsDestinationEn settingsDestination = _StringsSettingsDestinationEn._(_root); + late final _StringsHomeNavigationEn homeNavigation = _StringsHomeNavigationEn._(_root); + late final _StringsGraphsNavigationEn graphsNavigation = _StringsGraphsNavigationEn._(_root); + late final _StringsCalcNavigationEn calcNavigation = _StringsCalcNavigationEn._(_root); + late final _StringsAboutViewEn aboutView = _StringsAboutViewEn._(_root); + late final _StringsStatsEn stats = _StringsStatsEn._(_root); Map get countries => { '': 'Worldwide', 'AF': 'Afghanistan', @@ -658,6 +495,47 @@ class Translations implements BaseTranslations { }; } +// Path: destinations +class _StringsDestinationsEn { + _StringsDestinationsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get home => 'Home'; + String get graphs => 'Graphs'; + String get leaderboards => 'Leaderboards'; + String get cutoffs => 'Cutoffs'; + String get calc => 'Calculator'; + String get info => 'Info Center'; + String get data => 'Saved Data'; + String get settings => 'Settings'; +} + +// Path: xp +class _StringsXpEn { + _StringsXpEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get title => 'XP Level'; + String progressToNextLevel({required Object percentage}) => 'Progress to next level: ${percentage}'; + String progressTowardsGoal({required Object goal, required Object percentage, required Object left}) => 'Progress from 0 XP to level ${goal}: ${percentage} (${left} XP left)'; +} + +// Path: gametime +class _StringsGametimeEn { + _StringsGametimeEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get title => 'Exact gametime'; + String gametimeAday({required Object gametime}) => '${gametime} a day in average'; + String breakdown({required Object years, required Object months, required Object days, required Object minutes, required Object seconds}) => 'It\'s ${years} years,\nor ${months} months,\nor ${days} days,\nor ${minutes} minutes\nor ${seconds} seconds'; +} + // Path: newsParts class _StringsNewsPartsEn { _StringsNewsPartsEn._(this._root); @@ -680,126 +558,18 @@ class _StringsNewsPartsEn { String unknownNews({required Object type}) => 'Unknown news of type ${type}'; } -// Path: graphs -class _StringsGraphsEn { - _StringsGraphsEn._(this._root); +// Path: snackBarMessages +class _StringsSnackBarMessagesEn { + _StringsSnackBarMessagesEn._(this._root); final Translations _root; // ignore: unused_field // Translations - String get attack => 'Attack'; - String get speed => 'Speed'; - String get defense => 'Defense'; - String get cheese => 'Cheese'; -} - -// Path: statCellNum -class _StringsStatCellNumEn { - _StringsStatCellNumEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - String get xpLevel => 'XP Level'; - String get xpProgress => 'Progress to next level'; - String xpFrom0ToLevel({required Object n}) => 'Progress from 0 XP to level ${n}'; - String get xpLeft => 'XP left'; - String get hoursPlayed => 'Hours\nPlayed'; - String get onlineGames => 'Online\nGames'; - String get gamesWon => 'Games\nWon'; - String get totalGames => 'Total Games Played'; - String get totalWon => 'Total Games Won'; - String get friends => 'Friends'; - String get apm => 'Attack\nPer Minute'; - String get vs => 'Versus\nScore'; - String get recordLB => 'Leaderboard placement'; - String get lbp => 'Leaderboard\nplacement'; - String get lbpShort => '№ in LB'; - String get lbpc => 'Country LB\nplacement'; - String get lbpcShort => '№ in local LB'; - String get gamesPlayed => 'Games\nplayed'; - String get gamesWonTL => 'Games\nWon'; - String get winrate => 'Winrate'; - String get level => 'Level'; - String get score => 'Score'; - String get spp => 'Score\nPer Piece'; - String get pieces => 'Pieces\nPlaced'; - String get pps => 'Pieces\nPer Second'; - String get finesseFaults => 'Finesse\nFaults'; - String get finessePercentage => 'Finesse\nPercentage'; - String get keys => 'Key\nPresses'; - String get kpp => 'KP Per\nPiece'; - String get kps => 'KP Per\nSecond'; - String get tr => 'Tetra Rating'; - String get rd => 'Rating Deviation'; - String get app => 'Attack Per Piece'; - String get appDescription => '(Abbreviated as APP) Main efficiency metric. Tells how many attack you producing per piece'; - String get vsapmDescription => 'Basically, tells how much and how efficient you using garbage in your attacks'; - String get dss => 'Downstack\nPer Second'; - String get dssDescription => '(Abbreviated as DS/S) Downstack per Second measures how many garbage lines you clear in a second.'; - String get dsp => 'Downstack\nPer Piece'; - String get dspDescription => '(Abbreviated as DS/P) Downstack per Piece measures how many garbage lines you clear per piece.'; - String get appdsp => 'APP + DS/P'; - String get appdspDescription => 'Just a sum of Attack per Piece and Downstack per Piece.'; - String get cheese => 'Cheese\nIndex'; - String get cheeseDescription => '(Abbreviated as Cheese) Cheese Index is an approximation how much clean / cheese garbage player sends. Lower = more clean. Higher = more cheese.\nInvented by kerrmunism'; - String get gbe => 'Garbage\nEfficiency'; - String get gbeDescription => '(Abbreviated as Gb Eff.) Garbage Efficiency measures how well player uses their garbage. Higher = better or they use their garbage more. Lower = they mostly send their garbage back at cheese or rarely clear garbage.\nInvented by Zepheniah and Dragonboy.'; - String get nyaapp => 'Weighted\nAPP'; - String get nyaappDescription => '(Abbreviated as wAPP) Essentially, a measure of your ability to send cheese while still maintaining a high APP.\nInvented by Wertj.'; - String get area => 'Area'; - String get areaDescription => 'How much space your shape takes up on the graph, if you exclude the cheese and vs/apm sections'; - String get estOfTR => 'Estimated TR'; - String get estOfTRShort => 'Est. TR'; - String get accOfEst => 'Accuracy'; - String get accOfEstShort => 'Acc.'; -} - -// Path: numOfGameActions -class _StringsNumOfGameActionsEn { - _StringsNumOfGameActionsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - String get pc => 'All Clears'; - String get hold => 'Holds'; - String inputs({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} key presses', - one: '${n} key press', - two: '${n} key presses', - few: '${n} key presses', - many: '${n} key presses', - other: '${n} key presses', - ); - String tspinsTotal({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} T-spins total', - one: '${n} T-spin total', - two: '${n} T-spins total', - few: '${n} T-spins total', - many: '${n} T-spins total', - other: '${n} T-spins total', - ); - String lineClears({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} lines cleared', - one: '${n} line cleared', - two: '${n} lines cleared', - few: '${n} lines cleared', - many: '${n} lines cleared', - other: '${n} lines cleared', - ); -} - -// Path: popupActions -class _StringsPopupActionsEn { - _StringsPopupActionsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - String get cancel => 'Cancel'; - String get submit => 'Submit'; - String get ok => 'OK'; + String stateRemoved({required Object date}) => '${date} state was removed from database!'; + String matchRemoved({required Object date}) => '${date} match was removed from database!'; + String get notForWeb => 'Function is not available for web version'; + String get importSuccess => 'Import successful'; + String get importCancelled => 'Import was cancelled'; } // Path: errors @@ -809,6 +579,9 @@ class _StringsErrorsEn { final Translations _root; // ignore: unused_field // Translations + String get noRecords => 'No records'; + String get notEnoughData => 'Not enough data'; + String get noHistorySaved => 'No history saved'; String connection({required Object code, required Object message}) => 'Some issue with connection: ${code} ${message}'; String get noSuchUser => 'No such user'; String get noSuchUserSub => 'Either you mistyped something, or the account no longer exists'; @@ -837,1428 +610,901 @@ class _StringsErrorsEn { String get replayRejected => 'Third party API blocked your IP address'; } -// Path: -class _StringsRu implements Translations { - /// You can call this constructor and build your own translation instance of this locale. - /// Constructing via the enum [AppLocale.build] is preferred. - _StringsRu.build({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) - : assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'), - $meta = TranslationMetadata( - locale: AppLocale.ru, - overrides: overrides ?? {}, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ) { - $meta.setFlatMapFunction(_flatMapFunction); - } +// Path: actions +class _StringsActionsEn { + _StringsActionsEn._(this._root); - /// Metadata for the translations of . - @override final TranslationMetadata $meta; - - /// Access flat map - @override dynamic operator[](String key) => $meta.getTranslation(key); - - @override late final _StringsRu _root = this; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override Map get locales => { - 'en': 'Английский (English)', - 'ru': 'Русский', - 'zh-CN': 'Упрощенный Китайский (简体中文)', - }; - @override String get tetraLeague => 'Тетра Лига'; - @override String get tlRecords => 'Матчи ТЛ'; - @override String get history => 'История'; - @override String get sprint => '40 линий'; - @override String get blitz => 'Блиц'; - @override String get recent => 'Недавно'; - @override String get recentRuns => 'Недавние'; - @override String blitzScore({required Object p}) => '${p} очков'; - @override String get openSPreplay => 'Открыть повтор в TETR.IO'; - @override String get downloadSPreplay => 'Скачать повтор'; - @override String get other => 'Другое'; - @override String get distinguishment => 'Заслуга'; - @override String get zen => 'Дзен'; - @override String get bio => 'Биография'; - @override String get news => 'Новости'; - @override late final _StringsNewsPartsRu newsParts = _StringsNewsPartsRu._(_root); - @override String get openSearch => 'Искать игрока'; - @override String get closeSearch => 'Закрыть поиск'; - @override String get searchHint => 'Ник, ID или ID в Discord (с префиксом "ds:")'; - @override String get refresh => 'Обновить'; - @override String get fetchAndsaveTLHistory => 'Получить историю игрока'; - @override String get fetchAndSaveOldTLmatches => 'Получить старые матчи Тетра Лиги'; - @override String fetchAndsaveTLHistoryResult({required Object number}) => '${number} состояний было найдено'; - @override String fetchAndSaveOldTLmatchesResult({required Object number}) => '${number} старых матчей было найдено'; - @override String get showStoredData => 'Показать сохранённые данные'; - @override String get statsCalc => 'Калькулятор статистики'; - @override String get settings => 'Настройки'; - @override String get track => 'Отслеживать'; - @override String get stopTracking => 'Перестать\nотслеживать'; - @override String get becameTracked => 'Добавлен в список отслеживания!'; - @override String get stoppedBeingTracked => 'Удалён из списка отслеживания!'; - @override String get compare => 'Сравнить'; - @override String get tlLeaderboard => 'Рейтинговая таблица'; - @override String get noRecords => 'Нет записей'; - @override String noOldRecords({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: 'Нет записей', - one: 'Всего один матч', - two: 'Всего ${n} матча', - few: 'Всего ${n} матча', - many: 'Всего ${n} матчей', - other: '${n} матчей', - ); - @override String get noRecord => 'Нет рекорда'; - @override String get botRecord => 'Ботам нельзя ставить рекорды'; - @override String get anonRecord => 'Гостям нельзя ставить рекорды'; - @override String get notEnoughData => 'Недостаточно данных'; - @override String get noHistorySaved => 'Нет сохранённой истории'; - @override String get pseudoTooltipHeaderInit => 'Наведите курсор на точку'; - @override String get pseudoTooltipFooterInit => 'чтобы узнать подробности'; - @override String obtainDate({required Object date}) => 'Получено ${date}'; - @override String fetchDate({required Object date}) => 'На момент ${date}'; - @override String get exactGametime => 'Время, проведённое в игре'; - @override String get bigRedBanned => 'ЗАБАНЕН'; - @override String get normalBanned => 'Забанен'; - @override String get bigRedBadStanding => 'ПЛОХАЯ РЕПУТАЦИЯ'; - @override String get copiedToClipboard => 'Скопировано в буфер обмена!'; - @override String get playerRoleAccount => ', аккаунт которого '; - @override String get wasFromBeginning => 'существовал с самого начала'; - @override String get created => 'создан'; - @override String get botCreatedBy => 'игроком'; - @override String get notSupporter => 'Нет саппортерки'; - @override String supporter({required Object tier}) => 'Саппортерка ${tier} уровня'; - @override String get assignedManualy => 'Этот значок был присвоен вручную администрацией TETR.IO'; - @override String comparingWith({required Object newDate, required Object oldDate}) => 'Данные от ${newDate} в сравнении с данными от ${oldDate}'; - @override String get top => 'Топ'; - @override String get topRank => 'Топ ранг'; - @override String verdictGeneral({required Object verdict, required Object rank, required Object n}) => '${verdict} среднего ${rank} ранга на ${n}'; - @override String get verdictBetter => 'Лучше'; - @override String get verdictWorse => 'Хуже'; - @override String get smooth => 'Гладкий'; - @override String get postSeason => 'Внесезонье'; - @override String get seasonStarts => 'Сезон начнётся через:'; - @override String get nanow => 'Пока недоступно...'; - @override String seasonEnds({required Object countdown}) => 'Сезон закончится через ${countdown}'; - @override String get seasonEnded => 'Сезон закончился'; - @override String gamesUntilRanked({required Object left}) => '${left} матчей до получения рейтинга'; - @override String numOfVictories({required Object wins}) => '~${wins} побед'; - @override String get promotionOnNextWin => 'Повышение после следующей победы'; - @override String numOfdefeats({required Object losses}) => '~${losses} поражений'; - @override String get demotionOnNextLoss => 'Понижение после следующего поражения'; - @override String get nerdStats => 'Для задротов'; - @override String get playersYouTrack => 'Отслеживаемые игроки'; - @override String get formula => 'Формула'; - @override String get exactValue => 'Точное значение'; - @override String get neverPlayedTL => 'Этот игрок никогда не играл в Тетра Лигу'; - @override String get botTL => 'Ботам нельзя играть в Тетра Лигу'; - @override String get anonTL => 'Гостям нельзя играть в Тетра Лигу'; - @override String get quickPlay => 'Быстрая Игра'; - @override String get expert => 'Эксперт'; - @override String get withMods => 'С модами'; - @override String withModsPlural({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: 'с ${n} модами', - one: 'с ${n} модом', - two: 'с ${n} модами', - few: 'с ${n} модами', - many: 'с ${n} модами', - other: 'с ${n} модами', - ); - @override String get exportDB => 'Экспортировать локальную базу данных'; - @override String get exportDBDescription => 'Она содержит состояния аккаунтов и их матчей в Тетра Лиге для отслеживаемых игроков и список таких игроков.'; - @override String get desktopExportAlertTitle => 'Экспорт на десктопе'; - @override String get desktopExportText => 'Похоже, вы используете десктопную версию. Проверьте папку "Документы", там вы должны найти файл "TetraStats.db". Скопируйте его куда-нибудь'; - @override String get androidExportAlertTitle => 'Экспорт на Android'; - @override String androidExportText({required Object exportedDB}) => 'Экспортировано.\n${exportedDB}'; - @override String get importDB => 'Импортировать локальную базу данных'; - @override String get importDBDescription => 'Восстановите свою резеврную копию. Обратите внимание, что текущая база данных будет перезаписана.'; - @override String get importWrongFileType => 'Неверный тип файла'; - @override String get importCancelled => 'Операция была отменена'; - @override String get importSuccess => 'Успешно импортировано'; - @override String get yourID => 'Ваш аккаунт в TETR.IO'; - @override String get yourIDAlertTitle => 'Ваш ник в TETR.IO'; - @override String get yourIDText => 'При запуске приложения оно будет получать статистику этого игрока.'; - @override String get language => 'Язык (Language)'; - @override String get updateInBackground => 'Обновлять статистику в фоне'; - @override String get updateInBackgroundDescription => 'Пока Tetra Stats работает, он может обновлять статистику самостоятельно когда кеш истекает'; - @override String get customization => 'Кастомизация'; - @override String get customizationDescription => 'Измените внешний вид пользовательского интерфейса Tetra Stats'; - @override String get oskKagari => '"Оск Кагари" прикол'; - @override String get oskKagariDescription => 'Если включено, вместо настоящего ранга оска будет рендерится :kagari:'; - @override String get AccentColor => 'Цветовой акцент'; - @override String get AccentColorDescription => 'Почти все интерактивные элементы пользовательского интерфейса окрашены в этот цвет'; - @override String get timestamps => 'Метки времени'; - @override String get timestampsDescription => 'Вы можете выбрать, каким образом метки времени показывают время'; - @override String get timestampsAbsoluteGMT => 'Абсолютные (GMT)'; - @override String get timestampsAbsoluteLocalTime => 'Абсолютные (Ваш часовой пояс)'; - @override String get timestampsRelative => 'Относительные'; - @override String get rating => 'Основное представление рейтинга'; - @override String get ratingDescription => 'TR нелинеен, тогда как Glicko не имеет границ, а положение в таблице лидеров волатильно'; - @override String get ratingLBposition => 'Позиция в рейтинге'; - @override String get sheetbotGraphs => 'Графики-радары как у sheetBot'; - @override String get sheetbotGraphsDescription => 'Если включено, точки на графике могут появляться на противоположной стороне графика если значение отрицательное'; - @override String get lbStats => 'Показывать статистику, основанную на рейтинговой таблице'; - @override String get lbStatsDescription => 'Это повлияет на время загрузки, но позволит видеть положение в рейтинге и сравнение со средними значениями по рангу по каждой стате'; - @override String get aboutApp => 'О приложении'; - @override String aboutAppText({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) Версия ${version} Сборка ${buildNumber}\n\nРазработал dan63047\nФормулы предоставил kerrmunism\nИсторию предоставляет p1nkl0bst3r\nВозможность скачивать повторы из TETR.IO предоставляет szy'; - @override String stateViewTitle({required Object nickname, required Object date}) => 'Аккаунт ${nickname} ${date}'; - @override String statesViewTitle({required Object number, required Object nickname}) => '${number} состояний аккаунта ${nickname}'; - @override String matchesViewTitle({required Object nickname}) => 'Матчи аккаунта ${nickname}'; - @override String statesViewEntry({required Object level, required Object glicko, required Object rd, required Object games}) => '${level} TR, ${glicko}±${rd} Glicko, ${games} игр сыграно'; - @override String stateRemoved({required Object date}) => 'Состояние от ${date} было удалено из локальной базы данных!'; - @override String matchRemoved({required Object date}) => 'Матч от ${date} был удален из локальной базы данных!'; - @override String get viewAllMatches => 'Все матчи'; - @override String get trackedPlayersViewTitle => 'Сохранённые данные'; - @override String get trackedPlayersZeroEntrys => 'Пустой список. Вернитесь на предыдущий экран и нажмите кнопку "Отслеживать", чтобы текущий игрок появился здесь'; - @override String get trackedPlayersOneEntry => 'В списке только один игрок'; - @override String trackedPlayersManyEntrys({required Object numberOfPlayers}) => 'В списке ${numberOfPlayers} игроков'; - @override String trackedPlayersEntry({required Object nickname, required Object numberOfStates}) => '${nickname}: ${numberOfStates} состояний'; - @override String trackedPlayersDescription({required Object firstStateDate, required Object lastStateDate}) => 'Начиная с ${firstStateDate} и заканчивая ${lastStateDate}'; - @override String trackedPlayersStatesDeleted({required Object nickname}) => 'Состояния аккаунта ${nickname} были удалены из локальной базы данных!'; - @override String get duplicatedFix => 'Удалить дубликаты матчей в Тетра Лиге'; - @override String get compressDB => 'Сжать базу данных'; - @override String SpaceSaved({required Object size}) => 'Места освобождено: ${size}'; - @override String averageXrank({required Object rankLetter}) => 'Средний ${rankLetter} ранг'; - @override String get vs => 'против'; - @override String get inTLmatch => 'в матче ТЛ'; - @override String get downloadReplay => 'Скачать .ttrm повтор'; - @override String get openReplay => 'Открыть повтор в TETR.IO'; - @override String replaySaved({required Object path}) => 'Повтор сохранён по пути ${path}'; - @override String get match => 'Матч'; - @override String get timeWeightedmatch => 'Матч (взвешенная по времени)'; - @override String roundNumber({required Object n}) => 'Раунд ${n}'; - @override String get statsFor => 'Статистика за'; - @override String get numberOfRounds => 'Количество раундов'; - @override String get matchLength => 'Продолжительность матча'; - @override String get roundLength => 'Продолжительность раунда'; - @override String get matchStats => 'Статистика матча'; - @override String get timeWeightedmatchStats => 'Взвешенная по времени cтатистика матча'; - @override String get replayIssue => 'Ошибка обработки повтора'; - @override String get matchIsTooOld => 'Информация о повторе недоступна'; - @override String get winner => 'Победитель'; - @override String get registred => 'Зарегистрирован'; - @override String get playedTL => 'Играл в Тетра Лигу'; - @override String get winChance => 'Шансы на победу'; - @override String get byGlicko => 'По Glicko'; - @override String get byEstTR => 'По расч. TR'; - @override String compareViewNoValues({required Object avgR}) => 'Пожалуйста, введите никнейм, ID, APM-PPS-VS (неважно, какой разделитель, важен порядок) или ${avgR} (где R это ранг), в оба поля'; - @override String compareViewWrongValue({required Object value}) => 'Не удалось получить ${value}'; - @override String get mostRecentOne => 'Самый последний'; - @override String get yes => 'Да'; - @override String get no => 'Нет'; - @override String get daysLater => 'дней позже'; - @override String get dayseBefore => 'дней раньше'; - @override String get fromBeginning => 'С начала'; - @override String get calc => 'Считать'; - @override String get calcViewNoValues => 'Введите значения, чтобы посчитать статистику'; - @override String get rankAveragesViewTitle => 'Требования рангов'; - @override String get sprintAndBlitsViewTitle => 'Средние результаты 40 линий и блица'; - @override String sprintAndBlitsRelevance({required Object date}) => 'Актуальность: ${date}'; - @override String get rank => 'Ранг'; - @override String get averages => 'Средние значения'; - @override String get lbViewZeroEntrys => 'Рейтинговая таблица пуста'; - @override String get lbViewOneEntry => 'В рейтинговой таблице всего один игрок'; - @override String lbViewManyEntrys({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers}'; - @override String get everyoneAverages => 'Значения таблицы'; - @override String get sortBy => 'Cортировать по'; - @override String get reversed => 'Наоборот'; - @override String get country => 'Страна'; - @override String rankAverages({required Object rank}) => 'Значения для ${rank} ранга'; - @override String players({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} игроков', - one: '${n} игрок', - two: '${n} игрока', - few: '${n} игрока', - many: '${n} игроков', - other: '${n} игроков', - ); - @override String games({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} игр', - one: '${n} игра', - two: '${n} игры', - few: '${n} игры', - many: '${n} игр', - other: '${n} игр', - ); - @override String gamesPlayed({required Object games}) => '${games} сыграно'; - @override String get chart => 'График'; - @override String get entries => 'Список'; - @override String get minimums => 'Минимумы'; - @override String get maximums => 'Максимумы'; - @override String get lowestValues => 'Самые низкие показатели'; - @override String get averageValues => 'Средние значения показателей'; - @override String get highestValues => 'Самые высокие показатели'; - @override String forPlayer({required Object username}) => 'для игрока ${username}'; - @override String currentAxis({required Object axis}) => 'Ось ${axis}:'; - @override String get p1nkl0bst3rAlert => 'Эти данные были получены из стороннего API, который поддерживается p1nkl0bst3r'; - @override String get notForWeb => 'Функция недоступна для веб версии'; - @override late final _StringsGraphsRu graphs = _StringsGraphsRu._(_root); - @override late final _StringsStatCellNumRu statCellNum = _StringsStatCellNumRu._(_root); - @override Map get playerRole => { - 'user': 'Пользователь', - 'banned': 'Заблокированный пользователь', - 'bot': 'Бот', - 'sysop': 'Системный оператор', - 'admin': 'Администратор', - 'mod': 'Модератор', - 'halfmod': 'Модератор сообщества', - 'anon': 'Аноним', - }; - @override late final _StringsNumOfGameActionsRu numOfGameActions = _StringsNumOfGameActionsRu._(_root); - @override late final _StringsPopupActionsRu popupActions = _StringsPopupActionsRu._(_root); - @override late final _StringsErrorsRu errors = _StringsErrorsRu._(_root); - @override Map get countries => { - '': 'Во всём мире', - 'AF': 'Афганистан', - 'AX': 'Аландские острова', - 'AL': 'Албания', - 'DZ': 'Алжир', - 'AS': 'Американское Самоа', - 'AD': 'Андорра', - 'AO': 'Ангола', - 'AI': 'Ангилья', - 'AQ': 'Антарктида', - 'AG': 'Антигуа и Барбуда', - 'AR': 'Аргентина', - 'AM': 'Армения', - 'AW': 'Аруба', - 'AU': 'Австралия', - 'AT': 'Австрия', - 'AZ': 'Азербайджан', - 'BS': 'Багамские острова', - 'BH': 'Бахрейн', - 'BD': 'Бангладеш', - 'BB': 'Барбадос', - 'BY': 'Беларусь', - 'BE': 'Бельгия', - 'BZ': 'Белиз', - 'BJ': 'Бенин', - 'BM': 'Бермуды', - 'BT': 'Бутан', - 'BO': 'Боливия, Многонациональное Государство', - 'BA': 'Босния и Герцеговина', - 'BW': 'Ботсвана', - 'BV': 'Остров Буве', - 'BR': 'Бразилия', - 'IO': 'Британская территория в Индийском океане', - 'BN': 'Бруней-Даруссалам', - 'BG': 'Болгария', - 'BF': 'Буркина-Фасо', - 'BI': 'Бурунди', - 'KH': 'Камбоджа', - 'CM': 'Камерун', - 'CA': 'Канада', - 'CV': 'Кабо-Верде', - 'BQ': 'Карибские Нидерланды', - 'KY': 'Каймановы острова', - 'CF': 'Центральноафриканская Республика', - 'TD': 'Чад', - 'CL': 'Чили', - 'CN': 'Китай', - 'CX': 'Остров Рождества', - 'CC': 'Кокосовые острова', - 'CO': 'Колумбия', - 'KM': 'Коморские острова', - 'CG': 'Конго', - 'CD': 'Конго, Демократическая Республика', - 'CK': 'Острова Кука', - 'CR': 'Коста-Рика', - 'CI': 'Берег Слоновой Кости', - 'HR': 'Хорватия', - 'CU': 'Куба', - 'CW': 'Кюрасао', - 'CY': 'Кипр', - 'CZ': 'Чешская Республика', - 'DK': 'Дания', - 'DJ': 'Джибути', - 'DM': 'Доминика', - 'DO': 'Доминиканская Республика', - 'EC': 'Эквадор', - 'EG': 'Египет', - 'SV': 'Сальвадор', - 'GB-ENG': 'Англия', - 'GQ': 'Экваториальная Гвинея', - 'ER': 'Эритрея', - 'EE': 'Эстония', - 'ET': 'Эфиопия', - 'EU': 'Европа', - 'FK': 'Фолклендские (Мальвинские) острова', - 'FO': 'Фарерские острова', - 'FJ': 'Фиджи', - 'FI': 'Финляндия', - 'FR': 'Франция', - 'GF': 'Французская Гвиана', - 'PF': 'Французская Полинезия', - 'TF': 'Южные территории Франции', - 'GA': 'Габон', - 'GM': 'Гамбия', - 'GE': 'Грузия', - 'DE': 'Германия', - 'GH': 'Гана', - 'GI': 'Гибралтар', - 'GR': 'Греция', - 'GL': 'Гренландия', - 'GD': 'Гренада', - 'GP': 'Гваделупа', - 'GU': 'Гуам', - 'GT': 'Гватемала', - 'GG': 'Гернси', - 'GN': 'Гвинея', - 'GW': 'Гвинея-Бисау', - 'GY': 'Гайана', - 'HT': 'Гаити', - 'HM': 'Остров Херд и острова Макдональд', - 'VA': 'Святой Престол (государство-городок Ватикан)', - 'HN': 'Гондурас', - 'HK': 'Гонконг', - 'HU': 'Венгрия', - 'IS': 'Исландия', - 'IN': 'Индия', - 'ID': 'Индонезия', - 'IR': 'Иран, Исламская Республика', - 'IQ': 'Ирак', - 'IE': 'Ирландия', - 'IM': 'Остров Мэн', - 'IL': 'Израиль', - 'IT': 'Италия', - 'JM': 'Ямайка', - 'JP': 'Япония', - 'JE': 'Джерси', - 'JO': 'Иордания', - 'KZ': 'Казахстан', - 'KE': 'Кения', - 'KI': 'Кирибати', - 'KP': 'Корея, Народно-Демократическая Республика', - 'KR': 'Корея, Республика', - 'XK': 'Косово', - 'KW': 'Кувейт', - 'KG': 'Кыргызстан', - 'LA': 'Лаосская Народно-Демократическая Республика', - 'LV': 'Латвия', - 'LB': 'Ливан', - 'LS': 'Лесото', - 'LR': 'Либерия', - 'LY': 'Ливия', - 'LI': 'Лихтенштейн', - 'LT': 'Литва', - 'LU': 'Люксембург', - 'MO': 'Макао', - 'MK': 'Македония, бывшая югославская республика', - 'MG': 'Мадагаскар', - 'MW': 'Малави', - 'MY': 'Малайзия', - 'MV': 'Мальдивы', - 'ML': 'Мали', - 'MT': 'Мальта', - 'MH': 'Маршалловы острова', - 'MQ': 'Мартиника', - 'MR': 'Мавритания', - 'MU': 'Маврикий', - 'YT': 'Майотта', - 'MX': 'Мексика', - 'FM': 'Микронезия, Федеративные Штаты', - 'MD': 'Молдова, Республика', - 'MC': 'Монако', - 'ME': 'Черногория', - 'MA': 'Марокко', - 'MN': 'Монголия', - 'MS': 'Монтсеррат', - 'MZ': 'Мозамбик', - 'MM': 'Мьянма', - 'NA': 'Намибия', - 'NR': 'Науру', - 'NP': 'Непал', - 'NL': 'Нидерланды', - 'AN': 'Нидерландские Антильские острова', - 'NC': 'Новая Каледония', - 'NZ': 'Новая Зеландия', - 'NI': 'Никарагуа', - 'NE': 'Нигер', - 'NG': 'Нигерия', - 'NU': 'Ниуэ', - 'NF': 'Остров Норфолк', - 'GB-NIR': 'Северная Ирландия', - 'MP': 'Северные Марианские острова', - 'NO': 'Норвегия', - 'OM': 'Оман', - 'PK': 'Пакистан', - 'PW': 'Палау', - 'PS': 'Палестина', - 'PA': 'Панама', - 'PG': 'Папуа-Новая Гвинея', - 'PY': 'Парагвай', - 'PE': 'Перу', - 'PH': 'Филиппины', - 'PN': 'Питкэрн', - 'PL': 'Польша', - 'PT': 'Португалия', - 'PR': 'Пуэрто-Рико', - 'QA': 'Катар', - 'RE': 'Реюньон', - 'RO': 'Румыния', - 'RU': 'Российская Федерация', - 'RW': 'Руанда', - 'BL': 'Сен-Бартелеми', - 'SH': 'Острова Святой Елены, Вознесения и Тристан-да-Кунья', - 'KN': 'Сент-Китс и Невис', - 'LC': 'Сент-Люсия', - 'MF': 'Сен-Мартен', - 'PM': 'Сен-Пьер и Микелон', - 'VC': 'Сент-Винсент и Гренадины', - 'WS': 'Самоа', - 'SM': 'Сан-Марино', - 'ST': 'Сан-Томе и Принсипи', - 'SA': 'Саудовская Аравия', - 'GB-SCT': 'Шотландия', - 'SN': 'Сенегал', - 'RS': 'Сербия', - 'SC': 'Сейшельские острова', - 'SL': 'Сьерра-Леоне', - 'SG': 'Сингапур', - 'SX': 'Синт-Мартен (голландская часть)', - 'SK': 'Словакия', - 'SI': 'Словения', - 'SB': 'Соломоновы острова', - 'SO': 'Сомали', - 'ZA': 'ЮАР', - 'GS': 'Южная Георгия и Южные Сандвичевы острова', - 'SS': 'Южный Судан', - 'ES': 'Испания', - 'LK': 'Шри-Ланка', - 'SD': 'Судан', - 'SR': 'Суринам', - 'SJ': 'Острова Шпицберген и Ян-Майен', - 'SZ': 'Свазиленд', - 'SE': 'Швеция', - 'CH': 'Швейцария', - 'SY': 'Сирийская Арабская Республика', - 'TW': 'Тайвань', - 'TJ': 'Таджикистан', - 'TZ': 'Танзания, Объединенная Республика', - 'TH': 'Таиланд', - 'TL': 'Тимор-Лешти', - 'TG': 'Того', - 'TK': 'Токелау', - 'TO': 'Tonga', - 'TT': 'Тринидад и Тобаго', - 'TN': 'Тунис', - 'TR': 'Турция', - 'TM': 'Туркменистан', - 'TC': 'Острова Теркс и Кайкос', - 'ТВ': 'Тувалу', - 'UG': 'Уганда', - 'UA': 'Украина', - 'AE': 'Объединенные Арабские Эмираты', - 'GB': 'Великобритания', - 'US': 'Соединенные Штаты', - 'UY': 'Уругвай', - 'UM': 'Малые периферийные острова США', - 'UZ': 'Узбекистан', - 'VU': 'Вануату', - 'VE': 'Венесуэла, Боливарианская Республика', - 'VN': 'Вьетнам', - 'VG': 'Виргинские острова, Британские', - 'VI': 'Виргинские острова, США', - 'GB-WLS': 'Уэльс', - 'WF': 'Острова Уоллис и Футуна', - 'EH': 'Западная Сахара', - 'YE': 'Йемен', - 'ZM': 'Замбия', - 'ZW': 'Зимбабве', - 'XX': 'Неизвестно', - 'XM': 'Луна', - }; + String get cancel => 'Cancel'; + String get submit => 'Submit'; + String get ok => 'OK'; + String get apply => 'Apply'; + String get refresh => 'Refresh'; } -// Path: newsParts -class _StringsNewsPartsRu implements _StringsNewsPartsEn { - _StringsNewsPartsRu._(this._root); +// Path: graphsDestination +class _StringsGraphsDestinationEn { + _StringsGraphsDestinationEn._(this._root); - @override final _StringsRu _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get leaderboardStart => 'Взял '; - @override String get leaderboardMiddle => 'в таблице '; - @override String get personalbest => 'Поставил новый ЛР в '; - @override String get personalbestMiddle => 'с результатом в '; - @override String get badgeStart => 'Заработал значок '; - @override String get badgeEnd => ''; - @override String get rankupStart => 'Заработал '; - @override String rankupMiddle({required Object r}) => '${r} ранг '; - @override String get rankupEnd => 'в Тетра Лиге'; - @override String get tetoSupporter => 'TETR.IO supporter'; - @override String get supporterStart => 'Стал обладателем '; - @override String get supporterGiftStart => 'Получил подарок в виде '; - @override String unknownNews({required Object type}) => 'Неизвестная новость типа ${type}'; + String get fetchAndsaveTLHistory => 'Get player history'; + String get fetchAndSaveOldTLmatches => 'Get Tetra League matches history'; + String fetchAndsaveTLHistoryResult({required Object number}) => '${number} states was found'; + String fetchAndSaveOldTLmatchesResult({required Object number}) => '${number} matches was found'; + String gamesPlayed({required Object games}) => '${games} played'; + String get dateAndTime => 'Date & Time'; + String get filterModaleTitle => 'Filter ranks on graph'; } -// Path: graphs -class _StringsGraphsRu implements _StringsGraphsEn { - _StringsGraphsRu._(this._root); +// Path: filterModale +class _StringsFilterModaleEn { + _StringsFilterModaleEn._(this._root); - @override final _StringsRu _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get attack => 'Атака'; - @override String get speed => 'Скорость'; - @override String get defense => 'Защита'; - @override String get cheese => 'Сыр'; + String get all => 'All'; } -// Path: statCellNum -class _StringsStatCellNumRu implements _StringsStatCellNumEn { - _StringsStatCellNumRu._(this._root); +// Path: cutoffsDestination +class _StringsCutoffsDestinationEn { + _StringsCutoffsDestinationEn._(this._root); - @override final _StringsRu _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get xpLevel => 'Уровень\nопыта'; - @override String get xpProgress => 'Прогресс до следующего уровня'; - @override String xpFrom0ToLevel({required Object n}) => 'Прогресс от 0 XP до ${n} уровня'; - @override String get xpLeft => 'XP осталось'; - @override String get hoursPlayed => 'Часов\nСыграно'; - @override String get onlineGames => 'Онлайн\nИгр'; - @override String get gamesWon => 'Онлайн\nПобед'; - @override String get totalGames => 'Всего матчей'; - @override String get totalWon => 'Всего побед'; - @override String get friends => 'Друзей'; - @override String get apm => 'Атака в\nМинуту'; - @override String get vs => 'Показатель\nVersus'; - @override String get recordLB => 'Место в таблице'; - @override String get lbp => 'Положение\nв рейтинге'; - @override String get lbpShort => '№ в рейтинге'; - @override String get lbpc => 'Положение\nв рейтинге страны'; - @override String get lbpcShort => '№ по стране'; - @override String get gamesPlayed => 'Игр\nСыграно'; - @override String get gamesWonTL => 'Побед'; - @override String get winrate => 'Процент\nпобед'; - @override String get level => 'Уровень'; - @override String get score => 'Счёт'; - @override String get spp => 'Очков\nна Фигуру'; - @override String get pieces => 'Фигур\nУстановлено'; - @override String get pps => 'Фигур в\nСекунду'; - @override String get finesseFaults => 'Ошибок\nТехники'; - @override String get finessePercentage => '% Качества\nТехники'; - @override String get keys => 'Нажатий\nКлавиш'; - @override String get kpp => 'Нажатий\nна Фигуру'; - @override String get kps => 'Нажатий\nв Секунду'; - @override String get tr => 'Тетра Рейтинг'; - @override String get rd => 'Отклонение рейтинга'; - @override String get app => 'Атака на Фигуру'; - @override String get appDescription => '(Сокращенно APP) Главный показатель эффективности. Показывает, сколько атаки приходится на одну фигуру'; - @override String get vsapmDescription => 'В основном, показывает как много мусора игрок использует в своих атаках и насколько эффективно.'; - @override String get dss => 'Downstack\nв Секунду'; - @override String get dssDescription => '(Сокращенно DS/S) Downstack (спуск вниз) в Секунду показывает как много мусорных линий в среднем игрок убирает за одну секунду.'; - @override String get dsp => 'Downstack\nна Фигуру'; - @override String get dspDescription => '(Сокращенно DS/P) Downstack (спуск вниз) на Фигуру показывает как много мусорных линий в среднем игрок убирает одну фигуру.'; - @override String get appdsp => 'APP + DS/P'; - @override String get appdspDescription => 'Просто сумма Атаки на Фигуру и Downstack на Фигуру.'; - @override String get cheese => 'Индекс сыра'; - @override String get cheeseDescription => '(Сокращенно Cheese) Индекс сыра является аппроксимацией того, насколько чистый / дырявый мусор игрок отправляет. Меньше = более чистый. Больше = более дырявый.\nПридумал kerrmunism'; - @override String get gbe => 'Garbage\nEfficiency'; - @override String get gbeDescription => '(Сокращенно Gb Eff.) Garbage Efficiency показывает насколько хорошо игрок использует свой мусор. Больше = лучше (или он использует больше мусора). Меньше = в основном отправляют сыр (или он редко чистит мусор).\nПридумали Zepheniah и Dragonboy.'; - @override String get nyaapp => 'Взвешенный\nAPP'; - @override String get nyaappDescription => '(Сокращенно wAPP) По сути, показывает способность отправлять сыр, сохраняя при этом высокую эффективность.\nПридумал Wertj.'; - @override String get area => 'Area'; - @override String get areaDescription => 'Какую площадь занимает диаграмма, если не брать в расчёт индекс сыра и VS/APM'; - @override String get estOfTR => 'Расчётный TR'; - @override String get estOfTRShort => 'Расч. TR'; - @override String get accOfEst => 'Точность расчёта'; - @override String get accOfEstShort => 'Точность'; + String get title => 'Tetra League State'; + String relevance({required Object timestamp}) => 'as of ${timestamp}'; + String get actual => 'Actual'; + String get target => 'Target'; + String get cutoffTR => 'Cutoff TR'; + String get targetTR => 'Target TR'; + String get state => 'State'; + String get advanced => 'Advanced'; + String players({required Object n}) => 'Players (${n})'; + String get moreInfo => 'More Info'; + String NumberOne({required Object tr}) => '№ 1 is ${tr} TR'; + String inflated({required Object tr}) => 'Inflated on ${tr} TR'; + String get notInflated => 'Not inflated'; + String deflated({required Object tr}) => 'Deflated on ${tr} TR'; + String get notDeflated => 'Not deflated'; + String get wellDotDotDot => 'Well...'; + String fromPlace({required Object n}) => 'from № ${n}'; + String get viewButton => 'View'; } -// Path: numOfGameActions -class _StringsNumOfGameActionsRu implements _StringsNumOfGameActionsEn { - _StringsNumOfGameActionsRu._(this._root); +// Path: rankView +class _StringsRankViewEn { + _StringsRankViewEn._(this._root); - @override final _StringsRu _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get pc => 'Все чисто'; - @override String get hold => 'В запас'; - @override String inputs({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} нажатий клавиш', - one: '${n} нажатие на клавишу', - two: '${n} нажатия на клавишы', - few: '${n} нажатия на клавишы', - many: '${n} нажатий на клавиш', - other: '${n} нажатий на клавиш', + String rankTitle({required Object rank}) => '${rank} rank data'; + String get everyoneTitle => 'Entire leaderboard'; + String get trRange => 'TR Range'; + String get supposedToBe => 'Supposed to be'; + String gap({required Object value}) => '${value} gap'; + String get deflationGap => 'Deflation gap'; + String get inflationGap => 'Inflation gap'; + String get LBposRange => 'LB pos range'; + String overpopulated({required Object players}) => 'Overpopulated by a ${players}'; + String underpopulated({required Object players}) => 'Underpopulated by a ${players}'; + String get PlayersEqualSupposedToBe => 'cute'; + String get avgStats => 'Average Stats'; + String get avgNerdStats => 'Average Nerd Stats'; + String get minimums => 'Minimums'; + String get maximums => 'Maximums'; +} + +// Path: tlMatchView +class _StringsTlMatchViewEn { + _StringsTlMatchViewEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get match => 'Match'; + String get vs => 'vs'; + String get winner => 'Winner'; + String roundNumber({required Object n}) => 'Round ${n}'; + String get statsFor => 'Stats for'; + String get numberOfRounds => 'Number of rounds'; + String get matchLength => 'Match Length'; + String get roundLength => 'Round Length'; + String get matchStats => 'Match stats'; + String get downloadReplay => 'Download .ttrm replay'; + String get openReplay => 'Open replay in TETR.IO'; +} + +// Path: calcDestination +class _StringsCalcDestinationEn { + _StringsCalcDestinationEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get tip => 'Enter values and press "Calc" to see Nerd Stats for them'; + String get statsCalcButton => 'Calc'; + String get damageCalcTip => 'Click on the actions on the left to add them here'; + String get actions => 'Actions'; + String get results => 'Results'; + String get rules => 'Rules'; + String get noSpinClears => 'No Spin Clears'; + String get spins => 'Spins'; + String get miniSpins => 'Mini spins'; + String get noLineclear => 'No lineclear (Break Combo)'; + String get custom => 'Custom'; + String get multiplier => 'Multiplier'; + String get pcDamage => 'Perfect Clear Damage'; + String get comboTable => 'Combo Table'; + String get b2bChaining => 'Back-To-Back Chaining'; + String get surgeStartAtB2B => 'Starts at B2B'; + String get surgeStartAmount => 'Start amount'; + String get totalDamage => 'Total damage'; + String get lineclears => 'Lineclears'; + String get combo => 'Combo'; + String get surge => 'Surge'; + String get pcs => 'PCs'; +} + +// Path: infoDestination +class _StringsInfoDestinationEn { + _StringsInfoDestinationEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get title => 'Information Center'; + String get sprintAndBlitzAverages => '40 Lines & Blitz Averages'; + String get sprintAndBlitzAveragesDescription => 'Since calculating 40 Lines & Blitz averages is tedious process, it gets updated only once in a while. Click on the title of this card to see the full 40 Lines & Blitz averages table'; + String get tetraStatsWiki => 'Tetra Stats Wiki'; + String get tetraStatsWikiDescription => 'Find more information about Tetra Stats functions and statictic, that it provides'; + String get about => 'About Tetra Stats'; + String get aboutDescription => 'Developed by dan63\n'; +} + +// Path: leaderboardsDestination +class _StringsLeaderboardsDestinationEn { + _StringsLeaderboardsDestinationEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get title => 'Leaderboards'; + String get tl => 'Tetra League (Current Season)'; + String get fullTL => 'Tetra League (Current Season, full one)'; + String get ar => 'Acievement Points'; + String get fullTLnote => 'Heavy, but allows you to sort players by their stats and filter them by ranks'; +} + +// Path: settingsDestination +class _StringsSettingsDestinationEn { + _StringsSettingsDestinationEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get title => 'Settings'; + String get timestamps => 'Timestamps'; + String get timestampsDescription => 'You can choose, in which way timestamps shows time'; + String get timestampsAbsoluteGMT => 'Absolute (GMT)'; + String get timestampsAbsoluteLocalTime => 'Absolute (Your timezone)'; + String get timestampsRelative => 'Relative'; + String get exportDB => 'Export local database'; + String get desktopExportAlertTitle => 'Desktop export'; + String get desktopExportText => 'It seems like you using this app on desktop. Check your documents folder, you should find "TetraStats.db". Copy it somewhere'; + String get androidExportAlertTitle => 'Android export'; + String androidExportText({required Object exportedDB}) => 'Exported.\n${exportedDB}'; + String get importDB => 'Import local database'; + String get importDBDescription => 'Restore your backup. Notice that already stored database will be overwritten.'; + String get importWrongFileType => 'Wrong file type'; +} + +// Path: homeNavigation +class _StringsHomeNavigationEn { + _StringsHomeNavigationEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get overview => 'Overview'; + String get standing => 'Standing'; + String get seasons => 'Seasons'; + String get mathces => 'Matches'; + String get pb => 'PB'; + String get normal => 'Normal'; + String get expert => 'Expert'; + String get expertRecords => 'Ex Records'; +} + +// Path: graphsNavigation +class _StringsGraphsNavigationEn { + _StringsGraphsNavigationEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get history => 'Player History'; + String get league => 'League State'; + String get cutoffs => 'Cutoffs History'; +} + +// Path: calcNavigation +class _StringsCalcNavigationEn { + _StringsCalcNavigationEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get stats => 'Stats Calculator'; + String get damage => 'Damage Calculator'; +} + +// Path: aboutView +class _StringsAboutViewEn { + _StringsAboutViewEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get title => 'About Tetra Stats'; + String get about => 'Tetra Stats is a service, that works with TETR.IO Tetra Channel API, providing data from it and calculating some addtitional metrics, based on this data. Service allows user to track their progress in Tetra League with "Track" function, which records every Tetra League change into local database (not automatically, you have to visit service from time to time), so these changes could be looked through graphs.\n\nBeanserver blaster is a part of a Tetra Stats, that decoupled into a serverside script. It provides full Tetra League leaderboard, allowing Tetra Stats to sort leaderboard by any metric and build scatter chart, that allows user to analyse Tetra League trends. It also provides history of Tetra League ranks cutoffs, which can be viewed by user via graph as well.\n\nThere is a plans to add replay analysis and tournaments history, so stay tuned!\n\nService is not associated with TETR.IO or osk in any capacity.'; + String get appVersion => 'App Version'; + String build({required Object build}) => 'Build ${build}'; + String get GHrepo => 'GitHub Repository'; + String get submitAnIssue => 'Submit an issue'; + String get credits => 'Credits'; + String get authorAndDeveloper => 'Autor & developer'; + String get providedFormulas => 'Provided formulas'; + String get providedS1history => 'Provided S1 history'; + String get inoue => 'Inoue (replay grabber)'; + String get zhCNlocale => 'Simplfied Chinise locale'; + String get supportHim => 'Support him!'; +} + +// Path: stats +class _StringsStatsEn { + _StringsStatsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get registrationDate => 'Registration Date'; + String get gametime => 'Time Played'; + String get ogp => 'Online Games Played'; + String get ogw => 'Online Games Won'; + String get followers => 'Followers'; + late final _StringsStatsXpEn xp = _StringsStatsXpEn._(_root); + late final _StringsStatsTrEn tr = _StringsStatsTrEn._(_root); + late final _StringsStatsGlickoEn glicko = _StringsStatsGlickoEn._(_root); + late final _StringsStatsRdEn rd = _StringsStatsRdEn._(_root); + late final _StringsStatsGlixareEn glixare = _StringsStatsGlixareEn._(_root); + late final _StringsStatsS1trEn s1tr = _StringsStatsS1trEn._(_root); + late final _StringsStatsGpEn gp = _StringsStatsGpEn._(_root); + late final _StringsStatsGwEn gw = _StringsStatsGwEn._(_root); + late final _StringsStatsWinrateEn winrate = _StringsStatsWinrateEn._(_root); + late final _StringsStatsApmEn apm = _StringsStatsApmEn._(_root); + late final _StringsStatsPpsEn pps = _StringsStatsPpsEn._(_root); + late final _StringsStatsVsEn vs = _StringsStatsVsEn._(_root); + late final _StringsStatsAppEn app = _StringsStatsAppEn._(_root); + late final _StringsStatsVsapmEn vsapm = _StringsStatsVsapmEn._(_root); + late final _StringsStatsDssEn dss = _StringsStatsDssEn._(_root); + late final _StringsStatsDspEn dsp = _StringsStatsDspEn._(_root); + late final _StringsStatsAppdspEn appdsp = _StringsStatsAppdspEn._(_root); + late final _StringsStatsCheeseEn cheese = _StringsStatsCheeseEn._(_root); + late final _StringsStatsGbeEn gbe = _StringsStatsGbeEn._(_root); + late final _StringsStatsNyaappEn nyaapp = _StringsStatsNyaappEn._(_root); + late final _StringsStatsAreaEn area = _StringsStatsAreaEn._(_root); + late final _StringsStatsEtrEn etr = _StringsStatsEtrEn._(_root); + late final _StringsStatsEtraccEn etracc = _StringsStatsEtraccEn._(_root); + late final _StringsStatsOpenerEn opener = _StringsStatsOpenerEn._(_root); + late final _StringsStatsPlonkEn plonk = _StringsStatsPlonkEn._(_root); + late final _StringsStatsStrideEn stride = _StringsStatsStrideEn._(_root); + late final _StringsStatsInfdsEn infds = _StringsStatsInfdsEn._(_root); + late final _StringsStatsAltitudeEn altitude = _StringsStatsAltitudeEn._(_root); + late final _StringsStatsClimbSpeedEn climbSpeed = _StringsStatsClimbSpeedEn._(_root); + late final _StringsStatsPeakClimbSpeedEn peakClimbSpeed = _StringsStatsPeakClimbSpeedEn._(_root); + late final _StringsStatsKosEn kos = _StringsStatsKosEn._(_root); + late final _StringsStatsB2bEn b2b = _StringsStatsB2bEn._(_root); + late final _StringsStatsFinesseEn finesse = _StringsStatsFinesseEn._(_root); + late final _StringsStatsFinesseFaultsEn finesseFaults = _StringsStatsFinesseFaultsEn._(_root); + late final _StringsStatsTotalTimeEn totalTime = _StringsStatsTotalTimeEn._(_root); + late final _StringsStatsLevelEn level = _StringsStatsLevelEn._(_root); + late final _StringsStatsPiecesEn pieces = _StringsStatsPiecesEn._(_root); + late final _StringsStatsSppEn spp = _StringsStatsSppEn._(_root); + late final _StringsStatsKpEn kp = _StringsStatsKpEn._(_root); + late final _StringsStatsKppEn kpp = _StringsStatsKppEn._(_root); + late final _StringsStatsKpsEn kps = _StringsStatsKpsEn._(_root); + String blitzScore({required Object p}) => '${p} points'; + String levelUpRequirement({required Object p}) => 'Level up requirement: ${p}'; + String get piecesTotal => 'Total pieces placed'; + String get piecesWithPerfectFinesse => 'Placed with perfect finesse'; + String get score => 'Score'; + String get lines => 'Lines'; + String get pcs => 'Perfect Clears'; + String get holds => 'Holds'; + String get spike => 'Top Spike'; + String top({required Object percentage}) => 'Top ${percentage}'; + String topRank({required Object rank}) => 'Top rank: ${rank}'; + String get floor => 'Floor'; + String get split => 'Split'; + String get total => 'Total'; + String get sent => 'Sent'; + String get received => 'Received'; + String get placement => 'Placement'; + String qpWithMods({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + one: 'With 1 mod', + two: 'With ${n} mods', + few: 'With ${n} mods', + many: 'With ${n} mods', + other: 'With ${n} mods', ); - @override String tspinsTotal({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} T-спинов всего', - one: 'Всего ${n} T-спин', - two: '${n} T-спина всего', - few: '${n} T-спина всего', - many: '${n} T-спинов всего', - other: '${n} T-спинов всего', + String inputs({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} key presses', + one: '${n} key press', + two: '${n} key presses', + few: '${n} key presses', + many: '${n} key presses', + other: '${n} key presses', ); - @override String lineClears({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} линий очищено', - one: '${n} линия очищена', - two: '${n} линии очищено', - few: '${n} линии очищено', - many: '${n} линий очищено', - other: '${n} линий очищено', + String tspinsTotal({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} T-spins total', + one: '${n} T-spin total', + two: '${n} T-spins total', + few: '${n} T-spins total', + many: '${n} T-spins total', + other: '${n} T-spins total', ); + String linesCleared({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} lines cleared', + one: '${n} line cleared', + two: '${n} lines cleared', + few: '${n} lines cleared', + many: '${n} lines cleared', + other: '${n} lines cleared', + ); + late final _StringsStatsGraphsEn graphs = _StringsStatsGraphsEn._(_root); + String players({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} players', + one: '${n} player', + two: '${n} players', + few: '${n} players', + many: '${n} players', + other: '${n} players', + ); + String games({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} games', + one: '${n} game', + two: '${n} games', + few: '${n} games', + many: '${n} games', + other: '${n} games', + ); + late final _StringsStatsLineClearEn lineClear = _StringsStatsLineClearEn._(_root); + late final _StringsStatsLineClearsEn lineClears = _StringsStatsLineClearsEn._(_root); + String get mini => 'Mini'; + String get tSpin => 'T-spin'; + String get tSpins => 'T-spins'; + String get spin => 'Spin'; + String get spins => 'Spins'; } -// Path: popupActions -class _StringsPopupActionsRu implements _StringsPopupActionsEn { - _StringsPopupActionsRu._(this._root); +// Path: stats.xp +class _StringsStatsXpEn { + _StringsStatsXpEn._(this._root); - @override final _StringsRu _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get cancel => 'Отменить'; - @override String get submit => 'Подтвердить'; - @override String get ok => 'OK'; + String get short => 'XP'; + String get full => 'Experience Points'; } -// Path: errors -class _StringsErrorsRu implements _StringsErrorsEn { - _StringsErrorsRu._(this._root); +// Path: stats.tr +class _StringsStatsTrEn { + _StringsStatsTrEn._(this._root); - @override final _StringsRu _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String connection({required Object code, required Object message}) => 'Проблема с подключением: ${code} ${message}'; - @override String get noSuchUser => 'Нет такого пользователя'; - @override String get noSuchUserSub => 'Либо вы ошиблись при вводе, либо аккаунта больше не существует'; - @override String get discordNotAssigned => 'К данному Discord ID не привязан аккаунт'; - @override String get discordNotAssignedSub => 'Убедитесь в том, что вы вставили правильный ID'; - @override String get history => 'История данного игрока отсутствует'; - @override String get actionSuggestion => 'Возможно, вы хотите'; - @override String get p1nkl0bst3rTLmatches => 'Старых матчей Тетра Лиги не было найдено'; - @override String get clientException => 'Нет соединения с интернетом'; - @override String get forbidden => 'Ваш IP адрес заблокирован'; - @override String forbiddenSub({required Object nickname}) => 'Если у вас работает VPN или прокси, выключите его. Если это не помогло, свяжитесь с ${nickname}'; - @override String get tooManyRequests => 'Слишком много запросов'; - @override String get tooManyRequestsSub => 'Подождите немного и попробуйте снова'; - @override String get internal => 'Что-то случилось на стороне tetr.io'; - @override String get internalSub => 'Скорее всего, osk уже в курсе об этом'; - @override String get internalWebVersion => 'Что-то случилось на стороне tetr.io (или на стороне oskware_bridge, я хз если честно)'; - @override String get internalWebVersionSub => 'Если статус страница osk-а говорит, что всё ок - свяжитесь с dan63047'; - @override String get oskwareBridge => 'Что-то случилось с oskware_bridge'; - @override String get oskwareBridgeSub => 'Дайте dan63047 знать'; - @override String get p1nkl0bst3rForbidden => 'Стороннее API заблокировало ваш IP адрес'; - @override String get p1nkl0bst3rTooManyRequests => 'Слишком много запросов к стороннему API. Попробуйте позже'; - @override String get p1nkl0bst3rinternal => 'Что-то случилось на стороне p1nkl0bst3r-а'; - @override String get p1nkl0bst3rinternalWebVersion => 'Что-то случилось на стороне p1nkl0bst3r-а (или на стороне oskware_bridge, я хз если честно)'; - @override String get replayAlreadySaved => 'Повтор уже сохранён'; - @override String get replayExpired => 'Повтор истёк и больше недоступен'; - @override String get replayRejected => 'Стороннее API заблокировало ваш IP адрес'; + String get short => 'TR'; + String get full => 'Tetra Rating'; } -// Path: -class _StringsZhCn implements Translations { - /// You can call this constructor and build your own translation instance of this locale. - /// Constructing via the enum [AppLocale.build] is preferred. - _StringsZhCn.build({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) - : assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'), - $meta = TranslationMetadata( - locale: AppLocale.zhCn, - overrides: overrides ?? {}, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ) { - $meta.setFlatMapFunction(_flatMapFunction); - } +// Path: stats.glicko +class _StringsStatsGlickoEn { + _StringsStatsGlickoEn._(this._root); - /// Metadata for the translations of . - @override final TranslationMetadata $meta; - - /// Access flat map - @override dynamic operator[](String key) => $meta.getTranslation(key); - - @override late final _StringsZhCn _root = this; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override Map get locales => { - 'en': '英语 (English)', - 'ru': '俄语 (Русский)', - 'zh-CN': '简体中文', - }; - @override String get tetraLeague => 'Tetra联赛'; - @override String get tlRecords => 'Tetra联赛记录'; - @override String get history => '历史'; - @override String get sprint => '40行竞速'; - @override String get blitz => '闪电战'; - @override String get recent => '最近'; - @override String get recentRuns => '最近游玩局数'; - @override String blitzScore({required Object p}) => '${p} 分'; - @override String get openSPreplay => '在TETR.IO打开回放'; - @override String get downloadSPreplay => '下载回放'; - @override String get other => '其他'; - @override String get distinguishment => '区别'; - @override String get zen => '禅意模式'; - @override String get bio => '个人简介'; - @override String get news => '新闻'; - @override late final _StringsNewsPartsZhCn newsParts = _StringsNewsPartsZhCn._(_root); - @override String get openSearch => '搜索玩家'; - @override String get closeSearch => '关闭搜索'; - @override String get searchHint => '昵称,ID或Discord用户ID(需要 "ds:" 前缀)'; - @override String get refresh => '刷新'; - @override String get fetchAndsaveTLHistory => '获取玩家历史'; - @override String get fetchAndSaveOldTLmatches => '获取玩家Tetra联赛历史'; - @override String fetchAndsaveTLHistoryResult({required Object number}) => '找到 ${number} 个状态'; - @override String fetchAndSaveOldTLmatchesResult({required Object number}) => '找到 ${number} 场Tetra联赛比赛'; - @override String get showStoredData => '显示获得的数据'; - @override String get statsCalc => '统计计算器'; - @override String get settings => '设置'; - @override String get track => '添加到\n跟踪列表'; - @override String get stopTracking => '从跟踪列表\n中移除'; - @override String get becameTracked => '已添加到跟踪列表!'; - @override String get compare => '对比'; - @override String get stoppedBeingTracked => '已从跟踪列表中移除!'; - @override String get tlLeaderboard => 'Tetra联赛排行榜'; - @override String get noRecords => '无记录'; - @override String noOldRecords({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '无记录', - one: '只有 ${n} 个记录', - two: '只有 ${n} 个记录', - few: '只有 ${n} 个记录', - many: '只有 ${n} 个记录', - other: '只有 ${n} 个记录', - ); - @override String get noRecord => '没有记录'; - @override String get botRecord => '机器人不予参加排位赛'; - @override String get anonRecord => '匿名用户不予参加排位赛'; - @override String get notEnoughData => '没有足够的数据'; - @override String get noHistorySaved => '没有保存历史'; - @override String get pseudoTooltipHeaderInit => '将鼠标放在点上'; - @override String get pseudoTooltipFooterInit => '以查看详细信息'; - @override String obtainDate({required Object date}) => '在 ${date} 获得'; - @override String fetchDate({required Object date}) => 'Fetched ${date}'; - @override String get exactGametime => '实际游玩时长'; - @override String get bigRedBanned => '该账号封禁中'; - @override String get normalBanned => '封禁'; - @override String get bigRedBadStanding => '信誉不佳'; - @override String get copiedToClipboard => '已复制'; - @override String get playerRoleAccount => '账号'; - @override String get wasFromBeginning => '在很久很久以前'; - @override String get created => '创建于'; - @override String get botCreatedBy => ''; - @override String get notSupporter => '非会员'; - @override String get assignedManualy => '该勋章由 TETR.IO 管理员手动分配'; - @override String supporter({required Object tier}) => '会员等级 ${tier}'; - @override String comparingWith({required Object newDate, required Object oldDate}) => '${newDate} 时的数据与 ${oldDate} 比较'; - @override String get top => '前'; - @override String get topRank => '最高段位'; - @override String verdictGeneral({required Object rank, required Object verdict, required Object n}) => '比 ${rank} 段平均数据${verdict} ${n}'; - @override String get verdictBetter => '好'; - @override String get verdictWorse => '差'; - @override String get smooth => '平滑'; - @override String get postSeason => '淡季'; - @override String get seasonStarts => '下一赛即将开始于:'; - @override String get nanow => '暂未完成,敬请等待!'; - @override String seasonEnds({required Object countdown}) => '赛季将会在 ${countdown} 后结束'; - @override String get seasonEnded => 'Season has ended'; - @override String gamesUntilRanked({required Object left}) => '还有 ${left} 场比赛获取段位'; - @override String numOfVictories({required Object wins}) => '~${wins} 场胜局'; - @override String get promotionOnNextWin => '下一次胜利即可升段'; - @override String numOfdefeats({required Object losses}) => '~${losses} 场败局'; - @override String get demotionOnNextLoss => '下一次失败即可掉段'; - @override String get nerdStats => '详细信息'; - @override String get playersYouTrack => '跟踪'; - @override String get formula => '公式'; - @override String get exactValue => '实际值'; - @override String get neverPlayedTL => '此用户没有参与Tetra联赛'; - @override String get botTL => '机器人不予参加Tetra联赛'; - @override String get anonTL => '匿名用户不予参加Tetra联赛'; - @override String get quickPlay => '快速游戏'; - @override String get expert => '专家'; - @override String get withMods => '带着模组'; - @override String withModsPlural({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '带着 ${n} 个模组', - one: '带着 ${n} 个模组', - two: '带着 ${n} 个模组', - few: '带着 ${n} 个模组', - many: '带着 ${n} 个模组', - other: '带着 ${n} 个模组', - ); - @override String get exportDB => '导出本地数据'; - @override String get exportDBDescription => '它包含跟踪的玩家的状态和Tetra联赛记录和跟踪列表。'; - @override String get desktopExportAlertTitle => '桌面导出'; - @override String get desktopExportText => '您好像在使用桌面版。请查看你的“文档”文件夹,你应该能找到“TetraStats.db”。把它复制到一个地方'; - @override String get androidExportAlertTitle => '安卓导出'; - @override String androidExportText({required Object exportedDB}) => '导出成功\n${exportedDB}'; - @override String get importDB => '导入本地数据'; - @override String get importDBDescription => '恢复您的备份。请注意,已存储的数据库将被覆盖。'; - @override String get importWrongFileType => '文件类型错误'; - @override String get importCancelled => '已取消'; - @override String get importSuccess => '导入成功'; - @override String get yourID => '你的 TETR.IO 用户'; - @override String get yourIDAlertTitle => '你的 TETR.IO 昵称'; - @override String get yourIDText => '当程序加载,它将显示此用户的数据'; - @override String get language => '语言'; - @override String get updateInBackground => '自动升级数据'; - @override String get updateInBackgroundDescription => '当 Tetra Stats 运行时,它可以在缓存过期时更新当前玩家的统计数据'; - @override String get customization => '自定义'; - @override String get customizationDescription => '更改 Tetra Stats UI 中不同事物的外观'; - @override String get oskKagari => 'osk 特有的 Kagari 段位'; - @override String get oskKagariDescription => '如果打开,主视图上的 osk 段位将显示为 :kagari:'; - @override String get AccentColor => '主题色'; - @override String get AccentColorDescription => '几乎所有交互式 UI 元素都用此颜色突出显示'; - @override String get timestamps => '时间'; - @override String get timestampsDescription => '您可以选择显示时间的方式'; - @override String get timestampsAbsoluteGMT => '绝对 (GMT)'; - @override String get timestampsAbsoluteLocalTime => '绝对 (你的时区)'; - @override String get timestampsRelative => '相对'; - @override String get rating => '评级主要表现'; - @override String get ratingDescription => 'TR 不是线性的,而 Glicko 没有边界,百分位数易挥发'; - @override String get ratingLBposition => 'LB 位置'; - @override String get sheetbotGraphs => 'Sheetbot式雷达图'; - @override String get sheetbotGraphsDescription => '若开启,雷达图上的点为负时可以出现在对面'; - @override String get lbStats => '显示基于排行榜的数据'; - @override String get lbStatsDescription => '这会影响加载时间,但允许您通过统计数据查看排行榜上的位置并与平均值进行比较'; - @override String get aboutApp => '关于'; - @override String aboutAppText({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) ${version} 版 Build ${buildNumber}\n\n由 dan63047 制作\n由 kerrmunism 提供公式\n由 p1nkl0bst3r 提供历史\nTETR.IO 回放抓取器 API 由 szy 制作'; - @override String stateViewTitle({required Object nickname, required Object date}) => '${nickname} 在 ${date}'; - @override String statesViewTitle({required Object nickname, required Object number}) => '${nickname} 的 ${number} 个状态'; - @override String matchesViewTitle({required Object nickname}) => '${nickname} 的Tetra联赛历史'; - @override String statesViewEntry({required Object level, required Object glicko, required Object rd, required Object games}) => '${level} TR, ${glicko}±${rd} Glicko, ${games} 次游戏'; - @override String stateRemoved({required Object date}) => '成功移除 ${date} 的状态!'; - @override String matchRemoved({required Object date}) => '成功移除 ${date} 的比赛!'; - @override String get viewAllMatches => '查看所有比赛'; - @override String get trackedPlayersViewTitle => '获取的数据'; - @override String get trackedPlayersZeroEntrys => '列表为空。 点击 “添加到跟踪列表” 可以将玩家放在这里'; - @override String get trackedPlayersOneEntry => '只有 1 个玩家'; - @override String trackedPlayersManyEntrys({required Object numberOfPlayers}) => '${numberOfPlayers} 个玩家'; - @override String trackedPlayersEntry({required Object nickname, required Object numberOfStates}) => '${nickname}:${numberOfStates} 个状态'; - @override String trackedPlayersDescription({required Object firstStateDate, required Object lastStateDate}) => '从 ${firstStateDate} 到 ${lastStateDate}'; - @override String trackedPlayersStatesDeleted({required Object nickname}) => '成功从数据库中移除 ${nickname} 个状态!'; - @override String get duplicatedFix => '删除重复的 TL 匹配项'; - @override String get compressDB => '压缩数据库'; - @override String SpaceSaved({required Object size}) => '保存空白:${size}'; - @override String averageXrank({required Object rankLetter}) => '平均 ${rankLetter} 段'; - @override String get vs => 'vs'; - @override String get inTLmatch => '在Tetra联赛中'; - @override String get downloadReplay => '下载 .ttrm 回放'; - @override String get openReplay => '在 TETR.IO 打开回放'; - @override String replaySaved({required Object path}) => '已保存回放至 ${path}'; - @override String get match => '比赛'; - @override String get timeWeightedmatch => '比赛(时间加权)'; - @override String roundNumber({required Object n}) => '第 ${n} 回合'; - @override String get statsFor => '数据:'; - @override String get numberOfRounds => '回合数'; - @override String get matchLength => '比赛时长'; - @override String get roundLength => '回合时长'; - @override String get matchStats => '比赛数据'; - @override String get timeWeightedmatchStats => '时间加权比赛数据'; - @override String get replayIssue => '无法处理回放'; - @override String get matchIsTooOld => '无回放'; - @override String get winner => '赢家'; - @override String get registred => '注册日期'; - @override String get playedTL => '游玩过Tetra联赛'; - @override String get winChance => '胜利机会'; - @override String get byGlicko => '靠Glicko'; - @override String get byEstTR => '靠预测TR'; - @override String compareViewNoValues({required Object avgR}) => '请输入用户名,用户IO,APM-PPS-VS值 (分隔符不重要,只需要顺序)或者${avgR}(R是一个段位)到两个字段'; - @override String compareViewWrongValue({required Object value}) => '获取 ${value} 失败'; - @override String get mostRecentOne => '最接近的'; - @override String get yes => '是'; - @override String get no => '否'; - @override String get daysLater => '天后'; - @override String get dayseBefore => '天前'; - @override String get fromBeginning => '开服'; - @override String get calc => '计算器'; - @override String get calcViewNoValues => '输入值以计算数据'; - @override String get rankAveragesViewTitle => '段位分隔符'; - @override String get sprintAndBlitsViewTitle => '竞速与闪电战平均数据'; - @override String sprintAndBlitsRelevance({required Object date}) => '数据来自${date}'; - @override String get rank => '段位'; - @override String get averages => '平均'; - @override String get lbViewZeroEntrys => '空'; - @override String get lbViewOneEntry => '只有一个玩家'; - @override String lbViewManyEntrys({required Object numberOfPlayers}) => '有 ${numberOfPlayers}'; - @override String get everyoneAverages => 'Tetra联赛散点图'; - @override String get sortBy => '排序依据'; - @override String get reversed => '反向'; - @override String get country => '地区'; - @override String rankAverages({required Object rank}) => '${rank}段位散点图'; - @override String players({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '${n} 个玩家', - one: '${n} 个玩家', - two: '${n} 个玩家', - few: '${n} 个玩家', - many: '${n} 个玩家', - other: '${n} 个玩家', - ); - @override String games({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '${n} 场游戏', - one: '${n} 场游戏', - two: '${n} 场游戏', - few: '${n} 场游戏', - many: '${n} 场游戏', - other: '${n} 场游戏', - ); - @override String gamesPlayed({required Object games}) => '${games} 场游戏'; - @override String get chart => '列表'; - @override String get entries => '条目'; - @override String get minimums => '最小值'; - @override String get maximums => '最大值'; - @override String get lowestValues => '最小值'; - @override String get averageValues => '平均值'; - @override String get highestValues => '最大值'; - @override String forPlayer({required Object username}) => '来自用户 ${username}'; - @override String currentAxis({required Object axis}) => '${axis} 轴:'; - @override String get p1nkl0bst3rAlert => '该数据是从 p1nkl0bst3r 维护的第三方 API 中检索的'; - @override String get notForWeb => '浏览器版本暂不支持函数'; - @override late final _StringsGraphsZhCn graphs = _StringsGraphsZhCn._(_root); - @override late final _StringsStatCellNumZhCn statCellNum = _StringsStatCellNumZhCn._(_root); - @override Map get playerRole => { - 'user': '用户', - 'banned': '封禁', - 'bot': '机器人', - 'sysop': '系统管理员', - 'admin': '管理员', - 'mod': '管理员', - 'halfmod': '社区管理员', - 'anon': '匿名', - }; - @override late final _StringsNumOfGameActionsZhCn numOfGameActions = _StringsNumOfGameActionsZhCn._(_root); - @override late final _StringsPopupActionsZhCn popupActions = _StringsPopupActionsZhCn._(_root); - @override late final _StringsErrorsZhCn errors = _StringsErrorsZhCn._(_root); - @override Map get countries => { - '': '无', - 'AF': '阿富汗', - 'AX': '奥兰群岛', - 'AL': '阿尔巴尼亚', - 'DZ': '阿尔及利亚', - 'AS': '美属萨摩亚', - 'AD': '安道尔', - 'AO': '安哥拉', - 'AI': '安圭拉', - 'AQ': '南极洲', - 'AG': '安提瓜和巴布达', - 'AR': '阿根廷', - 'AM': '亚美尼亚', - 'AW': '阿鲁巴', - 'AU': '澳大利亚', - 'AT': '奥地利', - 'AZ': '阿塞拜疆', - 'BS': '巴哈马', - 'BH': '巴林', - 'BD': '孟加拉国', - 'BB': '巴巴多斯', - 'BY': '白俄罗斯', - 'BE': '比利时', - 'BZ': '伯利兹', - 'BJ': '贝宁', - 'BM': '百慕大', - 'BT': '不丹', - 'BO': '玻利维亚多民族国', - 'BA': '波斯尼亚和黑塞哥维那', - 'BW': '博茨瓦纳', - 'BV': '布韦岛', - 'BR': '巴西', - 'IO': '英属印度洋领地', - 'BN': '文莱达鲁萨兰国', - 'BG': '保加利亚', - 'BF': '布基纳法索', - 'BI': '布隆迪', - 'KH': '柬埔寨', - 'CM': '喀麦隆', - 'CA': '加拿大', - 'CV': '佛得角', - 'BQ': '荷兰加勒比区', - 'KY': '开曼群岛', - 'CF': '中非', - 'TD': '乍得', - 'CL': '智利', - 'CN': '中国', - 'CX': '圣诞岛', - 'CC': '科科斯(基林)群岛', - 'CO': '哥伦比亚', - 'KM': '科摩罗', - 'CG': '刚果(布)/刚果共和国', - 'CD': '刚果(金)/刚果民主共和国', - 'CK': '库克群岛', - 'CR': '哥斯达黎加', - 'CI': '科特迪瓦', - 'HR': '克罗地亚', - 'CU': '古巴', - 'CW': '库拉索', - 'CY': '塞浦路斯', - 'CZ': '捷克', - 'DK': '丹麦', - 'DJ': '吉布提', - 'DM': '多米尼加', - 'DO': '多米尼加共和国', - 'EC': '厄瓜多尔', - 'EG': '埃及', - 'SV': '萨尔瓦多', - 'GB-ENG': '英格兰', - 'GQ': '赤道几内亚', - 'ER': '厄立特里亚', - 'EE': '爱沙尼亚', - 'ET': '埃塞俄比亚', - 'EU': '欧洲', - 'FK': '福克兰群岛/马尔维纳斯群岛', - 'FO': '法罗群岛', - 'FJ': '斐济', - 'FI': '芬兰', - 'FR': '法国', - 'GF': '法属圭亚那', - 'PF': '法属波利尼西亚', - 'TF': '法属南部领地', - 'GA': '加蓬', - 'GM': '冈比亚', - 'GE': '格鲁吉亚', - 'DE': '德国', - 'GH': '加纳', - 'GI': '直布罗陀', - 'GR': '希腊', - 'GL': '格陵兰岛', - 'GD': '格林纳达', - 'GP': '瓜德罗普岛', - 'GU': '关岛', - 'GT': '危地马拉', - 'GG': '根西岛', - 'GN': '几内亚', - 'GW': '几内亚比绍', - 'GY': '圭亚那', - 'HT': '海地', - 'HM': '赫德岛和麦克唐纳群岛', - 'VA': '梵蒂冈', - 'HN': '洪都拉斯', - 'HK': '中国香港', - 'HU': '匈牙利', - 'IS': '冰岛', - 'IN': '印度', - 'ID': '印度尼西亚', - 'IR': '伊朗', - 'IQ': '伊拉克', - 'IE': '爱尔兰', - 'IM': '马恩岛', - 'IL': '以色列', - 'IT': '意大利', - 'JM': '牙买加', - 'JP': '日本', - 'JE': 'Jersey', - 'JO': '约旦', - 'KZ': '哈萨克斯坦', - 'KE': '肯尼亚', - 'KI': '基里巴斯', - 'KP': '朝鲜', - 'KR': '韩国', - 'XK': '科索沃', - 'KW': '科威特', - 'KG': '吉尔吉斯斯坦', - 'LA': '老挝', - 'LV': '拉脱维亚', - 'LB': '黎巴嫩', - 'LS': '莱索托', - 'LR': '利比里亚', - 'LY': '利比亚', - 'LI': '列支敦士登', - 'LT': '立陶宛', - 'LU': '卢森堡', - 'MO': '中国澳门', - 'MK': '马其顿', - 'MG': '马达加斯加', - 'MW': '马拉维', - 'MY': '马来西亚', - 'MV': '马尔代夫', - 'ML': '马里', - 'MT': '马耳他', - 'MH': '马绍尔群岛', - 'MQ': '马提尼克岛', - 'MR': '毛里塔尼亚', - 'MU': '毛里求斯', - 'YT': '马约特岛', - 'MX': '墨西哥', - 'FM': '密克罗尼西亚联邦', - 'MD': '摩尔多瓦共和国', - 'MC': '摩纳哥', - 'ME': '黑山', - 'MA': '摩洛哥', - 'MN': '蒙古', - 'MS': '蒙特塞拉特', - 'MZ': '莫桑比克', - 'MM': '缅甸', - 'NA': '纳米比亚', - 'NR': '瑙鲁', - 'NP': '尼泊尔', - 'NL': '尼德兰', - 'AN': '荷属安的列斯', - 'NC': '新喀里多尼亚', - 'NZ': '新西兰', - 'NI': '尼加拉瓜', - 'NE': '尼日尔', - 'NG': '尼日利亚', - 'NU': '纽埃', - 'NF': '诺福克岛', - 'GB-NIR': '北爱尔兰', - 'MP': '北马里亚纳群岛', - 'NO': '挪威', - 'OM': '阿曼', - 'PK': '巴基斯坦', - 'PW': '帕劳', - 'PS': '巴勒斯坦', - 'PA': '巴拿马', - 'PG': '巴布亚新几内亚', - 'PY': '巴拉圭', - 'PE': '秘鲁', - 'PH': '菲律宾', - 'PN': '皮特凯恩', - 'PL': '波兰', - 'PT': '葡萄牙', - 'PR': '波多黎各', - 'QA': '卡塔尔', - 'RE': '留尼汪', - 'RO': '罗马尼亚', - 'RU': '俄罗斯联邦', - 'RW': '卢旺达', - 'BL': '圣巴泰勒米', - 'SH': '圣赫勒拿,阿森松和特里斯坦-达库尼亚', - 'KN': '圣基茨和尼维斯', - 'LC': '圣卢西亚', - 'MF': '圣马丁', - 'PM': '圣皮埃尔和密克隆群岛', - 'VC': '圣文森特和格林纳丁斯', - 'WS': '萨摩亚', - 'SM': '圣马力诺', - 'ST': '圣多美和普林西比', - 'SA': '沙特阿拉伯', - 'GB-SCT': '苏格兰', - 'SN': '塞内加尔', - 'RS': '塞尔维亚', - 'SC': '塞舌尔', - 'SL': '塞拉利昂', - 'SG': '新加坡', - 'SX': '荷属圣马丁', - 'SK': '斯洛伐克', - 'SI': '斯洛文尼亚', - 'SB': '所罗门群岛', - 'SO': '索马里', - 'ZA': '南非', - 'GS': '南乔治亚和南桑威奇群岛', - 'SS': '南苏丹', - 'ES': '西班牙', - 'LK': '斯里兰卡', - 'SD': '苏丹', - 'SR': '苏里南', - 'SJ': '斯瓦尔巴和扬马延群岛', - 'SZ': '斯威士兰', - 'SE': '瑞典', - 'CH': '瑞士', - 'SY': '叙利亚', - 'TW': '中国台湾', - 'TJ': '塔吉克斯坦', - 'TZ': '坦桑尼亚', - 'TH': '泰国', - 'TL': '东帝汶', - 'TG': '多哥', - 'TK': '托克劳', - 'TO': '汤加', - 'TT': '特立尼达和多巴哥', - 'TN': '突尼斯', - 'TR': '土耳其', - 'TM': '土库曼斯坦', - 'TC': '特克斯和凯科斯群岛', - 'TV': '图瓦卢', - 'UG': '乌干达', - 'UA': '乌克兰', - 'AE': '阿拉伯联合酋长国', - 'GB': '英国', - 'US': '美国', - 'UY': '乌拉圭', - 'UM': '美国小岛屿', - 'UZ': '乌兹别克斯坦', - 'VU': '瓦努阿图', - 'VE': '委内瑞拉玻利瓦尔共和国', - 'VN': '越南', - 'VG': '英属维尔京群岛', - 'VI': '美属维尔京群岛', - 'GB-WLS': '威尔士', - 'WF': '瓦利斯和富图纳群岛', - 'EH': '西撒哈拉', - 'YE': '也门', - 'ZM': '赞比亚', - 'ZW': '津巴布韦', - 'XX': '未知', - 'XM': '月球', - }; + String get short => 'Glicko'; + String get full => 'Glicko'; } -// Path: newsParts -class _StringsNewsPartsZhCn implements _StringsNewsPartsEn { - _StringsNewsPartsZhCn._(this._root); +// Path: stats.rd +class _StringsStatsRdEn { + _StringsStatsRdEn._(this._root); - @override final _StringsZhCn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get leaderboardStart => '取得 '; - @override String get leaderboardMiddle => '于 '; - @override String get personalbest => '在 '; - @override String get personalbestMiddle => ' 中取得了新的个人最好成绩 '; - @override String get badgeStart => '获得勋章 '; - @override String get badgeEnd => ''; - @override String get rankupStart => '达成 '; - @override String rankupMiddle({required Object r}) => '${r} 段位 '; - @override String get rankupEnd => ''; - @override String get tetoSupporter => 'TETR.IO 会员'; - @override String get supporterStart => '成为了 '; - @override String get supporterGiftStart => '被赠送了 '; - @override String unknownNews({required Object type}) => '未知新闻 ${type}'; + String get short => 'RD'; + String get full => 'Rating Deviation'; } -// Path: graphs -class _StringsGraphsZhCn implements _StringsGraphsEn { - _StringsGraphsZhCn._(this._root); +// Path: stats.glixare +class _StringsStatsGlixareEn { + _StringsStatsGlixareEn._(this._root); - @override final _StringsZhCn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get attack => '攻击'; - @override String get speed => '速度'; - @override String get defense => '防御'; - @override String get cheese => '奶酪层'; + String get short => 'GXE'; + String get full => 'GLIXARE'; } -// Path: statCellNum -class _StringsStatCellNumZhCn implements _StringsStatCellNumEn { - _StringsStatCellNumZhCn._(this._root); +// Path: stats.s1tr +class _StringsStatsS1trEn { + _StringsStatsS1trEn._(this._root); - @override final _StringsZhCn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get xpLevel => 'XP等级'; - @override String get xpProgress => '到下一等级的进度'; - @override String xpFrom0ToLevel({required Object n}) => '从 0 到 ${n} 等级的进度'; - @override String get xpLeft => 'XP 还有'; - @override String get hoursPlayed => '小时游玩'; - @override String get onlineGames => '在线游戏场次'; - @override String get gamesWon => '获胜场次'; - @override String get totalGames => '总在线游戏场次'; - @override String get totalWon => '总在线游戏获胜场次'; - @override String get friends => '好友'; - @override String get apm => '每分\n发送垃圾行'; - @override String get vs => 'VS\n分数'; - @override String get recordLB => '名次'; - @override String get lbp => '名次'; - @override String get lbpShort => '名次'; - @override String get lbpc => '地区\n名次'; - @override String get lbpcShort => '地区名次'; - @override String get gamesPlayed => '游戏\n场次'; - @override String get gamesWonTL => '获胜\n场次'; - @override String get winrate => '胜率'; - @override String get level => '等级'; - @override String get score => '分数'; - @override String get spp => '每块\n得分'; - @override String get pieces => '放置\n块数'; - @override String get pps => '每秒\n放置块数'; - @override String get finesseFaults => '非极简\n操作'; - @override String get finessePercentage => '极简率'; - @override String get keys => '按键'; - @override String get kpp => '每块\n按键'; - @override String get kps => '每秒\n按键'; - @override String get tr => 'Tetra分数'; - @override String get rd => '偏移值'; - @override String get app => '每块发送垃圾行数'; - @override String get appDescription => '(Attack per Piece, 简称APP) 主要效率指标。表示玩家每块可以发动多少次攻击'; - @override String get vsapmDescription => '基本上可以告诉你在攻击中利用垃圾行的效率'; - @override String get dss => '每秒\n挖掘'; - @override String get dssDescription => '(Downstack per Second, 简称 DS/S) 测量一秒钟内清除多少条垃圾行。'; - @override String get dsp => '每块\n挖掘'; - @override String get dspDescription => '(Downstack per Piece, 简称 DS/P) 测量每一块清除多少条垃圾行。'; - @override String get appdsp => 'APP + DS/P'; - @override String get appdspDescription => '只是每块发送垃圾行数与每块挖掘之和。'; - @override String get cheese => '垃圾行\n混乱指数'; - @override String get cheeseDescription => '(Cheese Index, 简称Cheese) 是玩家发出的垃圾行有多整齐/混乱的近似值。低数据代表整齐,高数据代表混乱。\n由 kerrmunism 发明'; - @override String get gbe => '垃圾行\n效率'; - @override String get gbeDescription => '(Garbage Efficity, 简称Gb Eff.) 测量玩家如何很好地利用他们收到的垃圾行。高数据代表更好或者他们更多地用TA的垃圾行,低数据代表TA大多将垃圾行送回奶酪层,或者很少清理垃圾行。\n由 Zepheniah 与 Dragonboy 发明。'; - @override String get nyaapp => '加权\nAPP'; - @override String get nyaappDescription => '(Weighted APP, 简称wAPP) 在本质上是在衡量您在保持高 APP 的同时发送奶酪的能力。\n由 Wertj 发明。'; - @override String get area => '面积'; - @override String get areaDescription => '如果排除 Cheese 和 vs/apm 部分,您的形状在图表上占据了多少空间'; - @override String get estOfTR => '预测 TR'; - @override String get estOfTRShort => '预测 TR'; - @override String get accOfEst => '预测实际差量'; - @override String get accOfEstShort => '预测实际差量'; + String get short => 'S1 TR'; + String get full => 'Season 1 like TR'; } -// Path: numOfGameActions -class _StringsNumOfGameActionsZhCn implements _StringsNumOfGameActionsEn { - _StringsNumOfGameActionsZhCn._(this._root); +// Path: stats.gp +class _StringsStatsGpEn { + _StringsStatsGpEn._(this._root); - @override final _StringsZhCn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get pc => '全消数'; - @override String get hold => '暂存数'; - @override String inputs({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '${n} 次按键', - one: '${n} 次按键', - two: '${n} 次按键', - few: '${n} 次按键', - many: '${n} 次按键', - other: '${n} 次按键', - ); - @override String tspinsTotal({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '共 ${n} 次T旋', - one: '共 ${n} 次T旋', - two: '共 ${n} 次T旋', - few: '共 ${n} 次T旋', - many: '共 ${n} 次T旋', - other: '共 ${n} 次T旋', - ); - @override String lineClears({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '清除了 ${n} 行', - one: '清除了 ${n} 行', - two: '清除了 ${n} 行', - few: '清除了 ${n} 行', - many: '清除了 ${n} 行', - other: '清除了 ${n} 行', - ); + String get short => 'GP'; + String get full => 'Games Played'; } -// Path: popupActions -class _StringsPopupActionsZhCn implements _StringsPopupActionsEn { - _StringsPopupActionsZhCn._(this._root); +// Path: stats.gw +class _StringsStatsGwEn { + _StringsStatsGwEn._(this._root); - @override final _StringsZhCn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String get cancel => '取消'; - @override String get submit => '确定'; - @override String get ok => '彳亍'; + String get short => 'GW'; + String get full => 'Games Won'; } -// Path: errors -class _StringsErrorsZhCn implements _StringsErrorsEn { - _StringsErrorsZhCn._(this._root); +// Path: stats.winrate +class _StringsStatsWinrateEn { + _StringsStatsWinrateEn._(this._root); - @override final _StringsZhCn _root; // ignore: unused_field + final Translations _root; // ignore: unused_field // Translations - @override String connection({required Object code, required Object message}) => '连接错误: ${code} ${message}'; - @override String get noSuchUser => '没有这样的用户'; - @override String get noSuchUserSub => '检查用户名的拼写是否错误,也许用户不存在'; - @override String get discordNotAssigned => '没有用户绑定到该Discord ID'; - @override String get discordNotAssignedSub => '您必须输入合法的ID'; - @override String get history => '此玩家没有历史'; - @override String get actionSuggestion => '你也许想'; - @override String get p1nkl0bst3rTLmatches => '没有比赛'; - @override String get clientException => '连接不到网络'; - @override String get forbidden => '你的IP地址被封禁'; - @override String forbiddenSub({required Object nickname}) => '请关闭您的VPN。若问题仍然存在,请联系 ${nickname}'; - @override String get tooManyRequests => '您申请的请求过多'; - @override String get tooManyRequestsSub => '等一会再试吧'; - @override String get internal => 'tetr.io 似乎出错了'; - @override String get internalSub => 'osk,也许,要被'; - @override String get internalWebVersion => 'tetr.io 或者 oskware_bridge 似乎出错了'; - @override String get internalWebVersionSub => '如果 osk 说没有什么问题,请让dan63047知道'; - @override String get oskwareBridge => 'oskware_bridge 似乎出错了'; - @override String get oskwareBridgeSub => '请让 dan63047 知道'; - @override String get p1nkl0bst3rForbidden => '第三方API封禁了你的IP地址'; - @override String get p1nkl0bst3rTooManyRequests => '第三方API……太多请求了。'; - @override String get p1nkl0bst3rinternal => 'p1nkl0bst3r 那边似乎出错了'; - @override String get p1nkl0bst3rinternalWebVersion => 'p1nkl0bst3r (或 on oskware_bridge, 其实我并不知道) 那边似乎出错了'; - @override String get replayAlreadySaved => '你已保存此回放'; - @override String get replayExpired => '回放已过期'; - @override String get replayRejected => '第三方API封禁了你的IP地址'; + String get short => 'WR%'; + String get full => 'Win Rate'; +} + +// Path: stats.apm +class _StringsStatsApmEn { + _StringsStatsApmEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'APM'; + String get full => 'Attack Per Minute'; +} + +// Path: stats.pps +class _StringsStatsPpsEn { + _StringsStatsPpsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'PPS'; + String get full => 'Pieces Per Second'; +} + +// Path: stats.vs +class _StringsStatsVsEn { + _StringsStatsVsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'VS'; + String get full => 'Versus Score'; +} + +// Path: stats.app +class _StringsStatsAppEn { + _StringsStatsAppEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'APP'; + String get full => 'Attack Per Piece'; +} + +// Path: stats.vsapm +class _StringsStatsVsapmEn { + _StringsStatsVsapmEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'VS/APM'; + String get full => 'VS / APM'; +} + +// Path: stats.dss +class _StringsStatsDssEn { + _StringsStatsDssEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'DS/S'; + String get full => 'Downstack Per Second'; +} + +// Path: stats.dsp +class _StringsStatsDspEn { + _StringsStatsDspEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'DS/P'; + String get full => 'Downstack Per Piece'; +} + +// Path: stats.appdsp +class _StringsStatsAppdspEn { + _StringsStatsAppdspEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'APP+DSP'; + String get full => 'APP + DSP'; +} + +// Path: stats.cheese +class _StringsStatsCheeseEn { + _StringsStatsCheeseEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Cheese'; + String get full => 'Cheese Index'; +} + +// Path: stats.gbe +class _StringsStatsGbeEn { + _StringsStatsGbeEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'GbE'; + String get full => 'Garbage Efficiency'; +} + +// Path: stats.nyaapp +class _StringsStatsNyaappEn { + _StringsStatsNyaappEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'wAPP'; + String get full => 'Weigente APP'; +} + +// Path: stats.area +class _StringsStatsAreaEn { + _StringsStatsAreaEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Area'; + String get full => 'Area'; +} + +// Path: stats.etr +class _StringsStatsEtrEn { + _StringsStatsEtrEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'eTR'; + String get full => 'Estimated TR'; +} + +// Path: stats.etracc +class _StringsStatsEtraccEn { + _StringsStatsEtraccEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => '±eTR'; + String get full => 'Accuracy of Estimated TR'; +} + +// Path: stats.opener +class _StringsStatsOpenerEn { + _StringsStatsOpenerEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Opener'; + String get full => 'Opener'; +} + +// Path: stats.plonk +class _StringsStatsPlonkEn { + _StringsStatsPlonkEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Plonk'; + String get full => 'Plonk'; +} + +// Path: stats.stride +class _StringsStatsStrideEn { + _StringsStatsStrideEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Stride'; + String get full => 'Stride'; +} + +// Path: stats.infds +class _StringsStatsInfdsEn { + _StringsStatsInfdsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Inf. DS'; + String get full => 'Infinite Downstack'; +} + +// Path: stats.altitude +class _StringsStatsAltitudeEn { + _StringsStatsAltitudeEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'm'; + String get full => 'Altitude'; +} + +// Path: stats.climbSpeed +class _StringsStatsClimbSpeedEn { + _StringsStatsClimbSpeedEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'CSP'; + String get full => 'Climb Speed'; + String get gaugetTitle => 'Climb\nSpeed'; +} + +// Path: stats.peakClimbSpeed +class _StringsStatsPeakClimbSpeedEn { + _StringsStatsPeakClimbSpeedEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Peak CSP'; + String get full => 'Peak Climb Speed'; + String get gaugetTitle => 'Peak'; +} + +// Path: stats.kos +class _StringsStatsKosEn { + _StringsStatsKosEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'KO\'s'; + String get full => 'Knockouts'; +} + +// Path: stats.b2b +class _StringsStatsB2bEn { + _StringsStatsB2bEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'B2B'; + String get full => 'Back-To-Back'; +} + +// Path: stats.finesse +class _StringsStatsFinesseEn { + _StringsStatsFinesseEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'F'; + String get full => 'Finesse'; + String get widgetTitle => 'inesse'; +} + +// Path: stats.finesseFaults +class _StringsStatsFinesseFaultsEn { + _StringsStatsFinesseFaultsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'FF'; + String get full => 'Finesse Faults'; +} + +// Path: stats.totalTime +class _StringsStatsTotalTimeEn { + _StringsStatsTotalTimeEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Time'; + String get full => 'Total Time'; + String get widgetTitle => 'otal Time'; +} + +// Path: stats.level +class _StringsStatsLevelEn { + _StringsStatsLevelEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'Lvl'; + String get full => 'Level'; +} + +// Path: stats.pieces +class _StringsStatsPiecesEn { + _StringsStatsPiecesEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'P'; + String get full => 'Pieces'; +} + +// Path: stats.spp +class _StringsStatsSppEn { + _StringsStatsSppEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'SPP'; + String get full => 'Score Per Piece'; +} + +// Path: stats.kp +class _StringsStatsKpEn { + _StringsStatsKpEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'KP'; + String get full => 'Key presses'; +} + +// Path: stats.kpp +class _StringsStatsKppEn { + _StringsStatsKppEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'KPP'; + String get full => 'Key presses Per Piece'; +} + +// Path: stats.kps +class _StringsStatsKpsEn { + _StringsStatsKpsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get short => 'KPS'; + String get full => 'Key presses Per Second'; +} + +// Path: stats.graphs +class _StringsStatsGraphsEn { + _StringsStatsGraphsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get attack => 'Attack'; + String get speed => 'Speed'; + String get defense => 'Defense'; + String get cheese => 'Cheese'; +} + +// Path: stats.lineClear +class _StringsStatsLineClearEn { + _StringsStatsLineClearEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get single => 'Single'; + String get double => 'Double'; + String get triple => 'Triple'; + String get quad => 'Quad'; + String get penta => 'Penta'; + String get hexa => 'Hexa'; + String get hepta => 'Hepta'; + String get octa => 'Octa'; + String get ennea => 'Ennea'; + String get deca => 'Deca'; + String get hendeca => 'Hendeca'; + String get dodeca => 'Dodeca'; + String get triadeca => 'Triadeca'; + String get tessaradeca => 'Tessaradeca'; + String get pentedeca => 'Pentedeca'; + String get hexadeca => 'Hexadeca'; + String get heptadeca => 'Heptadeca'; + String get octadeca => 'Octadeca'; + String get enneadeca => 'Enneadeca'; + String get eicosa => 'Eicosa'; + String get kagaris => 'Kagaris'; +} + +// Path: stats.lineClears +class _StringsStatsLineClearsEn { + _StringsStatsLineClearsEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get zero => 'Zeros'; + String get single => 'Singles'; + String get double => 'Doubles'; + String get triple => 'Triples'; + String get quad => 'Quads'; + String get penta => 'Pentas'; } /// Flat map(s) containing all translations. @@ -2270,19 +1516,65 @@ extension on Translations { case 'locales.en': return 'English'; case 'locales.ru': return 'Russian (Русский)'; case 'locales.zh-CN': return 'Simplified Chinese (简体中文)'; - case 'tetraLeague': return 'Tetra League'; - case 'tlRecords': return 'TL Records'; - case 'history': return 'History'; - case 'sprint': return '40 Lines'; - case 'blitz': return 'Blitz'; - case 'recent': return 'Recent'; - case 'recentRuns': return 'Recent runs'; - case 'blitzScore': return ({required Object p}) => '${p} points'; - case 'openSPreplay': return 'Open replay in TETR.IO'; - case 'downloadSPreplay': return 'Download replay'; - case 'other': return 'Other'; + case 'gamemodes.league': return 'Tetra League'; + case 'gamemodes.zenith': return 'Quick Play'; + case 'gamemodes.zenithex': return 'Quick Play Expert'; + case 'gamemodes.40l': return '40 Lines'; + case 'gamemodes.blitz': return 'Blitz'; + case 'gamemodes.5mblast': return '5,000,000 Blast'; + case 'gamemodes.zen': return 'Zen'; + case 'destinations.home': return 'Home'; + case 'destinations.graphs': return 'Graphs'; + case 'destinations.leaderboards': return 'Leaderboards'; + case 'destinations.cutoffs': return 'Cutoffs'; + case 'destinations.calc': return 'Calculator'; + case 'destinations.info': return 'Info Center'; + case 'destinations.data': return 'Saved Data'; + case 'destinations.settings': return 'Settings'; + case 'goBackButton': return 'Go Back'; + case 'nanow': return 'Not avaliable for now...'; + case 'seasonEnds': return ({required Object countdown}) => 'Season ends in ${countdown}'; + case 'seasonEnded': return 'Season has ended'; + case 'overallPB': return ({required Object pb}) => 'Overall PB: ${pb}'; + case 'gamesUntilRanked': return ({required Object left}) => '${left} games until being ranked'; + case 'numOfVictories': return ({required Object wins}) => '~${wins} victories'; + case 'promotionOnNextWin': return 'Promotion on next win'; + case 'numOfdefeats': return ({required Object losses}) => '~${losses} defeats'; + case 'demotionOnNextLoss': return 'Demotion on next loss'; + case 'records': return 'Records'; + case 'nerdStats': return 'Nerd Stats'; + case 'playstyles': return 'Playstyles'; + case 'horoscopes': return 'Horoscopes'; + case 'season': return 'Season'; + case 'smooth': return 'Smooth'; + case 'dateAndTime': return 'Date & Time'; + case 'TLfullLBnote': return 'Heavy, but allows you to sort players by their stats and filter them by ranks'; + case 'rank': return 'Rank'; + case 'verdictGeneral': return ({required Object n, required Object verdict, required Object rank}) => '${n} ${verdict} of ${rank} rank avg'; + case 'verdictBetter': return 'ahead'; + case 'verdictWorse': return 'behind'; + case 'localStanding': return 'local'; + case 'xp.title': return 'XP Level'; + case 'xp.progressToNextLevel': return ({required Object percentage}) => 'Progress to next level: ${percentage}'; + case 'xp.progressTowardsGoal': return ({required Object goal, required Object percentage, required Object left}) => 'Progress from 0 XP to level ${goal}: ${percentage} (${left} XP left)'; + case 'gametime.title': return 'Exact gametime'; + case 'gametime.gametimeAday': return ({required Object gametime}) => '${gametime} a day in average'; + case 'gametime.breakdown': return ({required Object years, required Object months, required Object days, required Object minutes, required Object seconds}) => 'It\'s ${years} years,\nor ${months} months,\nor ${days} days,\nor ${minutes} minutes\nor ${seconds} seconds'; + case 'track': return 'Track'; + case 'stopTracking': return 'Stop tracking'; + case 'supporter': return ({required Object tier}) => 'Supporter tier ${tier}'; + case 'comparingWith': return ({required Object newDate, required Object oldDate}) => 'Data from ${newDate} comparing with ${oldDate}'; + case 'compare': return 'Compare'; + case 'comparison': return 'Comparison'; + case 'general': return 'General'; + case 'badges': return 'Badges'; + case 'obtainDate': return ({required Object date}) => 'Obtained ${date}'; + case 'assignedManualy': return 'That badge was assigned manualy by TETR.IO admins'; case 'distinguishment': return 'Distinguishment'; - case 'zen': return 'Zen'; + case 'bigRedBanned': return 'BANNED'; + case 'normalBanned': return 'Banned'; + case 'bigRedBadStanding': return 'BAD STANDING'; + case 'copiedToClipboard': return 'Copied to clipboard!'; case 'bio': return 'Bio'; case 'news': return 'News'; case 'newsParts.leaderboardStart': return 'Got '; @@ -2298,310 +1590,24 @@ extension on Translations { case 'newsParts.supporterStart': return 'Become a '; case 'newsParts.supporterGiftStart': return 'Received the gift of '; case 'newsParts.unknownNews': return ({required Object type}) => 'Unknown news of type ${type}'; - case 'openSearch': return 'Search player'; - case 'closeSearch': return 'Close search'; - case 'searchHint': return 'Nickname, ID or Discord userID (with "ds:" prefix)'; - case 'refresh': return 'Refresh'; - case 'fetchAndsaveTLHistory': return 'Get player history'; - case 'fetchAndSaveOldTLmatches': return 'Get Tetra League matches history'; - case 'fetchAndsaveTLHistoryResult': return ({required Object number}) => '${number} states was found'; - case 'fetchAndSaveOldTLmatchesResult': return ({required Object number}) => '${number} matches was found'; - case 'showStoredData': return 'Show stored data'; - case 'statsCalc': return 'Stats Calculator'; - case 'settings': return 'Settings'; - case 'track': return 'Track'; - case 'stopTracking': return 'Stop\ntracking'; - case 'becameTracked': return 'Added to tracking list!'; - case 'compare': return 'Compare'; - case 'stoppedBeingTracked': return 'Removed from tracking list!'; - case 'tlLeaderboard': return 'Tetra League leaderboard'; - case 'noRecords': return 'No records'; - case 'noOldRecords': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: 'No records', - one: 'Only ${n} record', - two: 'Only ${n} records', - few: 'Only ${n} records', - many: 'Only ${n} records', - other: 'Only ${n} records', - ); - case 'noRecord': return 'No record'; - case 'botRecord': return 'Bots are not allowed to set records'; - case 'anonRecord': return 'Guests are not allowed to set records'; - case 'notEnoughData': return 'Not enough data'; - case 'noHistorySaved': return 'No history saved'; - case 'pseudoTooltipHeaderInit': return 'Hover over point'; - case 'pseudoTooltipFooterInit': return 'to see detailed data'; - case 'obtainDate': return ({required Object date}) => 'Obtained ${date}'; - case 'fetchDate': return ({required Object date}) => 'Fetched ${date}'; - case 'exactGametime': return 'Exact gametime'; - case 'bigRedBanned': return 'BANNED'; - case 'normalBanned': return 'Banned'; - case 'bigRedBadStanding': return 'BAD STANDING'; - case 'copiedToClipboard': return 'Copied to clipboard!'; - case 'playerRoleAccount': return ' account '; - case 'wasFromBeginning': return 'that was from very beginning'; - case 'created': return 'created'; - case 'botCreatedBy': return 'by'; - case 'notSupporter': return 'Not a supporter'; - case 'assignedManualy': return 'That badge was assigned manualy by TETR.IO admins'; - case 'supporter': return ({required Object tier}) => 'Supporter tier ${tier}'; - case 'comparingWith': return ({required Object newDate, required Object oldDate}) => 'Data from ${newDate} comparing with ${oldDate}'; + case 'copyUserID': return 'Click to copy user ID'; + case 'searchHint': return 'Username or ID'; + case 'searchButton': return 'Search'; + case 'trackedPlayers': return 'Tracked Players'; + case 'standing': return 'Standing'; + case 'previousSeasons': return 'Previous Seasons'; + case 'recent': return 'Recent'; case 'top': return 'Top'; - case 'topRank': return 'Top rank'; - case 'verdictGeneral': return ({required Object n, required Object verdict, required Object rank}) => '${n} ${verdict} ${rank} rank avg'; - case 'verdictBetter': return 'better'; - case 'verdictWorse': return 'worse'; - case 'smooth': return 'Smooth'; - case 'postSeason': return 'Off-season'; - case 'seasonStarts': return 'Season starts in:'; - case 'nanow': return 'Not avaliable for now...'; - case 'seasonEnds': return ({required Object countdown}) => 'Season ends in ${countdown}'; - case 'seasonEnded': return 'Season has ended'; - case 'gamesUntilRanked': return ({required Object left}) => '${left} games until being ranked'; - case 'numOfVictories': return ({required Object wins}) => '~${wins} victories'; - case 'promotionOnNextWin': return 'Promotion on next win'; - case 'numOfdefeats': return ({required Object losses}) => '~${losses} defeats'; - case 'demotionOnNextLoss': return 'Demotion on next loss'; - case 'nerdStats': return 'Nerd Stats'; - case 'playersYouTrack': return 'Players you track'; - case 'formula': return 'Formula'; - case 'exactValue': return 'Exact value'; - case 'neverPlayedTL': return 'That user never played Tetra League'; - case 'botTL': return 'Bots are not allowed to play Tetra League'; - case 'anonTL': return 'Guests are not allowed to play Tetra League'; - case 'quickPlay': return 'Quick Play'; - case 'expert': return 'Expert'; - case 'withMods': return 'With mods'; - case 'withModsPlural': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: 'with ${n} mods', - one: 'with ${n} mod', - two: 'with ${n} mods', - few: 'with ${n} mods', - many: 'with ${n} mods', - other: 'with ${n} mods', - ); - case 'exportDB': return 'Export local database'; - case 'exportDBDescription': return 'It contains states and Tetra League records of the tracked players and list of tracked players.'; - case 'desktopExportAlertTitle': return 'Desktop export'; - case 'desktopExportText': return 'It seems like you using this app on desktop. Check your documents folder, you should find "TetraStats.db". Copy it somewhere'; - case 'androidExportAlertTitle': return 'Android export'; - case 'androidExportText': return ({required Object exportedDB}) => 'Exported.\n${exportedDB}'; - case 'importDB': return 'Import local database'; - case 'importDBDescription': return 'Restore your backup. Notice that already stored database will be overwritten.'; - case 'importWrongFileType': return 'Wrong file type'; - case 'importCancelled': return 'Operation was cancelled'; - case 'importSuccess': return 'Import successful'; - case 'yourID': return 'Your TETR.IO account'; - case 'yourIDAlertTitle': return 'Your nickname in TETR.IO'; - case 'yourIDText': return 'When app loads, it will retrieve data for this account'; - case 'language': return 'Language'; - case 'updateInBackground': return 'Update stats in the background'; - case 'updateInBackgroundDescription': return 'While Tetra Stats is running, it can update stats of the current player when cache expires'; - case 'customization': return 'Customization'; - case 'customizationDescription': return 'Change appearance of different things in Tetra Stats UI'; - case 'oskKagari': return 'Osk Kagari gimmick'; - case 'oskKagariDescription': return 'If on, osk\'s rank on main view will be rendered as :kagari:'; - case 'AccentColor': return 'Accent color'; - case 'AccentColorDescription': return 'Almost all interactive UI elements highlighted with this color'; - case 'timestamps': return 'Timestamps'; - case 'timestampsDescription': return 'You can choose, in which way timestamps shows time'; - case 'timestampsAbsoluteGMT': return 'Absolute (GMT)'; - case 'timestampsAbsoluteLocalTime': return 'Absolute (Your timezone)'; - case 'timestampsRelative': return 'Relative'; - case 'rating': return 'Main representation of rating'; - case 'ratingDescription': return 'TR is not linear, while Glicko does not have boundaries and percentile is volatile'; - case 'ratingLBposition': return 'LB position'; - case 'sheetbotGraphs': return 'Sheetbot-like behavior for radar graphs'; - case 'sheetbotGraphsDescription': return 'If on, points on the graphs can appear on the opposite half of the graph if value is negative'; - case 'lbStats': return 'Show leaderboard based stats'; - case 'lbStatsDescription': return 'That will impact on loading times, but will allow you to see position on LB by stats and comparison with average values'; - case 'aboutApp': return 'About app'; - case 'aboutAppText': return ({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) Version ${version} Build ${buildNumber}\n\nDeveloped by dan63047\nFormulas provided by kerrmunism\nHistory provided by p1nkl0bst3r\nTETR.IO replay grabber API by szy'; - case 'stateViewTitle': return ({required Object nickname, required Object date}) => '${nickname} account on ${date}'; - case 'statesViewTitle': return ({required Object number, required Object nickname}) => '${number} states of ${nickname} account'; - case 'matchesViewTitle': return ({required Object nickname}) => '${nickname} TL matches'; - case 'statesViewEntry': return ({required Object level, required Object glicko, required Object rd, required Object games}) => '${level} TR, ${glicko}±${rd} Glicko, ${games} игр сыграно'; - case 'stateRemoved': return ({required Object date}) => '${date} state was removed from database!'; - case 'matchRemoved': return ({required Object date}) => '${date} match was removed from database!'; - case 'viewAllMatches': return 'View all matches'; - case 'trackedPlayersViewTitle': return 'Stored data'; - case 'trackedPlayersZeroEntrys': return 'Empty list. Press "Track" button in previous view to add current player here'; - case 'trackedPlayersOneEntry': return 'There is only one player'; - case 'trackedPlayersManyEntrys': return ({required Object numberOfPlayers}) => 'There are ${numberOfPlayers} players'; - case 'trackedPlayersEntry': return ({required Object nickname, required Object numberOfStates}) => '${nickname}: ${numberOfStates} states'; - case 'trackedPlayersDescription': return ({required Object firstStateDate, required Object lastStateDate}) => 'From ${firstStateDate} until ${lastStateDate}'; - case 'trackedPlayersStatesDeleted': return ({required Object nickname}) => '${nickname} states was removed from database!'; - case 'duplicatedFix': return 'Remove duplicated TL mathces'; - case 'compressDB': return 'Compress DB'; - case 'SpaceSaved': return ({required Object size}) => 'Space saved: ${size}'; - case 'averageXrank': return ({required Object rankLetter}) => 'Average ${rankLetter} rank'; - case 'vs': return 'vs'; - case 'inTLmatch': return 'in TL match'; - case 'downloadReplay': return 'Download .ttrm replay'; - case 'openReplay': return 'Open replay in TETR.IO'; - case 'replaySaved': return ({required Object path}) => 'Replay saved to ${path}'; - case 'match': return 'Match'; - case 'timeWeightedmatch': return 'Match (time-weighted)'; - case 'roundNumber': return ({required Object n}) => 'Round ${n}'; - case 'statsFor': return 'Stats for'; - case 'numberOfRounds': return 'Number of rounds'; - case 'matchLength': return 'Match Length'; - case 'roundLength': return 'Round Length'; - case 'matchStats': return 'Match stats'; - case 'timeWeightedmatchStats': return 'Time-weighted match stats'; - case 'replayIssue': return 'Can\'t process replay'; - case 'matchIsTooOld': return 'Replay is not available'; - case 'winner': return 'Winner'; - case 'registred': return 'Registred'; - case 'playedTL': return 'Played Tetra League'; - case 'winChance': return 'Win Chance'; - case 'byGlicko': return 'By Glicko'; - case 'byEstTR': return 'By Est. TR'; - case 'compareViewNoValues': return ({required Object avgR}) => 'Please, enter username, user ID, APM-PPS-VS values (divider doesn\'t matter, only order matter) or ${avgR} (where R is rank) to both fields'; - case 'compareViewWrongValue': return ({required Object value}) => 'Falied to assign ${value}'; - case 'mostRecentOne': return 'Most recent one'; - case 'yes': return 'Yes'; - case 'no': return 'No'; - case 'daysLater': return 'days later'; - case 'dayseBefore': return 'days before'; - case 'fromBeginning': return 'From beginning'; - case 'calc': return 'Calc'; - case 'calcViewNoValues': return 'Enter values to calculate the stats'; - case 'rankAveragesViewTitle': return 'Ranks cutoffs'; - case 'sprintAndBlitsViewTitle': return '40 lines and Blitz averages'; + case 'noRecord': return 'No record'; case 'sprintAndBlitsRelevance': return ({required Object date}) => 'Relevance: ${date}'; - case 'rank': return 'Rank'; - case 'averages': return 'Averages'; - case 'lbViewZeroEntrys': return 'Empty list'; - case 'lbViewOneEntry': return 'There is only one player'; - case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'There are ${numberOfPlayers}'; - case 'everyoneAverages': return 'Values for leaderboard'; - case 'sortBy': return 'Sort by'; - case 'reversed': return 'Reversed'; - case 'country': return 'Country'; - case 'rankAverages': return ({required Object rank}) => 'Values for ${rank} rank'; - case 'players': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} players', - one: '${n} player', - two: '${n} players', - few: '${n} players', - many: '${n} players', - other: '${n} players', - ); - case 'games': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} games', - one: '${n} game', - two: '${n} games', - few: '${n} games', - many: '${n} games', - other: '${n} games', - ); - case 'gamesPlayed': return ({required Object games}) => '${games} played'; - case 'chart': return 'Chart'; - case 'entries': return 'Entries'; - case 'minimums': return 'Minimums'; - case 'maximums': return 'Maximums'; - case 'lowestValues': return 'Lowest Values'; - case 'averageValues': return 'Average Values'; - case 'highestValues': return 'Highest Values'; - case 'forPlayer': return ({required Object username}) => 'for player ${username}'; - case 'currentAxis': return ({required Object axis}) => '${axis} axis:'; - case 'p1nkl0bst3rAlert': return 'That data was retrived from third party API maintained by p1nkl0bst3r'; - case 'notForWeb': return 'Function is not available for web version'; - case 'graphs.attack': return 'Attack'; - case 'graphs.speed': return 'Speed'; - case 'graphs.defense': return 'Defense'; - case 'graphs.cheese': return 'Cheese'; - case 'statCellNum.xpLevel': return 'XP Level'; - case 'statCellNum.xpProgress': return 'Progress to next level'; - case 'statCellNum.xpFrom0ToLevel': return ({required Object n}) => 'Progress from 0 XP to level ${n}'; - case 'statCellNum.xpLeft': return 'XP left'; - case 'statCellNum.hoursPlayed': return 'Hours\nPlayed'; - case 'statCellNum.onlineGames': return 'Online\nGames'; - case 'statCellNum.gamesWon': return 'Games\nWon'; - case 'statCellNum.totalGames': return 'Total Games Played'; - case 'statCellNum.totalWon': return 'Total Games Won'; - case 'statCellNum.friends': return 'Friends'; - case 'statCellNum.apm': return 'Attack\nPer Minute'; - case 'statCellNum.vs': return 'Versus\nScore'; - case 'statCellNum.recordLB': return 'Leaderboard placement'; - case 'statCellNum.lbp': return 'Leaderboard\nplacement'; - case 'statCellNum.lbpShort': return '№ in LB'; - case 'statCellNum.lbpc': return 'Country LB\nplacement'; - case 'statCellNum.lbpcShort': return '№ in local LB'; - case 'statCellNum.gamesPlayed': return 'Games\nplayed'; - case 'statCellNum.gamesWonTL': return 'Games\nWon'; - case 'statCellNum.winrate': return 'Winrate'; - case 'statCellNum.level': return 'Level'; - case 'statCellNum.score': return 'Score'; - case 'statCellNum.spp': return 'Score\nPer Piece'; - case 'statCellNum.pieces': return 'Pieces\nPlaced'; - case 'statCellNum.pps': return 'Pieces\nPer Second'; - case 'statCellNum.finesseFaults': return 'Finesse\nFaults'; - case 'statCellNum.finessePercentage': return 'Finesse\nPercentage'; - case 'statCellNum.keys': return 'Key\nPresses'; - case 'statCellNum.kpp': return 'KP Per\nPiece'; - case 'statCellNum.kps': return 'KP Per\nSecond'; - case 'statCellNum.tr': return 'Tetra Rating'; - case 'statCellNum.rd': return 'Rating Deviation'; - case 'statCellNum.app': return 'Attack Per Piece'; - case 'statCellNum.appDescription': return '(Abbreviated as APP) Main efficiency metric. Tells how many attack you producing per piece'; - case 'statCellNum.vsapmDescription': return 'Basically, tells how much and how efficient you using garbage in your attacks'; - case 'statCellNum.dss': return 'Downstack\nPer Second'; - case 'statCellNum.dssDescription': return '(Abbreviated as DS/S) Downstack per Second measures how many garbage lines you clear in a second.'; - case 'statCellNum.dsp': return 'Downstack\nPer Piece'; - case 'statCellNum.dspDescription': return '(Abbreviated as DS/P) Downstack per Piece measures how many garbage lines you clear per piece.'; - case 'statCellNum.appdsp': return 'APP + DS/P'; - case 'statCellNum.appdspDescription': return 'Just a sum of Attack per Piece and Downstack per Piece.'; - case 'statCellNum.cheese': return 'Cheese\nIndex'; - case 'statCellNum.cheeseDescription': return '(Abbreviated as Cheese) Cheese Index is an approximation how much clean / cheese garbage player sends. Lower = more clean. Higher = more cheese.\nInvented by kerrmunism'; - case 'statCellNum.gbe': return 'Garbage\nEfficiency'; - case 'statCellNum.gbeDescription': return '(Abbreviated as Gb Eff.) Garbage Efficiency measures how well player uses their garbage. Higher = better or they use their garbage more. Lower = they mostly send their garbage back at cheese or rarely clear garbage.\nInvented by Zepheniah and Dragonboy.'; - case 'statCellNum.nyaapp': return 'Weighted\nAPP'; - case 'statCellNum.nyaappDescription': return '(Abbreviated as wAPP) Essentially, a measure of your ability to send cheese while still maintaining a high APP.\nInvented by Wertj.'; - case 'statCellNum.area': return 'Area'; - case 'statCellNum.areaDescription': return 'How much space your shape takes up on the graph, if you exclude the cheese and vs/apm sections'; - case 'statCellNum.estOfTR': return 'Estimated TR'; - case 'statCellNum.estOfTRShort': return 'Est. TR'; - case 'statCellNum.accOfEst': return 'Accuracy'; - case 'statCellNum.accOfEstShort': return 'Acc.'; - case 'playerRole.user': return 'User'; - case 'playerRole.banned': return 'Banned'; - case 'playerRole.bot': return 'Bot'; - case 'playerRole.sysop': return 'System operator'; - case 'playerRole.admin': return 'Admin'; - case 'playerRole.mod': return 'Moderator'; - case 'playerRole.halfmod': return 'Community moderator'; - case 'playerRole.anon': return 'Anonymous'; - case 'numOfGameActions.pc': return 'All Clears'; - case 'numOfGameActions.hold': return 'Holds'; - case 'numOfGameActions.inputs': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} key presses', - one: '${n} key press', - two: '${n} key presses', - few: '${n} key presses', - many: '${n} key presses', - other: '${n} key presses', - ); - case 'numOfGameActions.tspinsTotal': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} T-spins total', - one: '${n} T-spin total', - two: '${n} T-spins total', - few: '${n} T-spins total', - many: '${n} T-spins total', - other: '${n} T-spins total', - ); - case 'numOfGameActions.lineClears': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - zero: '${n} lines cleared', - one: '${n} line cleared', - two: '${n} lines cleared', - few: '${n} lines cleared', - many: '${n} lines cleared', - other: '${n} lines cleared', - ); - case 'popupActions.cancel': return 'Cancel'; - case 'popupActions.submit': return 'Submit'; - case 'popupActions.ok': return 'OK'; + case 'snackBarMessages.stateRemoved': return ({required Object date}) => '${date} state was removed from database!'; + case 'snackBarMessages.matchRemoved': return ({required Object date}) => '${date} match was removed from database!'; + case 'snackBarMessages.notForWeb': return 'Function is not available for web version'; + case 'snackBarMessages.importSuccess': return 'Import successful'; + case 'snackBarMessages.importCancelled': return 'Import was cancelled'; + case 'errors.noRecords': return 'No records'; + case 'errors.notEnoughData': return 'Not enough data'; + case 'errors.noHistorySaved': return 'No history saved'; case 'errors.connection': return ({required Object code, required Object message}) => 'Some issue with connection: ${code} ${message}'; case 'errors.noSuchUser': return 'No such user'; case 'errors.noSuchUserSub': return 'Either you mistyped something, or the account no longer exists'; @@ -2628,6 +1634,328 @@ extension on Translations { case 'errors.replayAlreadySaved': return 'Replay already saved'; case 'errors.replayExpired': return 'Replay expired and not available anymore'; case 'errors.replayRejected': return 'Third party API blocked your IP address'; + case 'actions.cancel': return 'Cancel'; + case 'actions.submit': return 'Submit'; + case 'actions.ok': return 'OK'; + case 'actions.apply': return 'Apply'; + case 'actions.refresh': return 'Refresh'; + case 'graphsDestination.fetchAndsaveTLHistory': return 'Get player history'; + case 'graphsDestination.fetchAndSaveOldTLmatches': return 'Get Tetra League matches history'; + case 'graphsDestination.fetchAndsaveTLHistoryResult': return ({required Object number}) => '${number} states was found'; + case 'graphsDestination.fetchAndSaveOldTLmatchesResult': return ({required Object number}) => '${number} matches was found'; + case 'graphsDestination.gamesPlayed': return ({required Object games}) => '${games} played'; + case 'graphsDestination.dateAndTime': return 'Date & Time'; + case 'graphsDestination.filterModaleTitle': return 'Filter ranks on graph'; + case 'filterModale.all': return 'All'; + case 'cutoffsDestination.title': return 'Tetra League State'; + case 'cutoffsDestination.relevance': return ({required Object timestamp}) => 'as of ${timestamp}'; + case 'cutoffsDestination.actual': return 'Actual'; + case 'cutoffsDestination.target': return 'Target'; + case 'cutoffsDestination.cutoffTR': return 'Cutoff TR'; + case 'cutoffsDestination.targetTR': return 'Target TR'; + case 'cutoffsDestination.state': return 'State'; + case 'cutoffsDestination.advanced': return 'Advanced'; + case 'cutoffsDestination.players': return ({required Object n}) => 'Players (${n})'; + case 'cutoffsDestination.moreInfo': return 'More Info'; + case 'cutoffsDestination.NumberOne': return ({required Object tr}) => '№ 1 is ${tr} TR'; + case 'cutoffsDestination.inflated': return ({required Object tr}) => 'Inflated on ${tr} TR'; + case 'cutoffsDestination.notInflated': return 'Not inflated'; + case 'cutoffsDestination.deflated': return ({required Object tr}) => 'Deflated on ${tr} TR'; + case 'cutoffsDestination.notDeflated': return 'Not deflated'; + case 'cutoffsDestination.wellDotDotDot': return 'Well...'; + case 'cutoffsDestination.fromPlace': return ({required Object n}) => 'from № ${n}'; + case 'cutoffsDestination.viewButton': return 'View'; + case 'rankView.rankTitle': return ({required Object rank}) => '${rank} rank data'; + case 'rankView.everyoneTitle': return 'Entire leaderboard'; + case 'rankView.trRange': return 'TR Range'; + case 'rankView.supposedToBe': return 'Supposed to be'; + case 'rankView.gap': return ({required Object value}) => '${value} gap'; + case 'rankView.deflationGap': return 'Deflation gap'; + case 'rankView.inflationGap': return 'Inflation gap'; + case 'rankView.LBposRange': return 'LB pos range'; + case 'rankView.overpopulated': return ({required Object players}) => 'Overpopulated by a ${players}'; + case 'rankView.underpopulated': return ({required Object players}) => 'Underpopulated by a ${players}'; + case 'rankView.PlayersEqualSupposedToBe': return 'cute'; + case 'rankView.avgStats': return 'Average Stats'; + case 'rankView.avgNerdStats': return 'Average Nerd Stats'; + case 'rankView.minimums': return 'Minimums'; + case 'rankView.maximums': return 'Maximums'; + case 'tlMatchView.match': return 'Match'; + case 'tlMatchView.vs': return 'vs'; + case 'tlMatchView.winner': return 'Winner'; + case 'tlMatchView.roundNumber': return ({required Object n}) => 'Round ${n}'; + case 'tlMatchView.statsFor': return 'Stats for'; + case 'tlMatchView.numberOfRounds': return 'Number of rounds'; + case 'tlMatchView.matchLength': return 'Match Length'; + case 'tlMatchView.roundLength': return 'Round Length'; + case 'tlMatchView.matchStats': return 'Match stats'; + case 'tlMatchView.downloadReplay': return 'Download .ttrm replay'; + case 'tlMatchView.openReplay': return 'Open replay in TETR.IO'; + case 'calcDestination.tip': return 'Enter values and press "Calc" to see Nerd Stats for them'; + case 'calcDestination.statsCalcButton': return 'Calc'; + case 'calcDestination.damageCalcTip': return 'Click on the actions on the left to add them here'; + case 'calcDestination.actions': return 'Actions'; + case 'calcDestination.results': return 'Results'; + case 'calcDestination.rules': return 'Rules'; + case 'calcDestination.noSpinClears': return 'No Spin Clears'; + case 'calcDestination.spins': return 'Spins'; + case 'calcDestination.miniSpins': return 'Mini spins'; + case 'calcDestination.noLineclear': return 'No lineclear (Break Combo)'; + case 'calcDestination.custom': return 'Custom'; + case 'calcDestination.multiplier': return 'Multiplier'; + case 'calcDestination.pcDamage': return 'Perfect Clear Damage'; + case 'calcDestination.comboTable': return 'Combo Table'; + case 'calcDestination.b2bChaining': return 'Back-To-Back Chaining'; + case 'calcDestination.surgeStartAtB2B': return 'Starts at B2B'; + case 'calcDestination.surgeStartAmount': return 'Start amount'; + case 'calcDestination.totalDamage': return 'Total damage'; + case 'calcDestination.lineclears': return 'Lineclears'; + case 'calcDestination.combo': return 'Combo'; + case 'calcDestination.surge': return 'Surge'; + case 'calcDestination.pcs': return 'PCs'; + case 'infoDestination.title': return 'Information Center'; + case 'infoDestination.sprintAndBlitzAverages': return '40 Lines & Blitz Averages'; + case 'infoDestination.sprintAndBlitzAveragesDescription': return 'Since calculating 40 Lines & Blitz averages is tedious process, it gets updated only once in a while. Click on the title of this card to see the full 40 Lines & Blitz averages table'; + case 'infoDestination.tetraStatsWiki': return 'Tetra Stats Wiki'; + case 'infoDestination.tetraStatsWikiDescription': return 'Find more information about Tetra Stats functions and statictic, that it provides'; + case 'infoDestination.about': return 'About Tetra Stats'; + case 'infoDestination.aboutDescription': return 'Developed by dan63\n'; + case 'leaderboardsDestination.title': return 'Leaderboards'; + case 'leaderboardsDestination.tl': return 'Tetra League (Current Season)'; + case 'leaderboardsDestination.fullTL': return 'Tetra League (Current Season, full one)'; + case 'leaderboardsDestination.ar': return 'Acievement Points'; + case 'leaderboardsDestination.fullTLnote': return 'Heavy, but allows you to sort players by their stats and filter them by ranks'; + case 'settingsDestination.title': return 'Settings'; + case 'settingsDestination.timestamps': return 'Timestamps'; + case 'settingsDestination.timestampsDescription': return 'You can choose, in which way timestamps shows time'; + case 'settingsDestination.timestampsAbsoluteGMT': return 'Absolute (GMT)'; + case 'settingsDestination.timestampsAbsoluteLocalTime': return 'Absolute (Your timezone)'; + case 'settingsDestination.timestampsRelative': return 'Relative'; + case 'settingsDestination.exportDB': return 'Export local database'; + case 'settingsDestination.desktopExportAlertTitle': return 'Desktop export'; + case 'settingsDestination.desktopExportText': return 'It seems like you using this app on desktop. Check your documents folder, you should find "TetraStats.db". Copy it somewhere'; + case 'settingsDestination.androidExportAlertTitle': return 'Android export'; + case 'settingsDestination.androidExportText': return ({required Object exportedDB}) => 'Exported.\n${exportedDB}'; + case 'settingsDestination.importDB': return 'Import local database'; + case 'settingsDestination.importDBDescription': return 'Restore your backup. Notice that already stored database will be overwritten.'; + case 'settingsDestination.importWrongFileType': return 'Wrong file type'; + case 'homeNavigation.overview': return 'Overview'; + case 'homeNavigation.standing': return 'Standing'; + case 'homeNavigation.seasons': return 'Seasons'; + case 'homeNavigation.mathces': return 'Matches'; + case 'homeNavigation.pb': return 'PB'; + case 'homeNavigation.normal': return 'Normal'; + case 'homeNavigation.expert': return 'Expert'; + case 'homeNavigation.expertRecords': return 'Ex Records'; + case 'graphsNavigation.history': return 'Player History'; + case 'graphsNavigation.league': return 'League State'; + case 'graphsNavigation.cutoffs': return 'Cutoffs History'; + case 'calcNavigation.stats': return 'Stats Calculator'; + case 'calcNavigation.damage': return 'Damage Calculator'; + case 'aboutView.title': return 'About Tetra Stats'; + case 'aboutView.about': return 'Tetra Stats is a service, that works with TETR.IO Tetra Channel API, providing data from it and calculating some addtitional metrics, based on this data. Service allows user to track their progress in Tetra League with "Track" function, which records every Tetra League change into local database (not automatically, you have to visit service from time to time), so these changes could be looked through graphs.\n\nBeanserver blaster is a part of a Tetra Stats, that decoupled into a serverside script. It provides full Tetra League leaderboard, allowing Tetra Stats to sort leaderboard by any metric and build scatter chart, that allows user to analyse Tetra League trends. It also provides history of Tetra League ranks cutoffs, which can be viewed by user via graph as well.\n\nThere is a plans to add replay analysis and tournaments history, so stay tuned!\n\nService is not associated with TETR.IO or osk in any capacity.'; + case 'aboutView.appVersion': return 'App Version'; + case 'aboutView.build': return ({required Object build}) => 'Build ${build}'; + case 'aboutView.GHrepo': return 'GitHub Repository'; + case 'aboutView.submitAnIssue': return 'Submit an issue'; + case 'aboutView.credits': return 'Credits'; + case 'aboutView.authorAndDeveloper': return 'Autor & developer'; + case 'aboutView.providedFormulas': return 'Provided formulas'; + case 'aboutView.providedS1history': return 'Provided S1 history'; + case 'aboutView.inoue': return 'Inoue (replay grabber)'; + case 'aboutView.zhCNlocale': return 'Simplfied Chinise locale'; + case 'aboutView.supportHim': return 'Support him!'; + case 'stats.registrationDate': return 'Registration Date'; + case 'stats.gametime': return 'Time Played'; + case 'stats.ogp': return 'Online Games Played'; + case 'stats.ogw': return 'Online Games Won'; + case 'stats.followers': return 'Followers'; + case 'stats.xp.short': return 'XP'; + case 'stats.xp.full': return 'Experience Points'; + case 'stats.tr.short': return 'TR'; + case 'stats.tr.full': return 'Tetra Rating'; + case 'stats.glicko.short': return 'Glicko'; + case 'stats.glicko.full': return 'Glicko'; + case 'stats.rd.short': return 'RD'; + case 'stats.rd.full': return 'Rating Deviation'; + case 'stats.glixare.short': return 'GXE'; + case 'stats.glixare.full': return 'GLIXARE'; + case 'stats.s1tr.short': return 'S1 TR'; + case 'stats.s1tr.full': return 'Season 1 like TR'; + case 'stats.gp.short': return 'GP'; + case 'stats.gp.full': return 'Games Played'; + case 'stats.gw.short': return 'GW'; + case 'stats.gw.full': return 'Games Won'; + case 'stats.winrate.short': return 'WR%'; + case 'stats.winrate.full': return 'Win Rate'; + case 'stats.apm.short': return 'APM'; + case 'stats.apm.full': return 'Attack Per Minute'; + case 'stats.pps.short': return 'PPS'; + case 'stats.pps.full': return 'Pieces Per Second'; + case 'stats.vs.short': return 'VS'; + case 'stats.vs.full': return 'Versus Score'; + case 'stats.app.short': return 'APP'; + case 'stats.app.full': return 'Attack Per Piece'; + case 'stats.vsapm.short': return 'VS/APM'; + case 'stats.vsapm.full': return 'VS / APM'; + case 'stats.dss.short': return 'DS/S'; + case 'stats.dss.full': return 'Downstack Per Second'; + case 'stats.dsp.short': return 'DS/P'; + case 'stats.dsp.full': return 'Downstack Per Piece'; + case 'stats.appdsp.short': return 'APP+DSP'; + case 'stats.appdsp.full': return 'APP + DSP'; + case 'stats.cheese.short': return 'Cheese'; + case 'stats.cheese.full': return 'Cheese Index'; + case 'stats.gbe.short': return 'GbE'; + case 'stats.gbe.full': return 'Garbage Efficiency'; + case 'stats.nyaapp.short': return 'wAPP'; + case 'stats.nyaapp.full': return 'Weigente APP'; + case 'stats.area.short': return 'Area'; + case 'stats.area.full': return 'Area'; + case 'stats.etr.short': return 'eTR'; + case 'stats.etr.full': return 'Estimated TR'; + case 'stats.etracc.short': return '±eTR'; + case 'stats.etracc.full': return 'Accuracy of Estimated TR'; + case 'stats.opener.short': return 'Opener'; + case 'stats.opener.full': return 'Opener'; + case 'stats.plonk.short': return 'Plonk'; + case 'stats.plonk.full': return 'Plonk'; + case 'stats.stride.short': return 'Stride'; + case 'stats.stride.full': return 'Stride'; + case 'stats.infds.short': return 'Inf. DS'; + case 'stats.infds.full': return 'Infinite Downstack'; + case 'stats.altitude.short': return 'm'; + case 'stats.altitude.full': return 'Altitude'; + case 'stats.climbSpeed.short': return 'CSP'; + case 'stats.climbSpeed.full': return 'Climb Speed'; + case 'stats.climbSpeed.gaugetTitle': return 'Climb\nSpeed'; + case 'stats.peakClimbSpeed.short': return 'Peak CSP'; + case 'stats.peakClimbSpeed.full': return 'Peak Climb Speed'; + case 'stats.peakClimbSpeed.gaugetTitle': return 'Peak'; + case 'stats.kos.short': return 'KO\'s'; + case 'stats.kos.full': return 'Knockouts'; + case 'stats.b2b.short': return 'B2B'; + case 'stats.b2b.full': return 'Back-To-Back'; + case 'stats.finesse.short': return 'F'; + case 'stats.finesse.full': return 'Finesse'; + case 'stats.finesse.widgetTitle': return 'inesse'; + case 'stats.finesseFaults.short': return 'FF'; + case 'stats.finesseFaults.full': return 'Finesse Faults'; + case 'stats.totalTime.short': return 'Time'; + case 'stats.totalTime.full': return 'Total Time'; + case 'stats.totalTime.widgetTitle': return 'otal Time'; + case 'stats.level.short': return 'Lvl'; + case 'stats.level.full': return 'Level'; + case 'stats.pieces.short': return 'P'; + case 'stats.pieces.full': return 'Pieces'; + case 'stats.spp.short': return 'SPP'; + case 'stats.spp.full': return 'Score Per Piece'; + case 'stats.kp.short': return 'KP'; + case 'stats.kp.full': return 'Key presses'; + case 'stats.kpp.short': return 'KPP'; + case 'stats.kpp.full': return 'Key presses Per Piece'; + case 'stats.kps.short': return 'KPS'; + case 'stats.kps.full': return 'Key presses Per Second'; + case 'stats.blitzScore': return ({required Object p}) => '${p} points'; + case 'stats.levelUpRequirement': return ({required Object p}) => 'Level up requirement: ${p}'; + case 'stats.piecesTotal': return 'Total pieces placed'; + case 'stats.piecesWithPerfectFinesse': return 'Placed with perfect finesse'; + case 'stats.score': return 'Score'; + case 'stats.lines': return 'Lines'; + case 'stats.pcs': return 'Perfect Clears'; + case 'stats.holds': return 'Holds'; + case 'stats.spike': return 'Top Spike'; + case 'stats.top': return ({required Object percentage}) => 'Top ${percentage}'; + case 'stats.topRank': return ({required Object rank}) => 'Top rank: ${rank}'; + case 'stats.floor': return 'Floor'; + case 'stats.split': return 'Split'; + case 'stats.total': return 'Total'; + case 'stats.sent': return 'Sent'; + case 'stats.received': return 'Received'; + case 'stats.placement': return 'Placement'; + case 'stats.qpWithMods': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + one: 'With 1 mod', + two: 'With ${n} mods', + few: 'With ${n} mods', + many: 'With ${n} mods', + other: 'With ${n} mods', + ); + case 'stats.inputs': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} key presses', + one: '${n} key press', + two: '${n} key presses', + few: '${n} key presses', + many: '${n} key presses', + other: '${n} key presses', + ); + case 'stats.tspinsTotal': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} T-spins total', + one: '${n} T-spin total', + two: '${n} T-spins total', + few: '${n} T-spins total', + many: '${n} T-spins total', + other: '${n} T-spins total', + ); + case 'stats.linesCleared': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} lines cleared', + one: '${n} line cleared', + two: '${n} lines cleared', + few: '${n} lines cleared', + many: '${n} lines cleared', + other: '${n} lines cleared', + ); + case 'stats.graphs.attack': return 'Attack'; + case 'stats.graphs.speed': return 'Speed'; + case 'stats.graphs.defense': return 'Defense'; + case 'stats.graphs.cheese': return 'Cheese'; + case 'stats.players': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} players', + one: '${n} player', + two: '${n} players', + few: '${n} players', + many: '${n} players', + other: '${n} players', + ); + case 'stats.games': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} games', + one: '${n} game', + two: '${n} games', + few: '${n} games', + many: '${n} games', + other: '${n} games', + ); + case 'stats.lineClear.single': return 'Single'; + case 'stats.lineClear.double': return 'Double'; + case 'stats.lineClear.triple': return 'Triple'; + case 'stats.lineClear.quad': return 'Quad'; + case 'stats.lineClear.penta': return 'Penta'; + case 'stats.lineClear.hexa': return 'Hexa'; + case 'stats.lineClear.hepta': return 'Hepta'; + case 'stats.lineClear.octa': return 'Octa'; + case 'stats.lineClear.ennea': return 'Ennea'; + case 'stats.lineClear.deca': return 'Deca'; + case 'stats.lineClear.hendeca': return 'Hendeca'; + case 'stats.lineClear.dodeca': return 'Dodeca'; + case 'stats.lineClear.triadeca': return 'Triadeca'; + case 'stats.lineClear.tessaradeca': return 'Tessaradeca'; + case 'stats.lineClear.pentedeca': return 'Pentedeca'; + case 'stats.lineClear.hexadeca': return 'Hexadeca'; + case 'stats.lineClear.heptadeca': return 'Heptadeca'; + case 'stats.lineClear.octadeca': return 'Octadeca'; + case 'stats.lineClear.enneadeca': return 'Enneadeca'; + case 'stats.lineClear.eicosa': return 'Eicosa'; + case 'stats.lineClear.kagaris': return 'Kagaris'; + case 'stats.lineClears.zero': return 'Zeros'; + case 'stats.lineClears.single': return 'Singles'; + case 'stats.lineClears.double': return 'Doubles'; + case 'stats.lineClears.triple': return 'Triples'; + case 'stats.lineClears.quad': return 'Quads'; + case 'stats.lineClears.penta': return 'Pentas'; + case 'stats.mini': return 'Mini'; + case 'stats.tSpin': return 'T-spin'; + case 'stats.tSpins': return 'T-spins'; + case 'stats.spin': return 'Spin'; + case 'stats.spins': return 'Spins'; case 'countries.': return 'Worldwide'; case 'countries.AF': return 'Afghanistan'; case 'countries.AX': return 'Åland Islands'; @@ -2891,1259 +2219,3 @@ extension on Translations { } } } - -extension on _StringsRu { - dynamic _flatMapFunction(String path) { - switch (path) { - case 'locales.en': return 'Английский (English)'; - case 'locales.ru': return 'Русский'; - case 'locales.zh-CN': return 'Упрощенный Китайский (简体中文)'; - case 'tetraLeague': return 'Тетра Лига'; - case 'tlRecords': return 'Матчи ТЛ'; - case 'history': return 'История'; - case 'sprint': return '40 линий'; - case 'blitz': return 'Блиц'; - case 'recent': return 'Недавно'; - case 'recentRuns': return 'Недавние'; - case 'blitzScore': return ({required Object p}) => '${p} очков'; - case 'openSPreplay': return 'Открыть повтор в TETR.IO'; - case 'downloadSPreplay': return 'Скачать повтор'; - case 'other': return 'Другое'; - case 'distinguishment': return 'Заслуга'; - case 'zen': return 'Дзен'; - case 'bio': return 'Биография'; - case 'news': return 'Новости'; - case 'newsParts.leaderboardStart': return 'Взял '; - case 'newsParts.leaderboardMiddle': return 'в таблице '; - case 'newsParts.personalbest': return 'Поставил новый ЛР в '; - case 'newsParts.personalbestMiddle': return 'с результатом в '; - case 'newsParts.badgeStart': return 'Заработал значок '; - case 'newsParts.badgeEnd': return ''; - case 'newsParts.rankupStart': return 'Заработал '; - case 'newsParts.rankupMiddle': return ({required Object r}) => '${r} ранг '; - case 'newsParts.rankupEnd': return 'в Тетра Лиге'; - case 'newsParts.tetoSupporter': return 'TETR.IO supporter'; - case 'newsParts.supporterStart': return 'Стал обладателем '; - case 'newsParts.supporterGiftStart': return 'Получил подарок в виде '; - case 'newsParts.unknownNews': return ({required Object type}) => 'Неизвестная новость типа ${type}'; - case 'openSearch': return 'Искать игрока'; - case 'closeSearch': return 'Закрыть поиск'; - case 'searchHint': return 'Ник, ID или ID в Discord (с префиксом "ds:")'; - case 'refresh': return 'Обновить'; - case 'fetchAndsaveTLHistory': return 'Получить историю игрока'; - case 'fetchAndSaveOldTLmatches': return 'Получить старые матчи Тетра Лиги'; - case 'fetchAndsaveTLHistoryResult': return ({required Object number}) => '${number} состояний было найдено'; - case 'fetchAndSaveOldTLmatchesResult': return ({required Object number}) => '${number} старых матчей было найдено'; - case 'showStoredData': return 'Показать сохранённые данные'; - case 'statsCalc': return 'Калькулятор статистики'; - case 'settings': return 'Настройки'; - case 'track': return 'Отслеживать'; - case 'stopTracking': return 'Перестать\nотслеживать'; - case 'becameTracked': return 'Добавлен в список отслеживания!'; - case 'stoppedBeingTracked': return 'Удалён из списка отслеживания!'; - case 'compare': return 'Сравнить'; - case 'tlLeaderboard': return 'Рейтинговая таблица'; - case 'noRecords': return 'Нет записей'; - case 'noOldRecords': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: 'Нет записей', - one: 'Всего один матч', - two: 'Всего ${n} матча', - few: 'Всего ${n} матча', - many: 'Всего ${n} матчей', - other: '${n} матчей', - ); - case 'noRecord': return 'Нет рекорда'; - case 'botRecord': return 'Ботам нельзя ставить рекорды'; - case 'anonRecord': return 'Гостям нельзя ставить рекорды'; - case 'notEnoughData': return 'Недостаточно данных'; - case 'noHistorySaved': return 'Нет сохранённой истории'; - case 'pseudoTooltipHeaderInit': return 'Наведите курсор на точку'; - case 'pseudoTooltipFooterInit': return 'чтобы узнать подробности'; - case 'obtainDate': return ({required Object date}) => 'Получено ${date}'; - case 'fetchDate': return ({required Object date}) => 'На момент ${date}'; - case 'exactGametime': return 'Время, проведённое в игре'; - case 'bigRedBanned': return 'ЗАБАНЕН'; - case 'normalBanned': return 'Забанен'; - case 'bigRedBadStanding': return 'ПЛОХАЯ РЕПУТАЦИЯ'; - case 'copiedToClipboard': return 'Скопировано в буфер обмена!'; - case 'playerRoleAccount': return ', аккаунт которого '; - case 'wasFromBeginning': return 'существовал с самого начала'; - case 'created': return 'создан'; - case 'botCreatedBy': return 'игроком'; - case 'notSupporter': return 'Нет саппортерки'; - case 'supporter': return ({required Object tier}) => 'Саппортерка ${tier} уровня'; - case 'assignedManualy': return 'Этот значок был присвоен вручную администрацией TETR.IO'; - case 'comparingWith': return ({required Object newDate, required Object oldDate}) => 'Данные от ${newDate} в сравнении с данными от ${oldDate}'; - case 'top': return 'Топ'; - case 'topRank': return 'Топ ранг'; - case 'verdictGeneral': return ({required Object verdict, required Object rank, required Object n}) => '${verdict} среднего ${rank} ранга на ${n}'; - case 'verdictBetter': return 'Лучше'; - case 'verdictWorse': return 'Хуже'; - case 'smooth': return 'Гладкий'; - case 'postSeason': return 'Внесезонье'; - case 'seasonStarts': return 'Сезон начнётся через:'; - case 'nanow': return 'Пока недоступно...'; - case 'seasonEnds': return ({required Object countdown}) => 'Сезон закончится через ${countdown}'; - case 'seasonEnded': return 'Сезон закончился'; - case 'gamesUntilRanked': return ({required Object left}) => '${left} матчей до получения рейтинга'; - case 'numOfVictories': return ({required Object wins}) => '~${wins} побед'; - case 'promotionOnNextWin': return 'Повышение после следующей победы'; - case 'numOfdefeats': return ({required Object losses}) => '~${losses} поражений'; - case 'demotionOnNextLoss': return 'Понижение после следующего поражения'; - case 'nerdStats': return 'Для задротов'; - case 'playersYouTrack': return 'Отслеживаемые игроки'; - case 'formula': return 'Формула'; - case 'exactValue': return 'Точное значение'; - case 'neverPlayedTL': return 'Этот игрок никогда не играл в Тетра Лигу'; - case 'botTL': return 'Ботам нельзя играть в Тетра Лигу'; - case 'anonTL': return 'Гостям нельзя играть в Тетра Лигу'; - case 'quickPlay': return 'Быстрая Игра'; - case 'expert': return 'Эксперт'; - case 'withMods': return 'С модами'; - case 'withModsPlural': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: 'с ${n} модами', - one: 'с ${n} модом', - two: 'с ${n} модами', - few: 'с ${n} модами', - many: 'с ${n} модами', - other: 'с ${n} модами', - ); - case 'exportDB': return 'Экспортировать локальную базу данных'; - case 'exportDBDescription': return 'Она содержит состояния аккаунтов и их матчей в Тетра Лиге для отслеживаемых игроков и список таких игроков.'; - case 'desktopExportAlertTitle': return 'Экспорт на десктопе'; - case 'desktopExportText': return 'Похоже, вы используете десктопную версию. Проверьте папку "Документы", там вы должны найти файл "TetraStats.db". Скопируйте его куда-нибудь'; - case 'androidExportAlertTitle': return 'Экспорт на Android'; - case 'androidExportText': return ({required Object exportedDB}) => 'Экспортировано.\n${exportedDB}'; - case 'importDB': return 'Импортировать локальную базу данных'; - case 'importDBDescription': return 'Восстановите свою резеврную копию. Обратите внимание, что текущая база данных будет перезаписана.'; - case 'importWrongFileType': return 'Неверный тип файла'; - case 'importCancelled': return 'Операция была отменена'; - case 'importSuccess': return 'Успешно импортировано'; - case 'yourID': return 'Ваш аккаунт в TETR.IO'; - case 'yourIDAlertTitle': return 'Ваш ник в TETR.IO'; - case 'yourIDText': return 'При запуске приложения оно будет получать статистику этого игрока.'; - case 'language': return 'Язык (Language)'; - case 'updateInBackground': return 'Обновлять статистику в фоне'; - case 'updateInBackgroundDescription': return 'Пока Tetra Stats работает, он может обновлять статистику самостоятельно когда кеш истекает'; - case 'customization': return 'Кастомизация'; - case 'customizationDescription': return 'Измените внешний вид пользовательского интерфейса Tetra Stats'; - case 'oskKagari': return '"Оск Кагари" прикол'; - case 'oskKagariDescription': return 'Если включено, вместо настоящего ранга оска будет рендерится :kagari:'; - case 'AccentColor': return 'Цветовой акцент'; - case 'AccentColorDescription': return 'Почти все интерактивные элементы пользовательского интерфейса окрашены в этот цвет'; - case 'timestamps': return 'Метки времени'; - case 'timestampsDescription': return 'Вы можете выбрать, каким образом метки времени показывают время'; - case 'timestampsAbsoluteGMT': return 'Абсолютные (GMT)'; - case 'timestampsAbsoluteLocalTime': return 'Абсолютные (Ваш часовой пояс)'; - case 'timestampsRelative': return 'Относительные'; - case 'rating': return 'Основное представление рейтинга'; - case 'ratingDescription': return 'TR нелинеен, тогда как Glicko не имеет границ, а положение в таблице лидеров волатильно'; - case 'ratingLBposition': return 'Позиция в рейтинге'; - case 'sheetbotGraphs': return 'Графики-радары как у sheetBot'; - case 'sheetbotGraphsDescription': return 'Если включено, точки на графике могут появляться на противоположной стороне графика если значение отрицательное'; - case 'lbStats': return 'Показывать статистику, основанную на рейтинговой таблице'; - case 'lbStatsDescription': return 'Это повлияет на время загрузки, но позволит видеть положение в рейтинге и сравнение со средними значениями по рангу по каждой стате'; - case 'aboutApp': return 'О приложении'; - case 'aboutAppText': return ({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) Версия ${version} Сборка ${buildNumber}\n\nРазработал dan63047\nФормулы предоставил kerrmunism\nИсторию предоставляет p1nkl0bst3r\nВозможность скачивать повторы из TETR.IO предоставляет szy'; - case 'stateViewTitle': return ({required Object nickname, required Object date}) => 'Аккаунт ${nickname} ${date}'; - case 'statesViewTitle': return ({required Object number, required Object nickname}) => '${number} состояний аккаунта ${nickname}'; - case 'matchesViewTitle': return ({required Object nickname}) => 'Матчи аккаунта ${nickname}'; - case 'statesViewEntry': return ({required Object level, required Object glicko, required Object rd, required Object games}) => '${level} TR, ${glicko}±${rd} Glicko, ${games} игр сыграно'; - case 'stateRemoved': return ({required Object date}) => 'Состояние от ${date} было удалено из локальной базы данных!'; - case 'matchRemoved': return ({required Object date}) => 'Матч от ${date} был удален из локальной базы данных!'; - case 'viewAllMatches': return 'Все матчи'; - case 'trackedPlayersViewTitle': return 'Сохранённые данные'; - case 'trackedPlayersZeroEntrys': return 'Пустой список. Вернитесь на предыдущий экран и нажмите кнопку "Отслеживать", чтобы текущий игрок появился здесь'; - case 'trackedPlayersOneEntry': return 'В списке только один игрок'; - case 'trackedPlayersManyEntrys': return ({required Object numberOfPlayers}) => 'В списке ${numberOfPlayers} игроков'; - case 'trackedPlayersEntry': return ({required Object nickname, required Object numberOfStates}) => '${nickname}: ${numberOfStates} состояний'; - case 'trackedPlayersDescription': return ({required Object firstStateDate, required Object lastStateDate}) => 'Начиная с ${firstStateDate} и заканчивая ${lastStateDate}'; - case 'trackedPlayersStatesDeleted': return ({required Object nickname}) => 'Состояния аккаунта ${nickname} были удалены из локальной базы данных!'; - case 'duplicatedFix': return 'Удалить дубликаты матчей в Тетра Лиге'; - case 'compressDB': return 'Сжать базу данных'; - case 'SpaceSaved': return ({required Object size}) => 'Места освобождено: ${size}'; - case 'averageXrank': return ({required Object rankLetter}) => 'Средний ${rankLetter} ранг'; - case 'vs': return 'против'; - case 'inTLmatch': return 'в матче ТЛ'; - case 'downloadReplay': return 'Скачать .ttrm повтор'; - case 'openReplay': return 'Открыть повтор в TETR.IO'; - case 'replaySaved': return ({required Object path}) => 'Повтор сохранён по пути ${path}'; - case 'match': return 'Матч'; - case 'timeWeightedmatch': return 'Матч (взвешенная по времени)'; - case 'roundNumber': return ({required Object n}) => 'Раунд ${n}'; - case 'statsFor': return 'Статистика за'; - case 'numberOfRounds': return 'Количество раундов'; - case 'matchLength': return 'Продолжительность матча'; - case 'roundLength': return 'Продолжительность раунда'; - case 'matchStats': return 'Статистика матча'; - case 'timeWeightedmatchStats': return 'Взвешенная по времени cтатистика матча'; - case 'replayIssue': return 'Ошибка обработки повтора'; - case 'matchIsTooOld': return 'Информация о повторе недоступна'; - case 'winner': return 'Победитель'; - case 'registred': return 'Зарегистрирован'; - case 'playedTL': return 'Играл в Тетра Лигу'; - case 'winChance': return 'Шансы на победу'; - case 'byGlicko': return 'По Glicko'; - case 'byEstTR': return 'По расч. TR'; - case 'compareViewNoValues': return ({required Object avgR}) => 'Пожалуйста, введите никнейм, ID, APM-PPS-VS (неважно, какой разделитель, важен порядок) или ${avgR} (где R это ранг), в оба поля'; - case 'compareViewWrongValue': return ({required Object value}) => 'Не удалось получить ${value}'; - case 'mostRecentOne': return 'Самый последний'; - case 'yes': return 'Да'; - case 'no': return 'Нет'; - case 'daysLater': return 'дней позже'; - case 'dayseBefore': return 'дней раньше'; - case 'fromBeginning': return 'С начала'; - case 'calc': return 'Считать'; - case 'calcViewNoValues': return 'Введите значения, чтобы посчитать статистику'; - case 'rankAveragesViewTitle': return 'Требования рангов'; - case 'sprintAndBlitsViewTitle': return 'Средние результаты 40 линий и блица'; - case 'sprintAndBlitsRelevance': return ({required Object date}) => 'Актуальность: ${date}'; - case 'rank': return 'Ранг'; - case 'averages': return 'Средние значения'; - case 'lbViewZeroEntrys': return 'Рейтинговая таблица пуста'; - case 'lbViewOneEntry': return 'В рейтинговой таблице всего один игрок'; - case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers}'; - case 'everyoneAverages': return 'Значения таблицы'; - case 'sortBy': return 'Cортировать по'; - case 'reversed': return 'Наоборот'; - case 'country': return 'Страна'; - case 'rankAverages': return ({required Object rank}) => 'Значения для ${rank} ранга'; - case 'players': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} игроков', - one: '${n} игрок', - two: '${n} игрока', - few: '${n} игрока', - many: '${n} игроков', - other: '${n} игроков', - ); - case 'games': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} игр', - one: '${n} игра', - two: '${n} игры', - few: '${n} игры', - many: '${n} игр', - other: '${n} игр', - ); - case 'gamesPlayed': return ({required Object games}) => '${games} сыграно'; - case 'chart': return 'График'; - case 'entries': return 'Список'; - case 'minimums': return 'Минимумы'; - case 'maximums': return 'Максимумы'; - case 'lowestValues': return 'Самые низкие показатели'; - case 'averageValues': return 'Средние значения показателей'; - case 'highestValues': return 'Самые высокие показатели'; - case 'forPlayer': return ({required Object username}) => 'для игрока ${username}'; - case 'currentAxis': return ({required Object axis}) => 'Ось ${axis}:'; - case 'p1nkl0bst3rAlert': return 'Эти данные были получены из стороннего API, который поддерживается p1nkl0bst3r'; - case 'notForWeb': return 'Функция недоступна для веб версии'; - case 'graphs.attack': return 'Атака'; - case 'graphs.speed': return 'Скорость'; - case 'graphs.defense': return 'Защита'; - case 'graphs.cheese': return 'Сыр'; - case 'statCellNum.xpLevel': return 'Уровень\nопыта'; - case 'statCellNum.xpProgress': return 'Прогресс до следующего уровня'; - case 'statCellNum.xpFrom0ToLevel': return ({required Object n}) => 'Прогресс от 0 XP до ${n} уровня'; - case 'statCellNum.xpLeft': return 'XP осталось'; - case 'statCellNum.hoursPlayed': return 'Часов\nСыграно'; - case 'statCellNum.onlineGames': return 'Онлайн\nИгр'; - case 'statCellNum.gamesWon': return 'Онлайн\nПобед'; - case 'statCellNum.totalGames': return 'Всего матчей'; - case 'statCellNum.totalWon': return 'Всего побед'; - case 'statCellNum.friends': return 'Друзей'; - case 'statCellNum.apm': return 'Атака в\nМинуту'; - case 'statCellNum.vs': return 'Показатель\nVersus'; - case 'statCellNum.recordLB': return 'Место в таблице'; - case 'statCellNum.lbp': return 'Положение\nв рейтинге'; - case 'statCellNum.lbpShort': return '№ в рейтинге'; - case 'statCellNum.lbpc': return 'Положение\nв рейтинге страны'; - case 'statCellNum.lbpcShort': return '№ по стране'; - case 'statCellNum.gamesPlayed': return 'Игр\nСыграно'; - case 'statCellNum.gamesWonTL': return 'Побед'; - case 'statCellNum.winrate': return 'Процент\nпобед'; - case 'statCellNum.level': return 'Уровень'; - case 'statCellNum.score': return 'Счёт'; - case 'statCellNum.spp': return 'Очков\nна Фигуру'; - case 'statCellNum.pieces': return 'Фигур\nУстановлено'; - case 'statCellNum.pps': return 'Фигур в\nСекунду'; - case 'statCellNum.finesseFaults': return 'Ошибок\nТехники'; - case 'statCellNum.finessePercentage': return '% Качества\nТехники'; - case 'statCellNum.keys': return 'Нажатий\nКлавиш'; - case 'statCellNum.kpp': return 'Нажатий\nна Фигуру'; - case 'statCellNum.kps': return 'Нажатий\nв Секунду'; - case 'statCellNum.tr': return 'Тетра Рейтинг'; - case 'statCellNum.rd': return 'Отклонение рейтинга'; - case 'statCellNum.app': return 'Атака на Фигуру'; - case 'statCellNum.appDescription': return '(Сокращенно APP) Главный показатель эффективности. Показывает, сколько атаки приходится на одну фигуру'; - case 'statCellNum.vsapmDescription': return 'В основном, показывает как много мусора игрок использует в своих атаках и насколько эффективно.'; - case 'statCellNum.dss': return 'Downstack\nв Секунду'; - case 'statCellNum.dssDescription': return '(Сокращенно DS/S) Downstack (спуск вниз) в Секунду показывает как много мусорных линий в среднем игрок убирает за одну секунду.'; - case 'statCellNum.dsp': return 'Downstack\nна Фигуру'; - case 'statCellNum.dspDescription': return '(Сокращенно DS/P) Downstack (спуск вниз) на Фигуру показывает как много мусорных линий в среднем игрок убирает одну фигуру.'; - case 'statCellNum.appdsp': return 'APP + DS/P'; - case 'statCellNum.appdspDescription': return 'Просто сумма Атаки на Фигуру и Downstack на Фигуру.'; - case 'statCellNum.cheese': return 'Индекс сыра'; - case 'statCellNum.cheeseDescription': return '(Сокращенно Cheese) Индекс сыра является аппроксимацией того, насколько чистый / дырявый мусор игрок отправляет. Меньше = более чистый. Больше = более дырявый.\nПридумал kerrmunism'; - case 'statCellNum.gbe': return 'Garbage\nEfficiency'; - case 'statCellNum.gbeDescription': return '(Сокращенно Gb Eff.) Garbage Efficiency показывает насколько хорошо игрок использует свой мусор. Больше = лучше (или он использует больше мусора). Меньше = в основном отправляют сыр (или он редко чистит мусор).\nПридумали Zepheniah и Dragonboy.'; - case 'statCellNum.nyaapp': return 'Взвешенный\nAPP'; - case 'statCellNum.nyaappDescription': return '(Сокращенно wAPP) По сути, показывает способность отправлять сыр, сохраняя при этом высокую эффективность.\nПридумал Wertj.'; - case 'statCellNum.area': return 'Area'; - case 'statCellNum.areaDescription': return 'Какую площадь занимает диаграмма, если не брать в расчёт индекс сыра и VS/APM'; - case 'statCellNum.estOfTR': return 'Расчётный TR'; - case 'statCellNum.estOfTRShort': return 'Расч. TR'; - case 'statCellNum.accOfEst': return 'Точность расчёта'; - case 'statCellNum.accOfEstShort': return 'Точность'; - case 'playerRole.user': return 'Пользователь'; - case 'playerRole.banned': return 'Заблокированный пользователь'; - case 'playerRole.bot': return 'Бот'; - case 'playerRole.sysop': return 'Системный оператор'; - case 'playerRole.admin': return 'Администратор'; - case 'playerRole.mod': return 'Модератор'; - case 'playerRole.halfmod': return 'Модератор сообщества'; - case 'playerRole.anon': return 'Аноним'; - case 'numOfGameActions.pc': return 'Все чисто'; - case 'numOfGameActions.hold': return 'В запас'; - case 'numOfGameActions.inputs': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} нажатий клавиш', - one: '${n} нажатие на клавишу', - two: '${n} нажатия на клавишы', - few: '${n} нажатия на клавишы', - many: '${n} нажатий на клавиш', - other: '${n} нажатий на клавиш', - ); - case 'numOfGameActions.tspinsTotal': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} T-спинов всего', - one: 'Всего ${n} T-спин', - two: '${n} T-спина всего', - few: '${n} T-спина всего', - many: '${n} T-спинов всего', - other: '${n} T-спинов всего', - ); - case 'numOfGameActions.lineClears': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, - zero: '${n} линий очищено', - one: '${n} линия очищена', - two: '${n} линии очищено', - few: '${n} линии очищено', - many: '${n} линий очищено', - other: '${n} линий очищено', - ); - case 'popupActions.cancel': return 'Отменить'; - case 'popupActions.submit': return 'Подтвердить'; - case 'popupActions.ok': return 'OK'; - case 'errors.connection': return ({required Object code, required Object message}) => 'Проблема с подключением: ${code} ${message}'; - case 'errors.noSuchUser': return 'Нет такого пользователя'; - case 'errors.noSuchUserSub': return 'Либо вы ошиблись при вводе, либо аккаунта больше не существует'; - case 'errors.discordNotAssigned': return 'К данному Discord ID не привязан аккаунт'; - case 'errors.discordNotAssignedSub': return 'Убедитесь в том, что вы вставили правильный ID'; - case 'errors.history': return 'История данного игрока отсутствует'; - case 'errors.actionSuggestion': return 'Возможно, вы хотите'; - case 'errors.p1nkl0bst3rTLmatches': return 'Старых матчей Тетра Лиги не было найдено'; - case 'errors.clientException': return 'Нет соединения с интернетом'; - case 'errors.forbidden': return 'Ваш IP адрес заблокирован'; - case 'errors.forbiddenSub': return ({required Object nickname}) => 'Если у вас работает VPN или прокси, выключите его. Если это не помогло, свяжитесь с ${nickname}'; - case 'errors.tooManyRequests': return 'Слишком много запросов'; - case 'errors.tooManyRequestsSub': return 'Подождите немного и попробуйте снова'; - case 'errors.internal': return 'Что-то случилось на стороне tetr.io'; - case 'errors.internalSub': return 'Скорее всего, osk уже в курсе об этом'; - case 'errors.internalWebVersion': return 'Что-то случилось на стороне tetr.io (или на стороне oskware_bridge, я хз если честно)'; - case 'errors.internalWebVersionSub': return 'Если статус страница osk-а говорит, что всё ок - свяжитесь с dan63047'; - case 'errors.oskwareBridge': return 'Что-то случилось с oskware_bridge'; - case 'errors.oskwareBridgeSub': return 'Дайте dan63047 знать'; - case 'errors.p1nkl0bst3rForbidden': return 'Стороннее API заблокировало ваш IP адрес'; - case 'errors.p1nkl0bst3rTooManyRequests': return 'Слишком много запросов к стороннему API. Попробуйте позже'; - case 'errors.p1nkl0bst3rinternal': return 'Что-то случилось на стороне p1nkl0bst3r-а'; - case 'errors.p1nkl0bst3rinternalWebVersion': return 'Что-то случилось на стороне p1nkl0bst3r-а (или на стороне oskware_bridge, я хз если честно)'; - case 'errors.replayAlreadySaved': return 'Повтор уже сохранён'; - case 'errors.replayExpired': return 'Повтор истёк и больше недоступен'; - case 'errors.replayRejected': return 'Стороннее API заблокировало ваш IP адрес'; - case 'countries.': return 'Во всём мире'; - case 'countries.AF': return 'Афганистан'; - case 'countries.AX': return 'Аландские острова'; - case 'countries.AL': return 'Албания'; - case 'countries.DZ': return 'Алжир'; - case 'countries.AS': return 'Американское Самоа'; - case 'countries.AD': return 'Андорра'; - case 'countries.AO': return 'Ангола'; - case 'countries.AI': return 'Ангилья'; - case 'countries.AQ': return 'Антарктида'; - case 'countries.AG': return 'Антигуа и Барбуда'; - case 'countries.AR': return 'Аргентина'; - case 'countries.AM': return 'Армения'; - case 'countries.AW': return 'Аруба'; - case 'countries.AU': return 'Австралия'; - case 'countries.AT': return 'Австрия'; - case 'countries.AZ': return 'Азербайджан'; - case 'countries.BS': return 'Багамские острова'; - case 'countries.BH': return 'Бахрейн'; - case 'countries.BD': return 'Бангладеш'; - case 'countries.BB': return 'Барбадос'; - case 'countries.BY': return 'Беларусь'; - case 'countries.BE': return 'Бельгия'; - case 'countries.BZ': return 'Белиз'; - case 'countries.BJ': return 'Бенин'; - case 'countries.BM': return 'Бермуды'; - case 'countries.BT': return 'Бутан'; - case 'countries.BO': return 'Боливия, Многонациональное Государство'; - case 'countries.BA': return 'Босния и Герцеговина'; - case 'countries.BW': return 'Ботсвана'; - case 'countries.BV': return 'Остров Буве'; - case 'countries.BR': return 'Бразилия'; - case 'countries.IO': return 'Британская территория в Индийском океане'; - case 'countries.BN': return 'Бруней-Даруссалам'; - case 'countries.BG': return 'Болгария'; - case 'countries.BF': return 'Буркина-Фасо'; - case 'countries.BI': return 'Бурунди'; - case 'countries.KH': return 'Камбоджа'; - case 'countries.CM': return 'Камерун'; - case 'countries.CA': return 'Канада'; - case 'countries.CV': return 'Кабо-Верде'; - case 'countries.BQ': return 'Карибские Нидерланды'; - case 'countries.KY': return 'Каймановы острова'; - case 'countries.CF': return 'Центральноафриканская Республика'; - case 'countries.TD': return 'Чад'; - case 'countries.CL': return 'Чили'; - case 'countries.CN': return 'Китай'; - case 'countries.CX': return 'Остров Рождества'; - case 'countries.CC': return 'Кокосовые острова'; - case 'countries.CO': return 'Колумбия'; - case 'countries.KM': return 'Коморские острова'; - case 'countries.CG': return 'Конго'; - case 'countries.CD': return 'Конго, Демократическая Республика'; - case 'countries.CK': return 'Острова Кука'; - case 'countries.CR': return 'Коста-Рика'; - case 'countries.CI': return 'Берег Слоновой Кости'; - case 'countries.HR': return 'Хорватия'; - case 'countries.CU': return 'Куба'; - case 'countries.CW': return 'Кюрасао'; - case 'countries.CY': return 'Кипр'; - case 'countries.CZ': return 'Чешская Республика'; - case 'countries.DK': return 'Дания'; - case 'countries.DJ': return 'Джибути'; - case 'countries.DM': return 'Доминика'; - case 'countries.DO': return 'Доминиканская Республика'; - case 'countries.EC': return 'Эквадор'; - case 'countries.EG': return 'Египет'; - case 'countries.SV': return 'Сальвадор'; - case 'countries.GB-ENG': return 'Англия'; - case 'countries.GQ': return 'Экваториальная Гвинея'; - case 'countries.ER': return 'Эритрея'; - case 'countries.EE': return 'Эстония'; - case 'countries.ET': return 'Эфиопия'; - case 'countries.EU': return 'Европа'; - case 'countries.FK': return 'Фолклендские (Мальвинские) острова'; - case 'countries.FO': return 'Фарерские острова'; - case 'countries.FJ': return 'Фиджи'; - case 'countries.FI': return 'Финляндия'; - case 'countries.FR': return 'Франция'; - case 'countries.GF': return 'Французская Гвиана'; - case 'countries.PF': return 'Французская Полинезия'; - case 'countries.TF': return 'Южные территории Франции'; - case 'countries.GA': return 'Габон'; - case 'countries.GM': return 'Гамбия'; - case 'countries.GE': return 'Грузия'; - case 'countries.DE': return 'Германия'; - case 'countries.GH': return 'Гана'; - case 'countries.GI': return 'Гибралтар'; - case 'countries.GR': return 'Греция'; - case 'countries.GL': return 'Гренландия'; - case 'countries.GD': return 'Гренада'; - case 'countries.GP': return 'Гваделупа'; - case 'countries.GU': return 'Гуам'; - case 'countries.GT': return 'Гватемала'; - case 'countries.GG': return 'Гернси'; - case 'countries.GN': return 'Гвинея'; - case 'countries.GW': return 'Гвинея-Бисау'; - case 'countries.GY': return 'Гайана'; - case 'countries.HT': return 'Гаити'; - case 'countries.HM': return 'Остров Херд и острова Макдональд'; - case 'countries.VA': return 'Святой Престол (государство-городок Ватикан)'; - case 'countries.HN': return 'Гондурас'; - case 'countries.HK': return 'Гонконг'; - case 'countries.HU': return 'Венгрия'; - case 'countries.IS': return 'Исландия'; - case 'countries.IN': return 'Индия'; - case 'countries.ID': return 'Индонезия'; - case 'countries.IR': return 'Иран, Исламская Республика'; - case 'countries.IQ': return 'Ирак'; - case 'countries.IE': return 'Ирландия'; - case 'countries.IM': return 'Остров Мэн'; - case 'countries.IL': return 'Израиль'; - case 'countries.IT': return 'Италия'; - case 'countries.JM': return 'Ямайка'; - case 'countries.JP': return 'Япония'; - case 'countries.JE': return 'Джерси'; - case 'countries.JO': return 'Иордания'; - case 'countries.KZ': return 'Казахстан'; - case 'countries.KE': return 'Кения'; - case 'countries.KI': return 'Кирибати'; - case 'countries.KP': return 'Корея, Народно-Демократическая Республика'; - case 'countries.KR': return 'Корея, Республика'; - case 'countries.XK': return 'Косово'; - case 'countries.KW': return 'Кувейт'; - case 'countries.KG': return 'Кыргызстан'; - case 'countries.LA': return 'Лаосская Народно-Демократическая Республика'; - case 'countries.LV': return 'Латвия'; - case 'countries.LB': return 'Ливан'; - case 'countries.LS': return 'Лесото'; - case 'countries.LR': return 'Либерия'; - case 'countries.LY': return 'Ливия'; - case 'countries.LI': return 'Лихтенштейн'; - case 'countries.LT': return 'Литва'; - case 'countries.LU': return 'Люксембург'; - case 'countries.MO': return 'Макао'; - case 'countries.MK': return 'Македония, бывшая югославская республика'; - case 'countries.MG': return 'Мадагаскар'; - case 'countries.MW': return 'Малави'; - case 'countries.MY': return 'Малайзия'; - case 'countries.MV': return 'Мальдивы'; - case 'countries.ML': return 'Мали'; - case 'countries.MT': return 'Мальта'; - case 'countries.MH': return 'Маршалловы острова'; - case 'countries.MQ': return 'Мартиника'; - case 'countries.MR': return 'Мавритания'; - case 'countries.MU': return 'Маврикий'; - case 'countries.YT': return 'Майотта'; - case 'countries.MX': return 'Мексика'; - case 'countries.FM': return 'Микронезия, Федеративные Штаты'; - case 'countries.MD': return 'Молдова, Республика'; - case 'countries.MC': return 'Монако'; - case 'countries.ME': return 'Черногория'; - case 'countries.MA': return 'Марокко'; - case 'countries.MN': return 'Монголия'; - case 'countries.MS': return 'Монтсеррат'; - case 'countries.MZ': return 'Мозамбик'; - case 'countries.MM': return 'Мьянма'; - case 'countries.NA': return 'Намибия'; - case 'countries.NR': return 'Науру'; - case 'countries.NP': return 'Непал'; - case 'countries.NL': return 'Нидерланды'; - case 'countries.AN': return 'Нидерландские Антильские острова'; - case 'countries.NC': return 'Новая Каледония'; - case 'countries.NZ': return 'Новая Зеландия'; - case 'countries.NI': return 'Никарагуа'; - case 'countries.NE': return 'Нигер'; - case 'countries.NG': return 'Нигерия'; - case 'countries.NU': return 'Ниуэ'; - case 'countries.NF': return 'Остров Норфолк'; - case 'countries.GB-NIR': return 'Северная Ирландия'; - case 'countries.MP': return 'Северные Марианские острова'; - case 'countries.NO': return 'Норвегия'; - case 'countries.OM': return 'Оман'; - case 'countries.PK': return 'Пакистан'; - case 'countries.PW': return 'Палау'; - case 'countries.PS': return 'Палестина'; - case 'countries.PA': return 'Панама'; - case 'countries.PG': return 'Папуа-Новая Гвинея'; - case 'countries.PY': return 'Парагвай'; - case 'countries.PE': return 'Перу'; - case 'countries.PH': return 'Филиппины'; - case 'countries.PN': return 'Питкэрн'; - case 'countries.PL': return 'Польша'; - case 'countries.PT': return 'Португалия'; - case 'countries.PR': return 'Пуэрто-Рико'; - case 'countries.QA': return 'Катар'; - case 'countries.RE': return 'Реюньон'; - case 'countries.RO': return 'Румыния'; - case 'countries.RU': return 'Российская Федерация'; - case 'countries.RW': return 'Руанда'; - case 'countries.BL': return 'Сен-Бартелеми'; - case 'countries.SH': return 'Острова Святой Елены, Вознесения и Тристан-да-Кунья'; - case 'countries.KN': return 'Сент-Китс и Невис'; - case 'countries.LC': return 'Сент-Люсия'; - case 'countries.MF': return 'Сен-Мартен'; - case 'countries.PM': return 'Сен-Пьер и Микелон'; - case 'countries.VC': return 'Сент-Винсент и Гренадины'; - case 'countries.WS': return 'Самоа'; - case 'countries.SM': return 'Сан-Марино'; - case 'countries.ST': return 'Сан-Томе и Принсипи'; - case 'countries.SA': return 'Саудовская Аравия'; - case 'countries.GB-SCT': return 'Шотландия'; - case 'countries.SN': return 'Сенегал'; - case 'countries.RS': return 'Сербия'; - case 'countries.SC': return 'Сейшельские острова'; - case 'countries.SL': return 'Сьерра-Леоне'; - case 'countries.SG': return 'Сингапур'; - case 'countries.SX': return 'Синт-Мартен (голландская часть)'; - case 'countries.SK': return 'Словакия'; - case 'countries.SI': return 'Словения'; - case 'countries.SB': return 'Соломоновы острова'; - case 'countries.SO': return 'Сомали'; - case 'countries.ZA': return 'ЮАР'; - case 'countries.GS': return 'Южная Георгия и Южные Сандвичевы острова'; - case 'countries.SS': return 'Южный Судан'; - case 'countries.ES': return 'Испания'; - case 'countries.LK': return 'Шри-Ланка'; - case 'countries.SD': return 'Судан'; - case 'countries.SR': return 'Суринам'; - case 'countries.SJ': return 'Острова Шпицберген и Ян-Майен'; - case 'countries.SZ': return 'Свазиленд'; - case 'countries.SE': return 'Швеция'; - case 'countries.CH': return 'Швейцария'; - case 'countries.SY': return 'Сирийская Арабская Республика'; - case 'countries.TW': return 'Тайвань'; - case 'countries.TJ': return 'Таджикистан'; - case 'countries.TZ': return 'Танзания, Объединенная Республика'; - case 'countries.TH': return 'Таиланд'; - case 'countries.TL': return 'Тимор-Лешти'; - case 'countries.TG': return 'Того'; - case 'countries.TK': return 'Токелау'; - case 'countries.TO': return 'Tonga'; - case 'countries.TT': return 'Тринидад и Тобаго'; - case 'countries.TN': return 'Тунис'; - case 'countries.TR': return 'Турция'; - case 'countries.TM': return 'Туркменистан'; - case 'countries.TC': return 'Острова Теркс и Кайкос'; - case 'countries.ТВ': return 'Тувалу'; - case 'countries.UG': return 'Уганда'; - case 'countries.UA': return 'Украина'; - case 'countries.AE': return 'Объединенные Арабские Эмираты'; - case 'countries.GB': return 'Великобритания'; - case 'countries.US': return 'Соединенные Штаты'; - case 'countries.UY': return 'Уругвай'; - case 'countries.UM': return 'Малые периферийные острова США'; - case 'countries.UZ': return 'Узбекистан'; - case 'countries.VU': return 'Вануату'; - case 'countries.VE': return 'Венесуэла, Боливарианская Республика'; - case 'countries.VN': return 'Вьетнам'; - case 'countries.VG': return 'Виргинские острова, Британские'; - case 'countries.VI': return 'Виргинские острова, США'; - case 'countries.GB-WLS': return 'Уэльс'; - case 'countries.WF': return 'Острова Уоллис и Футуна'; - case 'countries.EH': return 'Западная Сахара'; - case 'countries.YE': return 'Йемен'; - case 'countries.ZM': return 'Замбия'; - case 'countries.ZW': return 'Зимбабве'; - case 'countries.XX': return 'Неизвестно'; - case 'countries.XM': return 'Луна'; - default: return null; - } - } -} - -extension on _StringsZhCn { - dynamic _flatMapFunction(String path) { - switch (path) { - case 'locales.en': return '英语 (English)'; - case 'locales.ru': return '俄语 (Русский)'; - case 'locales.zh-CN': return '简体中文'; - case 'tetraLeague': return 'Tetra联赛'; - case 'tlRecords': return 'Tetra联赛记录'; - case 'history': return '历史'; - case 'sprint': return '40行竞速'; - case 'blitz': return '闪电战'; - case 'recent': return '最近'; - case 'recentRuns': return '最近游玩局数'; - case 'blitzScore': return ({required Object p}) => '${p} 分'; - case 'openSPreplay': return '在TETR.IO打开回放'; - case 'downloadSPreplay': return '下载回放'; - case 'other': return '其他'; - case 'distinguishment': return '区别'; - case 'zen': return '禅意模式'; - case 'bio': return '个人简介'; - case 'news': return '新闻'; - case 'newsParts.leaderboardStart': return '取得 '; - case 'newsParts.leaderboardMiddle': return '于 '; - case 'newsParts.personalbest': return '在 '; - case 'newsParts.personalbestMiddle': return ' 中取得了新的个人最好成绩 '; - case 'newsParts.badgeStart': return '获得勋章 '; - case 'newsParts.badgeEnd': return ''; - case 'newsParts.rankupStart': return '达成 '; - case 'newsParts.rankupMiddle': return ({required Object r}) => '${r} 段位 '; - case 'newsParts.rankupEnd': return ''; - case 'newsParts.tetoSupporter': return 'TETR.IO 会员'; - case 'newsParts.supporterStart': return '成为了 '; - case 'newsParts.supporterGiftStart': return '被赠送了 '; - case 'newsParts.unknownNews': return ({required Object type}) => '未知新闻 ${type}'; - case 'openSearch': return '搜索玩家'; - case 'closeSearch': return '关闭搜索'; - case 'searchHint': return '昵称,ID或Discord用户ID(需要 "ds:" 前缀)'; - case 'refresh': return '刷新'; - case 'fetchAndsaveTLHistory': return '获取玩家历史'; - case 'fetchAndSaveOldTLmatches': return '获取玩家Tetra联赛历史'; - case 'fetchAndsaveTLHistoryResult': return ({required Object number}) => '找到 ${number} 个状态'; - case 'fetchAndSaveOldTLmatchesResult': return ({required Object number}) => '找到 ${number} 场Tetra联赛比赛'; - case 'showStoredData': return '显示获得的数据'; - case 'statsCalc': return '统计计算器'; - case 'settings': return '设置'; - case 'track': return '添加到\n跟踪列表'; - case 'stopTracking': return '从跟踪列表\n中移除'; - case 'becameTracked': return '已添加到跟踪列表!'; - case 'compare': return '对比'; - case 'stoppedBeingTracked': return '已从跟踪列表中移除!'; - case 'tlLeaderboard': return 'Tetra联赛排行榜'; - case 'noRecords': return '无记录'; - case 'noOldRecords': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '无记录', - one: '只有 ${n} 个记录', - two: '只有 ${n} 个记录', - few: '只有 ${n} 个记录', - many: '只有 ${n} 个记录', - other: '只有 ${n} 个记录', - ); - case 'noRecord': return '没有记录'; - case 'botRecord': return '机器人不予参加排位赛'; - case 'anonRecord': return '匿名用户不予参加排位赛'; - case 'notEnoughData': return '没有足够的数据'; - case 'noHistorySaved': return '没有保存历史'; - case 'pseudoTooltipHeaderInit': return '将鼠标放在点上'; - case 'pseudoTooltipFooterInit': return '以查看详细信息'; - case 'obtainDate': return ({required Object date}) => '在 ${date} 获得'; - case 'fetchDate': return ({required Object date}) => 'Fetched ${date}'; - case 'exactGametime': return '实际游玩时长'; - case 'bigRedBanned': return '该账号封禁中'; - case 'normalBanned': return '封禁'; - case 'bigRedBadStanding': return '信誉不佳'; - case 'copiedToClipboard': return '已复制'; - case 'playerRoleAccount': return '账号'; - case 'wasFromBeginning': return '在很久很久以前'; - case 'created': return '创建于'; - case 'botCreatedBy': return ''; - case 'notSupporter': return '非会员'; - case 'assignedManualy': return '该勋章由 TETR.IO 管理员手动分配'; - case 'supporter': return ({required Object tier}) => '会员等级 ${tier}'; - case 'comparingWith': return ({required Object newDate, required Object oldDate}) => '${newDate} 时的数据与 ${oldDate} 比较'; - case 'top': return '前'; - case 'topRank': return '最高段位'; - case 'verdictGeneral': return ({required Object rank, required Object verdict, required Object n}) => '比 ${rank} 段平均数据${verdict} ${n}'; - case 'verdictBetter': return '好'; - case 'verdictWorse': return '差'; - case 'smooth': return '平滑'; - case 'postSeason': return '淡季'; - case 'seasonStarts': return '下一赛即将开始于:'; - case 'nanow': return '暂未完成,敬请等待!'; - case 'seasonEnds': return ({required Object countdown}) => '赛季将会在 ${countdown} 后结束'; - case 'seasonEnded': return 'Season has ended'; - case 'gamesUntilRanked': return ({required Object left}) => '还有 ${left} 场比赛获取段位'; - case 'numOfVictories': return ({required Object wins}) => '~${wins} 场胜局'; - case 'promotionOnNextWin': return '下一次胜利即可升段'; - case 'numOfdefeats': return ({required Object losses}) => '~${losses} 场败局'; - case 'demotionOnNextLoss': return '下一次失败即可掉段'; - case 'nerdStats': return '详细信息'; - case 'playersYouTrack': return '跟踪'; - case 'formula': return '公式'; - case 'exactValue': return '实际值'; - case 'neverPlayedTL': return '此用户没有参与Tetra联赛'; - case 'botTL': return '机器人不予参加Tetra联赛'; - case 'anonTL': return '匿名用户不予参加Tetra联赛'; - case 'quickPlay': return '快速游戏'; - case 'expert': return '专家'; - case 'withMods': return '带着模组'; - case 'withModsPlural': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '带着 ${n} 个模组', - one: '带着 ${n} 个模组', - two: '带着 ${n} 个模组', - few: '带着 ${n} 个模组', - many: '带着 ${n} 个模组', - other: '带着 ${n} 个模组', - ); - case 'exportDB': return '导出本地数据'; - case 'exportDBDescription': return '它包含跟踪的玩家的状态和Tetra联赛记录和跟踪列表。'; - case 'desktopExportAlertTitle': return '桌面导出'; - case 'desktopExportText': return '您好像在使用桌面版。请查看你的“文档”文件夹,你应该能找到“TetraStats.db”。把它复制到一个地方'; - case 'androidExportAlertTitle': return '安卓导出'; - case 'androidExportText': return ({required Object exportedDB}) => '导出成功\n${exportedDB}'; - case 'importDB': return '导入本地数据'; - case 'importDBDescription': return '恢复您的备份。请注意,已存储的数据库将被覆盖。'; - case 'importWrongFileType': return '文件类型错误'; - case 'importCancelled': return '已取消'; - case 'importSuccess': return '导入成功'; - case 'yourID': return '你的 TETR.IO 用户'; - case 'yourIDAlertTitle': return '你的 TETR.IO 昵称'; - case 'yourIDText': return '当程序加载,它将显示此用户的数据'; - case 'language': return '语言'; - case 'updateInBackground': return '自动升级数据'; - case 'updateInBackgroundDescription': return '当 Tetra Stats 运行时,它可以在缓存过期时更新当前玩家的统计数据'; - case 'customization': return '自定义'; - case 'customizationDescription': return '更改 Tetra Stats UI 中不同事物的外观'; - case 'oskKagari': return 'osk 特有的 Kagari 段位'; - case 'oskKagariDescription': return '如果打开,主视图上的 osk 段位将显示为 :kagari:'; - case 'AccentColor': return '主题色'; - case 'AccentColorDescription': return '几乎所有交互式 UI 元素都用此颜色突出显示'; - case 'timestamps': return '时间'; - case 'timestampsDescription': return '您可以选择显示时间的方式'; - case 'timestampsAbsoluteGMT': return '绝对 (GMT)'; - case 'timestampsAbsoluteLocalTime': return '绝对 (你的时区)'; - case 'timestampsRelative': return '相对'; - case 'rating': return '评级主要表现'; - case 'ratingDescription': return 'TR 不是线性的,而 Glicko 没有边界,百分位数易挥发'; - case 'ratingLBposition': return 'LB 位置'; - case 'sheetbotGraphs': return 'Sheetbot式雷达图'; - case 'sheetbotGraphsDescription': return '若开启,雷达图上的点为负时可以出现在对面'; - case 'lbStats': return '显示基于排行榜的数据'; - case 'lbStatsDescription': return '这会影响加载时间,但允许您通过统计数据查看排行榜上的位置并与平均值进行比较'; - case 'aboutApp': return '关于'; - case 'aboutAppText': return ({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) ${version} 版 Build ${buildNumber}\n\n由 dan63047 制作\n由 kerrmunism 提供公式\n由 p1nkl0bst3r 提供历史\nTETR.IO 回放抓取器 API 由 szy 制作'; - case 'stateViewTitle': return ({required Object nickname, required Object date}) => '${nickname} 在 ${date}'; - case 'statesViewTitle': return ({required Object nickname, required Object number}) => '${nickname} 的 ${number} 个状态'; - case 'matchesViewTitle': return ({required Object nickname}) => '${nickname} 的Tetra联赛历史'; - case 'statesViewEntry': return ({required Object level, required Object glicko, required Object rd, required Object games}) => '${level} TR, ${glicko}±${rd} Glicko, ${games} 次游戏'; - case 'stateRemoved': return ({required Object date}) => '成功移除 ${date} 的状态!'; - case 'matchRemoved': return ({required Object date}) => '成功移除 ${date} 的比赛!'; - case 'viewAllMatches': return '查看所有比赛'; - case 'trackedPlayersViewTitle': return '获取的数据'; - case 'trackedPlayersZeroEntrys': return '列表为空。 点击 “添加到跟踪列表” 可以将玩家放在这里'; - case 'trackedPlayersOneEntry': return '只有 1 个玩家'; - case 'trackedPlayersManyEntrys': return ({required Object numberOfPlayers}) => '${numberOfPlayers} 个玩家'; - case 'trackedPlayersEntry': return ({required Object nickname, required Object numberOfStates}) => '${nickname}:${numberOfStates} 个状态'; - case 'trackedPlayersDescription': return ({required Object firstStateDate, required Object lastStateDate}) => '从 ${firstStateDate} 到 ${lastStateDate}'; - case 'trackedPlayersStatesDeleted': return ({required Object nickname}) => '成功从数据库中移除 ${nickname} 个状态!'; - case 'duplicatedFix': return '删除重复的 TL 匹配项'; - case 'compressDB': return '压缩数据库'; - case 'SpaceSaved': return ({required Object size}) => '保存空白:${size}'; - case 'averageXrank': return ({required Object rankLetter}) => '平均 ${rankLetter} 段'; - case 'vs': return 'vs'; - case 'inTLmatch': return '在Tetra联赛中'; - case 'downloadReplay': return '下载 .ttrm 回放'; - case 'openReplay': return '在 TETR.IO 打开回放'; - case 'replaySaved': return ({required Object path}) => '已保存回放至 ${path}'; - case 'match': return '比赛'; - case 'timeWeightedmatch': return '比赛(时间加权)'; - case 'roundNumber': return ({required Object n}) => '第 ${n} 回合'; - case 'statsFor': return '数据:'; - case 'numberOfRounds': return '回合数'; - case 'matchLength': return '比赛时长'; - case 'roundLength': return '回合时长'; - case 'matchStats': return '比赛数据'; - case 'timeWeightedmatchStats': return '时间加权比赛数据'; - case 'replayIssue': return '无法处理回放'; - case 'matchIsTooOld': return '无回放'; - case 'winner': return '赢家'; - case 'registred': return '注册日期'; - case 'playedTL': return '游玩过Tetra联赛'; - case 'winChance': return '胜利机会'; - case 'byGlicko': return '靠Glicko'; - case 'byEstTR': return '靠预测TR'; - case 'compareViewNoValues': return ({required Object avgR}) => '请输入用户名,用户IO,APM-PPS-VS值 (分隔符不重要,只需要顺序)或者${avgR}(R是一个段位)到两个字段'; - case 'compareViewWrongValue': return ({required Object value}) => '获取 ${value} 失败'; - case 'mostRecentOne': return '最接近的'; - case 'yes': return '是'; - case 'no': return '否'; - case 'daysLater': return '天后'; - case 'dayseBefore': return '天前'; - case 'fromBeginning': return '开服'; - case 'calc': return '计算器'; - case 'calcViewNoValues': return '输入值以计算数据'; - case 'rankAveragesViewTitle': return '段位分隔符'; - case 'sprintAndBlitsViewTitle': return '竞速与闪电战平均数据'; - case 'sprintAndBlitsRelevance': return ({required Object date}) => '数据来自${date}'; - case 'rank': return '段位'; - case 'averages': return '平均'; - case 'lbViewZeroEntrys': return '空'; - case 'lbViewOneEntry': return '只有一个玩家'; - case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => '有 ${numberOfPlayers}'; - case 'everyoneAverages': return 'Tetra联赛散点图'; - case 'sortBy': return '排序依据'; - case 'reversed': return '反向'; - case 'country': return '地区'; - case 'rankAverages': return ({required Object rank}) => '${rank}段位散点图'; - case 'players': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '${n} 个玩家', - one: '${n} 个玩家', - two: '${n} 个玩家', - few: '${n} 个玩家', - many: '${n} 个玩家', - other: '${n} 个玩家', - ); - case 'games': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '${n} 场游戏', - one: '${n} 场游戏', - two: '${n} 场游戏', - few: '${n} 场游戏', - many: '${n} 场游戏', - other: '${n} 场游戏', - ); - case 'gamesPlayed': return ({required Object games}) => '${games} 场游戏'; - case 'chart': return '列表'; - case 'entries': return '条目'; - case 'minimums': return '最小值'; - case 'maximums': return '最大值'; - case 'lowestValues': return '最小值'; - case 'averageValues': return '平均值'; - case 'highestValues': return '最大值'; - case 'forPlayer': return ({required Object username}) => '来自用户 ${username}'; - case 'currentAxis': return ({required Object axis}) => '${axis} 轴:'; - case 'p1nkl0bst3rAlert': return '该数据是从 p1nkl0bst3r 维护的第三方 API 中检索的'; - case 'notForWeb': return '浏览器版本暂不支持函数'; - case 'graphs.attack': return '攻击'; - case 'graphs.speed': return '速度'; - case 'graphs.defense': return '防御'; - case 'graphs.cheese': return '奶酪层'; - case 'statCellNum.xpLevel': return 'XP等级'; - case 'statCellNum.xpProgress': return '到下一等级的进度'; - case 'statCellNum.xpFrom0ToLevel': return ({required Object n}) => '从 0 到 ${n} 等级的进度'; - case 'statCellNum.xpLeft': return 'XP 还有'; - case 'statCellNum.hoursPlayed': return '小时游玩'; - case 'statCellNum.onlineGames': return '在线游戏场次'; - case 'statCellNum.gamesWon': return '获胜场次'; - case 'statCellNum.totalGames': return '总在线游戏场次'; - case 'statCellNum.totalWon': return '总在线游戏获胜场次'; - case 'statCellNum.friends': return '好友'; - case 'statCellNum.apm': return '每分\n发送垃圾行'; - case 'statCellNum.vs': return 'VS\n分数'; - case 'statCellNum.recordLB': return '名次'; - case 'statCellNum.lbp': return '名次'; - case 'statCellNum.lbpShort': return '名次'; - case 'statCellNum.lbpc': return '地区\n名次'; - case 'statCellNum.lbpcShort': return '地区名次'; - case 'statCellNum.gamesPlayed': return '游戏\n场次'; - case 'statCellNum.gamesWonTL': return '获胜\n场次'; - case 'statCellNum.winrate': return '胜率'; - case 'statCellNum.level': return '等级'; - case 'statCellNum.score': return '分数'; - case 'statCellNum.spp': return '每块\n得分'; - case 'statCellNum.pieces': return '放置\n块数'; - case 'statCellNum.pps': return '每秒\n放置块数'; - case 'statCellNum.finesseFaults': return '非极简\n操作'; - case 'statCellNum.finessePercentage': return '极简率'; - case 'statCellNum.keys': return '按键'; - case 'statCellNum.kpp': return '每块\n按键'; - case 'statCellNum.kps': return '每秒\n按键'; - case 'statCellNum.tr': return 'Tetra分数'; - case 'statCellNum.rd': return '偏移值'; - case 'statCellNum.app': return '每块发送垃圾行数'; - case 'statCellNum.appDescription': return '(Attack per Piece, 简称APP) 主要效率指标。表示玩家每块可以发动多少次攻击'; - case 'statCellNum.vsapmDescription': return '基本上可以告诉你在攻击中利用垃圾行的效率'; - case 'statCellNum.dss': return '每秒\n挖掘'; - case 'statCellNum.dssDescription': return '(Downstack per Second, 简称 DS/S) 测量一秒钟内清除多少条垃圾行。'; - case 'statCellNum.dsp': return '每块\n挖掘'; - case 'statCellNum.dspDescription': return '(Downstack per Piece, 简称 DS/P) 测量每一块清除多少条垃圾行。'; - case 'statCellNum.appdsp': return 'APP + DS/P'; - case 'statCellNum.appdspDescription': return '只是每块发送垃圾行数与每块挖掘之和。'; - case 'statCellNum.cheese': return '垃圾行\n混乱指数'; - case 'statCellNum.cheeseDescription': return '(Cheese Index, 简称Cheese) 是玩家发出的垃圾行有多整齐/混乱的近似值。低数据代表整齐,高数据代表混乱。\n由 kerrmunism 发明'; - case 'statCellNum.gbe': return '垃圾行\n效率'; - case 'statCellNum.gbeDescription': return '(Garbage Efficity, 简称Gb Eff.) 测量玩家如何很好地利用他们收到的垃圾行。高数据代表更好或者他们更多地用TA的垃圾行,低数据代表TA大多将垃圾行送回奶酪层,或者很少清理垃圾行。\n由 Zepheniah 与 Dragonboy 发明。'; - case 'statCellNum.nyaapp': return '加权\nAPP'; - case 'statCellNum.nyaappDescription': return '(Weighted APP, 简称wAPP) 在本质上是在衡量您在保持高 APP 的同时发送奶酪的能力。\n由 Wertj 发明。'; - case 'statCellNum.area': return '面积'; - case 'statCellNum.areaDescription': return '如果排除 Cheese 和 vs/apm 部分,您的形状在图表上占据了多少空间'; - case 'statCellNum.estOfTR': return '预测 TR'; - case 'statCellNum.estOfTRShort': return '预测 TR'; - case 'statCellNum.accOfEst': return '预测实际差量'; - case 'statCellNum.accOfEstShort': return '预测实际差量'; - case 'playerRole.user': return '用户'; - case 'playerRole.banned': return '封禁'; - case 'playerRole.bot': return '机器人'; - case 'playerRole.sysop': return '系统管理员'; - case 'playerRole.admin': return '管理员'; - case 'playerRole.mod': return '管理员'; - case 'playerRole.halfmod': return '社区管理员'; - case 'playerRole.anon': return '匿名'; - case 'numOfGameActions.pc': return '全消数'; - case 'numOfGameActions.hold': return '暂存数'; - case 'numOfGameActions.inputs': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '${n} 次按键', - one: '${n} 次按键', - two: '${n} 次按键', - few: '${n} 次按键', - many: '${n} 次按键', - other: '${n} 次按键', - ); - case 'numOfGameActions.tspinsTotal': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '共 ${n} 次T旋', - one: '共 ${n} 次T旋', - two: '共 ${n} 次T旋', - few: '共 ${n} 次T旋', - many: '共 ${n} 次T旋', - other: '共 ${n} 次T旋', - ); - case 'numOfGameActions.lineClears': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n, - zero: '清除了 ${n} 行', - one: '清除了 ${n} 行', - two: '清除了 ${n} 行', - few: '清除了 ${n} 行', - many: '清除了 ${n} 行', - other: '清除了 ${n} 行', - ); - case 'popupActions.cancel': return '取消'; - case 'popupActions.submit': return '确定'; - case 'popupActions.ok': return '彳亍'; - case 'errors.connection': return ({required Object code, required Object message}) => '连接错误: ${code} ${message}'; - case 'errors.noSuchUser': return '没有这样的用户'; - case 'errors.noSuchUserSub': return '检查用户名的拼写是否错误,也许用户不存在'; - case 'errors.discordNotAssigned': return '没有用户绑定到该Discord ID'; - case 'errors.discordNotAssignedSub': return '您必须输入合法的ID'; - case 'errors.history': return '此玩家没有历史'; - case 'errors.actionSuggestion': return '你也许想'; - case 'errors.p1nkl0bst3rTLmatches': return '没有比赛'; - case 'errors.clientException': return '连接不到网络'; - case 'errors.forbidden': return '你的IP地址被封禁'; - case 'errors.forbiddenSub': return ({required Object nickname}) => '请关闭您的VPN。若问题仍然存在,请联系 ${nickname}'; - case 'errors.tooManyRequests': return '您申请的请求过多'; - case 'errors.tooManyRequestsSub': return '等一会再试吧'; - case 'errors.internal': return 'tetr.io 似乎出错了'; - case 'errors.internalSub': return 'osk,也许,要被'; - case 'errors.internalWebVersion': return 'tetr.io 或者 oskware_bridge 似乎出错了'; - case 'errors.internalWebVersionSub': return '如果 osk 说没有什么问题,请让dan63047知道'; - case 'errors.oskwareBridge': return 'oskware_bridge 似乎出错了'; - case 'errors.oskwareBridgeSub': return '请让 dan63047 知道'; - case 'errors.p1nkl0bst3rForbidden': return '第三方API封禁了你的IP地址'; - case 'errors.p1nkl0bst3rTooManyRequests': return '第三方API……太多请求了。'; - case 'errors.p1nkl0bst3rinternal': return 'p1nkl0bst3r 那边似乎出错了'; - case 'errors.p1nkl0bst3rinternalWebVersion': return 'p1nkl0bst3r (或 on oskware_bridge, 其实我并不知道) 那边似乎出错了'; - case 'errors.replayAlreadySaved': return '你已保存此回放'; - case 'errors.replayExpired': return '回放已过期'; - case 'errors.replayRejected': return '第三方API封禁了你的IP地址'; - case 'countries.': return '无'; - case 'countries.AF': return '阿富汗'; - case 'countries.AX': return '奥兰群岛'; - case 'countries.AL': return '阿尔巴尼亚'; - case 'countries.DZ': return '阿尔及利亚'; - case 'countries.AS': return '美属萨摩亚'; - case 'countries.AD': return '安道尔'; - case 'countries.AO': return '安哥拉'; - case 'countries.AI': return '安圭拉'; - case 'countries.AQ': return '南极洲'; - case 'countries.AG': return '安提瓜和巴布达'; - case 'countries.AR': return '阿根廷'; - case 'countries.AM': return '亚美尼亚'; - case 'countries.AW': return '阿鲁巴'; - case 'countries.AU': return '澳大利亚'; - case 'countries.AT': return '奥地利'; - case 'countries.AZ': return '阿塞拜疆'; - case 'countries.BS': return '巴哈马'; - case 'countries.BH': return '巴林'; - case 'countries.BD': return '孟加拉国'; - case 'countries.BB': return '巴巴多斯'; - case 'countries.BY': return '白俄罗斯'; - case 'countries.BE': return '比利时'; - case 'countries.BZ': return '伯利兹'; - case 'countries.BJ': return '贝宁'; - case 'countries.BM': return '百慕大'; - case 'countries.BT': return '不丹'; - case 'countries.BO': return '玻利维亚多民族国'; - case 'countries.BA': return '波斯尼亚和黑塞哥维那'; - case 'countries.BW': return '博茨瓦纳'; - case 'countries.BV': return '布韦岛'; - case 'countries.BR': return '巴西'; - case 'countries.IO': return '英属印度洋领地'; - case 'countries.BN': return '文莱达鲁萨兰国'; - case 'countries.BG': return '保加利亚'; - case 'countries.BF': return '布基纳法索'; - case 'countries.BI': return '布隆迪'; - case 'countries.KH': return '柬埔寨'; - case 'countries.CM': return '喀麦隆'; - case 'countries.CA': return '加拿大'; - case 'countries.CV': return '佛得角'; - case 'countries.BQ': return '荷兰加勒比区'; - case 'countries.KY': return '开曼群岛'; - case 'countries.CF': return '中非'; - case 'countries.TD': return '乍得'; - case 'countries.CL': return '智利'; - case 'countries.CN': return '中国'; - case 'countries.CX': return '圣诞岛'; - case 'countries.CC': return '科科斯(基林)群岛'; - case 'countries.CO': return '哥伦比亚'; - case 'countries.KM': return '科摩罗'; - case 'countries.CG': return '刚果(布)/刚果共和国'; - case 'countries.CD': return '刚果(金)/刚果民主共和国'; - case 'countries.CK': return '库克群岛'; - case 'countries.CR': return '哥斯达黎加'; - case 'countries.CI': return '科特迪瓦'; - case 'countries.HR': return '克罗地亚'; - case 'countries.CU': return '古巴'; - case 'countries.CW': return '库拉索'; - case 'countries.CY': return '塞浦路斯'; - case 'countries.CZ': return '捷克'; - case 'countries.DK': return '丹麦'; - case 'countries.DJ': return '吉布提'; - case 'countries.DM': return '多米尼加'; - case 'countries.DO': return '多米尼加共和国'; - case 'countries.EC': return '厄瓜多尔'; - case 'countries.EG': return '埃及'; - case 'countries.SV': return '萨尔瓦多'; - case 'countries.GB-ENG': return '英格兰'; - case 'countries.GQ': return '赤道几内亚'; - case 'countries.ER': return '厄立特里亚'; - case 'countries.EE': return '爱沙尼亚'; - case 'countries.ET': return '埃塞俄比亚'; - case 'countries.EU': return '欧洲'; - case 'countries.FK': return '福克兰群岛/马尔维纳斯群岛'; - case 'countries.FO': return '法罗群岛'; - case 'countries.FJ': return '斐济'; - case 'countries.FI': return '芬兰'; - case 'countries.FR': return '法国'; - case 'countries.GF': return '法属圭亚那'; - case 'countries.PF': return '法属波利尼西亚'; - case 'countries.TF': return '法属南部领地'; - case 'countries.GA': return '加蓬'; - case 'countries.GM': return '冈比亚'; - case 'countries.GE': return '格鲁吉亚'; - case 'countries.DE': return '德国'; - case 'countries.GH': return '加纳'; - case 'countries.GI': return '直布罗陀'; - case 'countries.GR': return '希腊'; - case 'countries.GL': return '格陵兰岛'; - case 'countries.GD': return '格林纳达'; - case 'countries.GP': return '瓜德罗普岛'; - case 'countries.GU': return '关岛'; - case 'countries.GT': return '危地马拉'; - case 'countries.GG': return '根西岛'; - case 'countries.GN': return '几内亚'; - case 'countries.GW': return '几内亚比绍'; - case 'countries.GY': return '圭亚那'; - case 'countries.HT': return '海地'; - case 'countries.HM': return '赫德岛和麦克唐纳群岛'; - case 'countries.VA': return '梵蒂冈'; - case 'countries.HN': return '洪都拉斯'; - case 'countries.HK': return '中国香港'; - case 'countries.HU': return '匈牙利'; - case 'countries.IS': return '冰岛'; - case 'countries.IN': return '印度'; - case 'countries.ID': return '印度尼西亚'; - case 'countries.IR': return '伊朗'; - case 'countries.IQ': return '伊拉克'; - case 'countries.IE': return '爱尔兰'; - case 'countries.IM': return '马恩岛'; - case 'countries.IL': return '以色列'; - case 'countries.IT': return '意大利'; - case 'countries.JM': return '牙买加'; - case 'countries.JP': return '日本'; - case 'countries.JE': return 'Jersey'; - case 'countries.JO': return '约旦'; - case 'countries.KZ': return '哈萨克斯坦'; - case 'countries.KE': return '肯尼亚'; - case 'countries.KI': return '基里巴斯'; - case 'countries.KP': return '朝鲜'; - case 'countries.KR': return '韩国'; - case 'countries.XK': return '科索沃'; - case 'countries.KW': return '科威特'; - case 'countries.KG': return '吉尔吉斯斯坦'; - case 'countries.LA': return '老挝'; - case 'countries.LV': return '拉脱维亚'; - case 'countries.LB': return '黎巴嫩'; - case 'countries.LS': return '莱索托'; - case 'countries.LR': return '利比里亚'; - case 'countries.LY': return '利比亚'; - case 'countries.LI': return '列支敦士登'; - case 'countries.LT': return '立陶宛'; - case 'countries.LU': return '卢森堡'; - case 'countries.MO': return '中国澳门'; - case 'countries.MK': return '马其顿'; - case 'countries.MG': return '马达加斯加'; - case 'countries.MW': return '马拉维'; - case 'countries.MY': return '马来西亚'; - case 'countries.MV': return '马尔代夫'; - case 'countries.ML': return '马里'; - case 'countries.MT': return '马耳他'; - case 'countries.MH': return '马绍尔群岛'; - case 'countries.MQ': return '马提尼克岛'; - case 'countries.MR': return '毛里塔尼亚'; - case 'countries.MU': return '毛里求斯'; - case 'countries.YT': return '马约特岛'; - case 'countries.MX': return '墨西哥'; - case 'countries.FM': return '密克罗尼西亚联邦'; - case 'countries.MD': return '摩尔多瓦共和国'; - case 'countries.MC': return '摩纳哥'; - case 'countries.ME': return '黑山'; - case 'countries.MA': return '摩洛哥'; - case 'countries.MN': return '蒙古'; - case 'countries.MS': return '蒙特塞拉特'; - case 'countries.MZ': return '莫桑比克'; - case 'countries.MM': return '缅甸'; - case 'countries.NA': return '纳米比亚'; - case 'countries.NR': return '瑙鲁'; - case 'countries.NP': return '尼泊尔'; - case 'countries.NL': return '尼德兰'; - case 'countries.AN': return '荷属安的列斯'; - case 'countries.NC': return '新喀里多尼亚'; - case 'countries.NZ': return '新西兰'; - case 'countries.NI': return '尼加拉瓜'; - case 'countries.NE': return '尼日尔'; - case 'countries.NG': return '尼日利亚'; - case 'countries.NU': return '纽埃'; - case 'countries.NF': return '诺福克岛'; - case 'countries.GB-NIR': return '北爱尔兰'; - case 'countries.MP': return '北马里亚纳群岛'; - case 'countries.NO': return '挪威'; - case 'countries.OM': return '阿曼'; - case 'countries.PK': return '巴基斯坦'; - case 'countries.PW': return '帕劳'; - case 'countries.PS': return '巴勒斯坦'; - case 'countries.PA': return '巴拿马'; - case 'countries.PG': return '巴布亚新几内亚'; - case 'countries.PY': return '巴拉圭'; - case 'countries.PE': return '秘鲁'; - case 'countries.PH': return '菲律宾'; - case 'countries.PN': return '皮特凯恩'; - case 'countries.PL': return '波兰'; - case 'countries.PT': return '葡萄牙'; - case 'countries.PR': return '波多黎各'; - case 'countries.QA': return '卡塔尔'; - case 'countries.RE': return '留尼汪'; - case 'countries.RO': return '罗马尼亚'; - case 'countries.RU': return '俄罗斯联邦'; - case 'countries.RW': return '卢旺达'; - case 'countries.BL': return '圣巴泰勒米'; - case 'countries.SH': return '圣赫勒拿,阿森松和特里斯坦-达库尼亚'; - case 'countries.KN': return '圣基茨和尼维斯'; - case 'countries.LC': return '圣卢西亚'; - case 'countries.MF': return '圣马丁'; - case 'countries.PM': return '圣皮埃尔和密克隆群岛'; - case 'countries.VC': return '圣文森特和格林纳丁斯'; - case 'countries.WS': return '萨摩亚'; - case 'countries.SM': return '圣马力诺'; - case 'countries.ST': return '圣多美和普林西比'; - case 'countries.SA': return '沙特阿拉伯'; - case 'countries.GB-SCT': return '苏格兰'; - case 'countries.SN': return '塞内加尔'; - case 'countries.RS': return '塞尔维亚'; - case 'countries.SC': return '塞舌尔'; - case 'countries.SL': return '塞拉利昂'; - case 'countries.SG': return '新加坡'; - case 'countries.SX': return '荷属圣马丁'; - case 'countries.SK': return '斯洛伐克'; - case 'countries.SI': return '斯洛文尼亚'; - case 'countries.SB': return '所罗门群岛'; - case 'countries.SO': return '索马里'; - case 'countries.ZA': return '南非'; - case 'countries.GS': return '南乔治亚和南桑威奇群岛'; - case 'countries.SS': return '南苏丹'; - case 'countries.ES': return '西班牙'; - case 'countries.LK': return '斯里兰卡'; - case 'countries.SD': return '苏丹'; - case 'countries.SR': return '苏里南'; - case 'countries.SJ': return '斯瓦尔巴和扬马延群岛'; - case 'countries.SZ': return '斯威士兰'; - case 'countries.SE': return '瑞典'; - case 'countries.CH': return '瑞士'; - case 'countries.SY': return '叙利亚'; - case 'countries.TW': return '中国台湾'; - case 'countries.TJ': return '塔吉克斯坦'; - case 'countries.TZ': return '坦桑尼亚'; - case 'countries.TH': return '泰国'; - case 'countries.TL': return '东帝汶'; - case 'countries.TG': return '多哥'; - case 'countries.TK': return '托克劳'; - case 'countries.TO': return '汤加'; - case 'countries.TT': return '特立尼达和多巴哥'; - case 'countries.TN': return '突尼斯'; - case 'countries.TR': return '土耳其'; - case 'countries.TM': return '土库曼斯坦'; - case 'countries.TC': return '特克斯和凯科斯群岛'; - case 'countries.TV': return '图瓦卢'; - case 'countries.UG': return '乌干达'; - case 'countries.UA': return '乌克兰'; - case 'countries.AE': return '阿拉伯联合酋长国'; - case 'countries.GB': return '英国'; - case 'countries.US': return '美国'; - case 'countries.UY': return '乌拉圭'; - case 'countries.UM': return '美国小岛屿'; - case 'countries.UZ': return '乌兹别克斯坦'; - case 'countries.VU': return '瓦努阿图'; - case 'countries.VE': return '委内瑞拉玻利瓦尔共和国'; - case 'countries.VN': return '越南'; - case 'countries.VG': return '英属维尔京群岛'; - case 'countries.VI': return '美属维尔京群岛'; - case 'countries.GB-WLS': return '威尔士'; - case 'countries.WF': return '瓦利斯和富图纳群岛'; - case 'countries.EH': return '西撒哈拉'; - case 'countries.YE': return '也门'; - case 'countries.ZM': return '赞比亚'; - case 'countries.ZW': return '津巴布韦'; - case 'countries.XX': return '未知'; - case 'countries.XM': return '月球'; - default: return null; - } - } -} diff --git a/lib/views/about_view.dart b/lib/views/about_view.dart index 8a0410d..b605b89 100644 --- a/lib/views/about_view.dart +++ b/lib/views/about_view.dart @@ -56,7 +56,7 @@ class AboutState extends State { void initState() { if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS){ windowManager.getTitle().then((value) => oldWindowTitle = value); - windowManager.setTitle("Tetra Stats: ${t.settings}"); + windowManager.setTitle(t.aboutView.title); } super.initState(); } @@ -69,15 +69,13 @@ class AboutState extends State { @override Widget build(BuildContext context) { - final t = Translations.of(context); - bool bigScreen = MediaQuery.of(context).size.width >= 368; return Scaffold( floatingActionButtonLocation: FloatingActionButtonLocation.startTop, floatingActionButton: Padding( padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), @@ -89,7 +87,7 @@ class AboutState extends State { children: [ Card(child: Center(child: Padding( padding: const EdgeInsets.fromLTRB(0.0, 6.0, 0.0, 18.0), - child: Text("About Tetra Stats", style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center), + child: Text(t.aboutView.title, style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center), ))), Column( mainAxisSize: MainAxisSize.min, @@ -103,41 +101,38 @@ class AboutState extends State { padding: const EdgeInsets.all(8.0), child: Container( constraints: BoxConstraints(maxWidth: 568.00), - child: Text( - textAlign: TextAlign.center, - "Tetra Stats is a service, that works with TETR.IO Tetra Channel API, providing data from it and calculating some addtitional metrics, based on this data. Service allows user to track their progress in Tetra League with \"Track\" function, which records every Tetra League change into local database (not automatically, you have to visit service from time to time), so these changes could be looked through graphs.\n\nBeanserver blaster is a part of a Tetra Stats, that decoupled into a serverside script. It provides full Tetra League leaderboard, allowing Tetra Stats to sort leaderboard by any metric and build scatter chart, that allows user to analyse Tetra League trends. It also provides history of Tetra League ranks cutoffs, which can be viewed by user via graph as well.\n\nThere is a plans to add replay analysis and tournaments history, so stay tuned!\n\nService is not associated with TETR.IO or osk in any capacity." - ), + child: Text(textAlign: TextAlign.center, t.aboutView.about), ), ), ), ], )), - AboutCard("App Version", packageInfo.version, "Build ${packageInfo.buildNumber}", [ + AboutCard(t.aboutView.appVersion, packageInfo.version, t.aboutView.build(build: packageInfo.buildNumber), [ TextSpan(text: "${packageInfo.appName} (${packageInfo.packageName}) • "), - TextSpan(text: "GitHub Repo", style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("github.com", "dan63047/TetraStats"));}), + TextSpan(text: t.aboutView.GHrepo, style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("github.com", "dan63047/TetraStats"));}), TextSpan(text: " • "), - TextSpan(text: "Submit an issue", style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("github.com", "dan63047/TetraStats/issues/new/choose"));}), + TextSpan(text: t.aboutView.submitAnIssue, style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("github.com", "dan63047/TetraStats/issues/new/choose"));}), ]), Card(child: Center(child: Padding( padding: const EdgeInsets.fromLTRB(0.0, 6.0, 0.0, 18.0), - child: Text("Credits", style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center), + child: Text(t.aboutView.credits, style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center), ))), Wrap( direction: Axis.horizontal, children: [ - FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard("Autor & developer", "dan63", null, [ - TextSpan(text: "Support him!", style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("dan63.by", "donate"));}) + FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard(t.aboutView.authorAndDeveloper, "dan63", null, [ + TextSpan(text: t.aboutView.supportHim, style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("dan63.by", "donate"));}) ])), - FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard("Provided formulas", "kerrmunism", null, [ + FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard(t.aboutView.providedFormulas, "kerrmunism", null, [ //TextSpan(text: "Support him!", style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("paypal.com", "paypalme/Kerrmunism"));}) ])), - FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard("Provided S1 history", "p1nkl0bst3r", null, [ + FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard(t.aboutView.providedS1history, "p1nkl0bst3r", null, [ //TextSpan(text: "Support him!", style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("paypal.com", "paypalme/Kerrmunism"));}) ])), - FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard("Inoue (replay grabber)", "szy", null, [ + FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard(t.aboutView.inoue, "szy", null, [ //TextSpan(text: "Support him!", style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("paypal.com", "paypalme/Kerrmunism"));}) ])), - FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard("Simplfied Chinise locale", "neko_ab4093", null, [ + FractionallySizedBox(widthFactor: 1/((MediaQuery.of(context).size.width/600).ceil()), child: AboutCard(t.aboutView.zhCNlocale, "neko_ab4093", null, [ //TextSpan(text: "Support him!", style: TextStyle(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, color: Theme.of(context).colorScheme.primary), recognizer: TapGestureRecognizer()..onTap = (){launchInBrowser(Uri.https("paypal.com", "paypalme/Kerrmunism"));}) ])), ], diff --git a/lib/views/compare_view_tiles.dart b/lib/views/compare_view_tiles.dart index 9796286..e043b1d 100644 --- a/lib/views/compare_view_tiles.dart +++ b/lib/views/compare_view_tiles.dart @@ -44,150 +44,150 @@ class CompareState extends State { List summaries = []; List nicknames = []; Map> TitesForStats = { - "General": [ - "Registration Date", - "XP", - "Time Played", - "Online Games Played", - "Online Games Won", - "Followers", + t.general: [ + t.stats.registrationDate, + t.stats.xp.short, + t.stats.gametime, + t.stats.ogp, + t.stats.ogw, + t.stats.followers, ], - "Tetra League": [ - "Tetra Rating", - "Glicko", - "RD", - "GLIXARE", - "S1-like TR", - "Position", - "Games Played", - "Games Won", - "Winrate", - "Attack Per Minute", - "Pieces Per Second", - "Versus Score", - "Nerd Stats", - "Attack Per Piece", - "VS / APM", - "Downstack Per Second", - "Downstack Per Piece", - "APP + DSP", - "Cheese Index", - "Garbage Efficiency", - "Weighted APP", - "Area", - "Playstyle", - "Opener", - "Plonk", - "Stride", - "Infinite Downstack" + t.gamemodes["league"]!: [ + t.stats.tr.full, + t.stats.glicko.full, + t.stats.rd.full, + t.stats.glixare.full, + t.stats.s1tr.full, + t.stats.placement, + t.stats.gp.full, + t.stats.gw.full, + t.stats.winrate.full, + t.stats.apm.full, + t.stats.pps.full, + t.stats.vs.full, + t.nerdStats, + t.stats.app.full, + t.stats.vsapm.full, + t.stats.dss.full, + t.stats.dsp.full, + t.stats.appdsp.full, + t.stats.cheese.full, + t.stats.gbe.full, + t.stats.nyaapp.full, + t.stats.area.full, + t.playstyles, + t.stats.opener.full, + t.stats.plonk.full, + t.stats.stride.full, + t.stats.infds.full ], - "Quick Play":[ - "Altitude", - "Position", - "Attack Per Minute", - "Pieces Per Second", - "Versus Score", - "KO's", - "Top B2B", - "Climb Speed", - "Peak Climb Speed", - "Time Spend", - "Finesse", - "Nerd Stats", - "Attack Per Piece", - "VS / APM", - "Downstack Per Second", - "Downstack Per Piece", - "APP + DSP", - "Cheese Index", - "Garbage Efficiency", - "Weighted APP", - "Area", - "Playstyle", - "Opener", - "Plonk", - "Stride", - "Infinite Downstack", + t.gamemodes["zenith"]!:[ + t.stats.altitude.full, + t.stats.placement, + t.stats.apm.full, + t.stats.pps.full, + t.stats.vs.full, + t.stats.kos.full, + t.stats.b2b.full, + t.stats.climbSpeed.full, + t.stats.peakClimbSpeed.full, + t.stats.totalTime.full, + t.stats.finesse.full, + t.nerdStats, + t.stats.app.full, + t.stats.vsapm.full, + t.stats.dss.full, + t.stats.dsp.full, + t.stats.appdsp.full, + t.stats.cheese.full, + t.stats.gbe.full, + t.stats.nyaapp.full, + t.stats.area.full, + t.playstyles, + t.stats.opener.full, + t.stats.plonk.full, + t.stats.stride.full, + t.stats.infds.full ], - "Quick Play Expert": [ - "Altitude", - "Position", - "Attack Per Minute", - "Pieces Per Second", - "Versus Score", - "KO's", - "Top B2B", - "Climb Speed", - "Peak Climb Speed", - "Time Spend", - "Finesse", - "Nerd Stats", - "Attack Per Piece", - "VS / APM", - "Downstack Per Second", - "Downstack Per Piece", - "APP + DSP", - "Cheese Index", - "Garbage Efficiency", - "Weighted APP", - "Area", - "Playstyle", - "Opener", - "Plonk", - "Stride", - "Infinite Downstack", + t.gamemodes["zenithex"]!:[ + t.stats.altitude.full, + t.stats.placement, + t.stats.apm.full, + t.stats.pps.full, + t.stats.vs.full, + t.stats.kos.full, + t.stats.b2b.full, + t.stats.climbSpeed.full, + t.stats.peakClimbSpeed.full, + t.stats.totalTime.full, + t.stats.finesse.full, + t.nerdStats, + t.stats.app.full, + t.stats.vsapm.full, + t.stats.dss.full, + t.stats.dsp.full, + t.stats.appdsp.full, + t.stats.cheese.full, + t.stats.gbe.full, + t.stats.nyaapp.full, + t.stats.area.full, + t.playstyles, + t.stats.opener.full, + t.stats.plonk.full, + t.stats.stride.full, + t.stats.infds.full ], - "40 Lines": [ - "Time", - "Pieces", - "Inputs", - "Key Presses Per Piece", - "Pieces Per Second", - "Key Presses Per Second", - "Finesse", - "Finesse Faults", + t.gamemodes["40l"]!: [ + t.stats.totalTime.short, + t.stats.pieces.full, + t.stats.kp.full, + t.stats.kpp.full, + t.stats.pps.full, + t.stats.kps.full, + t.stats.finesse.full, + t.stats.finesseFaults.full, "", - "Quads", - "Triples", - "Doubles", - "Singles", + t.stats.lineClears.quad, + t.stats.lineClears.triple, + t.stats.lineClears.double, + t.stats.lineClears.single, "", - "T-spins triples", - "T-spins doubles", - "T-spins singles", - "T-spins zeros", - "Mini T-spins doubles", - "Mini T-spins singles", - "Mini T-spins zeros" + "${t.stats.tSpins} ${t.stats.lineClears.triple}", + "${t.stats.tSpins} ${t.stats.lineClears.double}", + "${t.stats.tSpins} ${t.stats.lineClears.single}", + "${t.stats.tSpins} ${t.stats.lineClears.zero}", + "${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.double}", + "${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.single}", + "${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.zero}" ], - "Blitz": [ - "Score", - "Pieces", - "Lines", - "Level", - "Inputs", - "Key Presses Per Piece", - "Pieces Per Second", - "Key Presses Per Second", - "Finesse", - "Finesse Faults", + t.gamemodes["blitz"]!: [ + t.stats.score, + t.stats.pieces.full, + t.stats.lines, + t.stats.level.full, + t.stats.kp.full, + t.stats.kpp.full, + t.stats.pps.full, + t.stats.kps.full, + t.stats.finesse.full, + t.stats.finesseFaults.full, "", - "Quads", - "Triples", - "Doubles", - "Singles", + t.stats.lineClears.quad, + t.stats.lineClears.triple, + t.stats.lineClears.double, + t.stats.lineClears.single, "", - "T-spins triples", - "T-spins doubles", - "T-spins singles", - "T-spins zeros", - "Mini T-spins doubles", - "Mini T-spins singles", - "Mini T-spins zeros" + "${t.stats.tSpins} ${t.stats.lineClears.triple}", + "${t.stats.tSpins} ${t.stats.lineClears.double}", + "${t.stats.tSpins} ${t.stats.lineClears.single}", + "${t.stats.tSpins} ${t.stats.lineClears.zero}", + "${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.double}", + "${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.single}", + "${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.zero}" ], - "Zen": [ - "Score", - "Level" + t.gamemodes["zen"]!: [ + t.stats.score, + t.stats.level.full ] }; List>> rawValues = [[],[],[],[],[],[],[]]; @@ -725,7 +725,7 @@ class CompareState extends State { padding: const EdgeInsets.all(16.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), @@ -748,7 +748,7 @@ class CompareState extends State { child: Card( child: Padding( padding: const EdgeInsets.fromLTRB(90.0, 18.0, 5.0, 0), - child: Text("Comparison", style: TextStyle(fontSize: 28)), + child: Text(t.comparison, style: TextStyle(fontSize: 28)), ), ), ), @@ -1149,13 +1149,13 @@ class VsGraphs extends StatelessWidget{ getTitle: (index, angle) { switch (index) { case 0: - return RadarChartTitle(text: t.graphs.attack, angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: t.stats.graphs.attack, angle: 0, positionPercentageOffset: 0.05); case 1: - return RadarChartTitle(text: t.graphs.speed, angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: t.stats.graphs.speed, angle: 0, positionPercentageOffset: 0.05); case 2: - return RadarChartTitle(text: t.graphs.defense, angle: angle + 180, positionPercentageOffset: 0.05); + return RadarChartTitle(text: t.stats.graphs.defense, angle: angle + 180, positionPercentageOffset: 0.05); case 3: - return RadarChartTitle(text: t.graphs.cheese, angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: t.stats.graphs.cheese, angle: 0, positionPercentageOffset: 0.05); default: return const RadarChartTitle(text: ''); } diff --git a/lib/views/destination_calculator.dart b/lib/views/destination_calculator.dart index 5918f6d..12a893f 100644 --- a/lib/views/destination_calculator.dart +++ b/lib/views/destination_calculator.dart @@ -95,25 +95,25 @@ class ClearData{ } Map> clearsExisting = { - "No Spin Clears": [ - ClearData("No lineclear (Break Combo)", Lineclears.ZERO, 0, false, false), - ClearData("Single", Lineclears.SINGLE, 1, false, false), - ClearData("Double", Lineclears.DOUBLE, 2, false, false), - ClearData("Triple", Lineclears.TRIPLE, 3, false, false), - ClearData("Quad", Lineclears.QUAD, 4, false, false) + t.calcDestination.noSpinClears: [ + ClearData(t.calcDestination.noLineclear, Lineclears.ZERO, 0, false, false), + ClearData(t.stats.lineClears.single, Lineclears.SINGLE, 1, false, false), + ClearData(t.stats.lineClears.double, Lineclears.DOUBLE, 2, false, false), + ClearData(t.stats.lineClears.triple, Lineclears.TRIPLE, 3, false, false), + ClearData(t.stats.lineClears.quad, Lineclears.QUAD, 4, false, false) ], - "Spins": [ - ClearData("Spin Zero", Lineclears.TSPIN, 0, false, true), - ClearData("Spin Single", Lineclears.TSPIN_SINGLE, 1, false, true), - ClearData("Spin Double", Lineclears.TSPIN_DOUBLE, 2, false, true), - ClearData("Spin Triple", Lineclears.TSPIN_TRIPLE, 3, false, true), - ClearData("Spin Quad", Lineclears.TSPIN_QUAD, 4, false, true), + t.stats.spins: [ + ClearData("${t.stats.spin} ${t.stats.lineClears.zero}", Lineclears.TSPIN, 0, false, true), + ClearData("${t.stats.spin} ${t.stats.lineClears.single}", Lineclears.TSPIN_SINGLE, 1, false, true), + ClearData("${t.stats.spin} ${t.stats.lineClears.double}", Lineclears.TSPIN_DOUBLE, 2, false, true), + ClearData("${t.stats.spin} ${t.stats.lineClears.triple}", Lineclears.TSPIN_TRIPLE, 3, false, true), + ClearData("${t.stats.spin} ${t.stats.lineClears.quad}", Lineclears.TSPIN_QUAD, 4, false, true), ], - "Mini spins": [ - ClearData("Mini Spin Zero", Lineclears.TSPIN_MINI, 0, true, false), - ClearData("Mini Spin Single", Lineclears.TSPIN_MINI_SINGLE, 1, true, false), - ClearData("Mini Spin Double", Lineclears.TSPIN_MINI_DOUBLE, 2, true, false), - ClearData("Mini Spin Triple", Lineclears.TSPIN_MINI_TRIPLE, 3, true, false), + "${t.stats.mini} ${t.stats.spins}": [ + ClearData("${t.stats.mini} ${t.stats.spin} ${t.stats.lineClears.zero}", Lineclears.TSPIN_MINI, 0, true, false), + ClearData("${t.stats.mini} ${t.stats.spin} ${t.stats.lineClears.single}", Lineclears.TSPIN_MINI_SINGLE, 1, true, false), + ClearData("${t.stats.mini} ${t.stats.spin} ${t.stats.lineClears.double}", Lineclears.TSPIN_MINI_DOUBLE, 2, true, false), + ClearData("${t.stats.mini} ${t.stats.spin} ${t.stats.lineClears.triple}", Lineclears.TSPIN_MINI_TRIPLE, 3, true, false), ] }; @@ -165,8 +165,8 @@ class _DestinationCalculatorState extends State { List clears = []; Map customClearsChoice = { - "No Spin Clears": 5, - "Spins": 5 + t.calcDestination.noSpinClears: 5, + t.calcDestination.spins: 5 }; int idCounter = 0; Rules rules = Rules(); @@ -204,7 +204,7 @@ class _DestinationCalculatorState extends State { padding: const EdgeInsets.only(bottom: 8.0), child: Column( children: [ - Text("Stats Calucator", style: Theme.of(context).textTheme.titleLarge), + Text(t.calcNavigation.stats, style: Theme.of(context).textTheme.titleLarge), ], ), )), @@ -253,7 +253,7 @@ class _DestinationCalculatorState extends State { ), TextButton( onPressed: () => calc(), - child: Text(t.calc), + child: Text(t.calcDestination.statsCalcButton), ), ], ), @@ -265,7 +265,7 @@ class _DestinationCalculatorState extends State { if (playstyle != null) Card( child: Graphs(apm!, pps!, vs!, nerdStats!, playstyle!) ), - if (nerdStats == null) InfoThingy("Enter values and press \"Calc\" to see Nerd Stats for them") + if (nerdStats == null) InfoThingy(t.calcDestination.tip) ], ), ); @@ -275,7 +275,7 @@ class _DestinationCalculatorState extends State { return SizedBox( width: width - (hasSidebar ? 80 : 0), height: widget.constraints.maxHeight - (hasSidebar ? 108 : 178), - child: clears.isEmpty ? InfoThingy("Click on the actions on the left to add them here") : + child: clears.isEmpty ? InfoThingy(t.calcDestination.damageCalcTip) : Card( child: Column( children: [ @@ -301,7 +301,7 @@ class _DestinationCalculatorState extends State { padding: const EdgeInsets.fromLTRB(16.0, 0.0, 34.0, 0.0), child: Row( children: [ - Text("Total damage:", style: TextStyle(fontSize: 36, fontWeight: ui.FontWeight.w100)), + Text("${t.calcDestination.totalDamage}:", style: TextStyle(fontSize: 36, fontWeight: ui.FontWeight.w100)), Spacer(), Text(intf.format(totalDamage), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: ui.FontWeight.w100)) ], @@ -310,11 +310,11 @@ class _DestinationCalculatorState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Text("Lineclears: ${intf.format(normalDamage)}"), - Text("Combo: ${intf.format(comboDamage)}"), - Text("B2B: ${intf.format(b2bDamage)}"), - Text("Surge: ${intf.format(surgeDamage)}"), - Text("PCs: ${intf.format(pcDamage)}") + Text("${t.calcDestination.lineclears}: ${intf.format(normalDamage)}"), + Text("${t.calcDestination.combo}: ${intf.format(comboDamage)}"), + Text("${t.stats.b2b.short}: ${intf.format(b2bDamage)}"), + Text("${t.calcDestination.surge}: ${intf.format(surgeDamage)}"), + Text("${t.calcDestination.pcs}: ${intf.format(pcDamage)}") ], ), if (totalDamage > 0) SfLinearGauge( @@ -382,9 +382,9 @@ class _DestinationCalculatorState extends State { }, ), )); - if (key != "Mini spins") rSideWidgets.add(Card( + if (key != "${t.stats.mini} ${t.stats.spins}") rSideWidgets.add(Card( child: ListTile( - title: Text("Custom"), + title: Text(t.calcDestination.custom), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -394,13 +394,13 @@ class _DestinationCalculatorState extends State { decoration: InputDecoration(hintText: "5"), onChanged: (value) => customClearsChoice[key] = int.parse(value), )), - Text(" Lines", style: Theme.of(context).textTheme.displayLarge), + Text(" ${t.stats.lines}", style: Theme.of(context).textTheme.displayLarge), Icon(Icons.arrow_forward_ios) ], ), onTap: (){ setState((){ - clears.add(ClearData("${key == "Spins" ? "Spin " : ""}${clearNames[min(customClearsChoice[key]!, clearNames.length-1)]} (${customClearsChoice[key]!} Lines)", key == "Spins" ? Lineclears.TSPIN_PENTA : Lineclears.PENTA, customClearsChoice[key]!, false, key == "Spins").cloneWith(idCounter)); + clears.add(ClearData("${key == t.calcDestination.spins ? "${t.stats.spin} " : ""}${clearNames[min(customClearsChoice[key]!, clearNames.length-1)]} (${customClearsChoice[key]!} ${t.stats.lines})", key == t.calcDestination.spins ? Lineclears.TSPIN_PENTA : Lineclears.PENTA, customClearsChoice[key]!, false, key == t.calcDestination.spins).cloneWith(idCounter)); }); idCounter++; }, @@ -466,7 +466,7 @@ class _DestinationCalculatorState extends State { padding: const EdgeInsets.only(bottom: 8.0), child: Column( children: [ - Text("Damage Calucator", style: Theme.of(context).textTheme.titleLarge), + Text(t.calcNavigation.damage, style: Theme.of(context).textTheme.titleLarge), ], ), )), @@ -483,9 +483,9 @@ class _DestinationCalculatorState extends State { children: [ Card( child: TabBar(tabs: [ - Tab(text: "Actions"), - if (widget.constraints.maxWidth <= 768.0) Tab(text: "Results"), - Tab(text: "Rules"), + Tab(text: t.calcDestination.actions), + if (widget.constraints.maxWidth <= 768.0) Tab(text: t.calcDestination.results), + Tab(text: t.calcDestination.rules), ]), ), SizedBox( @@ -506,7 +506,7 @@ class _DestinationCalculatorState extends State { child: Column( children: [ ListTile( - title: Text("Multiplier", style: mainToggleInRules), + title: Text(t.calcDestination.multiplier, style: mainToggleInRules), trailing: SizedBox(width: 90.0, child: TextField( keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9.]'))], @@ -515,7 +515,7 @@ class _DestinationCalculatorState extends State { )), ), ListTile( - title: Text("Perfect Clear Damage"), + title: Text(t.calcDestination.pcDamage), trailing: SizedBox(width: 90.0, child: TextField( keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))], @@ -530,11 +530,11 @@ class _DestinationCalculatorState extends State { child: Column( children: [ ListTile( - title: Text("Combo", style: mainToggleInRules), + title: Text(t.calcDestination.combo, style: mainToggleInRules), trailing: Switch(value: rules.combo, onChanged: (v) => setState((){rules.combo = v;})), ), if (rules.combo) ListTile( - title: Text("Combo Table"), + title: Text(t.calcDestination.comboTable), trailing: DropdownButton( items: [for (var v in ComboTables.values) if (v != ComboTables.none) DropdownMenuItem(value: v.index, child: Text(comboTablesNames[v]!))], value: rules.comboTable.index, @@ -548,11 +548,11 @@ class _DestinationCalculatorState extends State { child: Column( children: [ ListTile( - title: Text("Back-To-Back (B2B)", style: mainToggleInRules), + title: Text("${t.stats.b2b.full} (${t.stats.b2b.short})", style: mainToggleInRules), trailing: Switch(value: rules.b2b, onChanged: (v) => setState((){rules.b2b = v;})), ), if (rules.b2b) ListTile( - title: Text("Back-To-Back Chaining"), + title: Text(t.calcDestination.b2bChaining), trailing: Switch(value: rules.b2bChaining, onChanged: (v) => setState((){rules.b2bChaining = v;})), ), ], @@ -562,11 +562,11 @@ class _DestinationCalculatorState extends State { child: Column( children: [ ListTile( - title: Text("Surge", style: mainToggleInRules), + title: Text(t.calcDestination.surge, style: mainToggleInRules), trailing: Switch(value: rules.surge, onChanged: (v) => setState((){rules.surge = v;})), ), if (rules.surge) ListTile( - title: Text("Starts at B2B"), + title: Text(t.calcDestination.surgeStartAtB2B), trailing: SizedBox(width: 90.0, child: TextField( keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], @@ -575,7 +575,7 @@ class _DestinationCalculatorState extends State { )), ), if (rules.surge) ListTile( - title: Text("Start amount"), + title: Text(t.calcDestination.surgeStartAmount), trailing: SizedBox(width: 90.0, child: TextField( keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], @@ -617,13 +617,13 @@ class _DestinationCalculatorState extends State { if (widget.constraints.maxWidth > 768.0) SegmentedButton( showSelectedIcon: false, segments: >[ - const ButtonSegment( + ButtonSegment( value: CalcCards.calc, - label: Text('Stats Calculator'), + label: Text(t.calcNavigation.stats), ), ButtonSegment( value: CalcCards.damage, - label: Text('Damage Calculator'), + label: Text(t.calcNavigation.damage), ), ], selected: {calcCard}, diff --git a/lib/views/destination_cutoffs.dart b/lib/views/destination_cutoffs.dart index 945bd81..564c6f5 100644 --- a/lib/views/destination_cutoffs.dart +++ b/lib/views/destination_cutoffs.dart @@ -5,6 +5,7 @@ import 'package:syncfusion_flutter_gauges/gauges.dart'; import 'package:tetra_stats/data_objects/cutoff_tetrio.dart'; import 'package:tetra_stats/data_objects/tetrio_constants.dart'; import 'package:tetra_stats/data_objects/tetrio_player_from_leaderboard.dart'; +import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/main.dart'; import 'package:tetra_stats/utils/numers_formats.dart'; import 'package:tetra_stats/utils/text_shadow.dart'; @@ -75,8 +76,8 @@ class _DestinationCutoffsState extends State { padding: const EdgeInsets.only(bottom: 8.0), child: Column( children: [ - Text("Tetra League State", style: Theme.of(context).textTheme.titleLarge), - Text("as of ${timestamp(snapshot.data!.timestamp)}"), + Text(t.cutoffsDestination.title, style: Theme.of(context).textTheme.titleLarge), + Text(t.cutoffsDestination.relevance(timestamp: timestamp(snapshot.data!.timestamp))), ], ), )), @@ -94,9 +95,9 @@ class _DestinationCutoffsState extends State { children: [ Padding( padding: const EdgeInsets.only(bottom: 12.0), - child: Text("Actual"), + child: Text(t.cutoffsDestination.actual), ), - Text("Target") + Text(t.cutoffsDestination.target) ] ), ), @@ -177,42 +178,42 @@ class _DestinationCutoffsState extends State { children: [ TableRow( children: [ - Text("Rank", textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), - const Padding( + Text(t.rank, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), + Padding( padding: EdgeInsets.only(right: 8.0), - child: Text("Cutoff TR", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.cutoffsDestination.cutoffTR, textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), ), - const Padding( + Padding( padding: EdgeInsets.only(right: 8.0), - child: Text("Target TR", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 24, fontWeight: FontWeight.w100, color: Colors.white)), + child: Text(t.cutoffsDestination.targetTR, textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 24, fontWeight: FontWeight.w100, color: Colors.white)), ), Padding( padding: const EdgeInsets.only(right: 8.0), - child: Text("State", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.cutoffsDestination.state, textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), ), - const Padding( + Padding( padding: EdgeInsets.only(right: 8.0), - child: Text("APM", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.stats.apm.short, textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), ), - const Padding( + Padding( padding: EdgeInsets.only(right: 8.0), - child: Text("PPS", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.stats.pps.short, textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), ), - const Padding( + Padding( padding: EdgeInsets.only(right: 8.0), - child: Text("VS", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.stats.vs.short, textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), ), - const Padding( + Padding( padding: EdgeInsets.only(right: 8.0), - child: Text("Advanced", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.cutoffsDestination.advanced, textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), ), Padding( padding: const EdgeInsets.only(right: 8.0), - child: Text("Players (${intf.format(snapshot.data!.total)})", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.cutoffsDestination.players(n: intf.format(snapshot.data!.total)), textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), ), Padding( padding: const EdgeInsets.only(right: 8.0), - child: TextButton(child: Text("More Info", textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500)), onPressed: () { + child: TextButton(child: Text(t.cutoffsDestination.moreInfo, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500)), onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (context) => RankView(rank: "", nextRankTR: snapshot.data!.data["top1"]!.tr, nextRankPercentile: 0.00, nextRankTargetTR: 25000.00, totalPlayers: snapshot.data!.total, cutoffTetrio: CutoffTetrio(apm: 0, pps: 0, vs: 0, pos: 0, percentile: 1, count: snapshot.data!.total, countPercentile: 1, tr: snapshot.data!.data["d"]!.tr, targetTr: snapshot.data!.data['d']!.targetTr)), ), @@ -240,11 +241,11 @@ class _DestinationCutoffsState extends State { text: TextSpan( style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: Colors.white, shadows: textShadow), children: [ - if (rank == "x+") TextSpan(text: "№ 1 is ${f2.format(snapshot.data!.data["top1"]!.tr)} TR", style: const TextStyle(color: Colors.white60, shadows: null)) - else TextSpan(text: snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr > snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr ? "Inflated on ${f2.format(snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr - snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr)} TR" : "Not inflated", style: TextStyle(color: snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr > snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr ? Colors.white :Colors.white60, shadows: null)), + if (rank == "x+") TextSpan(text: t.cutoffsDestination.NumberOne(tr: f2.format(snapshot.data!.data["top1"]!.tr)), style: const TextStyle(color: Colors.white60, shadows: null)) + else TextSpan(text: snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr > snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr ? t.cutoffsDestination.inflated(tr: f2.format(snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr - snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr)) : t.cutoffsDestination.notInflated, style: TextStyle(color: snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr > snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr ? Colors.white :Colors.white60, shadows: null)), TextSpan(text: "\n", style: const TextStyle(color: Colors.white60, shadows: null)), - if (rank == "d") TextSpan(text: "Well...", style: const TextStyle(color: Colors.white60, shadows: null)) - else TextSpan(text: snapshot.data!.data[rank]!.tr < snapshot.data!.data[rank]!.targetTr ? "Deflated on ${f2.format(snapshot.data!.data[rank]!.targetTr - snapshot.data!.data[rank]!.tr)} TR" : "Not deflated", style: TextStyle(color: snapshot.data!.data[rank]!.tr < snapshot.data!.data[rank]!.targetTr ? Colors.white : Colors.white60, shadows: null)) + if (rank == "d") TextSpan(text: t.cutoffsDestination.wellDotDotDot, style: const TextStyle(color: Colors.white60, shadows: null)) + else TextSpan(text: snapshot.data!.data[rank]!.tr < snapshot.data!.data[rank]!.targetTr ? t.cutoffsDestination.deflated(tr: f2.format(snapshot.data!.data[rank]!.targetTr - snapshot.data!.data[rank]!.tr)) : t.cutoffsDestination.notDeflated, style: TextStyle(color: snapshot.data!.data[rank]!.tr < snapshot.data!.data[rank]!.targetTr ? Colors.white : Colors.white60, shadows: null)) ] )), ), @@ -262,7 +263,7 @@ class _DestinationCutoffsState extends State { ), Padding( padding: const EdgeInsets.only(right: 8.0), - child: Text("${snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.pps != null ? f3.format(snapshot.data!.data[rank]!.apm! / (snapshot.data!.data[rank]!.pps! * 60)) : "-.---"} APP\n${snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.vs != null ? f3.format(snapshot.data!.data[rank]!.vs! / snapshot.data!.data[rank]!.apm!) : "-.---"} VS/APM", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.pps != null && snapshot.data?.data[rank]?.vs != null ? Colors.white : Colors.grey, shadows: textShadow)), + child: Text("${snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.pps != null ? f3.format(snapshot.data!.data[rank]!.apm! / (snapshot.data!.data[rank]!.pps! * 60)) : "-.---"} ${t.stats.app.short}\n${snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.vs != null ? f3.format(snapshot.data!.data[rank]!.vs! / snapshot.data!.data[rank]!.apm!) : "-.---"} ${t.stats.vsapm.short}", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.pps != null && snapshot.data?.data[rank]?.vs != null ? Colors.white : Colors.grey, shadows: textShadow)), ), Padding( padding: const EdgeInsets.only(right: 8.0), @@ -273,13 +274,13 @@ class _DestinationCutoffsState extends State { children: [ TextSpan(text: intf.format(snapshot.data!.data[rank]!.count)), TextSpan(text: " (${f2.format(snapshot.data!.data[rank]!.countPercentile * 100)}%)", style: const TextStyle(color: Colors.white60, shadows: null)), - TextSpan(text: "\n(from № ${intf.format(snapshot.data!.data[rank]!.pos)})", style: const TextStyle(color: Colors.white60, shadows: null)) + TextSpan(text: "\n(${t.cutoffsDestination.fromPlace(n: intf.format(snapshot.data!.data[rank]!.pos))})", style: const TextStyle(color: Colors.white60, shadows: null)) ] )) ), Padding( padding: const EdgeInsets.only(right: 8.0), - child: TextButton(child: Text("View", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500)), onPressed: () { + child: TextButton(child: Text(t.cutoffsDestination.viewButton, textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500)), onPressed: () { Navigator.push(context, MaterialPageRoute(maintainState: true, builder: (context) => RankView(rank: rank, nextRankTR: rank == "x+" ? snapshot.data!.data["top1"]!.tr : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr, nextRankPercentile: rank == "x+" ? 0.00 : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.percentile, nextRankTargetTR: rank == "x+" ? 25000.00 : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr, totalPlayers: snapshot.data!.total, cutoffTetrio: snapshot.data!.data[rank]!), ), diff --git a/lib/views/destination_graphs.dart b/lib/views/destination_graphs.dart index 31561b0..9d8e23f 100644 --- a/lib/views/destination_graphs.dart +++ b/lib/views/destination_graphs.dart @@ -76,7 +76,7 @@ class _DestinationGraphsState extends State { style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 20), ), ), - Text(_gamesPlayedInsteadOfDateAndTime ? t.gamesPlayed(games: t.games(n: data.gamesPlayed)) : timestamp(data.timestamp)) + Text(_gamesPlayedInsteadOfDateAndTime ? t.graphsDestination.gamesPlayed(games: t.stats.games(n: data.gamesPlayed)) : timestamp(data.timestamp)) ], ), ); @@ -145,9 +145,9 @@ class _DestinationGraphsState extends State { if(fetchHistory){ try{ var history = await teto.fetchAndsaveTLHistory(widget.searchFor); - if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.fetchAndsaveTLHistoryResult(number: history.length)))); + if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.graphsDestination.fetchAndsaveTLHistoryResult(number: history.length)))); }on TetrioHistoryNotExist{ - if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.noHistorySaved))); + if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.noHistorySaved))); }on P1nkl0bst3rForbidden { if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.errors.p1nkl0bst3rForbidden))); }on P1nkl0bst3rInternalProblem { @@ -208,7 +208,7 @@ class _DestinationGraphsState extends State { return const Center(child: CircularProgressIndicator()); case ConnectionState.done: if (snapshot.hasData){ - if (snapshot.data!.isEmpty || !snapshot.data!.containsKey(_season)) return ErrorThingy(eText: "Not enough data"); + if (snapshot.data!.isEmpty || !snapshot.data!.containsKey(_season)) return ErrorThingy(eText: t.errors.notEnoughData); List<_HistoryChartSpot> selectedGraph = snapshot.data![_season]![Ychart]!; yAxisTitle = chartsShortTitles[Ychart]!; return SfCartesianChart( @@ -394,7 +394,7 @@ class _DestinationGraphsState extends State { if (graph == Graph.history) Row( mainAxisSize: MainAxisSize.min, children: [ - const Padding(padding: EdgeInsets.all(8.0), child: Text("Season:", style: TextStyle(fontSize: 22))), + Padding(padding: EdgeInsets.all(8.0), child: Text("${t.season}:", style: TextStyle(fontSize: 22))), DropdownButton( items: [for (int i = 1; i <= currentSeason; i++) DropdownMenuItem(value: i-1, child: Text("$i"))], value: _season, @@ -412,7 +412,7 @@ class _DestinationGraphsState extends State { const Padding(padding: EdgeInsets.all(8.0), child: Text("X:", style: TextStyle(fontSize: 22))), DropdownButton( items: switch (graph){ - Graph.history => [DropdownMenuItem(value: false, child: Text("Date & Time")), DropdownMenuItem(value: true, child: Text("Games Played"))], + Graph.history => [DropdownMenuItem(value: false, child: Text(t.graphsDestination.dateAndTime)), DropdownMenuItem(value: true, child: Text(t.stats.gp.full))], Graph.leagueState => _yAxis, Graph.leagueCutoffs => [], }, @@ -462,11 +462,11 @@ class _DestinationGraphsState extends State { return StatefulBuilder( builder: (context, StateSetter setAlertState) { return AlertDialog( - title: Text("Filter ranks on graph", textAlign: TextAlign.center), + title: Text(t.graphsDestination.filterModaleTitle, textAlign: TextAlign.center), content: SingleChildScrollView( child: Column( children: [ - CheckboxListTile(value: getTotalFilterValue(), tristate: true, title: Text("All", style: TextStyle(fontFamily: "Eurostile Round Extended")), onChanged: (value){ + CheckboxListTile(value: getTotalFilterValue(), tristate: true, title: Text(t.filterModale.all, style: TextStyle(fontFamily: "Eurostile Round Extended")), onChanged: (value){ setAlertState( (){ if (excludeRanks.length*2 > ranks.length){ @@ -493,9 +493,13 @@ class _DestinationGraphsState extends State { ), actions: [ TextButton( - child: const Text("Apply"), + child: Text(t.actions.cancel), + onPressed: () {Navigator.of(context).pop();} + ), + TextButton( + child: Text(t.actions.apply), onPressed: () {Navigator.of(context).pop(); setState((){futureLeague = getTetraLeagueData(_Xchart, Ychart);});} - ) + ) ] ); } @@ -524,15 +528,15 @@ class _DestinationGraphsState extends State { if (!widget.noSidebar) SegmentedButton( showSelectedIcon: false, segments: >[ - const ButtonSegment( + ButtonSegment( value: Graph.history, - label: Text('Player History')), + label: Text(t.graphsNavigation.history)), ButtonSegment( value: Graph.leagueState, - label: Text('League State')), + label: Text(t.graphsNavigation.league)), ButtonSegment( value: Graph.leagueCutoffs, - label: Text('League Cutoffs'), + label: Text(t.graphsNavigation.cutoffs), ), ], selected: {graph}, diff --git a/lib/views/destination_home.dart b/lib/views/destination_home.dart index 8157533..b66d704 100644 --- a/lib/views/destination_home.dart +++ b/lib/views/destination_home.dart @@ -57,61 +57,61 @@ Cards rightCard = Cards.overview; CardMod cardMod = CardMod.info; Map>> modeButtons = { Cards.overview: [ - const ButtonSegment( + ButtonSegment( value: CardMod.info, - label: Text('General'), + label: Text(t.general), ), ], Cards.tetraLeague: [ - const ButtonSegment( + ButtonSegment( value: CardMod.info, - label: Text('Standing'), + label: Text(t.homeNavigation.standing), ), - const ButtonSegment( + ButtonSegment( value: CardMod.ex, // yeah i misusing my own Enum shut the fuck up - label: Text('Seasons'), + label: Text(t.homeNavigation.seasons), ), - const ButtonSegment( + ButtonSegment( value: CardMod.records, - label: Text('Matches'), + label: Text(t.homeNavigation.mathces), ), ], Cards.quickPlay: [ - const ButtonSegment( + ButtonSegment( value: CardMod.info, - label: Text('Normal'), + label: Text(t.homeNavigation.normal), ), - const ButtonSegment( + ButtonSegment( value: CardMod.records, - label: Text('Records'), + label: Text(t.records), ), - const ButtonSegment( + ButtonSegment( value: CardMod.ex, - label: Text('Expert'), + label: Text(t.homeNavigation.expert), ), - const ButtonSegment( + ButtonSegment( value: CardMod.exRecords, - label: Text('Ex Records'), + label: Text(t.homeNavigation.expertRecords), ) ], Cards.blitz: [ - const ButtonSegment( + ButtonSegment( value: CardMod.info, - label: Text('PB'), + label: Text(t.homeNavigation.pb), ), - const ButtonSegment( + ButtonSegment( value: CardMod.records, - label: Text('Records'), + label: Text(t.recent), ) ], Cards.sprint: [ - const ButtonSegment( + ButtonSegment( value: CardMod.info, - label: Text('PB'), + label: Text(t.homeNavigation.pb), ), - const ButtonSegment( + ButtonSegment( value: CardMod.records, - label: Text('Records'), + label: Text(t.recent), ) ] }; @@ -140,7 +140,7 @@ class ZenithCard extends StatelessWidget { fontSize: 65, height: 1.2, )), - const Positioned(left: 25, top: 20, child: Text("otal time", style: TextStyle(fontFamily: "Eurostile Round Extended"))), + Positioned(left: 25, top: 20, child: Text(t.stats.totalTime.widgetTitle, style: TextStyle(fontFamily: "Eurostile Round Extended"))), Padding( padding: const EdgeInsets.only(left: 10.0), child: Text(getMoreNormalTime(record!.stats.finalTime), style: const TextStyle( @@ -160,11 +160,11 @@ class ZenithCard extends StatelessWidget { 0: FixedColumnWidth(36) }, children: [ - const TableRow( + TableRow( children: [ - Text("Floor"), - Text("Split", textAlign: TextAlign.right), - Text("Total", textAlign: TextAlign.right), + Text(t.stats.floor), + Text(t.stats.split, textAlign: TextAlign.right), + Text(t.stats.total, textAlign: TextAlign.right), ] ), for (int i = 0; i < record!.stats.zenith!.splits.length; i++) TableRow( @@ -196,7 +196,7 @@ class ZenithCard extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text(t.quickPlay, style: Theme.of(context).textTheme.titleLarge), + Text(t.gamemodes["zenith"]!, style: Theme.of(context).textTheme.titleLarge), //Text("Leaderboard reset in ${countdown(postSeasonLeft)}", textAlign: TextAlign.center), ], ), @@ -307,7 +307,7 @@ class RecordCard extends StatelessWidget { )), if (record!.rank != -1) TextSpan(text: "№ ${intf.format(record!.rank)}", style: TextStyle(color: getColorOfRank(record!.rank))), if (record!.rank != -1) const TextSpan(text: " • "), - if (record!.countryRank != -1) TextSpan(text: "№ ${intf.format(record!.countryRank)} local", style: TextStyle(color: getColorOfRank(record!.countryRank))), + if (record!.countryRank != -1) TextSpan(text: "№ ${intf.format(record!.countryRank)} ${t.localStanding}", style: TextStyle(color: getColorOfRank(record!.countryRank))), if (record!.countryRank != -1) const TextSpan(text: " • "), TextSpan(text: timestamp(record!.timestamp)), ] @@ -332,15 +332,15 @@ class RecordCard extends StatelessWidget { _ => "What if " }, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)), Text(switch(record!.gamemode){ - "40l" => " Pieces", - "blitz" => " Level", - "5mblast" => " SPP", + "40l" => " ${t.stats.pieces.full}", + "blitz" => " ${t.stats.level.full}", + "5mblast" => " ${t.stats.spp.short}", _ => " i wanted to" }, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)), ]), TableRow(children: [ Text(f2.format(record!.stats.pps), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)), - const Text(" PPS", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)), + Text(" ${t.stats.pps.short}", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)), ]), TableRow(children: [ Text(switch(record!.gamemode){ @@ -350,9 +350,9 @@ class RecordCard extends StatelessWidget { _ => "but god said" }, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)), Text(switch(record!.gamemode){ - "40l" => " KPP", - "blitz" => " SPP", - "5mblast" => " Pieces", + "40l" => " ${t.stats.kpp.short}", + "blitz" => " ${t.stats.spp.short}", + "5mblast" => " ${t.stats.pieces.short}", _ => " no" }, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)), ]) @@ -365,11 +365,11 @@ class RecordCard extends StatelessWidget { children: [ TableRow(children: [ Text(intf.format(record!.stats.inputs), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)), - const Text(" Key presses", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)), + Text(" ${t.stats.kp.short}", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)), ]), TableRow(children: [ Text(f2.format(record!.stats.kps), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)), - const Text(" KPS", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)), + Text(" ${t.stats.kps.short}", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)), ]), TableRow(children: [ Text(switch(record!.gamemode){ @@ -380,8 +380,8 @@ class RecordCard extends StatelessWidget { }, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)), Text(switch(record!.gamemode){ "40l" => " ", - "blitz" => " Pieces", - "5mblast" => " Pieces", + "blitz" => " ${t.stats.pieces.short}", + "5mblast" => " ${t.stats.pieces.short}", _ => " no" }, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)), ]) @@ -402,7 +402,7 @@ class RecordCard extends StatelessWidget { children: [ FinesseThingy(record!.stats.finesse, record!.stats.finessePercentage), LineclearsThingy(record!.stats.clears, record!.stats.lines, record!.stats.holds, record!.stats.tSpins), - if (record!.gamemode == 'blitz') Text("${f2.format(record!.stats.kpp)} KPP") + if (record!.gamemode == 'blitz') Text("${f2.format(record!.stats.kpp)} ${t.stats.kpp.short}") ], ), ), @@ -412,8 +412,8 @@ class RecordCard extends StatelessWidget { @override Widget build(BuildContext context) { if (record == null) { - return const Card( - child: Center(child: Text("No record", style: TextStyle(fontSize: 42))), + return Card( + child: Center(child: Text(t.noRecord, style: TextStyle(fontSize: 42))), ); } return Column( @@ -427,9 +427,9 @@ class RecordCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ Text(switch(record!.gamemode){ - "40l" => t.sprint, - "blitz" => t.blitz, - "5mblast" => "5,000,000 Blast", + "40l" => t.gamemodes["40l"]!, + "blitz" => t.gamemodes["blitz"]!, + "5mblast" => t.gamemodes["5mblast"]!, _ => record!.gamemode }, style: Theme.of(context).textTheme.titleLarge) ], @@ -516,7 +516,7 @@ class RecordSummary extends StatelessWidget{ "blitz" => readableIntDifference(record!.stats.score, blitzAverages[rank]!), _ => record!.stats.score.toString() }, verdict: betterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle( - color: betterThanClosestAverage??false ? Colors.greenAccent : Colors.redAccent + color: betterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent )) else if ((rank == null || rank == "z") && closestAverage != null) TextSpan(text: "${t.verdictGeneral(n: switch(record!.gamemode){ "40l" => readableTimeDifference(record!.stats.finalTime, closestAverage!.value), @@ -527,7 +527,7 @@ class RecordSummary extends StatelessWidget{ )), if (record!.rank != -1) TextSpan(text: "№ ${intf.format(record!.rank)}", style: TextStyle(color: getColorOfRank(record!.rank))), if (record!.rank != -1 && record!.countryRank != -1) const TextSpan(text: " • "), - if (record!.countryRank != -1) TextSpan(text: "№ ${intf.format(record!.countryRank)} local", style: TextStyle(color: getColorOfRank(record!.countryRank))), + if (record!.countryRank != -1) TextSpan(text: "№ ${intf.format(record!.countryRank)} ${t.localStanding}", style: TextStyle(color: getColorOfRank(record!.countryRank))), const TextSpan(text: "\n"), TextSpan(text: timestamp(record!.timestamp)), ] @@ -609,11 +609,11 @@ class AchievementSummary extends StatelessWidget{ style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey), children: [ if (achievement!.object.isNotEmpty) TextSpan(text: "${achievement!.object}\n"), - if (achievement!.vt == 4) TextSpan(text: "Floor ${achievement?.a != null ? achievement!.a! : "-"}"), + if (achievement!.vt == 4) TextSpan(text: "${t.stats.floor} ${achievement?.a != null ? achievement!.a! : "-"}"), if (achievement!.vt == 4) TextSpan(text: " • "), if (achievement!.vt != 5) TextSpan(text: (achievement?.pos != null && !achievement!.pos!.isNegative) ? "№ ${intf.format(achievement!.pos!+1)}" : "№ ---", style: TextStyle(color: achievement?.pos != null ? getColorOfRank(achievement!.pos!+1) : Colors.grey)), if (achievement!.vt != 5) TextSpan(text: " • ", style: TextStyle(color: achievement?.pos != null ? getColorOfRank(achievement!.pos!+1) : Colors.grey)), - TextSpan(text: "Top ${achievement?.pos != null ? percentagef4.format(achievement!.pos! / achievement!.total!) : "---%"}", style: TextStyle(color: achievement?.pos != null ? getColorOfRank(achievement!.pos!+1) : Colors.grey)), + TextSpan(text: t.stats.top(percentage: achievement?.pos != null ? percentagef4.format(achievement!.pos! / achievement!.total!) : "---"), style: TextStyle(color: achievement?.pos != null ? getColorOfRank(achievement!.pos!+1) : Colors.grey)), ] ), ), @@ -653,7 +653,7 @@ class LeagueCard extends StatelessWidget{ crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [ - Text("Season ${league.season}", style: Theme.of(context).textTheme.titleSmall), + Text("${t.season} ${league.season}", style: Theme.of(context).textTheme.titleSmall), Spacer(), Text( "${seasonStarts.elementAtOrNull(league.season - 1) != null ? timestamp(seasonStarts[league.season - 1]) : "---"} — ${seasonEnds.elementAtOrNull(league.season - 1) != null ? timestamp(seasonEnds[league.season - 1]) : "---"}", @@ -663,14 +663,14 @@ class LeagueCard extends StatelessWidget{ ) : Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Season ${league.season}", style: Theme.of(context).textTheme.titleSmall), + Text("${t.season} ${league.season}", style: Theme.of(context).textTheme.titleSmall), Text( "${seasonStarts.elementAtOrNull(league.season - 1) != null ? timestamp(seasonStarts[league.season - 1]) : "---"} — ${seasonEnds.elementAtOrNull(league.season - 1) != null ? timestamp(seasonEnds[league.season - 1]) : "---"}", textAlign: TextAlign.center, style: TextStyle(color: Colors.grey)), ], ) - else Text("Tetra League", style: Theme.of(context).textTheme.titleSmall), + else Text(t.gamemodes["league"]!, style: Theme.of(context).textTheme.titleSmall), const Divider(), TLRatingThingy(userID: league.id, tlData: league, showPositions: true), const Divider(), @@ -679,15 +679,15 @@ class LeagueCard extends StatelessWidget{ text: TextSpan( style: const TextStyle(fontFamily: "Eurostile Round", color: Colors.grey), children: [ - TextSpan(text: "${league.apm != null ? f2.format(league.apm) : "-.--"} APM", style: TextStyle(color: league.apm != null ? getStatColor(league.apm!, averages?.apm, true) : null)), + TextSpan(text: "${league.apm != null ? f2.format(league.apm) : "-.--"} ${t.stats.apm.short}", style: TextStyle(color: league.apm != null ? getStatColor(league.apm!, averages?.apm, true) : null)), TextSpan(text: " • "), - TextSpan(text: "${league.pps != null ? f2.format(league.pps) : "-.--"} PPS", style: TextStyle(color: league.pps != null ? getStatColor(league.pps!, averages?.pps, true) : null)), + TextSpan(text: "${league.pps != null ? f2.format(league.pps) : "-.--"} ${t.stats.pps.short}", style: TextStyle(color: league.pps != null ? getStatColor(league.pps!, averages?.pps, true) : null)), TextSpan(text: " • "), - TextSpan(text: "${league.vs != null ? f2.format(league.vs) : "-.--"} VS", style: TextStyle(color: league.vs != null ? getStatColor(league.vs!, averages?.vs, true) : null)), + TextSpan(text: "${league.vs != null ? f2.format(league.vs) : "-.--"} ${t.stats.vs.short}", style: TextStyle(color: league.vs != null ? getStatColor(league.vs!, averages?.vs, true) : null)), TextSpan(text: " • "), - TextSpan(text: "${league.nerdStats != null ? f2.format(league.nerdStats!.app) : "-.--"} APP", style: TextStyle(color: league.nerdStats != null ? getStatColor(league.nerdStats!.app, averages?.nerdStats?.app, true) : null)), + TextSpan(text: "${league.nerdStats != null ? f2.format(league.nerdStats!.app) : "-.--"} ${t.stats.app.short}", style: TextStyle(color: league.nerdStats != null ? getStatColor(league.nerdStats!.app, averages?.nerdStats?.app, true) : null)), TextSpan(text: " • "), - TextSpan(text: "${league.nerdStats != null ? f2.format(league.nerdStats!.vsapm) : "-.--"} VS/APM", style: TextStyle(color: league.nerdStats != null ? getStatColor(league.nerdStats!.vsapm, averages?.nerdStats?.vsapm, true) : null)), + TextSpan(text: "${league.nerdStats != null ? f2.format(league.nerdStats!.vsapm) : "-.--"} ${t.stats.vsapm.short}", style: TextStyle(color: league.nerdStats != null ? getStatColor(league.nerdStats!.vsapm, averages?.nerdStats?.vsapm, true) : null)), ] )), ], @@ -712,7 +712,6 @@ class _DestinationHomeState extends State with SingleTickerProv Widget getOverviewCard(Summaries summaries, CutoffTetrio? averages, double width){ return LayoutGrid( - // ASCII-art named areas 🔥 areas: width > 600 ? ''' h h t t @@ -730,13 +729,10 @@ class _DestinationHomeState extends State with SingleTickerProv 6 7 ''', - // Concise track sizing extension methods 🔥 columnSizes: width > 600 ? [auto, auto] : [auto], rowSizes: width > 600 ? [auto, auto, auto, auto, auto, auto] : [auto, auto, auto, auto, auto, auto, auto, auto], - // Column and row gaps! 🔥 columnGap: 0, rowGap: 0, - // Handy grid placement extension methods on Widget 🔥 children: [ if (width > 600) Card( child: Padding( @@ -746,7 +742,7 @@ class _DestinationHomeState extends State with SingleTickerProv mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Overview", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)), + Text(t.homeNavigation.overview, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)), ], ), ), @@ -759,7 +755,7 @@ class _DestinationHomeState extends State with SingleTickerProv child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("40 Lines", style: Theme.of(context).textTheme.titleSmall), + Text(t.gamemodes['40l']!, style: Theme.of(context).textTheme.titleSmall), const Divider(), RecordSummary(record: summaries.sprint, betterThanClosestAverage: sprintBetterThanClosestAverage, betterThanRankAverage: sprintBetterThanRankAverage, closestAverage: closestAverageSprint, rank: summaries.league.percentileRank), const Divider(), @@ -774,7 +770,7 @@ class _DestinationHomeState extends State with SingleTickerProv child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Blitz", style: Theme.of(context).textTheme.titleSmall), + Text(t.gamemodes['blitz']!, style: Theme.of(context).textTheme.titleSmall), const Divider(), RecordSummary(record: summaries.blitz, betterThanClosestAverage: blitzBetterThanClosestAverage, betterThanRankAverage: blitzBetterThanRankAverage, closestAverage: closestAverageBlitz, rank: summaries.league.percentileRank), const Divider(), @@ -789,11 +785,11 @@ class _DestinationHomeState extends State with SingleTickerProv child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("QP", style: Theme.of(context).textTheme.titleSmall), + Text(t.gamemodes['zenith']!, style: Theme.of(context).textTheme.titleSmall), const Divider(), RecordSummary(record: summaries.zenith != null ? summaries.zenith : summaries.zenithCareerBest, hideRank: true, old: summaries.zenith == null), const Divider(), - Text("Overall PB: ${(summaries.achievements.isNotEmpty && summaries.achievements.firstWhere((e) => e.k == 18).v != null) ? f2.format(summaries.achievements.firstWhere((e) => e.k == 18).v!) : "-.--"} m", style: const TextStyle(color: Colors.grey)) + Text(t.overallPB(pb: (summaries.achievements.isNotEmpty && summaries.achievements.firstWhere((e) => e.k == 18).v != null) ? f2.format(summaries.achievements.firstWhere((e) => e.k == 18).v!) : "-.--"), style: const TextStyle(color: Colors.grey)) ], ), ), @@ -804,11 +800,11 @@ class _DestinationHomeState extends State with SingleTickerProv child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("QP Expert", style: Theme.of(context).textTheme.titleSmall), + Text(t.gamemodes['zenithex']!, style: Theme.of(context).textTheme.titleSmall), const Divider(), RecordSummary(record: summaries.zenithEx != null ? summaries.zenithEx : summaries.zenithExCareerBest, hideRank: true, old: summaries.zenith == null), const Divider(), - Text("Overall PB: ${(summaries.achievements.isNotEmpty && summaries.achievements.firstWhere((e) => e.k == 19).v != null) ? f2.format(summaries.achievements.firstWhere((e) => e.k == 19).v!) : "-.--"} m", style: const TextStyle(color: Colors.grey)) + Text(t.overallPB(pb: (summaries.achievements.isNotEmpty && summaries.achievements.firstWhere((e) => e.k == 19).v != null) ? f2.format(summaries.achievements.firstWhere((e) => e.k == 19).v!) : "-.--"), style: const TextStyle(color: Colors.grey)) ], ), ), @@ -819,10 +815,10 @@ class _DestinationHomeState extends State with SingleTickerProv child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Center(child: Text("Zen", style: Theme.of(context).textTheme.titleSmall)), - Text("Level ${intf.format(summaries.zen.level)}", style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white)), - Text("Score ${intf.format(summaries.zen.score)}"), - Text("Level up requirement: ${intf.format(summaries.zen.scoreRequirement)}", style: const TextStyle(color: Colors.grey)) + Center(child: Text(t.gamemodes['zen']!, style: Theme.of(context).textTheme.titleSmall)), + Text("${t.stats.level.full} ${intf.format(summaries.zen.level)}", style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white)), + Text("${t.stats.score} ${intf.format(summaries.zen.score)}"), + Text(t.stats.levelUpRequirement(p: intf.format(summaries.zen.scoreRequirement)), style: const TextStyle(color: Colors.grey)) ], ), ), @@ -841,7 +837,7 @@ class _DestinationHomeState extends State with SingleTickerProv fontSize: 65, height: 1.2, )), - const Positioned(left: 25, top: 20, child: Text("inesse", style: TextStyle(fontFamily: "Eurostile Round Extended"))), + Positioned(left: 25, top: 20, child: Text(t.stats.finesse.widgetTitle, style: TextStyle(fontFamily: "Eurostile Round Extended"))), Padding( padding: const EdgeInsets.only(left: 10.0), child: Text("${(summaries.achievements.isNotEmpty && summaries.achievements.firstWhere((e) => e.k == 4).v != null && summaries.achievements.firstWhere((e) => e.k == 1).v != null) ? @@ -857,14 +853,14 @@ class _DestinationHomeState extends State with SingleTickerProv ), Row( children: [ - const Text("Total pieces placed:"), + Text("${t.stats.piecesTotal}:"), const Spacer(), Text((summaries.achievements.isNotEmpty && summaries.achievements.firstWhere((e) => e.k == 1).v != null) ? intf.format(summaries.achievements.firstWhere((e) => e.k == 1).v!) : "---"), ], ), Row( children: [ - const Text(" - Placed with perfect finesse:"), + Text(" - ${t.stats.piecesWithPerfectFinesse}:"), const Spacer(), Text((summaries.achievements.isNotEmpty && summaries.achievements.firstWhere((e) => e.k == 4).v != null) ? intf.format(summaries.achievements.firstWhere((e) => e.k == 4).v!) : "---"), ], @@ -873,7 +869,7 @@ class _DestinationHomeState extends State with SingleTickerProv ), ), ).inGridArea('6'), - Card( + if (summaries.achievements.isNotEmpty) Card( child: Padding( padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0), child: Column( @@ -913,7 +909,7 @@ class _DestinationHomeState extends State with SingleTickerProv mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text(t.tetraLeague, style: Theme.of(context).textTheme.titleLarge), + Text(t.gamemodes["league"]!, style: Theme.of(context).textTheme.titleLarge), //Text("${states.last.timestamp} ${states.last.tr}", textAlign: TextAlign.center) ], ), @@ -949,7 +945,7 @@ class _DestinationHomeState extends State with SingleTickerProv mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Previous Seasons", style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center), + Text(t.previousSeasons, style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center), //Text("${t.seasonStarts} ${countdown(postSeasonLeft)}", textAlign: TextAlign.center) ], ), @@ -966,7 +962,7 @@ class _DestinationHomeState extends State with SingleTickerProv Widget getListOfRecords(String recentStream, String topStream, BoxConstraints constraints){ return Column( children: [ - const Card( + Card( child: Padding( padding: EdgeInsets.only(bottom: 4.0), child: Center( @@ -974,7 +970,7 @@ class _DestinationHomeState extends State with SingleTickerProv mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text("Records", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)), + Text(t.records, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)), //Text("${t.seasonStarts} ${countdown(postSeasonLeft)}", textAlign: TextAlign.center) ], ), @@ -987,10 +983,10 @@ class _DestinationHomeState extends State with SingleTickerProv child: Column( mainAxisSize: MainAxisSize.min, children: [ - const TabBar( + TabBar( tabs: [ - Tab(text: "Recent"), - Tab(text: "Top"), + Tab(text: t.recent), + Tab(text: t.top), ], ), SizedBox( @@ -1026,10 +1022,10 @@ class _DestinationHomeState extends State with SingleTickerProv title: Text( switch (snapshot.data!.records[i].gamemode){ "40l" => get40lTime(snapshot.data!.records[i].stats.finalTime.inMicroseconds), - "blitz" => t.blitzScore(p: NumberFormat.decimalPattern().format(snapshot.data!.records[i].stats.score)), + "blitz" => t.stats.blitzScore(p: NumberFormat.decimalPattern().format(snapshot.data!.records[i].stats.score)), "5mblast" => get40lTime(snapshot.data!.records[i].stats.finalTime.inMicroseconds), - "zenith" => "${f2.format(snapshot.data!.records[i].stats.zenith!.altitude)} m${(snapshot.data!.records[i].extras as ZenithExtras).mods.isNotEmpty ? " (${t.withModsPlural(n: (snapshot.data!.records[i].extras as ZenithExtras).mods.length)})" : ""}", - "zenithex" => "${f2.format(snapshot.data!.records[i].stats.zenith!.altitude)} m${(snapshot.data!.records[i].extras as ZenithExtras).mods.isNotEmpty ? " (${t.withModsPlural(n: (snapshot.data!.records[i].extras as ZenithExtras).mods.length)})" : ""}", + "zenith" => "${f2.format(snapshot.data!.records[i].stats.zenith!.altitude)} m${(snapshot.data!.records[i].extras as ZenithExtras).mods.isNotEmpty ? " (${t.stats.qpWithMods(n: (snapshot.data!.records[i].extras as ZenithExtras).mods.length)})" : ""}", + "zenithex" => "${f2.format(snapshot.data!.records[i].stats.zenith!.altitude)} m${(snapshot.data!.records[i].extras as ZenithExtras).mods.isNotEmpty ? " (${t.stats.qpWithMods(n: (snapshot.data!.records[i].extras as ZenithExtras).mods.length)})" : ""}", String() => "huh", }, style: Theme.of(context).textTheme.displayLarge), @@ -1067,10 +1063,10 @@ class _DestinationHomeState extends State with SingleTickerProv title: Text( switch (snapshot.data!.records[i].gamemode){ "40l" => get40lTime(snapshot.data!.records[i].stats.finalTime.inMicroseconds), - "blitz" => t.blitzScore(p: NumberFormat.decimalPattern().format(snapshot.data!.records[i].stats.score)), + "blitz" => t.stats.blitzScore(p: NumberFormat.decimalPattern().format(snapshot.data!.records[i].stats.score)), "5mblast" => get40lTime(snapshot.data!.records[i].stats.finalTime.inMicroseconds), - "zenith" => "${f2.format(snapshot.data!.records[i].stats.zenith!.altitude)} m${(snapshot.data!.records[i].extras as ZenithExtras).mods.isNotEmpty ? " (${t.withModsPlural(n: (snapshot.data!.records[i].extras as ZenithExtras).mods.length)})" : ""}", - "zenithex" => "${f2.format(snapshot.data!.records[i].stats.zenith!.altitude)} m${(snapshot.data!.records[i].extras as ZenithExtras).mods.isNotEmpty ? " (${t.withModsPlural(n: (snapshot.data!.records[i].extras as ZenithExtras).mods.length)})" : ""}", + "zenith" => "${f2.format(snapshot.data!.records[i].stats.zenith!.altitude)} m${(snapshot.data!.records[i].extras as ZenithExtras).mods.isNotEmpty ? " (${t.stats.qpWithMods(n: (snapshot.data!.records[i].extras as ZenithExtras).mods.length)})" : ""}", + "zenithex" => "${f2.format(snapshot.data!.records[i].stats.zenith!.altitude)} m${(snapshot.data!.records[i].extras as ZenithExtras).mods.isNotEmpty ? " (${t.stats.qpWithMods(n: (snapshot.data!.records[i].extras as ZenithExtras).mods.length)})" : ""}", String() => "huh", }, style: Theme.of(context).textTheme.displayLarge), diff --git a/lib/views/destination_info.dart b/lib/views/destination_info.dart index d107d4c..4aab37a 100644 --- a/lib/views/destination_info.dart +++ b/lib/views/destination_info.dart @@ -78,8 +78,8 @@ class _DestinationInfo extends State { height: widget.constraints.maxHeight - 77, viewportWidth: widget.constraints.maxWidth, assetLink: "res/images/info card 1 focus.png", - title: "40 Lines & Blitz Averages", - description: "Since calculating 40 Lines & Blitz averages is tedious process, it gets updated only once in a while. Click on the title of this card to see the full 40 Lines & Blitz averages table\n\n${t.sprintAndBlitsRelevance(date: DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).format(sprintAndBlitzRelevance))}", + title: t.infoDestination.sprintAndBlitzAverages, + description: "${t.infoDestination.sprintAndBlitzAveragesDescription}\n\n${t.sprintAndBlitsRelevance(date: DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).format(sprintAndBlitzRelevance))}", onPressed: (){ Navigator.push(context, MaterialPageRoute( builder: (context) => SprintAndBlitzView(), @@ -90,8 +90,8 @@ class _DestinationInfo extends State { height: widget.constraints.maxHeight - 77, viewportWidth: widget.constraints.maxWidth, assetLink: "res/images/Снимок экрана_2023-11-06_01-00-50.png", - title: "Tetra Stats Wiki", - description: "Find more information about Tetra Stats functions and statictic, that it provides", + title: t.infoDestination.tetraStatsWiki, + description: t.infoDestination.tetraStatsWikiDescription, onPressed: (){ launchInBrowser(Uri.https("github.com", "dan63047/TetraStats/wiki")); } @@ -100,8 +100,8 @@ class _DestinationInfo extends State { height: widget.constraints.maxHeight - 77, viewportWidth: widget.constraints.maxWidth, assetLink: "res/images/Снимок экрана_2023-11-06_01-00-50.png", - title: "About Tetra Stats", - description: "Developed by dan63\n", + title: t.infoDestination.about, + description: t.infoDestination.aboutDescription, onPressed: (){ Navigator.push(context, MaterialPageRoute( builder: (context) => AboutView(), @@ -114,7 +114,7 @@ class _DestinationInfo extends State { mainAxisSize: MainAxisSize.min, children: [ Card( - child: Center(child: Text("Information Center", style: Theme.of(context).textTheme.titleLarge)), + child: Center(child: Text(t.infoDestination.title, style: Theme.of(context).textTheme.titleLarge)), ), SingleChildScrollView( scrollDirection: Axis.horizontal, diff --git a/lib/views/destination_leaderboards.dart b/lib/views/destination_leaderboards.dart index 6b14fda..8a5187d 100644 --- a/lib/views/destination_leaderboards.dart +++ b/lib/views/destination_leaderboards.dart @@ -37,14 +37,14 @@ enum Leaderboards{ class _DestinationLeaderboardsState extends State { //Duration postSeasonLeft = seasonStart.difference(DateTime.now()); final Map leaderboards = { - Leaderboards.tl: "Tetra League (Current Season)", - Leaderboards.fullTL: "Tetra League (Current Season, full one)", - Leaderboards.xp: "XP", - Leaderboards.ar: "Acievement Points", - Leaderboards.sprint: "40 Lines", - Leaderboards.blitz: "Blitz", - Leaderboards.zenith: "Quick Play", - Leaderboards.zenithex: "Quick Play Expert", + Leaderboards.tl: t.leaderboardsDestination.tl, + Leaderboards.fullTL: t.leaderboardsDestination.fullTL, + Leaderboards.xp: t.stats.xp.full, + Leaderboards.ar: t.leaderboardsDestination.ar, + Leaderboards.sprint: t.gamemodes["40l"]!, + Leaderboards.blitz: t.gamemodes["blitz"]!, + Leaderboards.zenith: t.gamemodes["zenith"]!, + Leaderboards.zenithex: t.gamemodes["zenithex"]!, }; Leaderboards _currentLb = Leaderboards.tl; final StreamController> _dataStreamController = StreamController>.broadcast(); @@ -342,7 +342,7 @@ class _DestinationLeaderboardsState extends State { mainAxisSize: MainAxisSize.min, children: [ Spacer(), - Text("Leaderboards", style: Theme.of(context).textTheme.headlineMedium!.copyWith(fontSize: 32)), + Text(t.leaderboardsDestination.title, style: Theme.of(context).textTheme.headlineMedium!.copyWith(fontSize: 32)), Spacer() ], ), @@ -355,7 +355,7 @@ class _DestinationLeaderboardsState extends State { child: ListTile( title: Text(leaderboards.values.elementAt(index)), trailing: Icon(Icons.arrow_right, color: _currentLb.index == index ? Colors.white : Colors.grey), - subtitle: index == 1 ? Text("Heavy, but allows you to sort players by their stats and filter them by ranks", style: TextStyle(color: Colors.grey, fontSize: 12)) : null, + subtitle: index == 1 ? Text(t.leaderboardsDestination.fullTLnote, style: TextStyle(color: Colors.grey, fontSize: 12)) : null, onTap: () { if (widget.constraints.maxWidth <= transformThreshold) Navigator.push( context, @@ -366,7 +366,7 @@ class _DestinationLeaderboardsState extends State { padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), diff --git a/lib/views/destination_saved_data.dart b/lib/views/destination_saved_data.dart index 28e31ab..374b4ae 100644 --- a/lib/views/destination_saved_data.dart +++ b/lib/views/destination_saved_data.dart @@ -42,7 +42,7 @@ class _DestinationSavedData extends State { leading: IconButton( onPressed: () { teto.deleteState(data.id+data.timestamp.millisecondsSinceEpoch.toRadixString(16)).then((value) => setState(() { - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.stateRemoved(date: timestamp(data.timestamp))))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.snackBarMessages.stateRemoved(date: timestamp(data.timestamp))))); })); }, icon: Icon(Icons.delete_forever) @@ -165,7 +165,7 @@ class _DestinationSavedData extends State { padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), diff --git a/lib/views/destination_settings.dart b/lib/views/destination_settings.dart index c3b472c..91436c6 100644 --- a/lib/views/destination_settings.dart +++ b/lib/views/destination_settings.dart @@ -355,9 +355,9 @@ class _DestinationSettings extends State with SingleTickerP trailing: DropdownButton( value: timestampMode, items: [ - DropdownMenuItem(value: 0, child: Text(t.timestampsAbsoluteGMT)), - DropdownMenuItem(value: 1, child: Text(t.timestampsAbsoluteLocalTime)), - DropdownMenuItem(value: 2, child: Text(t.timestampsRelative)) + DropdownMenuItem(value: 0, child: Text(t.settingsDestination.timestampsAbsoluteGMT)), + DropdownMenuItem(value: 1, child: Text(t.settingsDestination.timestampsAbsoluteLocalTime)), + DropdownMenuItem(value: 2, child: Text(t.settingsDestination.timestampsRelative)) ], onChanged: (dynamic value){ prefs.setInt("timestampMode", value); @@ -491,7 +491,7 @@ class _DestinationSettings extends State with SingleTickerP title: Text("Export Database", style: Theme.of(context).textTheme.displayLarge), onTap: () { if (kIsWeb){ - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.notForWeb))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.snackBarMessages.notForWeb))); } else if (Platform.isAndroid){ var downloadFolder = Directory("/storage/emulated/0/Download"); File exportedDB = File("${downloadFolder.path}/TetraStats.db"); @@ -500,15 +500,15 @@ class _DestinationSettings extends State with SingleTickerP showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: Text(t.androidExportAlertTitle, + title: Text(t.settingsDestination.androidExportAlertTitle, style: const TextStyle( fontFamily: "Eurostile Round Extended")), content: SingleChildScrollView( - child: ListBody(children: [Text(t.androidExportText(exportedDB: exportedDB))]), + child: ListBody(children: [Text(t.settingsDestination.androidExportText(exportedDB: exportedDB))]), ), actions: [ TextButton( - child: Text(t.popupActions.ok), + child: Text(t.actions.ok), onPressed: () { Navigator.of(context).pop(); }, @@ -520,17 +520,17 @@ class _DestinationSettings extends State with SingleTickerP showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: Text(t.desktopExportAlertTitle, + title: Text(t.settingsDestination.desktopExportAlertTitle, style: const TextStyle( fontFamily: "Eurostile Round Extended")), content: SingleChildScrollView( child: ListBody(children: [ - Text(t.desktopExportText) + Text(t.settingsDestination.desktopExportText) ]), ), actions: [ TextButton( - child: Text(t.popupActions.ok), + child: Text(t.actions.ok), onPressed: () { Navigator.of(context).pop(); }, @@ -546,7 +546,7 @@ class _DestinationSettings extends State with SingleTickerP title: Text("Import Database", style: Theme.of(context).textTheme.displayLarge), onTap: (){ if (kIsWeb){ - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.notForWeb))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.snackBarMessages.notForWeb))); }else if(Platform.isAndroid){ FilePicker.platform.pickFiles( type: FileType.any, @@ -560,7 +560,7 @@ class _DestinationSettings extends State with SingleTickerP var oldDB = File("${value.path}/TetraStats.db"); oldDB.writeAsBytes(File(newDB).readAsBytesSync()).then((value){ teto.open(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importSuccess))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.snackBarMessages.importSuccess))); }); }); }); @@ -569,7 +569,7 @@ class _DestinationSettings extends State with SingleTickerP } }); } else { - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importCancelled))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.snackBarMessages.importCancelled))); } }); }else{ @@ -587,7 +587,7 @@ class _DestinationSettings extends State with SingleTickerP var oldDB = File("${value.path}/TetraStats.db"); oldDB.writeAsBytes(File(newDB).readAsBytesSync()).then((value){ teto.open(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importSuccess))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.snackBarMessages.importSuccess))); }); }); }); @@ -596,7 +596,7 @@ class _DestinationSettings extends State with SingleTickerP } }); } else { - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importCancelled))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.snackBarMessages.importCancelled))); } }); } @@ -661,7 +661,7 @@ class _DestinationSettings extends State with SingleTickerP padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), diff --git a/lib/views/main_view.dart b/lib/views/main_view.dart index 6548127..22d2569 100644 --- a/lib/views/main_view.dart +++ b/lib/views/main_view.dart @@ -97,12 +97,12 @@ class MainView extends StatefulWidget { enum Cards {overview, tetraLeague, quickPlay, sprint, blitz} enum CardMod {info, records, ex, exRecords} Map cardsTitles = { - Cards.overview: "Overview", - Cards.tetraLeague: t.tetraLeague, - Cards.quickPlay: t.quickPlay, + Cards.overview: t.homeNavigation.overview, + Cards.tetraLeague: t.gamemodes["league"]!, + Cards.quickPlay: t.gamemodes["zenith"]!, //Cards.quickPlayExpert: "${t.quickPlay} ${t.expert}", - Cards.sprint: t.sprint, - Cards.blitz: t.blitz, + Cards.sprint: t.gamemodes["zenith"]!, + Cards.blitz: t.gamemodes["zenithex"]!, //Cards.other: t.other }; diff --git a/lib/views/rank_view.dart b/lib/views/rank_view.dart index 5ef0e25..4e0536a 100644 --- a/lib/views/rank_view.dart +++ b/lib/views/rank_view.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:tetra_stats/data_objects/cutoff_tetrio.dart'; +import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/main.dart'; import 'package:tetra_stats/utils/numers_formats.dart'; import 'package:tetra_stats/widgets/future_error.dart'; @@ -36,70 +37,70 @@ class _RankState extends State { return Column( children: [ Divider(), - Text("Average Stats", style: Theme.of(context).textTheme.displayLarge), - Text("${f2.format(data != null ? data[0].apm : widget.cutoffTetrio.apm)} APM • ${f2.format(data != null ? data[0].pps : widget.cutoffTetrio.pps)} PPS • ${f2.format(data != null ? data[0].vs : widget.cutoffTetrio.vs)} VS", style: Theme.of(context).textTheme.displayLarge), + Text(t.rankView.avgStats, style: Theme.of(context).textTheme.displayLarge), + Text("${f2.format(data != null ? data[0].apm : widget.cutoffTetrio.apm)} ${t.stats.apm.short} • ${f2.format(data != null ? data[0].pps : widget.cutoffTetrio.pps)} ${t.stats.pps.short} • ${f2.format(data != null ? data[0].vs : widget.cutoffTetrio.vs)} ${t.stats.vs.short}", style: Theme.of(context).textTheme.displayLarge), Divider(), - Center(child: Text("Average Nerd Stats", style: Theme.of(context).textTheme.displayLarge)), + Center(child: Text(t.rankView.avgNerdStats, style: Theme.of(context).textTheme.displayLarge)), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Attack Per Piece", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.app.full, style: Theme.of(context).textTheme.displayLarge), Text(f3.format(data != null ? data[1]["avgAPP"] : widget.cutoffTetrio.nerdStats?.app), style: Theme.of(context).textTheme.displayLarge) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("VS / APM", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.vsapm.full, style: Theme.of(context).textTheme.displayLarge), Text(f3.format(data != null ? data[1]["avgVSAPM"] : widget.cutoffTetrio.nerdStats?.vsapm), style: Theme.of(context).textTheme.displayLarge) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Downstack Per Second", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.dss.full, style: Theme.of(context).textTheme.displayLarge), Text(f3.format(data != null ? data[1]["avgDSS"] : widget.cutoffTetrio.nerdStats?.dss), style: Theme.of(context).textTheme.displayLarge) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Downstack Per Piece", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.dsp.full, style: Theme.of(context).textTheme.displayLarge), Text(f3.format(data != null ? data[1]["avgDSP"] : widget.cutoffTetrio.nerdStats?.dsp), style: Theme.of(context).textTheme.displayLarge) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("APP + DSP", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.appdsp.full, style: Theme.of(context).textTheme.displayLarge), Text(f3.format(data != null ? data[1]["avgAPPDSP"] : widget.cutoffTetrio.nerdStats?.appdsp), style: Theme.of(context).textTheme.displayLarge) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Cheese Index", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.cheese.full, style: Theme.of(context).textTheme.displayLarge), Text(f2.format(data != null ? data[1]["avgCheese"] : widget.cutoffTetrio.nerdStats?.cheese), style: Theme.of(context).textTheme.displayLarge) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Garbage Efficiency", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.gbe.full, style: Theme.of(context).textTheme.displayLarge), Text(f3.format(data != null ? data[1]["avgGBE"] : widget.cutoffTetrio.nerdStats?.gbe), style: Theme.of(context).textTheme.displayLarge) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Weighted APP", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.nyaapp.full, style: Theme.of(context).textTheme.displayLarge), Text(f3.format(data != null ? data[1]["avgNyaAPP"] : widget.cutoffTetrio.nerdStats?.nyaapp), style: Theme.of(context).textTheme.displayLarge) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Area", style: Theme.of(context).textTheme.displayLarge), + Text(t.stats.area.full, style: Theme.of(context).textTheme.displayLarge), Text(f1.format(data != null ? data[1]["avgArea"] : widget.cutoffTetrio.nerdStats?.area), style: Theme.of(context).textTheme.displayLarge) ], ), @@ -255,7 +256,7 @@ class _RankState extends State { padding: const EdgeInsets.fromLTRB(8.0, 4.0, 0.0, 0.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), diff --git a/lib/views/singleplayer_record_view.dart b/lib/views/singleplayer_record_view.dart index 0b87728..e6471eb 100644 --- a/lib/views/singleplayer_record_view.dart +++ b/lib/views/singleplayer_record_view.dart @@ -21,7 +21,7 @@ class SingleplayerRecordView extends StatelessWidget { padding: const EdgeInsets.fromLTRB(16.0, 8.0, 0.0, 0.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), diff --git a/lib/views/sprint_and_blitz_averages.dart b/lib/views/sprint_and_blitz_averages.dart index 4ed9a99..aeff773 100644 --- a/lib/views/sprint_and_blitz_averages.dart +++ b/lib/views/sprint_and_blitz_averages.dart @@ -22,16 +22,16 @@ class SprintAndBlitzState extends State { @override void initState() { - if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS){ - windowManager.getTitle().then((value) => oldWindowTitle = value); - windowManager.setTitle("Tetra Stats: ${t.settings}"); - } + // if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS){ + // windowManager.getTitle().then((value) => oldWindowTitle = value); + // windowManager.setTitle("Tetra Stats: ${t.settings}"); + // } super.initState(); } @override void dispose(){ - if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS) windowManager.setTitle(oldWindowTitle); + // if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS) windowManager.setTitle(oldWindowTitle); super.dispose(); } @@ -45,7 +45,7 @@ class SprintAndBlitzState extends State { padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), @@ -73,11 +73,11 @@ class SprintAndBlitzState extends State { Text(t.rank, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), Padding( padding: const EdgeInsets.only(right: 8.0), - child: Text(t.sprint, textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.gamemodes["40l"]!, textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), ), Padding( padding: const EdgeInsets.only(right: 8.0), - child: Text(t.blitz, textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), + child: Text(t.gamemodes["blitz"]!, textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)), ), ] ), diff --git a/lib/views/tl_match_view.dart b/lib/views/tl_match_view.dart index d2bbfda..5ff2c5e 100644 --- a/lib/views/tl_match_view.dart +++ b/lib/views/tl_match_view.dart @@ -1,8 +1,6 @@ // ignore_for_file: use_build_context_synchronously, type_literal_in_constant_pattern import 'dart:io'; -import 'package:tetra_stats/data_objects/beta_league_round.dart'; -import 'package:tetra_stats/data_objects/beta_league_stats.dart'; import 'package:tetra_stats/data_objects/beta_record.dart'; import 'package:tetra_stats/data_objects/tetrio_multiplayer_replay.dart'; import 'package:tetra_stats/utils/relative_timestamps.dart'; @@ -45,60 +43,23 @@ class TlMatchResultState extends State { late String reason; Duration totalTime = const Duration(); List roundLengths = []; - List timeWeightedStats = []; late bool initPlayerWon; @override void initState(){ - rounds = [DropdownMenuItem(value: -1, child: Text(t.match))]; - rounds.addAll([for (int i = 0; i < widget.record.results.rounds.length; i++) DropdownMenuItem(value: i, child: Text(t.roundNumber(n: i+1)))]); - if (rounds.indexWhere((element) => element.value == -2) == -1) rounds.insert(1, DropdownMenuItem(value: -2, child: Text(t.timeWeightedmatch))); + rounds = [DropdownMenuItem(value: -1, child: Text(t.tlMatchView.match))]; + rounds.addAll([for (int i = 0; i < widget.record.results.rounds.length; i++) DropdownMenuItem(value: i, child: Text(t.tlMatchView.roundNumber(n: i+1)))]); greenSidePlayer = widget.record.results.leaderboard.indexWhere((element) => element.id == widget.initPlayerId); redSidePlayer = widget.record.results.leaderboard.indexWhere((element) => element.id != widget.initPlayerId); - List apmMultipliedByWeights = [0, 0]; - List ppsMultipliedByWeights= [0, 0]; - List vsMultipliedByWeights = [0, 0]; for (var round in widget.record.results.rounds){ var longerLifetime = round[0].lifetime.compareTo(round[1].lifetime) == 1 ? round[0].lifetime : round[1].lifetime; roundLengths.add(longerLifetime); totalTime += longerLifetime; - - BetaLeagueRound greenSide = round.firstWhere((element) => element.id == widget.initPlayerId); - BetaLeagueRound redSide = round.firstWhere((element) => element.id != widget.initPlayerId); - - apmMultipliedByWeights[0] += greenSide.stats.apm*longerLifetime.inMilliseconds; - apmMultipliedByWeights[1] += redSide.stats.apm*longerLifetime.inMilliseconds; - ppsMultipliedByWeights[0] += greenSide.stats.pps*longerLifetime.inMilliseconds; - ppsMultipliedByWeights[1] += redSide.stats.pps*longerLifetime.inMilliseconds; - vsMultipliedByWeights[0] += greenSide.stats.vs*longerLifetime.inMilliseconds; - vsMultipliedByWeights[1] += redSide.stats.vs*longerLifetime.inMilliseconds; } - timeWeightedStats = [ - BetaLeagueStats( - apm: apmMultipliedByWeights[0]/totalTime.inMilliseconds, - pps: ppsMultipliedByWeights[0]/totalTime.inMilliseconds, - vs: vsMultipliedByWeights[0]/totalTime.inMilliseconds, - garbageSent: widget.record.results.leaderboard[greenSidePlayer].stats.garbageSent, - garbageReceived: widget.record.results.leaderboard[greenSidePlayer].stats.garbageReceived, - kills: widget.record.results.leaderboard[greenSidePlayer].stats.kills, - altitude: widget.record.results.leaderboard[greenSidePlayer].stats.altitude, - rank: widget.record.results.leaderboard[greenSidePlayer].stats.rank - ), - BetaLeagueStats( - apm: apmMultipliedByWeights[1]/totalTime.inMilliseconds, - pps: ppsMultipliedByWeights[1]/totalTime.inMilliseconds, - vs: vsMultipliedByWeights[1]/totalTime.inMilliseconds, - garbageSent: widget.record.results.leaderboard[redSidePlayer].stats.garbageSent, - garbageReceived: widget.record.results.leaderboard[redSidePlayer].stats.garbageReceived, - kills: widget.record.results.leaderboard[redSidePlayer].stats.kills, - altitude: widget.record.results.leaderboard[redSidePlayer].stats.altitude, - rank: widget.record.results.leaderboard[redSidePlayer].stats.rank - ), - ]; initPlayerWon = widget.record.results.leaderboard[greenSidePlayer].wins > widget.record.results.leaderboard[redSidePlayer].wins; if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS){ windowManager.getTitle().then((value) => oldWindowTitle = value); - windowManager.setTitle("Tetra Stats: ${widget.record.results.leaderboard[greenSidePlayer].username.toUpperCase()} ${t.vs} ${widget.record.results.leaderboard[redSidePlayer].username.toUpperCase()} ${t.inTLmatch} ${widget.record.gamemode} ${timestamp(widget.record.ts)}"); + windowManager.setTitle("Tetra Stats: ${widget.record.results.leaderboard[greenSidePlayer].username.toUpperCase()} ${t.tlMatchView.vs} ${widget.record.results.leaderboard[redSidePlayer].username.toUpperCase()} ${timestamp(widget.record.ts)}"); } super.initState(); } @@ -114,11 +75,11 @@ class TlMatchResultState extends State { bool bigScreen = width >= 768; if (roundSelector.isNegative){ time = totalTime; - readableTime = !time.isNegative ? "${t.matchLength}: ${time.inMinutes}:${secs.format(time.inMicroseconds /1000000 % 60)}" : "${t.matchLength}: ---"; + readableTime = !time.isNegative ? "${t.tlMatchView.matchLength}: ${time.inMinutes}:${secs.format(time.inMicroseconds /1000000 % 60)}" : "${t.tlMatchView.matchLength}: ---"; }else{ time = roundLengths[roundSelector]; int alive = widget.record.results.rounds[roundSelector].indexWhere((element) => element.alive); - readableTime = "${t.roundLength}: ${!time.isNegative ? "${time.inMinutes}:${secs.format(time.inMicroseconds /1000000 % 60)}" : "---"}\n${t.winner}: ${alive == -1 ? "idk" : widget.record.results.rounds[roundSelector][alive].username}"; + readableTime = "${t.tlMatchView.roundLength}: ${!time.isNegative ? "${time.inMinutes}:${secs.format(time.inMicroseconds /1000000 % 60)}" : "---"}\n${t.tlMatchView.winner}: ${alive == -1 ? "idk" : widget.record.results.rounds[roundSelector][alive].username}"; } return SizedBox( width: width, @@ -191,7 +152,7 @@ class TlMatchResultState extends State { crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [ - Text("${t.statsFor}: ", + Text("${t.tlMatchView.statsFor}: ", style: const TextStyle(color: Colors.white, fontSize: 25)), DropdownButton(items: rounds, value: roundSelector, onChanged: ((value) { roundSelector = value; @@ -201,9 +162,6 @@ class TlMatchResultState extends State { ), ), ), - if (widget.record.id == widget.record.replayID && showMobileSelector) SliverToBoxAdapter( - child: Center(child: Text(t.p1nkl0bst3rAlert, textAlign: TextAlign.center)), - ), if (showMobileSelector) SliverToBoxAdapter(child: Center(child: Text(readableTime, textAlign: TextAlign.center))), const SliverToBoxAdapter( child: Divider(), @@ -215,38 +173,32 @@ class TlMatchResultState extends State { Column( children: [ CompareThingy( - label: "APM", - greenSide: roundSelector == -2 ? timeWeightedStats[0].apm : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.apm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.apm, - redSide: roundSelector == -2 ? timeWeightedStats[1].apm : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.apm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.apm, + label: t.stats.apm.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.apm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.apm, + redSide: roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.apm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.apm, fractionDigits: 2, higherIsBetter: true, ), CompareThingy( - label: "PPS", - greenSide: roundSelector == -2 ? timeWeightedStats[0].pps : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.pps : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.pps, - redSide: roundSelector == -2 ? timeWeightedStats[1].pps : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.pps : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.pps, + label: t.stats.pps.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.pps : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.pps, + redSide: roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.pps : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.pps, fractionDigits: 2, higherIsBetter: true, ), CompareThingy( - label: "VS", - greenSide: roundSelector == -2 ? timeWeightedStats[0].vs : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.vs : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.vs, - redSide: roundSelector == -2 ? timeWeightedStats[1].vs : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.vs : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.vs, + label: t.stats.vs.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.vs : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.vs, + redSide: roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.vs : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.vs, fractionDigits: 2, higherIsBetter: true, ), if (widget.record.gamemode == "league") CompareThingy(greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.garbageSent : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.garbageSent, redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.garbageSent : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.garbageSent, - label: "Sent", higherIsBetter: true), + label: t.stats.sent, higherIsBetter: true), if (widget.record.gamemode == "league") CompareThingy(greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.garbageReceived : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.garbageReceived, redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.garbageReceived : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.garbageReceived, - label: "Received", higherIsBetter: true), const Divider(), + label: t.stats.received, higherIsBetter: true), const Divider(), Column( children: [ Padding( @@ -257,142 +209,114 @@ class TlMatchResultState extends State { fontSize: bigScreen ? 42 : 28)), ), CompareThingy( - label: "APP", - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.app : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.app : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.app, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.app : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.app : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.app, + label: t.stats.app.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.app : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.app, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.app : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.app, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "VS/APM", - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.vsapm : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.vsapm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.vsapm, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.vsapm : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.vsapm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.vsapm, + label: t.stats.vsapm.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.vsapm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.vsapm, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.vsapm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.vsapm, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "DS/S", - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.dss : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.dss : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.dss, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.dss : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.dss : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.dss, + label: t.stats.dss.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.dss : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.dss, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.dss : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.dss, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "DS/P", - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.dsp : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.dsp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.dsp, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.dsp : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.dsp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.dsp, + label: t.stats.dsp.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.dsp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.dsp, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.dsp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.dsp, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "APP + DS/P", - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.appdsp : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.appdsp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.appdsp, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.appdsp : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.appdsp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.appdsp, + label: t.stats.appdsp.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.appdsp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.appdsp, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.appdsp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.appdsp, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: t.statCellNum.cheese.replaceAll(RegExp(r'\n'), " "), - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.cheese : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.cheese : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.cheese, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.cheese : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.cheese : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.cheese, + label: t.stats.cheese.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.cheese : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.cheese, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.cheese : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.cheese, fractionDigits: 2, higherIsBetter: false, ), CompareThingy( - label: "Gb Eff.", - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.gbe : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.gbe : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.gbe, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.gbe : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.gbe : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.gbe, + label: t.stats.gbe.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.gbe : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.gbe, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.gbe : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.gbe, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "wAPP", - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.nyaapp : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.nyaapp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.nyaapp, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.nyaapp : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.nyaapp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.nyaapp, + label: t.stats.nyaapp.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.nyaapp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.nyaapp, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.nyaapp : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.nyaapp, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "Area", - greenSide: roundSelector == -2 ? timeWeightedStats[0].nerdStats.area : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.area : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.area, - redSide: roundSelector == -2 ? timeWeightedStats[1].nerdStats.area : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.area : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.area, + label: t.stats.area.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats.area : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats.area, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats.area : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats.area, fractionDigits: 2, higherIsBetter: true, ), CompareThingy( - label: t.statCellNum.estOfTRShort, - greenSide: roundSelector == -2 ? timeWeightedStats[0].estTr.esttr : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.estTr.esttr : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.estTr.esttr, - redSide: roundSelector == -2 ? timeWeightedStats[1].estTr.esttr : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.estTr.esttr : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.estTr.esttr, + label: t.stats.etr.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.estTr.esttr : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.estTr.esttr, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.estTr.esttr : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.estTr.esttr, fractionDigits: 2, higherIsBetter: true, ), CompareThingy( - label: "Opener", - greenSide: roundSelector == -2 ? timeWeightedStats[0].playstyle.opener : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle.opener : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle.opener, - redSide: roundSelector == -2 ? timeWeightedStats[1].playstyle.opener : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle.opener : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle.opener, + label: t.stats.opener.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle.opener : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle.opener, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle.opener : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle.opener, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "Plonk", - greenSide: roundSelector == -2 ? timeWeightedStats[0].playstyle.plonk : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle.plonk : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle.plonk, - redSide: roundSelector == -2 ? timeWeightedStats[1].playstyle.plonk : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle.plonk : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle.plonk, + label: t.stats.plonk.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle.plonk : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle.plonk, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle.plonk : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle.plonk, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "Stride", - greenSide: roundSelector == -2 ? timeWeightedStats[0].playstyle.stride : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle.stride : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle.stride, - redSide: roundSelector == -2 ? timeWeightedStats[1].playstyle.stride : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle.stride : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle.stride, + label: t.stats.stride.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle.stride : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle.stride, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle.stride : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle.stride, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( - label: "Inf. DS", - greenSide: roundSelector == -2 ? timeWeightedStats[0].playstyle.infds : - roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle.infds : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle.infds, - redSide: roundSelector == -2 ? timeWeightedStats[1].playstyle.infds : - roundSelector == -1 ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle.infds : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle.infds, + label: t.stats.infds.short, + greenSide: roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle.infds : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle.infds, + redSide: roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle.infds : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle.infds, fractionDigits: 3, higherIsBetter: true, ), VsGraphs( - roundSelector == -2 ? timeWeightedStats[0].apm : roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.apm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.apm, - roundSelector == -2 ? timeWeightedStats[0].pps : roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.pps : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.pps, - roundSelector == -2 ? timeWeightedStats[0].vs : roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.vs : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.vs, - roundSelector == -2 ? timeWeightedStats[0].nerdStats : roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats, - roundSelector == -2 ? timeWeightedStats[0].playstyle : roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle, - roundSelector == -2 ? timeWeightedStats[1].apm : roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.apm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.apm, - roundSelector == -2 ? timeWeightedStats[1].pps : roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.pps : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.pps, - roundSelector == -2 ? timeWeightedStats[1].vs : roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.vs : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.vs, - roundSelector == -2 ? timeWeightedStats[1].nerdStats : roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats, - roundSelector == -2 ? timeWeightedStats[1].playstyle : roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle, + roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.apm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.apm, + roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.pps : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.pps, + roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.vs : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.vs, + roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.nerdStats : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.nerdStats, + roundSelector.isNegative ? widget.record.results.leaderboard[greenSidePlayer].stats.playstyle : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id == widget.initPlayerId).stats.playstyle, + roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.apm : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.apm, + roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.pps : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.pps, + roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.vs : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.vs, + roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.nerdStats : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.nerdStats, + roundSelector.isNegative ? widget.record.results.leaderboard[redSidePlayer].stats.playstyle : widget.record.results.rounds[roundSelector].firstWhere((element) => element.id != widget.initPlayerId).stats.playstyle, ) ], ), @@ -449,7 +373,7 @@ class TlMatchResultState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(t.matchLength), + Text(t.tlMatchView.matchLength), RichText( text: !totalTime.isNegative ? TextSpan( text: "${totalTime.inMinutes}:${NumberFormat("00", LocaleSettings.currentLocale.languageCode).format(totalTime.inSeconds%60)}", @@ -465,7 +389,7 @@ class TlMatchResultState extends State { if (widget.record.id != widget.record.replayID) Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ - Text(t.numberOfRounds), + Text(t.tlMatchView.numberOfRounds), RichText( text: TextSpan( text: widget.record.results.rounds.length.toString(), @@ -478,25 +402,15 @@ class TlMatchResultState extends State { ), ) ],), - Column(children: [ - OverflowBar( - alignment: MainAxisAlignment.spaceEvenly, - children: [ - TextButton( style: roundSelector == -1 ? ButtonStyle(backgroundColor: WidgetStatePropertyAll(Colors.grey.shade900)) : null, - onPressed: () { - roundSelector = -1; - setState(() {}); - }, child: Text(t.matchStats)), - TextButton( style: roundSelector == -2 ? ButtonStyle(backgroundColor: WidgetStatePropertyAll(Colors.grey.shade900)) : null, - onPressed: timeWeightedStatsAvaliable ? () { - roundSelector = -2; - setState(() {}); - } : null, child: Text(t.timeWeightedmatchStats)) , - ], - ) - ]), ], ) + ), + SliverToBoxAdapter( + child: TextButton( style: roundSelector == -1 ? ButtonStyle(backgroundColor: WidgetStatePropertyAll(Colors.grey.shade900)) : null, + onPressed: () { + roundSelector = -1; + setState(() {}); + }, child: Text(t.tlMatchView.matchStats)), ) ]; }, @@ -572,7 +486,7 @@ class TlMatchResultState extends State { return Scaffold( appBar: AppBar( title: Text( - "${widget.record.results.leaderboard[greenSidePlayer].username.toUpperCase()} ${t.vs} ${widget.record.results.leaderboard[redSidePlayer].username.toUpperCase()} ${t.inTLmatch} ${widget.record.gamemode} ${timestamp(widget.record.ts)}", + "${widget.record.results.leaderboard[greenSidePlayer].username.toUpperCase()} ${t.tlMatchView.vs} ${widget.record.results.leaderboard[redSidePlayer].username.toUpperCase()} ${widget.record.gamemode} ${timestamp(widget.record.ts)}", style: Theme.of(context).textTheme.titleMedium!.copyWith(fontSize: 28), ), actions: [ @@ -581,11 +495,11 @@ class TlMatchResultState extends State { itemBuilder: (BuildContext context) => [ PopupMenuItem( value: 1, - child: Text(t.downloadReplay), + child: Text(t.tlMatchView.downloadReplay), ), PopupMenuItem( value: 2, - child: Text(t.openReplay), + child: Text(t.tlMatchView.openReplay), ), ], onSelected: (value) async { diff --git a/lib/views/user_view.dart b/lib/views/user_view.dart index 23e0027..772263c 100644 --- a/lib/views/user_view.dart +++ b/lib/views/user_view.dart @@ -49,7 +49,7 @@ class UserState extends State { padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0), child: FloatingActionButton( onPressed: () => Navigator.pop(context), - tooltip: 'Fuck go back', + tooltip: t.goBackButton, child: const Icon(Icons.arrow_back), ), ), diff --git a/lib/widgets/badges_thingy.dart b/lib/widgets/badges_thingy.dart index b223198..ce30875 100644 --- a/lib/widgets/badges_thingy.dart +++ b/lib/widgets/badges_thingy.dart @@ -56,7 +56,7 @@ class BadgesThingy extends StatelessWidget{ ), actions: [ TextButton( - child: Text(t.popupActions.ok), + child: Text(t.actions.ok), onPressed: () { Navigator.of(context).pop(); }, diff --git a/lib/widgets/graphs.dart b/lib/widgets/graphs.dart index 7815b0c..2d45421 100644 --- a/lib/widgets/graphs.dart +++ b/lib/widgets/graphs.dart @@ -452,13 +452,13 @@ class Graphs extends StatelessWidget{ getTitle: (index, angle) { switch (index) { case 0: - return RadarChartTitle(text: '${t.graphs.attack}\n${f2.format(apm)} APM', angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: '${t.stats.graphs.attack}\n${f2.format(apm)} APM', angle: 0, positionPercentageOffset: 0.05); case 1: - return RadarChartTitle(text: '${t.graphs.speed}\n${f2.format(pps)} PPS', angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: '${t.stats.graphs.speed}\n${f2.format(pps)} PPS', angle: 0, positionPercentageOffset: 0.05); case 2: - return RadarChartTitle(text: '${t.graphs.defense}\n${f2.format(nerdStats.dss)} DS/S', angle: angle + 180, positionPercentageOffset: 0.05); + return RadarChartTitle(text: '${t.stats.graphs.defense}\n${f2.format(nerdStats.dss)} DS/S', angle: angle + 180, positionPercentageOffset: 0.05); case 3: - return RadarChartTitle(text: '${t.graphs.cheese}\n${f3.format(nerdStats.cheese)}', angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: '${t.stats.graphs.cheese}\n${f3.format(nerdStats.cheese)}', angle: 0, positionPercentageOffset: 0.05); default: return const RadarChartTitle(text: ''); } diff --git a/lib/widgets/lineclears_thingy.dart b/lib/widgets/lineclears_thingy.dart index cb739b8..3373e03 100644 --- a/lib/widgets/lineclears_thingy.dart +++ b/lib/widgets/lineclears_thingy.dart @@ -21,14 +21,14 @@ class LineclearsThingy extends StatelessWidget{ child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text(t.numOfGameActions.lineClears(n: lines), style: const TextStyle(color: Colors.white, fontFamily: "Eurostile Round Extended"), textAlign: TextAlign.center), - if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Pentas"), Text(clears.pentas.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Quads"), Text(clears.quads.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Triples"), Text(clears.triples.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Doubles"), Text(clears.doubles.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Singles"), Text(clears.singles.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("\n${t.numOfGameActions.pc}"), Text("\n${clears.allClears.toString()}")]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text(t.numOfGameActions.hold), Text(holds.toString())]), + Text(t.stats.linesCleared(n: lines), style: const TextStyle(color: Colors.white, fontFamily: "Eurostile Round Extended"), textAlign: TextAlign.center), + if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text(t.stats.lineClears.penta), Text(clears.pentas.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text(t.stats.lineClears.quad), Text(clears.quads.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text(t.stats.lineClears.triple), Text(clears.triples.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text(t.stats.lineClears.double), Text(clears.doubles.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text(t.stats.lineClears.single), Text(clears.singles.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("\n${t.stats.pcs}"), Text("\n${clears.allClears.toString()}")]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text(t.stats.holds), Text(holds.toString())]), ], ), ), @@ -37,18 +37,18 @@ class LineclearsThingy extends StatelessWidget{ child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text(t.numOfGameActions.tspinsTotal(n: tSpins), style: const TextStyle(color: Colors.white, fontFamily: "Eurostile Round Extended"), textAlign: TextAlign.center), - if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("T-spin pentas"), Text(clears.tSpinPentas.toString())]), - if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("T-spin quads"), Text(clears.tSpinQuads.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("T-spins triples"), Text(clears.tSpinTriples.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("T-spins doubles"), Text(clears.tSpinDoubles.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("T-spins singles"), Text(clears.tSpinSingles.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("T-spins zeros"), Text(clears.tSpinZeros.toString())]), - if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Mini T-spins quads"), Text(clears.tSpinMiniQuads.toString())]), - if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Mini T-spins triples"), Text(clears.tSpinMiniTriples.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Mini T-spins doubles"), Text(clears.tSpinMiniDoubles.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Mini T-spins singles"), Text(clears.tSpinMiniSingles.toString())]), - Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [const Text("Mini T-spins zeros"), Text(clears.tSpinMiniZeros.toString())]), + Text(t.stats.tspinsTotal(n: tSpins), style: const TextStyle(color: Colors.white, fontFamily: "Eurostile Round Extended"), textAlign: TextAlign.center), + if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.tSpins} ${t.stats.lineClears.penta}"), Text(clears.tSpinPentas.toString())]), + if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.tSpins} ${t.stats.lineClears.quad}"), Text(clears.tSpinQuads.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.tSpins} ${t.stats.lineClears.triple}"), Text(clears.tSpinTriples.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.tSpins} ${t.stats.lineClears.double}"), Text(clears.tSpinDoubles.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.tSpins} ${t.stats.lineClears.single}"), Text(clears.tSpinSingles.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.tSpins} ${t.stats.lineClears.zero}"), Text(clears.tSpinZeros.toString())]), + if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.quad}"), Text(clears.tSpinMiniQuads.toString())]), + if (showMoreClears) Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.triple}"), Text(clears.tSpinMiniTriples.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.double}"), Text(clears.tSpinMiniDoubles.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.single}"), Text(clears.tSpinMiniSingles.toString())]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("${t.stats.mini} ${t.stats.tSpins} ${t.stats.lineClears.zero}"), Text(clears.tSpinMiniZeros.toString())]), ], ), ), diff --git a/lib/widgets/list_tile_trailing_stats.dart b/lib/widgets/list_tile_trailing_stats.dart index 8e3b101..7108599 100644 --- a/lib/widgets/list_tile_trailing_stats.dart +++ b/lib/widgets/list_tile_trailing_stats.dart @@ -13,7 +13,7 @@ class TrailingStats extends StatelessWidget{ @override Widget build(BuildContext context) { - const TextStyle style = TextStyle(height: 1.1, fontWeight: FontWeight.w100, fontSize: 15); + const TextStyle style = TextStyle(height: 1.0, fontWeight: FontWeight.w100, fontSize: 14); return Table( defaultColumnWidth: const IntrinsicColumnWidth(), defaultVerticalAlignment: TableCellVerticalAlignment.baseline, diff --git a/lib/widgets/news_thingy.dart b/lib/widgets/news_thingy.dart index 57c9905..3914990 100644 --- a/lib/widgets/news_thingy.dart +++ b/lib/widgets/news_thingy.dart @@ -13,14 +13,6 @@ class NewsThingy extends StatelessWidget{ const NewsThingy(this.news, {super.key}); ListTile getNewsTile(NewsEntry news){ - Map gametypes = { - "40l": t.sprint, - "blitz": t.blitz, - "5mblast": "5,000,000 Blast", - "zenith": "Quick Play", - "zenithex": "Quick Play Expert", - }; - // Individuly handle each entry type switch (news.type) { case "leaderboard": @@ -32,7 +24,7 @@ class NewsThingy extends StatelessWidget{ children: [ TextSpan(text: "№${news.data["rank"]} ", style: const TextStyle(fontWeight: FontWeight.bold)), TextSpan(text: t.newsParts.leaderboardMiddle), - TextSpan(text: "№${gametypes[news.data["gametype"]]}", style: const TextStyle(fontWeight: FontWeight.bold)), + TextSpan(text: "№${t.gamemodes[news.data["gametype"]]}", style: const TextStyle(fontWeight: FontWeight.bold)), ] ) ), @@ -45,7 +37,7 @@ class NewsThingy extends StatelessWidget{ style: const TextStyle(fontFamily: 'Eurostile Round', fontSize: 16, color: Colors.white), text: t.newsParts.personalbest, children: [ - TextSpan(text: "${gametypes[news.data["gametype"]]} ", style: const TextStyle(fontWeight: FontWeight.bold)), + TextSpan(text: "${t.gamemodes[news.data["gametype"]]} ", style: const TextStyle(fontWeight: FontWeight.bold)), TextSpan(text: t.newsParts.personalbestMiddle), TextSpan(text: switch (news.data["gametype"]){ "blitz" => NumberFormat.decimalPattern().format(news.data["result"]), diff --git a/lib/widgets/recent_sp_games.dart b/lib/widgets/recent_sp_games.dart index 028815d..c8446d6 100644 --- a/lib/widgets/recent_sp_games.dart +++ b/lib/widgets/recent_sp_games.dart @@ -37,7 +37,7 @@ class RecentSingleplayerGames extends StatelessWidget{ title: Text( switch (record.gamemode){ "40l" => get40lTime(record.stats.finalTime.inMicroseconds), - "blitz" => t.blitzScore(p: NumberFormat.decimalPattern().format(record.stats.score)), + "blitz" => t.stats.blitzScore(p: NumberFormat.decimalPattern().format(record.stats.score)), "5mblast" => get40lTime(record.stats.finalTime.inMicroseconds), String() => "huh", }, diff --git a/lib/widgets/tl_rating_thingy.dart b/lib/widgets/tl_rating_thingy.dart index 7caa4ad..368f949 100644 --- a/lib/widgets/tl_rating_thingy.dart +++ b/lib/widgets/tl_rating_thingy.dart @@ -114,7 +114,7 @@ class TLRatingThingy extends StatelessWidget{ children: [ TextSpan(text: prefs.getInt("ratingMode") == 2 ? "${f2.format(tlData.tr)} TR • % ${t.rank}: ${tlData.percentileRank.toUpperCase()}" : "${t.top} ${f2.format(tlData.percentile * 100)}% (${tlData.percentileRank.toUpperCase()})"), if (tlData.bestRank != "z") const TextSpan(text: " • "), - if (tlData.bestRank != "z") TextSpan(text: "${t.topRank}: ${tlData.bestRank.toUpperCase()}"), + if (tlData.bestRank != "z") TextSpan(text: t.stats.topRank(rank: tlData.bestRank.toUpperCase())), if (topTR != null) TextSpan(text: " (${f2.format(topTR)} TR)"), TextSpan(text: " • ${prefs.getInt("ratingMode") == 1 ? "${f2.format(tlData.tr)} TR • RD: " : "Glicko: ${tlData.glicko != null ? f2.format(tlData.glicko) : "---"}±"}"), TextSpan(text: f2.format(tlData.rd!), style: tlData.decaying ? TextStyle(color: tlData.rd! > 98 ? Colors.red : Colors.yellow) : null), diff --git a/lib/widgets/user_thingy.dart b/lib/widgets/user_thingy.dart index 3d56a30..783e585 100644 --- a/lib/widgets/user_thingy.dart +++ b/lib/widgets/user_thingy.dart @@ -215,14 +215,14 @@ class _UserThingyState extends State with SingleTickerProviderStateM showLabels: false ), ), - Text("${t.statCellNum.xpProgress}: ${((widget.player.level - widget.player.level.floor()) * 100).toStringAsFixed(2)} %"), - Text("${t.statCellNum.xpFrom0ToLevel(n: xpTableScuffed.keys.toList()[xpTableID])}: ${((widget.player.xp / xpTableScuffed.values.toList()[xpTableID]) * 100).toStringAsFixed(2)} % (${NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 0).format(xpTableScuffed.values.toList()[xpTableID] - widget.player.xp)} ${t.statCellNum.xpLeft})") + Text(t.xp.progressToNextLevel(percentage: percentage.format((widget.player.level - widget.player.level.floor())))), + Text(t.xp.progressTowardsGoal(goal: xpTableScuffed.keys.toList()[xpTableID], percentage: percentage.format(widget.player.xp / xpTableScuffed.values.toList()[xpTableID]), left: NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 0).format(xpTableScuffed.values.toList()[xpTableID] - widget.player.xp))) ] ), ), actions: [ TextButton( - child: const Text("OK"), + child: Text(t.actions.ok), onPressed: () {Navigator.of(context).pop();} ) ] @@ -236,7 +236,7 @@ class _UserThingyState extends State with SingleTickerProviderStateM showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: Text(t.exactGametime, textAlign: TextAlign.center), + title: Text(t.gametime.title, textAlign: TextAlign.center), content: SingleChildScrollView( child: Column( children: [ @@ -248,15 +248,20 @@ class _UserThingyState extends State with SingleTickerProviderStateM TextSpan(text: ".${nonsecs3.format(widget.player.gameTime.inMicroseconds%1000000)}", style: TextStyle(fontSize: 14)) ] )), - Text("${playtime(avgGametimeADay)} a day in average"), + Text(t.gametime.gametimeAday(gametime: playtime(avgGametimeADay))), Padding( padding: const EdgeInsets.only(top: 8.0), - child: Text("It's ${f4.format(widget.player.gameTime.inSeconds/31536000)} years,"), - ), - Text("or ${f4.format(widget.player.gameTime.inSeconds/2628000)} months,"), - Text("or ${f4.format(widget.player.gameTime.inSeconds/86400)} days,"), - Text("or ${f2.format(widget.player.gameTime.inMilliseconds/60000)} minutes,"), - Text("or ${intf.format(widget.player.gameTime.inSeconds)} seconds"), + child: Text( + textAlign: TextAlign.center, + t.gametime.breakdown( + years: f4.format(widget.player.gameTime.inSeconds/31536000), + months: f4.format(widget.player.gameTime.inSeconds/2628000), + days: f4.format(widget.player.gameTime.inSeconds/86400), + minutes: f2.format(widget.player.gameTime.inMilliseconds/60000), + seconds: intf.format(widget.player.gameTime.inSeconds) + ) + ), + ) ] ), ), diff --git a/lib/widgets/vs_graphs.dart b/lib/widgets/vs_graphs.dart index 9dce22d..6440b83 100644 --- a/lib/widgets/vs_graphs.dart +++ b/lib/widgets/vs_graphs.dart @@ -227,13 +227,13 @@ class VsGraphs extends StatelessWidget{ getTitle: (index, angle) { switch (index) { case 0: - return RadarChartTitle(text: t.graphs.attack, angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: t.stats.graphs.attack, angle: 0, positionPercentageOffset: 0.05); case 1: - return RadarChartTitle(text: t.graphs.speed, angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: t.stats.graphs.speed, angle: 0, positionPercentageOffset: 0.05); case 2: - return RadarChartTitle(text: t.graphs.defense, angle: angle + 180, positionPercentageOffset: 0.05); + return RadarChartTitle(text: t.stats.graphs.defense, angle: angle + 180, positionPercentageOffset: 0.05); case 3: - return RadarChartTitle(text: t.graphs.cheese, angle: 0, positionPercentageOffset: 0.05); + return RadarChartTitle(text: t.stats.graphs.cheese, angle: 0, positionPercentageOffset: 0.05); default: return const RadarChartTitle(text: ''); } diff --git a/res/i18n/strings_ru.i18n.json b/res/i18n/old_strings_ru.i18n.json similarity index 100% rename from res/i18n/strings_ru.i18n.json rename to res/i18n/old_strings_ru.i18n.json diff --git a/res/i18n/strings_zh-CN.i18n.json b/res/i18n/old_strings_zh-CN.i18n.json similarity index 100% rename from res/i18n/strings_zh-CN.i18n.json rename to res/i18n/old_strings_zh-CN.i18n.json diff --git a/res/i18n/strings.i18n.json b/res/i18n/strings.i18n.json index 901cc39..c048cdd 100644 --- a/res/i18n/strings.i18n.json +++ b/res/i18n/strings.i18n.json @@ -4,13 +4,14 @@ "ru": "Russian (Русский)", "zh-CN": "Simplified Chinese (简体中文)" }, - "gamemodes":{ - "tl": "Tetra League", + "gamemodes(map)":{ + "league": "Tetra League", "zenith": "Quick Play", "zenithex": "Quick Play Expert", "40l": "40 Lines", "blitz": "Blitz", - "5mblast": "5,000,000 Blast" + "5mblast": "5,000,000 Blast", + "zen": "Zen" }, "destinations": { "home": "Home", @@ -26,6 +27,7 @@ "nanow": "Not avaliable for now...", "seasonEnds": "Season ends in ${countdown}", "seasonEnded": "Season has ended", + "overallPB": "Overall PB: $pb", "gamesUntilRanked": "${left} games until being ranked", "numOfVictories": "~${wins} victories", "promotionOnNextWin": "Promotion on next win", @@ -33,6 +35,7 @@ "demotionOnNextLoss": "Demotion on next loss", "records": "Records", "nerdStats": "Nerd Stats", + "playstyles": "Playstyles", "horoscopes": "Horoscopes", "season": "Season", "smooth": "Smooth", @@ -43,12 +46,15 @@ "verdictBetter": "ahead", "verdictWorse": "behind", "localStanding": "local", - "xpProgressToNextLevel": "Progress to next level: $percentage", - "xpProgressTowardsGoal": "Progress from 0 XP to level $goal: $percentage ($left xp left)", + "xp": { + "title": "XP Level", + "progressToNextLevel": "Progress to next level: $percentage", + "progressTowardsGoal": "Progress from 0 XP to level $goal: $percentage ($left XP left)" + }, "gametime":{ "title": "Exact gametime", "gametimeAday": "$gametime a day in average", - "breakdown": "It's $years years,\nor $months months,\nor $days days,\nor$minutes minutes\nor $seconds seconds" + "breakdown": "It's $years years,\nor $months months,\nor $days days,\nor $minutes minutes\nor $seconds seconds" }, "track": "Track", "stopTracking": "Stop tracking", @@ -90,6 +96,15 @@ "previousSeasons": "Previous Seasons", "recent": "Recent", "top": "Top", + "noRecord": "No record", + "sprintAndBlitsRelevance": "Relevance: ${date}", + "snackBarMessages":{ + "stateRemoved": "${date} state was removed from database!", + "matchRemoved": "${date} match was removed from database!", + "notForWeb": "Function is not available for web version", + "importSuccess": "Import successful", + "importCancelled": "Import was cancelled" + }, "errors": { "noRecords": "No records", "notEnoughData": "Not enough data", @@ -125,8 +140,21 @@ "cancel": "Cancel", "submit": "Submit", "ok": "OK", + "apply": "Apply", "refresh": "Refresh" }, + "graphsDestination": { + "fetchAndsaveTLHistory": "Get player history", + "fetchAndSaveOldTLmatches": "Get Tetra League matches history", + "fetchAndsaveTLHistoryResult": "${number} states was found", + "fetchAndSaveOldTLmatchesResult": "${number} matches was found", + "gamesPlayed": "$games played", + "dateAndTime": "Date & Time", + "filterModaleTitle": "Filter ranks on graph" + }, + "filterModale":{ + "all": "All" + }, "cutoffsDestination": { "title": "Tetra League State", "relevance": "as of $timestamp", @@ -140,7 +168,9 @@ "moreInfo": "More Info", "NumberOne": "№ 1 is $tr TR", "inflated": "Inflated on $tr TR", + "notInflated": "Not inflated", "deflated": "Deflated on $tr TR", + "notDeflated": "Not deflated", "wellDotDotDot": "Well...", "fromPlace": "from № $n", "viewButton": "View" @@ -162,8 +192,74 @@ "minimums": "Minimums", "maximums": "Maximums" }, + "tlMatchView": { + "match": "Match", + "vs": "vs", + "winner": "Winner", + "roundNumber": "Round $n", + "statsFor": "Stats for", + "numberOfRounds": "Number of rounds", + "matchLength": "Match Length", + "roundLength": "Round Length", + "matchStats": "Match stats", + "downloadReplay": "Download .ttrm replay", + "openReplay": "Open replay in TETR.IO" + }, "calcDestination": { - "tip": "Enter values and press \"Calc\" to see Nerd Stats for them" + "tip": "Enter values and press \"Calc\" to see Nerd Stats for them", + "statsCalcButton": "Calc", + "damageCalcTip": "Click on the actions on the left to add them here", + "actions": "Actions", + "results": "Results", + "rules": "Rules", + "noSpinClears": "No Spin Clears", + "spins": "Spins", + "miniSpins": "Mini spins", + "noLineclear": "No lineclear (Break Combo)", + "custom": "Custom", + "multiplier": "Multiplier", + "pcDamage": "Perfect Clear Damage", + "comboTable": "Combo Table", + "b2bChaining": "Back-To-Back Chaining", + "surgeStartAtB2B": "Starts at B2B", + "surgeStartAmount": "Start amount", + "totalDamage": "Total damage", + "lineclears": "Lineclears", + "combo": "Combo", + "surge": "Surge", + "pcs": "PCs" + }, + "infoDestination": { + "title": "Information Center", + "sprintAndBlitzAverages": "40 Lines & Blitz Averages", + "sprintAndBlitzAveragesDescription": "Since calculating 40 Lines & Blitz averages is tedious process, it gets updated only once in a while. Click on the title of this card to see the full 40 Lines & Blitz averages table", + "tetraStatsWiki": "Tetra Stats Wiki", + "tetraStatsWikiDescription": "Find more information about Tetra Stats functions and statictic, that it provides", + "about": "About Tetra Stats", + "aboutDescription": "Developed by dan63\n" + }, + "leaderboardsDestination": { + "title": "Leaderboards", + "tl": "Tetra League (Current Season)", + "fullTL": "Tetra League (Current Season, full one)", + "ar": "Acievement Points", + "fullTLnote": "Heavy, but allows you to sort players by their stats and filter them by ranks" + }, + "settingsDestination": { + "title": "Settings", + "timestamps": "Timestamps", + "timestampsDescription": "You can choose, in which way timestamps shows time", + "timestampsAbsoluteGMT": "Absolute (GMT)", + "timestampsAbsoluteLocalTime": "Absolute (Your timezone)", + "timestampsRelative": "Relative", + "exportDB": "Export local database", + "desktopExportAlertTitle": "Desktop export", + "desktopExportText": "It seems like you using this app on desktop. Check your documents folder, you should find \"TetraStats.db\". Copy it somewhere", + "androidExportAlertTitle": "Android export", + "androidExportText": "Exported.\n${exportedDB}", + "importDB": "Import local database", + "importDBDescription": "Restore your backup. Notice that already stored database will be overwritten.", + "importWrongFileType": "Wrong file type" }, "homeNavigation": { "overview": "Overview", @@ -184,7 +280,31 @@ "stats": "Stats Calculator", "damage": "Damage Calculator" }, + "aboutView": { + "title": "About Tetra Stats", + "about": "Tetra Stats is a service, that works with TETR.IO Tetra Channel API, providing data from it and calculating some addtitional metrics, based on this data. Service allows user to track their progress in Tetra League with \"Track\" function, which records every Tetra League change into local database (not automatically, you have to visit service from time to time), so these changes could be looked through graphs.\n\nBeanserver blaster is a part of a Tetra Stats, that decoupled into a serverside script. It provides full Tetra League leaderboard, allowing Tetra Stats to sort leaderboard by any metric and build scatter chart, that allows user to analyse Tetra League trends. It also provides history of Tetra League ranks cutoffs, which can be viewed by user via graph as well.\n\nThere is a plans to add replay analysis and tournaments history, so stay tuned!\n\nService is not associated with TETR.IO or osk in any capacity.", + "appVersion": "App Version", + "build": "Build $build", + "GHrepo": "GitHub Repository", + "submitAnIssue": "Submit an issue", + "credits": "Credits", + "authorAndDeveloper": "Autor & developer", + "providedFormulas": "Provided formulas", + "providedS1history": "Provided S1 history", + "inoue": "Inoue (replay grabber)", + "zhCNlocale": "Simplfied Chinise locale", + "supportHim": "Support him!" + }, "stats": { + "registrationDate": "Registration Date", + "gametime": "Time Played", + "ogp": "Online Games Played", + "ogw": "Online Games Won", + "followers": "Followers", + "xp": { + "short": "XP", + "full": "Experience Points" + }, "tr": { "short": "TR", "full": "Tetra Rating" @@ -201,6 +321,10 @@ "short": "GXE", "full": "GLIXARE" }, + "s1tr": { + "short": "S1 TR", + "full": "Season 1 like TR" + }, "gp":{ "short": "GP", "full": "Games Played" @@ -229,6 +353,10 @@ "short": "APP", "full": "Attack Per Piece" }, + "vsapm":{ + "short": "VS/APM", + "full": "VS / APM" + }, "dss":{ "short": "DS/S", "full": "Downstack Per Second" @@ -237,6 +365,10 @@ "short": "DS/P", "full": "Downstack Per Piece" }, + "appdsp": { + "short": "APP+DSP", + "full": "APP + DSP" + }, "cheese":{ "short": "Cheese", "full": "Cheese Index" @@ -304,6 +436,10 @@ "full": "Finesse", "widgetTitle": "inesse" }, + "finesseFaults":{ + "short": "FF", + "full": "Finesse Faults" + }, "totalTime":{ "short": "Time", "full": "Total Time", @@ -313,12 +449,43 @@ "short": "Lvl", "full": "Level" }, + "pieces": { + "short": "P", + "full": "Pieces" + }, + "spp": { + "short": "SPP", + "full": "Score Per Piece" + }, + "kp": { + "short": "KP", + "full": "Key presses" + }, + "kpp": { + "short": "KPP", + "full": "Key presses Per Piece" + }, + "kps": { + "short": "KPS", + "full": "Key presses Per Second" + }, + "blitzScore": "$p points", + "levelUpRequirement": "Level up requirement: $p", + "piecesTotal": "Total pieces placed", + "piecesWithPerfectFinesse": "Placed with perfect finesse", + "score": "Score", + "lines": "Lines", + "pcs": "Perfect Clears", + "holds": "Holds", "spike": "Top Spike", "top": "Top $percentage", "topRank": "Top rank: $rank", "floor": "Floor", "split": "Split", "total": "Total", + "sent": "Sent", + "received": "Received", + "placement": "Placement", "qpWithMods(plural)": { "one": "With 1 mod", "two": "With $n mods", @@ -342,7 +509,7 @@ "many": "$n T-spins total", "other": "$n T-spins total" }, - "lineClears(plural)": { + "linesCleared(plural)": { "zero": "$n lines cleared", "one": "$n line cleared", "two": "$n lines cleared", @@ -372,7 +539,7 @@ "many": "$n games", "other": "$n games" }, - "lineClears(map)": { + "lineClear": { "single": "Single", "double": "Double", "triple": "Triple", @@ -395,8 +562,19 @@ "eicosa": "Eicosa", "kagaris": "Kagaris" }, + "lineClears": { + "zero": "Zeros", + "single": "Singles", + "double": "Doubles", + "triple": "Triples", + "quad": "Quads", + "penta": "Pentas" + }, + "mini": "Mini", "tSpin": "T-spin", - "spin": "Spin" + "tSpins": "T-spins", + "spin": "Spin", + "spins": "Spins" }, "countries(map)": { "": "Worldwide",