visual-game.js 37.8 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
export default {
  appName: 'voko.world',
  productBrandSub: 'O seu kosmo está chamando.',
  mobileCredit: { title: 'Meus créditos', buyCredits: 'Comprar créditos', history: 'Histórico de créditos', purchaseHistory: 'Compras', usageHistory: 'Uso', emptyHistory: 'Ainda não há histórico.', loadMore: 'Carregar mais', balanceAfter: 'Saldo: {points}', pending: 'Pendente', paid: 'Pago', canceled: 'Cancelado', failed: 'Falhou', refunded: 'Reembolsado', disputed: 'Em disputa', autoReload: 'Recarga automática', bonusCredits: 'Créditos bônus', buyNow: 'Comprar agora', lowBalance: 'Saldo baixo', enabled: 'Ativada', whenBelow: 'Quando meu saldo ficar abaixo de', choosePack: 'Escolha um pacote', consent: 'Autorizo a Voko a comprar automaticamente este pacote quando meu saldo atingir o limite.', terms: 'Termos de Uso', continueSecurely: 'Continuar com segurança', save: 'Salvar configurações', disable: 'Desativar recarga', setupComplete: 'Forma de pagamento salva e recarga ativada.', setupCanceled: 'Configuração cancelada.', actionRequired: 'A última recarga falhou. Configure novamente a forma de pagamento.', howTitle: 'Como funciona', howBalance: 'Compramos o pacote escolhido quando o saldo atinge o limite.', howSecure: 'A Stripe armazena os dados de pagamento; a Voko não guarda o número do cartão.', howCancel: 'Você pode desativar a qualquer momento. Compras anteriores não são reembolsadas.' },
  nav: { play: 'Jogar', notes: 'Pistas', state: 'Estado', editor: 'Autoria' },
  scenario: { title: 'Cenário', available: 'Cenários', assetManifest: 'Recursos' },
  character: { title: 'Personagem', start: 'Iniciar', current: 'Personagem atual' },
  stage: { empty: 'Escolha cenário e personagem', turn: 'Turno {turn}', ending: 'Final', transcript: 'Registro' },
  composer: { act: 'Agir', say: 'Falar', placeholder: 'Digite uma ação ou fala' },
  actions: { refresh: 'Atualizar', start: 'Iniciar', home: 'Início', backHome: 'Voltar', newRun: 'Reiniciar', send: 'Enviar', save: 'Salvar', compile: 'Compilar', publish: 'Publicar', rollback: 'Reverter', upload: 'Enviar', select: 'Selecionar', endingText: 'Texto final', load: 'Carregar', backToGame: 'Voltar', cancel: 'Cancelar', confirm: 'Confirmar' },
  account: {
    signIn: 'Entrar',
    signedIn: 'Conectado',
    signedOut: 'Desconectado',
    sessionExpired: 'Sua sessão expirou. Entre novamente.',
    logoutFailed: 'Falha ao sair. Tente novamente.',
    registered: 'Registrado',
    email: 'Email',
    emailPlaceholder: 'Endereço de email',
    password: 'Senha',
    passwordPlaceholder: 'Digite a senha',
    confirmPassword: 'Confirmar senha',
    confirmPasswordPlaceholder: 'Digite a senha novamente',
    verificationCode: 'Código de verificação',
    verificationCodePlaceholder: 'Código de 6 dígitos',
    inviteToken: 'Código de convite',
    inviteTokenPlaceholder: 'Digite o código de convite de 8 caracteres',
    sendCode: 'Enviar código',
    resendCode: 'Reenviar',
    codeSent: 'Código enviado. Verifique seu email.',
    codeRequired: 'Digite primeiro o código de verificação.',
    inviteInvalid: 'Digite um código de convite válido de 8 caracteres.',
    emailRequired: 'Digite primeiro seu email.',
    emailInvalid: 'Digite um email válido.',
    passwordRequired: 'Digite primeiro sua senha.',
    confirmPasswordRequired: 'Confirme sua senha primeiro.',
    loginFieldsRequired: 'Digite seu email e senha.',
    inviteEmailMismatch: 'Este email não corresponde ao email da solicitação vinculado ao código de convite.',
    passwordMismatch: 'As senhas não coincidem.',
    createAccount: 'Criar conta',
    hasAccount: 'Já tem conta?',
    noAccount: 'Ainda não tem conta?',
    termsHint: 'Ao continuar, você confirma que este email é seu e aceita salvar progresso, pedidos e créditos.',
    login: 'Entrar',
    register: 'Registrar',
    reset: 'Redefinir',
    forgotPassword: 'Esqueceu a senha?',
    resetPassword: 'Redefinir senha',
    resetTitle: 'Redefinir senha',
    resetBody: 'Verifique o código enviado por email e defina uma nova senha. As sessões antigas serão revogadas.',
    resetCodeSent: 'Código de redefinição enviado. Verifique seu email.',
    resetFieldsRequired: 'Informe o email, o código, a nova senha e a confirmação da senha.',
    passwordResetDone: 'Senha redefinida. Entre com a nova senha.',
    logout: 'Sair',
    logoutAll: 'Sair de todos os dispositivos',
    credits: 'Créditos',
    buy: 'Comprar créditos',
    billing: 'Cobrança',
    promptTitle: 'Entre ou registre-se para começar',
    promptBody: 'Sua conta salva progresso, saves, finais, créditos e pedidos para continuar em outro dispositivo.',
    signedInBody: 'Seu progresso, saves e créditos são gravados no banco de dados.',
    registerAndStart: 'Registrar e escolher papel',
    guestStart: 'Testar como convidado',
    savedHint: 'Entre para salvar progresso e saves automaticamente',
    currentAccount: 'Conta atual',
    saveKicker: 'Salvar conta',
    saveTitle: 'Salvar progresso e pedidos',
    loginTitle: 'Entrar',
    loginBody: 'Após entrar, o progresso convidado deste dispositivo será mesclado quando possível.',
    registerTitle: 'Criar conta',
    registerBody: 'Cadastre-se com um código de convite e confirme seu email. O registro entra automaticamente, concede 100 créditos e mescla o progresso do dispositivo.',
    openBilling: 'Ver créditos e pedidos',
    mergePending: 'Mesclando progresso convidado deste dispositivo...',
    mergeSuccess: 'Dados locais mesclados: {details}.',
    mergeSeparator: ', ',
    mergeRuns: '{count} runs',
    mergeTurns: '{count} turnos',
    mergeProgress: '{count} registros de progresso',
    mergeSaveSlots: '{count} saves',
    mergeEndingRecords: '{count} finais',
    mergeEvents: '{count} eventos',
    mergeAgentCalls: '{count} chamadas de IA',
    mergeBillingLedger: '{count} lançamentos de saldo',
    mergeBillingUnlocks: '{count} desbloqueios pagos',
    mergeBillingFreeQuota: '{count} cotas grátis',
    mergePaymentOrders: '{count} pedidos',
    mergeEmpty: 'Não há progresso local para mesclar.',
    mergeFailed: 'Você entrou, mas o progresso local não foi mesclado. Atualize e tente mais tarde.',
  },
  billing: {
    title: 'Créditos e pedidos',
    subtitle: 'Saldo, recargas, lançamentos e pedidos vêm do banco de dados.',
    guestSubtitle: 'Convidados podem ver pacotes. Compra, saldo, pedidos e lançamentos exigem login.',
    balance: 'Saldo atual',
    products: 'Pacotes de créditos',
    ledger: 'Lançamentos',
    orders: 'Pedidos',
    refresh: 'Atualizar cobrança',
    testModeTitle: 'Ambiente de teste do Stripe',
    testModeBody: 'O checkout usa pagamentos de teste e não gera cobranças reais.',
    testPurchase: 'Compra de teste',
    buy: 'Comprar {points} créditos',
    checkoutReady: 'Link de checkout pronto.',
    openCheckout: 'Abrir checkout',
    selectedPack: 'Selecionado',
    selectedProduct: '{title} selecionado. Seu saldo aumentará em {points} créditos.',
    signInToBuy: 'Entrar para comprar',
    readyToBuy: 'Pronto para comprar créditos',
    readyToBuyBody: 'Escolha um pacote e siga para o checkout. Pedidos podem aparecer em processamento antes da confirmação.',
    checkoutPending: 'Redirecionando para checkout...',
    checkoutReturnedSuccess: 'Você voltou ao app. Atualizando saldo e pedidos; o crédito depende do status do pedido.',
    checkoutReturnedCancel: 'Checkout cancelado ou não concluído. Nenhum crédito confirmado.',
    signInHint: 'Entre para ver saldo, pedidos e lançamentos.',
    emptyProducts: 'Nenhum pacote de créditos.',
    emptyLedger: 'Nenhum lançamento.',
    emptyOrders: 'Nenhum pedido.',
    productFallback: 'Pacote de créditos',
    points: '{points} créditos',
    price: '{amount} {currency}',
    ledgerAmount: '{amount} créditos',
    orderStatus: 'Status {status}',
    orderStatusPending: 'Processando',
    orderStatusPaid: 'Pago',
    orderStatusRefunded: 'Reembolsado',
    orderStatusDisputed: 'Em disputa',
    orderStatusUnknown: 'Status desconhecido',
    ledgerReasonSignupGift: 'Bônus de registro',
    ledgerReasonCheckout: 'Compra de créditos',
    ledgerReasonRefund: 'Reembolso de pedido',
    ledgerReasonChargeback: 'Reversão de disputa',
    ledgerReasonUnlock: 'Desbloqueio de conteúdo',
    paywallTitle: 'Desbloqueio pago',
    paywallTarget: 'Alvo',
    paywallReason: 'Motivo da cobrança',
    paywallGenericReason: 'Créditos são necessários para continuar este conteúdo.',
    paywallFreeContinue: 'Ainda há cota grátis. Você pode continuar.',
    paywallInsufficient: 'Créditos insuficientes. Compre créditos primeiro.',
    paywallPrice: 'Créditos necessários',
    paywallFreeQuota: 'Cota grátis restante',
    paywallBalance: 'Saldo disponível',
  },
  endings: {
    title: 'Coleção de finais',
    unlocked: 'Desbloqueado',
    locked: 'Bloqueado',
    collected: 'Coletados {count}/{total}',
    lockedHint: 'Alcance este final para desbloqueá-lo.',
  },
  saves: {
    title: 'Salvamentos',
    progress: 'Progresso atual',
    activeRun: 'Jogo atual',
    slot: 'Slot {slotNo}',
    savedRun: 'Progresso salvo',
    emptySlot: 'Slot vazio',
    emptyHint: 'Salve a run atual para restaurar após recarregar.',
    saveHere: 'Salvar',
    overwrite: 'Sobrescrever',
    restore: 'Carregar',
    delete: 'Excluir',
    saved: 'Salvamento gravado.',
    restored: 'Salvamento carregado.',
    deleted: 'Salvamento excluído.',
    conflict: 'Já existe um salvamento. Confirme antes de sobrescrever este ponto.',
    restoreConfirm: 'Carregar mudará o jogo atual para este ponto salvo.',
    deleteConfirm: 'Excluir este ponto salvo não pode ser desfeito.',
    noRunHint: 'Não há run atual para salvar. Inicie ou continue uma run primeiro.',
  },
  map: {
    title: 'Mapa',
    current: 'Local atual',
    route: 'Rota disponível',
    routes: 'Destinos disponíveis',
    locked: 'Bloqueado',
    moveTo: 'Ir para {location}',
    objects: 'Objetos investigáveis',
    inspect: 'Investigar',
    inspected: 'Investigado',
    inspectObject: 'Investigar {object}',
  },
  videoCenter: {
    eyebrow: 'Partidas dos jogadores',
    title: 'Central de vídeos',
    backHome: 'Voltar',
    chooseScenario: 'Escolher cenário',
    allScenarios: 'Todos os cenários',
    searchScenario: 'Buscar cenários',
    scenarioPaintedSkin: 'Pele pintada',
    scenarioGuian: 'O caso do coração perdido de Guian',
    nowPlaying: 'Reproduzindo',
    player: 'Jogador',
    views: 'Visualizações',
    ending: 'Final',
    duration: 'Duração',
    libraryEyebrow: 'Mais deste cenário',
    allVideos: 'Todos os vídeos',
    sort: 'Ordem dos vídeos',
    recommended: 'Recomendados',
    latest: 'Mais recentes',
    videoMeta: '{player} · {date}',
    emptyTitle: 'Ainda não há vídeos',
    emptyText: 'Não há partidas públicas para este cenário.',
    viewAll: 'Ver todos os vídeos de jogadores',
    discoverStories: 'Veja as escolhas de outros',
    backPrevious: 'Voltar', aiSummary: 'Resumo IA:', endingCount: ' finais', publicSeriesCount: ' séries públicas', totalPlays: ' reproduções', seriesList: 'Séries de jogadores', completed: 'Concluída', updating: 'Episódio {count} · Em andamento', seriesMetrics: '{episodes} episódios · ▶ {plays} · ♥ {likes}', watchSeries: 'Assistir esta série', playOwnSeries: 'Crie sua própria série', minutes: '{count} min', share: 'Compartilhar', shareCopied: 'Link copiado', shareFailed: 'Não foi possível compartilhar o vídeo', like: 'Curtir', liked: 'Curtido', save: 'Salvar', saved: 'Salvo', storyHighlight: 'Destaques da história', startPlay: 'Começar a jogar · Reescrever o final', episodeList: 'Episódios', episodeTotal: '{count} episódios', episodeTitle: 'Episódio {count} · {title}',
  },
  runHistory: {
    eyebrow: 'Registros pessoais',
    title: 'Minhas partidas',
    allRuns: 'Todas as partidas',
    count: '{count} registros',
    empty: 'Ainda não há registros. Comece uma partida e ela aparecerá aqui.',
    loadFailed: 'Falha ao carregar: {error}',
    noTime: 'Hora desconhecida',
    statusActive: 'Em andamento',
    statusCompleted: 'Encerrada',
    videoNone: 'Sem vídeo',
    videoQueued: 'Vídeo na fila',
    videoRunning: 'Gerando vídeo',
    videoReady: 'Vídeo pronto',
    videoFailed: 'Vídeo falhou',
    videoRetry: 'Gerar novamente',
    untitledEnding: 'Sem final ainda',
    meta: '{scenario} · Turno {turn} · {date}',
    openRun: 'Abrir partida',
    openNotes: 'Notas',
    watchVideo: 'Assistir vídeo',
  },
  mobileProfile: { title: 'MEU PERFIL', settings: 'Configurações', content: 'Conteúdo', benefits: 'Benefícios', creator: 'Criador', support: 'Dúvidas e suporte', contact: 'Suporte ao cliente', terms: 'Termos de Uso', privacy: 'Política de Privacidade', social: 'Redes sociais' },
  profileEditor: { editProfile: 'Editar perfil', nameSection: 'Nome do perfil', nameHint: 'Este nome aparece ao lado dos seus jogos e vídeos.', name: 'Nome', saveName: 'Salvar nome', nameRequired: 'Digite seu nome.', nameSaved: 'Seu nome foi atualizado.', passwordSection: 'Alterar senha', passwordHint: 'Confirme sua identidade com o código enviado ao seu e-mail.', email: 'E-mail', verificationCode: 'Código de verificação', sendCode: 'Enviar código', codeSent: 'Um código foi enviado ao seu e-mail.', newPassword: 'Nova senha', confirmPassword: 'Confirmar nova senha', savePassword: 'Atualizar senha', passwordRequirements: 'Digite o código e uma senha com pelo menos 8 caracteres.', passwordMismatch: 'As senhas não coincidem.', passwordSaved: 'Sua senha foi atualizada.' },
  myGames: { recent: 'Jogados recentemente', popular: 'Histórias populares', emptyRecent: 'As histórias jogadas recentemente aparecerão aqui.', loadError: 'Não foi possível carregar seus jogos. Tente novamente.' },
  storyDetail: { title: 'Informações da história', description: 'Descrição', episodes: '{count} episódios', endings: '{count} finais', by: 'Por {name}', lastUpdate: 'Última atualização', newPlay: 'Novo jogo', notFound: 'Esta história não foi encontrada.', loadError: 'Não foi possível carregar a história.' },
  accountCenter: { loadFailed: 'Não foi possível carregar o perfil', loadTimeout: 'A solicitação expirou. Verifique a conexão e tente novamente.', title: 'Central pessoal', eyebrow: 'Perfil do jogador', runs: 'Meus jogos', videos: 'Coleção de vídeos', favorites: 'Favoritos', watchSeason: 'Ver temporada', emptyGames: 'Você ainda não iniciou nenhum jogo.', emptyVideos: 'Ainda não há vídeos gerados.', emptyFavorites: 'Ainda não há vídeos favoritos.', lastPlayed: 'Última partida · {date}', currentTurn: 'Em andamento · Turno {turn}', noActiveRun: 'Nenhuma partida ativa', endingsUnlocked: 'Finais {unlocked}/{total}', runsPlayed: '{count} partidas', continueGame: 'Continuar jogo', startGame: 'Iniciar jogo', viewHistory: 'Ver histórico', levelProgress: '{played}/{total} fases jogadas', viewSeasonDetails: 'Ver detalhes da temporada', hideSeasonDetails: 'Ocultar detalhes', levelInProgress: 'Em andamento', levelCompleted: 'Concluído', endingLabel: 'Final alcançado', cluesLabel: 'Pistas obtidas', clueCount: '{count} pistas', viewRunRecords: 'Ver registros do jogo', runRecordSummary: '{clues} pistas · {ending} final', noEnding: 'Nenhum final alcançado ainda', noClues: 'Nenhuma pista encontrada ainda', seasonDetailsLoadFailed: 'Não foi possível carregar a temporada. Tente novamente.', public: 'Público', private: 'Só eu', deleteVideo: 'Excluir vídeo', confirmDelete: 'Confirmar exclusão', signInTitle: 'Entre primeiro', signInBody: 'Entre para gerenciar seus jogos e vídeos.' },
  visual: {
    eyebrow: 'TRPG Visual',
    chooseScript: 'Escolher roteiro',
    actTitle: 'Ato {count} · {title}',
    actLocked: '{title} está bloqueado',
    actSealed: 'Ato selado',
    toBeContinued: 'Continua',
    finishPreviousAct: 'Alcance um final no ato anterior',
    revealAfterAct: 'Revelado após concluir o Ato {count}',
    moreScripts: 'Mais níveis',
    comingSoon: 'Em breve',
    watchScriptVideo: 'Assistir ao vídeo da história',
    scenarioKicker: 'Roteiro',
    hiddenTitle: 'Tianyou',
    revealedTitle: 'Pele pintada',
    objectives: 'Objetivos atuais',
    playHistory: 'Registro de jogo',
    objectiveLabel: 'Objetivo',
    close: 'Fechar',
    noObjectives: 'Nenhum objetivo ativo.',
    taskProgress: 'Etapas {done}/{total}',
    entryKicker: 'Entrar no jogo',
    entryTitle: 'Entrar no quarto hoje',
    emptyScenarioEyebrow: 'Roteiro indisponível',
    emptyScenarioTitle: 'Nenhum roteiro jogável',
    emptyScenarioText: 'O servidor não retornou um roteiro publicado. Atualize ou verifique o estado de publicação.',
    emptyScenarioActionTitle: 'Aguardando publicação',
    emptyScenarioActionText: 'O app não inicia um roteiro local falso sem dados reais.',
    continueTitle: 'Continuar última run',
    entryBody: 'Escolha um personagem antes de entrar na casa antiga.',
    chooseCharacter: 'Escolher personagem',
    enterStory: 'Entrar na história',
    back: 'Voltar',
    skip: 'Pular',
    editor: 'Editor',
    debugPage: 'Depurar',
    state: 'Estado',
    settings: 'Configurações',
    language: 'Idioma',
    languageUnavailable: 'Este nível ainda não tem uma tradução disponível para esse idioma.',
    turnVideoMatching: 'Correspondência inteligente de CG',
    turnVideoMatchingHint: 'Quando ativada, procura CGs de cenas semelhantes para este turno. Desativada, só toca CGs vinculados exatamente.',
    turnVideoMatchingOn: 'Ativada',
    turnVideoMatchingOff: 'Desativada',
    exitGame: 'Sair do jogo',
    exitGameHint: 'Saia da sessão atual e volte à seleção de cenários.',
    saveAndExit: 'Salvar e sair',
    exitWithoutSaving: 'Sair sem salvar',
    notes: 'Notas',
    saves: 'Salvamentos',
    continueRun: 'Continuar run',
    balanceEntry: 'Saldo {credits}',
    endingCollection: 'Coleção de finais',
    narrator: 'Narrador',
    npcName: 'Mulher no quarto',
    npcLine: '"{line}"',
    notStarted: 'Não iniciado',
    startHint: 'Pressione iniciar para entrar na casa velha.',
    debug: 'Depurar atributos',
    debugOnly: 'Somente depuração',
    waiting: 'Aguardando.',
    modeAct: 'Agir',
    modeSay: 'Falar',
    inputMethod: 'Método de entrada',
    textInputMode: 'Texto',
    voiceInputMode: 'Voz',
    choiceGroupLabel: 'Escolhas da história',
    inputPlaceholder: 'Exemplo: ergo o espelho de bronze para ela e para o retrato.',
    mobileInputPlaceholder: 'Fale ou aja…',
    voiceStart: 'Iniciar entrada de voz',
    voiceStop: 'Parar entrada de voz',
    voiceListening: 'Ouvindo…',
    voiceRecognizing: 'Reconhecendo…',
    voiceUnsupported: 'Este navegador não oferece suporte à entrada de voz',
    voicePermissionDenied: 'O acesso ao microfone foi negado. Verifique as permissões do navegador',
    voiceMicrophoneUnavailable: 'Nenhum microfone disponível foi encontrado',
    voiceNoSpeech: 'Nenhuma fala foi reconhecida. Tente novamente',
    voiceNoAudioCaptured: 'Áudio do microfone não capturado. Verifique as permissões do navegador',
    voiceRecognitionFailed: 'Falha no reconhecimento de voz. Tente novamente',
    voiceHoldToTalk: 'Segure para falar',
    voicePreparing: 'A preparar o microfone…',
    voiceShortcutLabel: 'Atalho',
    voiceReleaseSend: 'Solte para enviar',
    voiceSlideCancel: 'Deslize para cima para cancelar',
    voiceReleaseCancel: 'Solte para cancelar',
    voiceUnderstanding: 'Entendendo seu comando…',
    ending: 'Final',
    endingLabel: 'Final',
    endingLine: 'Final: {title}\n{description}',
    endingSummary: 'Resumo do final',
    endingPoem: 'Poema final',
    endingFallbackPoem: '...',
    endingBackgroundLoadFailed: 'Não foi possível carregar a cena final. Atualize a página e tente novamente.',
    recordSeal: 'Caso',
    recordTitle: 'Registro do guarda',
    recordKicker: 'Arquivo do condado',
    recordMeta: 'Depois da noite chuvosa',
    continue: 'Continuar',
    enterNextEpisode: 'Entrar no próximo episódio',
    viewCurrentSeasonStory: 'Ver esta temporada',
    played: 'Reproduzido',
    nextPage: 'Próxima página',
    statusCreating: 'Preparando sua história...',
    statusStarted: 'Iniciado. Digite uma fala ou ação.',
    statusHistoryRun: 'Visualizando uma partida antiga. Continuar usa o progresso do servidor.',
    statusKp: 'KP está julgando...',
    statusDone: 'Turno concluído.',
    contentFiltered: 'Esta ação não pode ser descrita. Tente agir de outra forma.',
    turnFailed: 'Não foi possível concluir esta etapa. Tente novamente.',
    audioFailed: 'Não foi possível reproduzir a voz. Tente novamente.',
    actionRejected: 'Essa ação ainda não pode funcionar. Tente outra abordagem.',
    statusEnded: 'Jogo encerrado.',
    statusEndingText: 'Gerando texto final...',
    statusEndingLocked: 'Final determinado. Entrando no final...',
    statusNpcAction: 'NPC está tentando agir. Aguardando julgamento do KP...',
    statusNpcDone: 'NPC respondeu.',
    clueGained: 'Pista obtida',
    landscapeTitle: 'Gire o dispositivo',
    landscapeBody: 'Jogue na horizontal para ver toda a cena e as imagens CG.',
    stats: {
      suspicion: 'Suspeita',
      charm: 'Encanto',
      fear: 'Medo',
    },
    guide: {
      label: 'Guia',
      skip: 'Pular',
      next: 'Próximo',
      done: 'Entendi',
      optionsTitle: 'Escolher diretamente',
      optionsText: 'Após a resposta do NPC, duas sugestões aparecem: falar ou agir.',
      keyboardTitle: 'Mudar para entrada pelo teclado',
      keyboardText: 'A entrada por voz é o padrão. Toque no botão do teclado para escrever o que você diz ou faz.',
      inputTitle: 'Escolher Falar ou Agir',
      inputText: 'Antes de escrever, escolha se você vai falar ou agir. O KP avaliará qualquer uma das opções.',
      notesTitle: 'Ver notas',
      notesText: 'O botão de notas registra pistas descobertas e finais desbloqueados.',
      goalTitle: 'Sobreviver',
      goalText: 'Não é só conversa. Escute, mas observe o quarto, as pistas e as anomalias.',
      videoTitle: 'Complete a história e transforme sua aventura em um vídeo só seu',
      videoExampleLabel: 'Vídeo de exemplo',
      videoExampleNotice: 'Este vídeo é apenas um exemplo e não representa o conteúdo gerado a partir da sua partida.',
      videoLoading: 'Carregando um vídeo de exemplo…',
      videoUnavailable: 'Esta história ainda não tem um vídeo de exemplo.',
      videoDone: 'Começar minha história',
    },
    openingOptions: {
      say: 'Desculpe, eu não queria invadir. Algo lá fora estava me perseguindo.',
      act: 'Falar baixo e observar portas, janelas, a lamparina e a posição dela.',
    },
  },
  panels: { clues: 'Pistas', conclusions: 'Conclusões', info: 'Informações', inventory: 'Inventário', events: 'Eventos', stats: 'Atributos', flags: 'Marcadores', objects: 'Objetos', npcs: 'NPCs', endingRecords: 'Finais desbloqueados' },
  standalone: {
    summary: 'Resumo',
    availableClues: 'Pistas disponíveis',
    recentTurns: 'Turnos recentes',
    audit: {
      title: 'Auditoria de IA',
      subtitle: 'Custos e falhas de chamadas KP, NPC, finais e TTS.',
      totalCalls: 'Chamadas',
      failedCalls: 'Falhas',
      tokens: 'Tokens entrada/saída',
      cost: 'Custo',
      roles: 'Resumo por papel',
      models: 'Resumo por modelo',
      recentCalls: 'Chamadas recentes',
      empty: 'Nenhuma chamada de IA registrada.',
      calls: '{count} chamadas',
      tokenPair: 'tokens {tokens}',
    },
    state: {
      title: 'Visualização de estado',
      waiting: 'Aguardando RunState.',
      noRun: 'Sem runId. Abra pelo jogo ou digite um runId.',
      loading: 'Carregando {runId}...',
      loaded: '{runId} carregado',
    },
    notes: {
      title: 'Notas',
      waiting: 'Carregando notas.',
      noRun: 'Nenhum save atual encontrado. Inicie ou continue uma run primeiro.',
      loading: 'Carregando {runId}...',
      loaded: '{runId} carregado',
      unavailable: 'As notas desta partida estão temporariamente indisponíveis.',
      emptyClues: 'Ainda não há pistas',
      emptyConclusions: 'Ainda não há conclusões',
      emptyEndings: 'Ainda não há finais',
      tabs: 'Categorias de notas',
      list: 'Lista de entradas',
      detail: 'Detalhe da entrada',
      locked: 'Bloqueado',
      lockedHint: 'Este final ainda não foi registrado.',
      recorded: 'Registrado',
      importance: { minor: 'Secundária', major: 'Importante', critical: 'Crítica' },
      relatedClues: 'Pistas relacionadas',
      noRelatedClues: 'Nenhuma pista de apoio foi encontrada ainda.',
    },
  },
  editor: {
    title: 'Autoria de cenário',
    pack: 'Pacote',
    section: 'Seção',
    raw: 'JSON',
    structured: 'Editor estruturado',
    debugJson: 'JSON de depuração',
    item: 'Item',
    noStructuredFields: 'Esta seção ainda não tem campos estruturados editáveis diretamente.',
    updated: 'Salvo',
    assetUploaded: 'Asset enviado ao rascunho',
    compiled: 'Rascunho compilado',
    published: 'Versão publicada',
    rolledBack: 'Versão revertida',
    versions: 'Versões',
    assets: 'Índice de assets',
    current: 'Atual',
    currentVersion: 'Versão atual',
    noPublishedVersion: 'Não publicado',
    noVersions: 'Ainda não há versões. Compile um rascunho primeiro.',
    noAssets: 'Ainda não há índice de assets. Compile o manifesto primeiro.',
    noFilteredAssets: 'Nenhum asset corresponde aos filtros.',
    assetSearch: 'Buscar',
    assetSearchPlaceholder: 'Tag, arquivo ou objectKey',
    assetTypeFilter: 'Tipo',
    assetSourceFilter: 'Origem',
    assetFilterAll: 'Todos',
    assetFilterResult: '{shown}/{total}',
    assetSource: {
      uploaded: 'Objeto enviado',
      static: 'Arquivo estático',
      missing: 'Localizador ausente',
    },
    uploadFile: 'Arquivo',
    uploadTag: 'Tag',
    uploadTagPlaceholder: 'opening_cg',
    uploadType: 'Tipo',
    noUploadFile: 'Nenhum arquivo',
  },
  waitingList: {
    eyebrow: 'Acesso antecipado',
    apply: 'Solicitar acesso',
    useInvite: 'Usar código de convite',
    invitedRegister: 'Tem um convite? Criar conta',
    title: 'Entre na waiting list do servidor de jogo',
    body: 'Informe email e caso de uso. Operadores enviarão convites pelo admin.',
    displayName: 'Nome',
    displayNamePlaceholder: 'Opcional',
    useCase: 'Caso de uso',
    useCaseOptional: 'Caso de uso (opcional)',
    useCasePlaceholder: 'Teste de equipe, criador, evento',
    useCaseRequired: 'O caso de uso é obrigatório.',
    consent: 'Aceito receber emails de convite e produto desta waiting list.',
    join: 'Entrar',
    joined: 'Solicitação recebida. Aguarde a notificação por email.',
    joinedTitle: 'Solicitação enviada',
    changeEmail: 'Usar outro email',
    accountAlreadyRegistered: 'Este email já está cadastrado. Entre na sua conta.',
    emailRequired: 'Email é obrigatório.',
    consentRequired: 'Consentimento de email é necessário antes de entrar.',
    inviteEyebrow: 'Convite',
    inviteTitle: 'Crie sua conta voko.world',
    inviteBody: 'Este convite está vinculado ao seu email. Defina uma senha para concluir o cadastro.',
    inviteMissing: 'Token de convite ausente.',
    inviteEnterCode: 'Digite o código de convite de 8 caracteres que você recebeu para criar uma conta.',
    inviteValidate: 'Verificar código',
    inviteReenter: 'Inserir outro código',
    inviteInvalid: 'Convite inválido ou expirado.',
    codeSent: 'Código de verificação enviado.',
    passwordMismatch: 'As senhas não coincidem.',
    acceptInvite: 'Criar conta',
  },
  landing: { officialVideo: 'Ver o vídeo oficial', officialVideoEyebrow: 'Conheça VOKO', officialVideoTitle: 'O seu mundo está chamando.', officialVideoBody: 'Crie seu próprio mundo, viva histórias que chamam você de volta e compartilhe cada momento como um vídeo que vale assistir.', homeLabel: 'Início do voko.world', navHome: 'Home', navScripts: 'Histórias', navVideos: 'Vídeos', featuredStories: 'Histórias em destaque', featuredStoriesEyebrow: 'Comece a jogar', endingCount: '{count} finais', allStories: 'Todas as histórias', dramaTitle: 'Drama', brandSub: 'Histórias interativas', navLabel: 'Navegação principal', navStories: 'Jogos', navGallery: 'Galeria', eyebrow: 'RPG visual com IA', loadError: 'Não foi possível carregar a página.', retry: 'Tentar novamente', emptyGames: 'Ainda não há jogos publicados.', scenarioFallback: 'Mude a história com suas escolhas.', publicVideos: 'vídeos de jogadores', publicGames: 'jogos públicos', watchDrama: 'Assistir drama', enterPlay: 'Começar a jogar', comingSoon: 'Em breve', carouselLabel: 'Carrossel de jogos', previousGame: 'Jogo anterior', nextGame: 'Próximo jogo', showcaseTitle: 'Histórias criadas por jogadores', showcaseBody: 'Veja outros finais e crie sua própria versão.', searchLabel: 'Buscar histórias', searchPlaceholder: 'Buscar pelo título', sortLabel: 'Ordenação', latest: 'Recentes', popular: 'Populares', videoCount: '{count} vídeos', levelCount: '{count} níveis', levelNumber: 'Nível {count}', singleLevel: 'Nível independente', publicGame: 'Jogo público', noSearchResults: 'Nenhuma história encontrada', clearSearch: 'Limpar busca', finalEyebrow: 'Sua história está esperando', finalTitle: 'Quem você será?', finalBody: 'Atravesse o limiar e diga suas primeiras palavras.', begin: 'Começar a jornada', footer: '© 2026 voko.world', earlyAccess: 'Acesso antecipado', footerSocial: 'Comunidade', footerLegal: 'Legal e contato', privacy: 'Política de Privacidade', terms: 'Termos de Serviço', contact: 'Email de contato' },
  landingCarousel: { introEyebrow: 'Jogo dramático generativo', introSummary: 'Assista a um drama curto, entre no papel e mude a história com suas escolhas.', dramaEyebrow: 'Drama em destaque {count}', controls: 'Carrossel inicial', goToSlide: 'Ir para o slide {count}' },
  landingCinema: { navHome: 'Início', navDramas: 'Jogo', navPlayerStories: 'Dramas', navMy: 'Eu', featuredDramas: 'Jogos', playerStories: 'Dramas' },
  searchPage: { placeholder: 'Buscar histórias, dramas ou contas', popular: 'Pesquisas populares', history: 'Pesquisas recentes', clearHistory: 'Limpar', resultTypes: 'Tipos de resultado', all: 'Tudo', accounts: 'Conta', accountStats: '{titles} títulos · {plays} reproduções' },
  landingIntro: { title: 'voko.world', apply: 'Solicitar acesso', watchVideo: 'Ver vídeos', start: 'Iniciar jogo', continue: 'Continuar jogo', viewJourney: 'Histórico de jogo', continueProgress: 'Temporada {season}  {scenario}', storyLine: 'Linha narrativa', viewMore: 'Ver mais' },
  storyTree: {
    eyebrow: 'Linhas de temporada',
    subtitle: 'Cada linha é uma temporada e cada nó é uma fase.',
    root: 'Drama',
    branch: 'Ramo',
    active: 'Em andamento',
    completed: 'Concluído',
    locked: 'Não alcançado',
    empty: 'Ainda não há linhas de temporada.',
    loadError: 'Falha ao carregar as linhas de temporada.',
    navigation: 'Intervalo de temporadas',
    range: 'Temporadas {first}–{last} · {total} no total',
    newer: 'Anterior',
    older: 'Próximo',
    startPlaying: 'Jogar agora',
    turnProgress: 'Turno {turn}',
    continuePlaying: 'Continuar jogando',
    playLog: 'Registro de jogo',
    seasonEnding: 'Final da temporada',
    currentSeason: 'Temporada atual',
    logLoadError: 'Falha ao carregar o registro.',
    logEmpty: 'Ainda não há histórico nesta temporada.',
    turnNumber: 'Turno {turn}',
    playerSaid: 'Você disse',
    playerDid: 'Você fez',
    storyOpening: 'Início da história',
    turnVideos: 'Vídeos correspondentes',
    playActionVideo: 'Vídeo de ação',
    playPlayerVideo: 'Vídeo do jogador',
    playNpcVideo: 'Vídeo do NPC',
    replayTurn: 'Rever',
    replayTurnTitle: 'Repetição do turno {turn}',
    replayProgress: 'Trecho {current}/{total}',
    actionSegment: 'Ação',
    playerSpeechSegment: 'Fala do jogador',
    npcSpeechSegment: 'Fala do NPC',
    pauseReplay: 'Pausar',
    continueReplay: 'Continuar',
    restartReplay: 'Repetir',
    exportReplay: 'Exportar replay',
    replayQueued: 'Na fila',
    replayExporting: 'Exportando',
    playFullReplay: 'Reproduzir tudo',
    retryReplayExport: 'Tentar novamente',
    downloadReplay: 'Baixar MP4',
    downloadSegment: 'Baixar este trecho',
    downloadTurn: 'Baixar turno completo',
    turnExporting: 'Preparando vídeo do turno',
    turnExportError: 'Falha ao exportar o turno.',
    segmentExporting: 'Preparando trecho',
    segmentExportError: 'Falha ao exportar o trecho.',
    fullReplayTitle: '{title} · Replay completo',
    replayExportError: 'Falha ao exportar o replay.',
    videoLoadError: 'Não foi possível carregar o vídeo.',
    tools: 'Pesquisar, filtrar e ordenar histórias',
    search: 'Pesquisar',
    searchPlaceholder: 'Pesquisar fase, final ou ação recente',
    filter: 'Status',
    filterAll: 'Todas',
    filterInProgress: 'Em andamento',
    filterCompleted: 'Concluídas',
    sort: 'Ordenar',
    sortRecent: 'Jogado recentemente',
    sortSeasonDesc: 'Temporada decrescente',
    sortSeasonAsc: 'Temporada crescente',
    resultCount: '{count} temporadas',
    noResults: 'Nenhuma história corresponde aos critérios.',
    canvasHint: 'Arraste a tela ou role para ver as fases à direita',
    canvasLabel: 'Tela da árvore da história com movimento horizontal',
    storySwitch: 'História',
  },
  storyTreeCurrentSeasonHint: 'Progresso mais recente',
  storyTreeViewDetails: 'Ver detalhes da temporada {number}',
  storyTreeDelete: { action: 'Excluir ramo', confirm: 'Excluir a temporada {number} e todos os ramos derivados? Esta ação não pode ser desfeita.', deleting: 'Excluindo…', error: 'Não foi possível excluir o ramo.' },
  storyTreeVideoUnavailable: 'Vídeo indisponível',
  storyTreeFork: { action: 'Jogar novamente daqui', confirm: 'Uma nova ramificação será criada a partir do turno {turn}. O histórico atual não será alterado.', failed: 'Não foi possível criar a nova ramificação. Tente novamente.', creating: 'Criando…' },
  runVideoGeneration: { title: 'Gerar vídeo completo', description: 'Gere um vídeo completo desta partida. Os pontos são cobrados após a confirmação e devolvidos se a geração falhar.', generate: 'Gerar vídeo', regenerate: 'Gerar novamente', retry: 'Tentar novamente', queued: 'Na fila', running: 'Gerando', price: 'Pontos necessários', balance: 'Saldo atual', balanceAfter: 'Saldo após a cobrança' },
  landingShowcase: { title: 'Vidas em cena', body: 'Veja os destinos traçados por outros jogadores, entre na história e escreva seu próprio final.' },
  landingMetrics: { playCount: 'Reproduções', likeCount: 'Curtidas' },
  landingCard: { level: 'Episódio', searchPlaceholder: 'Encontre histórias, vídeos ou jogadores', scriptFilter: 'Drama', scriptAll: 'Todos os dramas', playerVideoCount: '{count} vídeos públicos', publishedAt: 'Publicado', publishedAll: 'Tudo', publishedToday: 'Hoje', publishedWeek: 'Últimos 7 dias', publishedMonth: 'Últimos 30 dias', expandSynopsis: 'Ver mais', collapseSynopsis: 'Ver menos' },
  playerPage: { loadError: 'Não foi possível carregar os vídeos do jogador.', notFound: 'Jogador não encontrado ou sem vídeos públicos.', searchPlaceholder: 'Buscar dramas, fases ou temporadas' },
  season: { choose: 'Escolha uma temporada', chooseBody: 'Este episódio continuará a história da temporada escolhida.', number: 'Temporada {number}', empty: 'Conclua o episódio anterior de uma temporada antes de continuar.' },
  status: { loading: 'Carregando', empty: 'Sem dados', error: 'Falha ao carregar', streaming: 'Processando' },
  storiesPage: { tags: 'Tags de histórias', allTags: 'Todas', swipeForNextStory: 'Deslize para cima para ver a próxima história' },
  creator: { nav: 'Criar', queued: 'Na fila', attachmentTypeError: 'Envie um arquivo TXT, PDF, Word, PNG, JPG ou WEBP.', attachmentSizeError: 'O anexo deve ter no máximo 10 MB.', attachmentReadError: 'Não foi possível ler o anexo.', generationFailed: 'Falha na geração', reviewRejected: 'Revisão rejeitada', published: 'Publicado', archived: 'Arquivado', composerTitle: 'Que mundo você quer criar hoje?', submitIdea: 'Enviar ideia', examplesNote: 'Jogos publicados reais exibidos como referência visual.', exampleStatus: 'Exemplo publicado', projectsEyebrow: 'Visual Game Creator', projectsTitle: 'Meus jogos', projectsBody: 'Gerencie seus jogos e acompanhe a geração e revisão.', newGame: 'Criar novo jogo', draftStatus: 'Rascunho', continueEditing: 'Continuar editando', generatedScopes: 'itens de geração', emptyTitle: 'Crie seu primeiro jogo', emptyBody: 'Comece com uma ideia, roteiro ou universo e transforme-o em um jogo.', eyebrow: 'Visual Game Creator', title: 'Transforme sua história em um mundo jogável', subtitle: 'Compartilhe uma ideia, roteiro ou universo. O sistema criará, produzirá e validará o jogo.', stepIdea: 'Ideia', stepGenerate: 'Gerar', stepReview: 'Revisão', ideaTitle: 'Descreva seu jogo', ideaBody: 'Escreva naturalmente. Você não precisa conhecer JSON.', ideaLabel: 'Ideia ou roteiro', ideaHint: 'Inclua mundo, personagens, conflito e experiência.', ideaPlaceholder: 'Um viajante acorda numa hospedaria onde todos lembram uma noite diferente…', ideaError: 'Digite pelo menos 20 caracteres.', languageLabel: 'Idioma', languages: { zh: 'Chinês', en: 'Inglês', ja: 'Japonês', ko: 'Coreano' }, scopeTitle: 'Gerar agora', scopeStory: 'História e fases', scopeStoryBody: 'Personagens, missões, estados e finais', scopeVisuals: 'Mídia visual', scopeVisualsBody: 'Personagens, cenas, objetos e vídeos', scopeVoice: 'Vozes', scopeVoiceBody: 'Jogador, NPC e narração', scopeError: 'Selecione ao menos um item.', assetsTitle: 'Material de referência', assetsBody: 'Opcional. Ajuda a manter a consistência.', uploadAction: 'Adicionar arquivos', uploadHint: 'Um arquivo · TXT, PDF, Word, PNG, JPG ou WEBP · até 10 MB', supportedTitle: 'Material compatível', supportedBody: 'Imagens, roteiros, documentos, vídeo e áudio.', removeFile: 'Remover {name}', saved: 'Rascunho salvo.', draftNote: 'Esta primeira versão salva um rascunho local.', save: 'Salvar rascunho' },
  labels: { scenario: 'Cenário', asset: 'Recurso', mode: 'Modo', phase: 'Fase', location: 'Local', noRun: 'Não iniciado', none: 'Nenhum' },
}