38be7fea96
- Screen.svelte shell: nav bar grows, ad+content+tabbar pinned bottom (mobile feel) - AdBanner.svelte + banner.ts rotator (params, mock long/short, linkify); Header CSS chevron + grow; Menu (bigger CSS hamburger); TabBar + HoldConfirm shared components; user-select:none - Lobby: hide-empty sections, tab order New/Tournaments/Stats, place-based result badges (result.ts) - Settings: Board style > Labels (beginner/classic/none) + prefs plumbing (boardlabels.ts); i18n keys + ru mirror
149 lines
5.0 KiB
TypeScript
149 lines
5.0 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',
|
|
|
|
'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',
|
|
'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.new': 'New',
|
|
'lobby.stats': 'Stats',
|
|
'lobby.tournaments': 'Tourn.',
|
|
'lobby.profile': 'Profile',
|
|
'lobby.settings': 'Settings',
|
|
'lobby.about': 'About',
|
|
'lobby.yourTurn': 'Your turn',
|
|
'lobby.theirTurn': 'Their turn',
|
|
'lobby.vs': 'vs {opponents}',
|
|
'lobby.soon': 'Coming soon',
|
|
|
|
'new.title': 'New game',
|
|
'new.subtitle': 'Auto-match with another player',
|
|
'new.english': 'English',
|
|
'new.russian': 'Russian',
|
|
'new.erudit': 'Эрудит',
|
|
'new.find': 'Find a game',
|
|
'new.searching': 'Looking for an opponent…',
|
|
|
|
'game.bag': 'Bag {n}',
|
|
'game.hints': 'Hints {n}',
|
|
'game.yourTurn': 'Your turn',
|
|
'game.waiting': "Waiting for {name}",
|
|
'game.makeMove': 'Make move',
|
|
'game.reset': 'Reset',
|
|
'game.draw': 'Draw',
|
|
'game.skip': 'Skip',
|
|
'game.shuffle': 'Shuffle',
|
|
'game.hint': 'Hint',
|
|
'game.history': 'History',
|
|
'game.chat': 'Chat',
|
|
'game.checkWord': 'Check word',
|
|
'game.dropGame': 'Drop game',
|
|
'game.preview': 'Scores {n}',
|
|
'game.previewIllegal': 'Not a legal move',
|
|
'game.chooseBlank': 'Choose a letter for the blank',
|
|
'game.exchangeTitle': 'Select tiles to exchange',
|
|
'game.exchangeConfirm': 'Exchange {n}',
|
|
'game.confirmResign': 'Resign this game?',
|
|
'game.hintShown': 'Best move: {word} for {n}',
|
|
'game.over': 'Game over',
|
|
'game.won': 'You won',
|
|
'game.lost': 'You lost',
|
|
'game.tied': 'Draw',
|
|
'game.checkWordPrompt': 'Enter a word',
|
|
'game.wordLegal': '“{word}” is valid',
|
|
'game.wordIllegal': '“{word}” is not valid',
|
|
'game.complain': 'Disagree',
|
|
'game.complaintSent': 'Thanks, sent for review.',
|
|
'game.confirm': 'Ok',
|
|
'game.check': 'Check',
|
|
'game.checkWait': 'Please wait a moment.',
|
|
'game.noHintOptions': 'No options with your letters.',
|
|
'game.scores': 'Scores: {n}',
|
|
|
|
'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': 'Nudge',
|
|
'chat.empty': 'No messages yet.',
|
|
'chat.nudged': '{name} nudged you',
|
|
|
|
'profile.title': 'Profile',
|
|
'profile.language': 'Language',
|
|
'profile.timezone': 'Time zone',
|
|
'profile.hintBalance': 'Hint balance',
|
|
'profile.guest': 'Guest account',
|
|
'profile.readonly': 'Editing your profile arrives in a later update.',
|
|
|
|
'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',
|
|
|
|
'about.title': 'About',
|
|
'about.description': 'A multiplatform Scrabble game.',
|
|
'about.version': 'Version {v}',
|
|
|
|
'lang.en': 'English',
|
|
'lang.ru': 'Русский',
|
|
|
|
'error.not_your_turn': "It is not your turn.",
|
|
'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.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.',
|
|
} as const;
|
|
|
|
export type MessageKey = keyof typeof en;
|