bf46b9492d
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 21s
CI / ui (pull_request) Successful in 1m25s
CI / conformance (pull_request) Successful in 11s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 2m2s
Board-highlight bug (reported on the contour): formedGeometry walked cross words
unconditionally, so in a single-word (one-word-per-turn) game a staged tile sitting
next to a committed tile lit up a green "cross word" the engine ignores — and which
need not even be a real word (the reported "БО lights up green in a one-word ПОПА
play"). Gate the cross-word walk on the game's multipleWordsPerTurn flag. The score
(8) was already correct — a premium square under the main word.
Also, from review:
- the turn strip reads the staged play's "WORD+WORD = N" while composing a legal move,
reverting to the turn / result text otherwise;
- the Exchange/Pass dialog shows the bag count ("In the bag: N" / "Bag is empty")
right-aligned in the title row, via a new optional Modal `titleAside`;
- cosmetics: half the turn strip's bottom padding (the plaques below carry their own
top pad); a top gap above the landscape rack (it sat flush under the docked history);
more horizontal padding on tab count badges so a 2-3 digit bag count clears the pill
ends;
- admin console: the game Summary now shows the single-word / multiple-words rule.
Tests: formed single-word case added; full unit (584) + e2e (chromium + webkit, 113
each) green; backend build + adminconsole templates parse. Docs (FUNCTIONAL +_ru,
UI_DESIGN) updated.
466 lines
19 KiB
TypeScript
466 lines
19 KiB
TypeScript
// English message catalog (authoritative). Keys are flat dotted strings; ru.ts must
|
||
// provide exactly the same keys (enforced by its type and a Vitest parity test).
|
||
// {name} placeholders are filled by t(key, params).
|
||
|
||
export const en = {
|
||
'app.title': 'Scrabble',
|
||
'app.brand': 'Erudit',
|
||
'dict.loading': 'Loading…',
|
||
'connection.connecting': 'Connecting…',
|
||
'maintenance.title': 'Under maintenance',
|
||
'maintenance.body': 'Scrabble is briefly down for an update. It will be back in a moment — no need to reload the page.',
|
||
'maintenance.retry': 'Try again',
|
||
|
||
'blocked.title': 'Account blocked',
|
||
'blocked.permanent': 'Your account is blocked.',
|
||
'blocked.temporary': 'Your account is blocked until {until}.',
|
||
'blocked.reason': 'Reason:',
|
||
|
||
'boot.errorTitle': "Couldn't load the game",
|
||
'boot.errorBody': 'Please try again in a moment.',
|
||
|
||
'launch.errorTitle': "Can't open in Telegram",
|
||
'launch.errorBody': 'Screenshot or share this with the developer.',
|
||
'launch.share': 'Share',
|
||
'launch.copied': 'Copied',
|
||
|
||
'common.back': 'Back',
|
||
'common.cancel': 'Cancel',
|
||
'common.ok': 'OK',
|
||
'common.close': 'Close',
|
||
'common.loading': 'Loading…',
|
||
'common.retry': 'Retry',
|
||
'common.you': 'You',
|
||
'common.save': 'Save',
|
||
|
||
'login.title': 'Sign in',
|
||
'login.guest': 'Play as guest',
|
||
'login.email': 'Email',
|
||
'login.emailPlaceholder': 'you@example.com',
|
||
'login.sendCode': 'Send code',
|
||
'login.codePlaceholder': '6-digit code',
|
||
'login.signIn': 'Sign in',
|
||
'confirm.busy': 'Confirming your email…',
|
||
'confirm.linked': 'Email confirmed.',
|
||
'confirm.merge': 'Almost done — finish the merge in the app.',
|
||
'confirm.close': 'You can close this window and return to the game.',
|
||
'confirm.expired': 'This link is invalid or has expired. Request a new code.',
|
||
'login.codeSent': 'We sent a code to {email}.',
|
||
|
||
'lobby.activeGames': 'Active games',
|
||
'lobby.finishedGames': 'Finished games',
|
||
'lobby.noActive': 'No active games yet.',
|
||
'lobby.noFinished': 'No finished games yet.',
|
||
'lobby.limitReached': "You've reached the simultaneous games limit.",
|
||
'lobby.new': 'Play',
|
||
'lobby.stats': 'Stats',
|
||
'lobby.profile': 'Profile',
|
||
'lobby.settings': 'Settings',
|
||
'lobby.about': 'About',
|
||
'lobby.yourTurn': 'Your turn',
|
||
'lobby.theirTurn': 'Their turn',
|
||
'lobby.hideGame': 'Remove from list',
|
||
'lobby.vs': 'vs {opponents}',
|
||
|
||
'new.title': 'New game',
|
||
'new.english': 'Scrabble',
|
||
'new.russian': 'Скрэббл',
|
||
'new.erudit': 'Erudite',
|
||
'new.find': 'Find a game',
|
||
'new.searching': 'Looking for an opponent…',
|
||
'new.rulesEnglish': '100 tiles · bingo +50',
|
||
'new.rulesRussian': '104 tiles · ё is a letter · bingo +50',
|
||
'new.rulesErudit': '131 tiles · ё = е · no centre ×2 · bonus +15',
|
||
'new.moveLimit': 'Move time: {n} h 00 min',
|
||
'new.searchHint':
|
||
'Finding an opponent can sometimes take a while. If you do not want to wait, close the app after starting the game and come back in a couple of minutes.',
|
||
|
||
// First-run coachmark hints (components/Coachmark.svelte). The leading emoji in each comment
|
||
// names the UI element the bubble's tail points at.
|
||
'onboarding.lobbySettings': 'Friends, game & profile settings, feedback', // ⚙️
|
||
'onboarding.lobbyStats': 'Stats refresh after each game with an opponent', // ✏️
|
||
'onboarding.lobbyNew': 'Practise against the AI', // 🎲
|
||
'onboarding.gameHeader': 'Move history, chat and word check', // scoreboard strip
|
||
'onboarding.gameTurn': 'Pass a turn, swap tiles', // 🔄
|
||
'onboarding.gameHints': 'Available hints', // 🛟
|
||
'onboarding.gameShuffle': 'Shuffle your tiles', // 🔀
|
||
'onboarding.gameRack': 'Pick a tile and place it on the board', // rack
|
||
|
||
'game.bag': '{n} in the bag',
|
||
'game.bagCount': 'In the bag: {n}',
|
||
'game.bagEmpty': 'Bag is empty',
|
||
'game.hints': 'Hints {n}',
|
||
'game.yourTurn': 'Your turn',
|
||
'game.yourTurnBy': '{name}: Your turn!',
|
||
'game.opponentsTurn': "Opponent's turn",
|
||
'game.searchingForOpponent': 'Waiting for opponent…',
|
||
'game.waiting': "Waiting for {name}",
|
||
'game.makeMove': 'Make move',
|
||
'game.reset': 'Reset',
|
||
'game.draw': 'Exchange/Pass',
|
||
'game.shuffle': 'Shuffle',
|
||
'game.hint': 'Hint',
|
||
'game.hintLockedIn': 'Available in {n} min.',
|
||
'game.chat': 'Chat',
|
||
'game.checkWord': 'Check word',
|
||
'game.dictionary': 'Dictionary',
|
||
'game.dropGame': 'Drop game',
|
||
'game.oneWordRule': 'One word per turn',
|
||
'game.chooseBlank': 'Choose a letter for the blank',
|
||
'game.exchangeTitle': 'Exchange or pass',
|
||
'game.exchangeConfirm': 'Exchange {n}',
|
||
'game.passNoExchange': 'Pass without exchanging',
|
||
'game.confirmResign': 'Resign this game?',
|
||
'game.hintShown': 'Best move: {word} for {n}',
|
||
'game.won': 'You won',
|
||
'game.lost': 'You lost',
|
||
'game.tied': 'Draw',
|
||
'game.abortedNote': 'This game could not be continued by the organizer and was ended in a draw.',
|
||
'game.checkWordPrompt': 'Enter a word',
|
||
'game.wordLegal': '“{word}” is valid',
|
||
'game.wordIllegal': '“{word}” is not valid',
|
||
'game.complain': 'Disagree',
|
||
'game.lookup': 'Look it up',
|
||
'game.complaintSent': 'Thanks, sent for review.',
|
||
'game.check': 'Check',
|
||
'game.checkWait': 'Please wait a moment.',
|
||
'game.noHintOptions': 'No options with your letters.',
|
||
'game.thinking': 'thinking…',
|
||
|
||
'move.pass': 'pass',
|
||
'move.exchange': 'exchange',
|
||
'move.resign': 'resign',
|
||
'move.timeout': 'timeout',
|
||
|
||
'result.victory': 'Victory',
|
||
'result.defeat': 'Defeat',
|
||
'result.draw': 'Draw',
|
||
'result.place2': 'II place',
|
||
'result.place3': 'III place',
|
||
'result.place4': 'IV place',
|
||
'result.yourMove': 'Your move',
|
||
'result.oppMove': "Opponent's move",
|
||
|
||
'chat.placeholder': 'Quick message…',
|
||
'chat.send': 'Send',
|
||
'chat.nudge': 'Waiting for your move 🤭',
|
||
'chat.nudgeBy': '{name}: Waiting for your move 🤭',
|
||
'chat.nudgeAction': 'Nudge',
|
||
'chat.awaitingReply': "Let's be patient",
|
||
'chat.empty': 'No messages yet.',
|
||
'chat.nudged': '{name} nudged you',
|
||
'chat.sentThisTurn': 'You can write again next turn.',
|
||
|
||
'profile.title': 'Profile',
|
||
'profile.language': 'Language',
|
||
'profile.timezone': 'Time zone',
|
||
'profile.hintBalance': 'Hint balance',
|
||
'profile.guest': 'Guest account',
|
||
'profile.edit': 'Edit profile',
|
||
'profile.displayName': 'Display name',
|
||
'profile.awayWindow': 'Away window',
|
||
'profile.awayHint': 'You are not auto-resigned during these hours.',
|
||
'profile.from': 'From',
|
||
'profile.to': 'To',
|
||
'profile.blockChat': 'Disable chat',
|
||
'profile.blockFriendRequests': 'Disable friend requests',
|
||
'profile.notificationsInAppOnly': 'Notifications in the app only',
|
||
'profile.preferences': 'Preferences',
|
||
'profile.preferencesHint': 'The game variants you can be matched into. Pick at least one.',
|
||
'profile.email': 'Email',
|
||
'profile.bindEmail': 'Bind email',
|
||
'profile.emailCode': 'Confirmation code',
|
||
'profile.emailSent': 'We sent a code to {email}.',
|
||
'profile.emailBound': 'Email confirmed.',
|
||
'profile.saved': 'Profile saved.',
|
||
'profile.guestLocked': 'Sign in with email to manage your profile.',
|
||
'profile.linkAccount': 'Link an account',
|
||
'profile.linkTelegram': 'Link Telegram',
|
||
'profile.linkVK': 'Link VK',
|
||
'profile.linked': 'Account linked.',
|
||
'profile.merged': 'Accounts merged.',
|
||
'profile.mergeTitle': 'Merge accounts?',
|
||
'profile.mergeBody': 'This identity already belongs to “{name}” ({games} games, {friends} friends).',
|
||
'profile.mergeIrreversible': 'Merging combines both accounts into this one and cannot be undone.',
|
||
'profile.mergeConfirm': 'Merge',
|
||
'profile.accountsTitle': 'Sign-in methods',
|
||
'profile.changeEmail': 'Change',
|
||
'profile.newEmailPlaceholder': 'New email address',
|
||
'profile.emailChanged': 'Email updated.',
|
||
'profile.emailChangeTaken': 'Check the address or contact support.',
|
||
'profile.unlink': 'Unlink',
|
||
'profile.unlinked': 'Account unlinked.',
|
||
'profile.unlinkTitle': 'Unlink account?',
|
||
'profile.unlinkBody': 'Remove {provider} as a sign-in method? You can link it again later.',
|
||
'profile.deleteAccount': 'Delete account',
|
||
'profile.deleteTitle': 'Delete your account?',
|
||
'profile.deleteWarn': 'This removes your account and frees your sign-in methods. It cannot be undone.',
|
||
'profile.deleteEmailPrompt': 'We sent a code to your email. Enter it to delete your account.',
|
||
'profile.deletePhrasePrompt': 'Type DELETE to confirm.',
|
||
'profile.deletePhrasePlaceholder': 'DELETE',
|
||
'profile.deleteConfirm': 'Delete permanently',
|
||
'deleted.title': 'Account deleted',
|
||
'deleted.body': 'Your account has been removed. Reopening the app just creates a new account.',
|
||
|
||
'settings.title': 'Settings',
|
||
'settings.theme': 'Theme',
|
||
'settings.themeAuto': 'Auto',
|
||
'settings.themeLight': 'Light',
|
||
'settings.themeDark': 'Dark',
|
||
'settings.language': 'Interface language',
|
||
'settings.boardStyle': 'Board style',
|
||
'settings.boardLabels': 'Bonus labels',
|
||
'settings.labelsBeginner': 'Beginner',
|
||
'settings.labelsClassic': 'Classic',
|
||
'settings.labelsNone': 'None',
|
||
'settings.reduceMotion': 'Reduce motion',
|
||
'settings.zoomBoard': 'Zoom the board',
|
||
'settings.offlineMode': 'Play mode',
|
||
'settings.online': 'Online',
|
||
'settings.offline': 'Offline',
|
||
'settings.offlineChecking': 'Loading dictionaries…',
|
||
'settings.offlineNeedsData': 'Not enough data on the device. Internet access is needed to download it.',
|
||
'offline.preloadWarning': 'Poor internet connection. Some features may be unavailable.',
|
||
'offline.promptTitle': 'No connection. Enable offline mode?',
|
||
'offline.promptYes': 'Enable',
|
||
'offline.promptNo': 'Keep trying',
|
||
|
||
// --- wallet ---
|
||
'wallet.title': 'Wallet',
|
||
'wallet.tab': 'Wallet',
|
||
'wallet.balance': 'Balance',
|
||
'wallet.noChips': 'No chips yet',
|
||
'wallet.source.vk': 'VK',
|
||
'wallet.source.telegram': 'Telegram',
|
||
'wallet.source.direct': 'Web',
|
||
'wallet.viewOnly': 'view only',
|
||
'wallet.benefits': 'Benefits',
|
||
'wallet.noAdsUntil': 'No ads until {date}',
|
||
'wallet.noAdsForever': 'No ads forever',
|
||
'wallet.adsOn': 'Ads are on',
|
||
'wallet.hints': 'Hints {n}',
|
||
'wallet.store': 'Store',
|
||
'wallet.empty': 'The store is empty for now',
|
||
'wallet.buy': 'Buy',
|
||
'wallet.rewardWatch': 'Watch an ad for {n} 🪙',
|
||
'wallet.rewardCta': 'Watch',
|
||
'wallet.rewardCredited': '+{n} 🪙 for watching',
|
||
'wallet.rewardCapped': "You've reached today's reward limit",
|
||
'wallet.rewardFailed': 'The ad could not be shown',
|
||
'wallet.offer': 'Public offer',
|
||
'wallet.platformNoBuy': 'Purchases are not available on this platform',
|
||
'wallet.iosBlockedPre': 'Purchases on iOS are prohibited by Apple policy. Try the ',
|
||
'wallet.iosBlockedLink': 'other version',
|
||
'wallet.iosBlockedPost': ' of the game.',
|
||
'wallet.gpStub': 'To buy chips, install the RuStore build.',
|
||
'wallet.cur.RUB': '₽',
|
||
'wallet.cur.VOTE': 'votes',
|
||
'wallet.cur.XTR': '⭐',
|
||
'wallet.warnTitle': 'Web-only purchase',
|
||
'wallet.warnBody':
|
||
'This spends your VK/Telegram chips, and the benefit will work on the web and in the app only — because of store rules.',
|
||
'wallet.warnConfirm': 'Continue',
|
||
'wallet.warnCancel': 'Cancel',
|
||
'about.title': 'About',
|
||
'about.tab': 'Info',
|
||
'about.description': 'A multiplatform Scrabble game.',
|
||
'about.version': 'Version {v}',
|
||
|
||
'feedback.title': 'Feedback',
|
||
'feedback.placeholder': 'Describe the problem or share your suggestion…',
|
||
'feedback.attach': 'Attach file',
|
||
'feedback.removeFile': 'Remove',
|
||
'feedback.send': 'Send',
|
||
'feedback.fileRejected': 'This file can’t be attached.',
|
||
'feedback.sent': 'Your message has been sent.',
|
||
'feedback.waiting': 'We are reviewing your last message.',
|
||
'feedback.banned': 'Feedback submission is unavailable.',
|
||
'feedback.replyTitle': 'Reply to your last message',
|
||
|
||
'landing.tagline': 'Play Scrabble with friends, random opponent or an AI.',
|
||
'landing.playTelegram': 'Play in Telegram',
|
||
'landing.playVK': 'Play on VK',
|
||
'landing.playWeb': 'Play in your browser',
|
||
'landing.captionTelegram': 'Telegram',
|
||
'landing.captionVK': 'VK',
|
||
'landing.captionWeb': 'Web',
|
||
'landing.offer': 'Public offer',
|
||
|
||
'install.title': 'Install the app',
|
||
'install.subtitle': 'Put the app icon on your desktop (home screen) to open the game in one tap.',
|
||
'install.iosTitle': 'Add to Home Screen',
|
||
'install.iosStep1': 'Tap the Share button in the browser toolbar.',
|
||
'install.iosStep2': 'Choose “Add to Home Screen”.',
|
||
'install.iosStep3': 'Tap “Add”.',
|
||
|
||
'lang.en': 'English',
|
||
'lang.ru': 'Русский',
|
||
|
||
'error.not_your_turn': "It is not your turn.",
|
||
'error.nudge_own_turn': 'It is your turn — there is no one to nudge.',
|
||
'error.illegal_play': 'That is not a legal play.',
|
||
'error.hint_unavailable': 'No hints available.',
|
||
'error.no_hint_available': 'No options with your letters.',
|
||
'error.chat_rejected': 'Message rejected (too long or contains contact info).',
|
||
'error.nudge_too_soon': "Please don't rush your opponent so often.",
|
||
'error.chat_not_your_turn': 'You can chat only on your turn.',
|
||
'error.chat_already_sent': 'You can send only one message per turn.',
|
||
'error.game_finished': 'This game is finished.',
|
||
'error.not_a_player': 'You are not a player in this game.',
|
||
'error.already_queued': 'You are already in the queue.',
|
||
'error.email_taken': 'That email belongs to another account.',
|
||
'error.code_invalid': 'Invalid or expired code.',
|
||
'error.invalid_email': 'Enter a valid email address.',
|
||
'error.invalid_config': 'Invalid game settings.',
|
||
'error.not_found': 'Not found.',
|
||
'error.session_invalid': 'Your session expired. Please sign in again.',
|
||
'error.unauthenticated': 'Please sign in.',
|
||
'error.rate_limited': 'Too many requests, slow down.',
|
||
'error.unavailable': 'Connection problem. Retrying…',
|
||
'error.internal': 'Something went wrong.',
|
||
'error.generic': 'Something went wrong.',
|
||
|
||
'lobby.invitations': 'Invitations',
|
||
'lobby.friends': 'Friends',
|
||
|
||
'friends.title': 'Friends',
|
||
'friends.yours': 'Your friends',
|
||
'friends.none': 'No friends yet.',
|
||
'friends.incoming': 'Friend requests',
|
||
'friends.accept': 'Accept',
|
||
'friends.decline': 'Decline',
|
||
'friends.unfriend': 'Remove',
|
||
'friends.block': 'Block',
|
||
'friends.actions': 'Actions',
|
||
'friends.blockConfirm': 'Block this player?',
|
||
'friends.unfriendConfirm': 'Remove from friends?',
|
||
'friends.add': 'Add a friend',
|
||
'friends.addFromGame': 'Add to friends',
|
||
'friends.blockFromGame': 'Block player',
|
||
'friends.requestSent': 'Friend request sent.',
|
||
'friends.getCode': 'Show my code',
|
||
'friends.codeHint': 'Give this code to a friend within 12 hours.',
|
||
'friends.codeExpires': 'Expires at {time}',
|
||
'friends.enterCode': 'Have a code? Add a friend',
|
||
'friends.codePlaceholder': '6-digit code',
|
||
'friends.redeem': 'Add',
|
||
'friends.copy': 'Copy',
|
||
'friends.codeCopied': 'Code copied.',
|
||
'friends.shareTelegram': 'Share',
|
||
'friends.inviteText': "Let's play Scrabble!",
|
||
'friends.linkCopied': 'Link copied.',
|
||
'friends.selfInvite': "Hopefully you've been friends with yourself for a while ☺️",
|
||
'friends.staleInviteTitle': 'Link expired',
|
||
'friends.staleInvite': 'You opened the game from an outdated link. Open the bot {bot} to play and get notifications.',
|
||
'friends.welcomeRedeemTitle': 'Welcome!',
|
||
'friends.welcomeRedeem': 'Welcome, {name}!\n\nUse {bot} to join games the most convenient way.',
|
||
'friends.added': 'Added {name}.',
|
||
'friends.blockedList': 'Blocked players',
|
||
'friends.unblock': 'Unblock',
|
||
'friends.noneBlocked': 'No blocked players.',
|
||
|
||
'invitations.none': 'No invitations.',
|
||
'invitations.from': 'From {name}',
|
||
'invitations.with': 'With {names}',
|
||
'invitations.accept': 'Accept',
|
||
'invitations.decline': 'Decline',
|
||
'invitations.declineConfirm': 'Decline invitation?',
|
||
'invitations.cancel': 'Cancel',
|
||
'invitations.waiting': 'Waiting for replies',
|
||
|
||
'new.auto': 'Quick match',
|
||
'new.withFriends': 'Play with friends',
|
||
'new.pickFriends': 'Choose who to invite',
|
||
'new.searchFriends': 'Search friends',
|
||
'new.gameType': 'Variant',
|
||
'new.invite': 'Send invitation',
|
||
'new.moveTime': 'Move time',
|
||
'new.hintsPerPlayer': 'Hints',
|
||
'new.multipleWordsPerTurn': 'Multiple words per turn',
|
||
'new.start': 'Start game',
|
||
'new.invited': 'Invitation sent.',
|
||
'new.limitGuestTitle': 'More games?',
|
||
'new.limitGuestBody': 'Sign in or create an account to use all the game features.',
|
||
'new.limitDurableTitle': 'Game limit',
|
||
'new.limitDurableBody': 'You have reached the limit. Finish your active games to start a new one.',
|
||
'new.limitLogin': 'Sign in',
|
||
'new.noFriends': 'Add friends first to invite them.',
|
||
'new.opponentAI': 'AI',
|
||
'new.opponentRandom': 'Random player',
|
||
'new.aiInactiveLimit': 'Loss after 7 days of inactivity',
|
||
|
||
'stats.title': 'Statistics',
|
||
'stats.wins': 'Wins',
|
||
'stats.losses': 'Losses',
|
||
'stats.draws': 'Draws',
|
||
'stats.played': 'Games',
|
||
'stats.moves': 'Moves',
|
||
'stats.hintShare': 'Hint share',
|
||
'stats.winRate': 'Win rate',
|
||
'stats.maxGame': 'Best game',
|
||
'stats.maxWord': 'Best move',
|
||
'stats.guestHint': 'Sign in to track your statistics.',
|
||
|
||
'game.exportGcg': 'Export game',
|
||
'game.exportChoice': 'Export the finished game as:',
|
||
'game.exportImageOpt': 'Image (PNG)',
|
||
'game.exportGcgOpt': 'GCG file',
|
||
'game.gcgActiveOnly': 'Available once the game is finished.',
|
||
'game.gcgCopied': 'GCG copied to the clipboard.',
|
||
'game.addFriendShort': 'Add friend?',
|
||
'game.blockShort': 'Block?',
|
||
|
||
'time.minutes': '{n} min',
|
||
'time.hours': '{n} h',
|
||
|
||
'error.self_relation': 'You cannot do that to yourself.',
|
||
'error.request_exists': 'A request or friendship already exists.',
|
||
'error.request_blocked': 'This player is not accepting requests.',
|
||
'error.request_not_found': 'No matching friend request.',
|
||
'error.no_shared_game': 'You can only add someone you have played with.',
|
||
'error.request_declined': 'This player declined your request.',
|
||
'error.friend_code_invalid': 'That friend code is invalid or expired.',
|
||
'error.invalid_invitation': 'Invalid invitation.',
|
||
'error.invitation_blocked': 'You cannot invite this player.',
|
||
'error.invitation_not_found': 'Invitation not found.',
|
||
'error.invitation_not_pending': 'This invitation is no longer open.',
|
||
'error.invitation_expired': 'This invitation has expired.',
|
||
'error.not_invited': 'You were not invited.',
|
||
'error.already_responded': 'You already responded.',
|
||
'error.not_inviter': 'Only the inviter can do that.',
|
||
'error.game_active': 'Available only after the game is finished.',
|
||
'error.invalid_profile': 'Some profile fields are invalid.',
|
||
'error.already_confirmed': 'This email is already confirmed.',
|
||
|
||
'pin.enter': 'Enter PIN',
|
||
'pin.create': 'Create a PIN',
|
||
'pin.repeat': 'Repeat the PIN',
|
||
'pin.enterCurrent': 'Enter current PIN',
|
||
'pin.mismatch': "PINs don't match",
|
||
'pin.wrong': 'Wrong PIN',
|
||
'pin.setNew': 'Set a new PIN',
|
||
'pin.remove': 'Remove PIN',
|
||
|
||
'hotseat.hostPin': 'Host password',
|
||
'hotseat.setPin': 'Password',
|
||
'hotseat.changePin': 'Change',
|
||
'hotseat.playerName': 'Player name',
|
||
'hotseat.addPlayer': 'Add player',
|
||
'hotseat.removePlayer': 'Remove player',
|
||
'hotseat.hostPlaysTitle': 'Are you playing too?',
|
||
'hotseat.hostPlaysYes': 'Yes, I play',
|
||
'hotseat.hostPlaysNo': 'No',
|
||
'hotseat.unlock': 'Unlock',
|
||
'hotseat.unlockTitle': 'Unlock: {name}',
|
||
'hotseat.turnOf': 'Turn: {name}',
|
||
'hotseat.host': 'Host',
|
||
'hotseat.skip': 'Skip the current turn',
|
||
'hotseat.exclude': 'Exclude a player:',
|
||
'hotseat.terminate': 'End the game',
|
||
'hotseat.askSkip': "Skip {name}'s turn?",
|
||
'hotseat.askExclude': 'Remove {name} from the game?',
|
||
'hotseat.askTerminate': 'End the game with no result?',
|
||
} as const;
|
||
|
||
export type MessageKey = keyof typeof en;
|