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' },
}