kasy-cli 1.29.0 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands/new.js +9 -1
- package/lib/scaffold/shared/post-build.js +45 -0
- package/lib/utils/i18n/messages-en.js +2 -2
- package/lib/utils/i18n/messages-es.js +57 -57
- package/lib/utils/i18n/messages-pt.js +61 -61
- package/package.json +1 -1
- package/templates/firebase/lib/core/bottom_menu/bottom_menu.dart +14 -1
- package/templates/firebase/lib/core/web_device_preview/web_device_preview.dart +1 -9
package/lib/commands/new.js
CHANGED
|
@@ -42,7 +42,7 @@ const { generateFirebaseProject } = require('../scaffold/backends/firebase/gener
|
|
|
42
42
|
const { generateSupabaseProject } = require('../scaffold/backends/supabase/generator');
|
|
43
43
|
const { generateApiProject } = require('../scaffold/backends/api/generator');
|
|
44
44
|
const { createProjectAndGetKeys, setupLinkedProject, checkLoggedIn, getOrgsList, getProjectsByOrg, getProjectKeys, classifyCreateError } = require('../scaffold/backends/supabase/deploy');
|
|
45
|
-
const { writeSupabaseGoogleAuthOptions, readSupabaseGoogleCredentials, getGoogleClientSecretViaGcloud, flutterfireConfigure, writeGoogleAuthOptions, writeGoogleIosUrlScheme, writeGoogleIosUrlSchemeFromClientId } = require('../scaffold/shared/post-build');
|
|
45
|
+
const { writeSupabaseGoogleAuthOptions, readSupabaseGoogleCredentials, getGoogleClientSecretViaGcloud, flutterfireConfigure, writeGoogleAuthOptions, ensureGoogleServiceInfoPlist, writeGoogleIosUrlScheme, writeGoogleIosUrlSchemeFromClientId } = require('../scaffold/shared/post-build');
|
|
46
46
|
const { toPackageName } = require('../scaffold/backends/firebase/tokens');
|
|
47
47
|
const { setupFromScratch, setupExistingProject, listBillingAccounts, listGcpOrganizations, checkGcloudAuth, getFirebaseAccount, getGcloudInstallInstructions, enableAuthProviders, ensureFirebaseAuthInitialized, registerDebugSha1 } = require('../scaffold/backends/firebase/setup-from-scratch');
|
|
48
48
|
const { enableAuthViaFirebaseCli } = require('../scaffold/backends/firebase/enable-auth-via-cli');
|
|
@@ -1857,6 +1857,10 @@ async function runNew(directory, { language: langHint = null, backend: backendHi
|
|
|
1857
1857
|
includeWeb: answers.includeWeb !== false,
|
|
1858
1858
|
});
|
|
1859
1859
|
rerunSpinner.stop(tr('new.google.refreshConfigs'));
|
|
1860
|
+
// flutterfire may not drop the iOS plist even with the iOS app
|
|
1861
|
+
// registered; the iOS Client ID below is read from it, so fetch it from
|
|
1862
|
+
// the Firebase API when missing.
|
|
1863
|
+
await ensureGoogleServiceInfoPlist(targetDir, answers.firebaseProjectId);
|
|
1860
1864
|
} else if (cliResult.error === 'support_email_required') {
|
|
1861
1865
|
ui.log.warn(tr('new.google.manualHint.noEmail'));
|
|
1862
1866
|
}
|
|
@@ -2074,6 +2078,10 @@ async function runNew(directory, { language: langHint = null, backend: backendHi
|
|
|
2074
2078
|
if (ffRerun.ok) {
|
|
2075
2079
|
const gaResult = await writeGoogleAuthOptions(targetDir);
|
|
2076
2080
|
printStepResult({ name: 'google-auth-options', ok: gaResult.ok, detail: gaResult.error }, language);
|
|
2081
|
+
// flutterfire sometimes doesn't drop the iOS GoogleService-Info.plist
|
|
2082
|
+
// even with the iOS app registered. Fetch it from the Firebase API so the
|
|
2083
|
+
// URL-scheme step (and native iOS Firebase/FCM) always has its config.
|
|
2084
|
+
await ensureGoogleServiceInfoPlist(targetDir, answers.firebaseProjectId);
|
|
2077
2085
|
const iosResult = await writeGoogleIosUrlScheme(targetDir);
|
|
2078
2086
|
printStepResult({ name: 'google-ios-url-scheme', ok: iosResult.ok, detail: iosResult.error }, language);
|
|
2079
2087
|
}
|
|
@@ -287,6 +287,50 @@ function syncGoogleIosUrlSchemeContent(infoPlistContent, reversedClientId) {
|
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Make sure ios/Runner/GoogleService-Info.plist exists. `flutterfire configure`
|
|
292
|
+
* is supposed to download it, but in practice it sometimes doesn't drop the iOS
|
|
293
|
+
* file even though the iOS app is registered in Firebase (the Android
|
|
294
|
+
* google-services.json still lands fine). When that happens the native iOS
|
|
295
|
+
* Firebase config is missing AND Google Sign-In's REVERSED_CLIENT_ID can't be
|
|
296
|
+
* read, so the URL-scheme step fails. We fetch the plist straight from the
|
|
297
|
+
* Firebase API (`firebase apps:sdkconfig IOS`) — the authoritative source — and
|
|
298
|
+
* write it ourselves. No-op when the file is already there. Best-effort.
|
|
299
|
+
*
|
|
300
|
+
* @returns {Promise<{ ok: boolean, existed?: boolean, error?: string }>}
|
|
301
|
+
*/
|
|
302
|
+
async function ensureGoogleServiceInfoPlist(projectDir, projectId) {
|
|
303
|
+
const plistPath = path.join(projectDir, 'ios', 'Runner', 'GoogleService-Info.plist');
|
|
304
|
+
if (await fs.pathExists(plistPath)) {
|
|
305
|
+
return { ok: true, existed: true };
|
|
306
|
+
}
|
|
307
|
+
if (!projectId) {
|
|
308
|
+
return { ok: false, error: 'GoogleService-Info.plist missing and no projectId to fetch it' };
|
|
309
|
+
}
|
|
310
|
+
// No app id: the CLI auto-selects the single iOS app in the project, which is
|
|
311
|
+
// exactly our case (kasy creates one iOS app per project).
|
|
312
|
+
const result = await run(
|
|
313
|
+
`firebase apps:sdkconfig IOS --project ${projectId}`,
|
|
314
|
+
projectDir,
|
|
315
|
+
120_000,
|
|
316
|
+
);
|
|
317
|
+
if (!result.ok) {
|
|
318
|
+
return { ok: false, error: (result.stderr || result.error || '').slice(0, 300) };
|
|
319
|
+
}
|
|
320
|
+
// The command prints a spinner line before the XML; keep only the plist body.
|
|
321
|
+
const xmlStart = result.stdout.indexOf('<?xml');
|
|
322
|
+
if (xmlStart === -1 || !result.stdout.includes('REVERSED_CLIENT_ID')) {
|
|
323
|
+
return { ok: false, error: 'Unexpected apps:sdkconfig output (no plist body)' };
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
await fs.ensureDir(path.dirname(plistPath));
|
|
327
|
+
await fs.writeFile(plistPath, result.stdout.slice(xmlStart), 'utf8');
|
|
328
|
+
return { ok: true, existed: false };
|
|
329
|
+
} catch (err) {
|
|
330
|
+
return { ok: false, error: `Failed to write GoogleService-Info.plist: ${err.message}` };
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
290
334
|
/**
|
|
291
335
|
* Register the REVERSED_CLIENT_ID from GoogleService-Info.plist as a URL scheme
|
|
292
336
|
* in ios/Runner/Info.plist so that Google Sign-In can redirect back to the app
|
|
@@ -886,6 +930,7 @@ module.exports = {
|
|
|
886
930
|
dartFix,
|
|
887
931
|
flutterfireConfigure,
|
|
888
932
|
writeGoogleAuthOptions,
|
|
933
|
+
ensureGoogleServiceInfoPlist,
|
|
889
934
|
writeGoogleIosUrlScheme,
|
|
890
935
|
writeSupabaseGoogleAuthOptions,
|
|
891
936
|
writeGoogleIosUrlSchemeFromClientId,
|
|
@@ -550,7 +550,7 @@ module.exports = {
|
|
|
550
550
|
'new.firebase.q.appName.hint': 'e.g.: My Amazing App',
|
|
551
551
|
'new.firebase.q.appName.required': 'App name is required.',
|
|
552
552
|
|
|
553
|
-
'new.firebase.q.bundleId': '
|
|
553
|
+
'new.firebase.q.bundleId': 'How would you like the unique identifier (Bundle ID) of your app?',
|
|
554
554
|
'new.firebase.q.bundleId.hint': 'It works like an address for your app, e.g.: com.mycompany.myapp',
|
|
555
555
|
'new.firebase.q.bundleId.invalid': 'Invalid format. Use: com.company.app',
|
|
556
556
|
'new.firebase.q.bundleId.required': 'Bundle ID is required.',
|
|
@@ -674,7 +674,7 @@ module.exports = {
|
|
|
674
674
|
'new.firebase.interactive.step2': '2. Upgrade to Blaze Plan (Pay-as-you-go): ',
|
|
675
675
|
'new.firebase.interactive.step3': '3. Enable Authentication (Email/Password): ',
|
|
676
676
|
|
|
677
|
-
'new.firebase.interactive.prompt1': 'Did you create the Firestore Database and
|
|
677
|
+
'new.firebase.interactive.prompt1': 'Did you create the Firestore Database and enable Authentication?',
|
|
678
678
|
'new.firebase.interactive.prompt2': 'Did you upgrade to the Blaze Plan? (Required for Cloud Functions)',
|
|
679
679
|
'new.firebase.interactive.googleAuthNote': '* Enable Google Sign-In manually (Email/Password and Anonymous are already enabled): ',
|
|
680
680
|
'new.firebase.interactive.billingNeeded': 'Blaze plan not yet active. Activate it at the link above, then wait.',
|
|
@@ -104,7 +104,7 @@ module.exports = {
|
|
|
104
104
|
'modules.feature.base.home.description': 'Pantalla principal de la app después del login',
|
|
105
105
|
'modules.feature.base.settings.description': 'Tema, idioma, cuenta y preferencias',
|
|
106
106
|
'modules.feature.base.notifications.description': 'Notificaciones push via Firebase Cloud Messaging (funciona con cualquier backend)',
|
|
107
|
-
'modules.feature.base.subscription.description': 'Pantalla y modelo de
|
|
107
|
+
'modules.feature.base.subscription.description': 'Pantalla y modelo de suscripción premium (añade RevenueCat para habilitar pagos reales)',
|
|
108
108
|
'modules.backend.firebase.description': 'Adapter de backend Firebase',
|
|
109
109
|
'modules.backend.supabase.description': 'Adapter de backend Supabase',
|
|
110
110
|
'modules.backend.api.description': 'Adapter de backend API REST/GraphQL',
|
|
@@ -116,7 +116,7 @@ module.exports = {
|
|
|
116
116
|
'modules.feature.web.description': 'Soporte Web/PWA',
|
|
117
117
|
'modules.feature.widget.description': 'Widget de pantalla inicial iOS/Android',
|
|
118
118
|
'modules.feature.ai_chat.description': 'Pantalla de chat con IA usando OpenAI o Gemini',
|
|
119
|
-
'modules.feature.feedback.description': 'Solicitudes y
|
|
119
|
+
'modules.feature.feedback.description': 'Solicitudes y votación de features dentro de la app',
|
|
120
120
|
'modules.feature.local_reminders.description': 'Recordatorios locales programados por el usuario (sin servidor)',
|
|
121
121
|
'modules.feature.ci.description': 'CI/CD: GitHub/GitLab (tests + build) + Codemagic (publicación en tiendas)',
|
|
122
122
|
'checks.checking': 'Verificando {name}...',
|
|
@@ -165,7 +165,7 @@ module.exports = {
|
|
|
165
165
|
'license.expired': '❌ Tu suscripción ha expirado. Renueva en kasy.dev.',
|
|
166
166
|
'license.inactive': '❌ Tu clave fue desactivada. Contacta soporte en kasy.dev.',
|
|
167
167
|
'license.offlineWarning': '⚠️ No se pudo conectar al servidor — continuando sin conexión.',
|
|
168
|
-
'license.subscriptionExpired': '❌ Tu
|
|
168
|
+
'license.subscriptionExpired': '❌ Tu suscripción expiró. Las actualizaciones requieren plan activo. Renueva en kasy.dev.\n Tus proyectos siguen funcionando — solo las actualizaciones están bloqueadas.',
|
|
169
169
|
'prompt.license.enter': '👉 Ingresa tu clave de activación (XXXX-XXXX-XXXX-XXXX)',
|
|
170
170
|
'prompt.license.invalid': 'Formato inválido. Usa XXXX-XXXX-XXXX-XXXX.',
|
|
171
171
|
'prompt.appName.enter': 'Ingresa el nombre de tu app',
|
|
@@ -176,7 +176,7 @@ module.exports = {
|
|
|
176
176
|
'prompt.backend.select': 'Elige el proveedor de backend',
|
|
177
177
|
'prompt.features.select': 'Elige las features opcionales a incluir',
|
|
178
178
|
'prompt.features.instructions': 'Espacio para marcar, enter para confirmar',
|
|
179
|
-
'prompt.multiselect.instructions': '\
|
|
179
|
+
'prompt.multiselect.instructions': '\nInstrucciónes:\n ↑/↓: Resaltar opción\n ←/→/[space]: Marcar/desmarcar\n a: Marcar/desmarcar todos\n enter/return: Confirmar',
|
|
180
180
|
'prompt.multiselect.warnDisabled': 'Usa ↓ para ir a una opción seleccionable, Space para marcar, Enter para confirmar',
|
|
181
181
|
'prompt.firebase.projectId.enter': 'Ingresa el Firebase Project ID',
|
|
182
182
|
'prompt.firebase.projectId.required': 'Firebase Project ID es obligatorio.',
|
|
@@ -293,20 +293,20 @@ module.exports = {
|
|
|
293
293
|
'setup.license.invalid': 'Formato de licencia inválido. Se espera XXXX-XXXX-XXXX-XXXX.',
|
|
294
294
|
'setup.error.targetNotEmpty': 'El directorio de destino no está vacío: {path}',
|
|
295
295
|
'setup.error.targetExists': 'El directorio de destino ya existe: {path}',
|
|
296
|
-
'setup.error.coreMissing': 'No se
|
|
296
|
+
'setup.error.coreMissing': 'No se encontró la carpeta del core template: {path}',
|
|
297
297
|
'setup.error.requiredChecksFailed': 'Fallo en verificaciones obligatorias. Ejecuta `kasy doctor`.',
|
|
298
298
|
'setup.error.generatingFailed': 'Error al generar el proyecto.',
|
|
299
299
|
'setup.error.conflictHint': 'Consejo: Elimina la carpeta del proyecto y ejecuta de nuevo, o usa un directorio vacío.',
|
|
300
300
|
'setup.spinner.generating': 'Generando archivos del proyecto...',
|
|
301
301
|
'setup.success.created': 'Proyecto creado correctamente.',
|
|
302
302
|
'setup.success.complete': '✓ Setup completado',
|
|
303
|
-
'setup.success.location': '
|
|
303
|
+
'setup.success.location': 'Ubicación',
|
|
304
304
|
'setup.success.nextSteps': 'Siguientes pasos',
|
|
305
305
|
'setup.success.stepPubGet': 'flutter pub get',
|
|
306
306
|
'setup.success.stepRun': 'flutter run',
|
|
307
307
|
'validate.title': 'Kasy Validate',
|
|
308
308
|
'validate.success': '✓ Matriz de validación aprobada.',
|
|
309
|
-
'validate.failed': 'La matriz de validación
|
|
309
|
+
'validate.failed': 'La matriz de validación falló.',
|
|
310
310
|
'validate.error': 'Una o más combinaciones de validación fallaron.',
|
|
311
311
|
'validate.projectNotFound': 'Proyecto no encontrado',
|
|
312
312
|
'validate.ok': 'ok',
|
|
@@ -318,18 +318,18 @@ module.exports = {
|
|
|
318
318
|
'new.banner': '✨ Nuevo app Flutter',
|
|
319
319
|
'new.subtitle': 'Elige el backend: Firebase, Supabase o API REST.',
|
|
320
320
|
'new.subtitle2': '🔒 El setup corre en tu máquina con tus credenciales — sin acceso de terceros.',
|
|
321
|
-
'new.q.backend': '¿
|
|
321
|
+
'new.q.backend': '¿Dónde quieres guardar los datos de tu app?',
|
|
322
322
|
'new.q.backend.firebase.desc': 'El más fácil para empezar — auth, base de datos y storage listos',
|
|
323
323
|
'new.q.backend.supabase.desc': 'Base de datos SQL (PostgreSQL) con más control',
|
|
324
324
|
'new.q.backend.api.desc': 'Ya tienes tu propio servidor',
|
|
325
325
|
|
|
326
|
-
'new.q.mode': '¿
|
|
326
|
+
'new.q.mode': '¿Cómo quieres crear la app?',
|
|
327
327
|
'new.q.mode.quick': '⚡ Rápido (recomendado): todo listo, cero configuración',
|
|
328
328
|
'new.q.mode.advanced': '🛠 Paso a paso: elegir cada detalle',
|
|
329
329
|
|
|
330
330
|
'new.q.preset': '¿Qué features incluir?',
|
|
331
331
|
'new.q.preset.starter': '⚡ Starter — analytics + errores + onboarding',
|
|
332
|
-
'new.q.preset.saas': '💰 SaaS —
|
|
332
|
+
'new.q.preset.saas': '💰 SaaS — suscripciónes + analytics + onboarding + feedback',
|
|
333
333
|
'new.q.preset.content': '📱 Contenido — crash reports + analytics + onboarding + AI chat',
|
|
334
334
|
'new.q.preset.full': '🚀 Completo — todas las features',
|
|
335
335
|
'new.q.preset.custom': '⚙️ Personalizar — elige feature a feature',
|
|
@@ -379,7 +379,7 @@ module.exports = {
|
|
|
379
379
|
'deploy.q.serviceAccount': 'Ruta al service account JSON:',
|
|
380
380
|
'deploy.detected.project': '✓ Proyecto Firebase detectado:',
|
|
381
381
|
'deploy.detected.serviceAccount': '✓ Service account detectado:',
|
|
382
|
-
'deploy.error.notProject': 'No se
|
|
382
|
+
'deploy.error.notProject': 'No se encontró firebase.json. Ejecute kasy deploy desde dentro de la carpeta del proyecto.',
|
|
383
383
|
|
|
384
384
|
'cli.command.ios.description': 'Publica la app en la App Store (necesita Mac)',
|
|
385
385
|
'cli.command.ios.configure.description': 'Configurar credenciales Apple para subida local del IPA',
|
|
@@ -388,7 +388,7 @@ module.exports = {
|
|
|
388
388
|
'cli.command.ios.clean.description': 'Limpia cachés Flutter/Xcode tras fallo en build iOS',
|
|
389
389
|
'cli.command.ios.picker.intro': 'Publicar en la App Store',
|
|
390
390
|
'cli.command.ios.picker.message': '¿Qué quieres hacer?',
|
|
391
|
-
'cli.command.ios.help.before': '
|
|
391
|
+
'cli.command.ios.help.before': 'Cómo publicar en la App Store:\n 1) kasy ios configure → hazlo una vez (guarda las credenciales Apple)\n 2) kasy ios release → ejecuta en cada nueva versión (build + subida)\n\nUsa "build" si solo quieres generar el IPA, "clean" si un build falló.\n',
|
|
392
392
|
'cli.command.codemagic.description': 'Compila la app en la nube (sin necesitar Mac)',
|
|
393
393
|
'cli.command.codemagic.configure.description': 'Configurar credenciales API de Codemagic',
|
|
394
394
|
'cli.command.codemagic.release.description': 'Iniciar build del workflow iOS en Codemagic',
|
|
@@ -396,14 +396,14 @@ module.exports = {
|
|
|
396
396
|
'cli.command.codemagic.picker.intro': 'Compilar en la nube con Codemagic',
|
|
397
397
|
'cli.command.codemagic.picker.message': '¿Qué quieres hacer?',
|
|
398
398
|
'cli.command.codemagic.picker.statusHint': 'Pregunta el ID del build',
|
|
399
|
-
'cli.command.codemagic.help.before': '
|
|
399
|
+
'cli.command.codemagic.help.before': 'Cómo compilar con Codemagic (sin necesitar Mac):\n 1) kasy codemagic configure → hazlo una vez (guarda el token de la API)\n 2) kasy codemagic release → inicia un build en la nube por versión\n\nUsa "status <buildId>" para seguir el progreso de un build.\n',
|
|
400
400
|
|
|
401
401
|
'ios.configure.title': 'App Store iOS — configuración',
|
|
402
402
|
'ios.configure.bundleId': 'Bundle ID',
|
|
403
403
|
'ios.configure.doc': 'Guía',
|
|
404
404
|
'ios.configure.openingLinks': 'Abriendo App Store Connect en el navegador…',
|
|
405
405
|
'ios.configure.note.title': 'Voy a pedir 3 cosas de App Store Connect',
|
|
406
|
-
'ios.configure.note.body': '1) API Key ID — en Users and Access → Keys.\n2) Issuer ID — arriba de la misma
|
|
406
|
+
'ios.configure.note.body': '1) API Key ID — en Users and Access → Keys.\n2) Issuer ID — arriba de la misma página.\n3) El archivo .p8 (clave privada) descargado al crear la key.\n\nEl App ID es opcional, solo si tienes varias apps.',
|
|
407
407
|
'ios.configure.q.apiKey': 'Key ID de la API App Store Connect',
|
|
408
408
|
'ios.configure.q.issuerId': 'Issuer ID (UUID)',
|
|
409
409
|
'ios.configure.q.p8Path': 'Ruta del archivo AuthKey_XXXXX.p8 descargado',
|
|
@@ -419,12 +419,12 @@ module.exports = {
|
|
|
419
419
|
'ios.release.task.building': 'Compilando IPA (puede tardar 2-5 min)…',
|
|
420
420
|
'ios.release.task.uploading': 'Subiendo IPA a App Store Connect…',
|
|
421
421
|
'ios.release.task.done': 'Compilacion + subida completadas',
|
|
422
|
-
'ios.release.task.failed': 'La
|
|
422
|
+
'ios.release.task.failed': 'La compilación falló — mira la salida debajo',
|
|
423
423
|
'ios.build.title': 'Generando IPA iOS…',
|
|
424
424
|
'ios.build.success': 'IPA generado',
|
|
425
425
|
'ios.build.task.building': 'Compilando IPA (puede tardar 2-5 min)…',
|
|
426
426
|
'ios.build.task.done': 'IPA listo en build/ios/ipa/',
|
|
427
|
-
'ios.build.task.failed': 'La
|
|
427
|
+
'ios.build.task.failed': 'La compilación falló — mira la salida debajo',
|
|
428
428
|
'ios.error.notProject': 'No es un proyecto Flutter iOS (pubspec.yaml + ios/ requeridos).',
|
|
429
429
|
'ios.error.noScript': 'scripts/release-ios.sh no encontrado. Ejecute: kasy update ios-release',
|
|
430
430
|
'ios.error.notMac': 'Release iOS local requiere macOS con Xcode.',
|
|
@@ -527,7 +527,7 @@ module.exports = {
|
|
|
527
527
|
'add.iosRelease.success': 'Archivos de release iOS agregados',
|
|
528
528
|
'add.iosRelease.already': 'Archivos de release iOS ya presentes',
|
|
529
529
|
|
|
530
|
-
'new.api.q.baseUrl': '¿
|
|
530
|
+
'new.api.q.baseUrl': '¿Cuál es la URL base de tu API?',
|
|
531
531
|
'new.api.q.baseUrl.hint': 'https://api.example.com',
|
|
532
532
|
'new.firebase.banner': '🔥 Nuevo app Flutter — Firebase',
|
|
533
533
|
'new.firebase.subtitle': 'Proyecto completo: auth, Firestore, notificaciones, login social y más.',
|
|
@@ -550,7 +550,7 @@ module.exports = {
|
|
|
550
550
|
'new.firebase.q.appName.hint': 'ej: Mi App Increible',
|
|
551
551
|
'new.firebase.q.appName.required': 'El nombre de la app es obligatorio.',
|
|
552
552
|
|
|
553
|
-
'new.firebase.q.bundleId': '¿
|
|
553
|
+
'new.firebase.q.bundleId': '¿Cómo quieres el identificador único (Bundle ID) de tu app?',
|
|
554
554
|
'new.firebase.q.bundleId.hint': 'Funciona como una dirección para tu app, ej: com.miempresa.miapp',
|
|
555
555
|
'new.firebase.q.bundleId.invalid': 'Formato inválido. Usa: com.empresa.app',
|
|
556
556
|
'new.firebase.q.bundleId.required': 'El Bundle ID es obligatorio.',
|
|
@@ -565,9 +565,9 @@ module.exports = {
|
|
|
565
565
|
'new.modules.header.features': '── Pantallas y features ──',
|
|
566
566
|
'new.modules.header.feedback': '── Feedback (Firebase + Supabase) ──',
|
|
567
567
|
'new.modules.header.ci': '── CI/CD ──',
|
|
568
|
-
'new.modules.header.monetization': '──
|
|
569
|
-
'new.firebase.module.revenuecat': '💰 RevenueCat (
|
|
570
|
-
'new.firebase.module.stripe': '🌐 Stripe (
|
|
568
|
+
'new.modules.header.monetization': '── Monetización ──',
|
|
569
|
+
'new.firebase.module.revenuecat': '💰 RevenueCat (suscripciónes móvil)',
|
|
570
|
+
'new.firebase.module.stripe': '🌐 Stripe (suscripciónes en web)',
|
|
571
571
|
'new.firebase.module.sentry': '🚨 Crash Reports (Sentry)',
|
|
572
572
|
'new.firebase.module.analytics': '📊 Analytics (Mixpanel)',
|
|
573
573
|
'new.firebase.module.facebook': '👤 Facebook (Login + Ads)',
|
|
@@ -597,7 +597,7 @@ module.exports = {
|
|
|
597
597
|
'new.firebase.q.revenuecat.android': 'Clave API RevenueCat para Android',
|
|
598
598
|
'new.firebase.q.revenuecat.ios': 'Clave API RevenueCat para iOS',
|
|
599
599
|
'new.firebase.q.paywall': '¿Qué estilo de paywall?',
|
|
600
|
-
'new.firebase.q.paywall.hint': 'Layout de la pantalla de
|
|
600
|
+
'new.firebase.q.paywall.hint': 'Layout de la pantalla de suscripciónes — puedes cambiarlo después en RevenueCat',
|
|
601
601
|
'new.firebase.q.stripe.secretKey': 'Stripe Secret Key (sk_test_… / sk_live_…) — opcional, configurar después',
|
|
602
602
|
'new.firebase.q.stripe.webhookSecret': 'Stripe Webhook Signing Secret (whsec_…) — opcional, configurar después',
|
|
603
603
|
'new.firebase.q.stripe.webhookSecret.hint': 'En Stripe → Developers → Webhooks → tu endpoint',
|
|
@@ -652,7 +652,7 @@ module.exports = {
|
|
|
652
652
|
'new.firebase.success.googleSignIn': '• Login con Gmail: 1) Activa en Firebase Console → Auth → Sign-in method → Google. 2) El CLI rellena kGoogleWebClientId (google_auth_options.dart) desde google-services.json para Android/iOS. Web usa signInWithPopup.',
|
|
653
653
|
'new.firebase.success.sentry': '• Sentry: Para reportes de error en producción. Obtén DSN en sentry.io. Ya en launch.json para dev. Para release: --dart-define=SENTRY_DSN=xxx',
|
|
654
654
|
'new.firebase.success.mixpanel': '• Mixpanel: Para analytics en producción. Ya en launch.json para dev. Para release: --dart-define=MIXPANEL_TOKEN=xxx',
|
|
655
|
-
'new.firebase.success.web': '• Web (adicional): Android e iOS funcionan con normalidad. Para probar en browser: "flutter run -d chrome" o "flutter run -d web-server --web-port=5000". Para publicar: "flutter build web". Las notificaciones push son exclusivas de mobile y se desactivan
|
|
655
|
+
'new.firebase.success.web': '• Web (adicional): Android e iOS funcionan con normalidad. Para probar en browser: "flutter run -d chrome" o "flutter run -d web-server --web-port=5000". Para publicar: "flutter build web". Las notificaciones push son exclusivas de mobile y se desactivan automáticamente en web.',
|
|
656
656
|
|
|
657
657
|
'new.firebase.q.deploy': '¿Hacer deploy de Cloud Functions + reglas de Firestore ahora?',
|
|
658
658
|
'new.firebase.q.deploy.hint': 'Requiere plan Blaze y firebase-tools instalado globalmente',
|
|
@@ -676,7 +676,7 @@ module.exports = {
|
|
|
676
676
|
|
|
677
677
|
'new.firebase.interactive.prompt1': '¿Ya creaste Firestore y habilitaste Autenticación en el enlace arriba?',
|
|
678
678
|
'new.firebase.interactive.prompt2': '¿Hiciste el upgrade al Plan Blaze? (Requerido para Cloud Functions)',
|
|
679
|
-
'new.firebase.interactive.googleAuthNote': '* Activa Google Sign-In manualmente (Email/Contraseña y
|
|
679
|
+
'new.firebase.interactive.googleAuthNote': '* Activa Google Sign-In manualmente (Email/Contraseña y Anónimo ya fueron activados): ',
|
|
680
680
|
'new.firebase.interactive.billingNeeded': 'Plan Blaze aún no activo. Actívalo en el enlace de arriba y espera la detección automática.',
|
|
681
681
|
'new.firebase.interactive.billingWaiting': 'Verificando estado del Blaze...',
|
|
682
682
|
'new.firebase.interactive.billingTimeout': 'Plan Blaze no confirmado tras el tiempo límite. Despliegue omitido — ejecuta manualmente cuando estés listo.',
|
|
@@ -705,15 +705,15 @@ module.exports = {
|
|
|
705
705
|
'new.supabase.prereq.login': ' Si creas manualmente: ten URL y anon key del proyecto listos',
|
|
706
706
|
'new.supabase.loginRequired': '⚠️ Debes estar conectado para crear proyecto. Ejecuta supabase login primero.',
|
|
707
707
|
'new.supabase.loginCommand': ' supabase login',
|
|
708
|
-
'new.supabase.success.done.db': '• Base de datos: tablas,
|
|
709
|
-
'new.supabase.success.done.storage': '• Storage: bucket kasy con
|
|
708
|
+
'new.supabase.success.done.db': '• Base de datos: tablas, políticas RLS',
|
|
709
|
+
'new.supabase.success.done.storage': '• Storage: bucket kasy con políticas',
|
|
710
710
|
'new.supabase.success.done.webhook': '• Edge Function revenuecat-webhook',
|
|
711
711
|
'new.supabase.success.done.secrets': '• Secrets de Edge Function (si se informaron)',
|
|
712
712
|
'new.supabase.success.done.launch': '• launch.json con Sentry, Mixpanel, RevenueCat',
|
|
713
713
|
'new.supabase.success.auth': '• Auth: Email ya activado. Activa Google, Apple y Facebook en: {authUrl}',
|
|
714
|
-
'new.supabase.success.storage': '• Storage: Bucket kasy creado con
|
|
714
|
+
'new.supabase.success.storage': '• Storage: Bucket kasy creado con políticas (listo)',
|
|
715
715
|
'new.supabase.success.fcm': '• Push (FCM): Configura en Firebase Console (plan Blaze). App lista para Supabase + FCM. URL: {fcmUrl}',
|
|
716
|
-
'new.supabase.success.deployLater': '• Deploy del backend cuando
|
|
716
|
+
'new.supabase.success.deployLater': '• Deploy del backend cuando estés listo (desde dentro de la carpeta del proyecto):',
|
|
717
717
|
|
|
718
718
|
'new.api.prereq.1': '1. Tu API REST corriendo y accesible',
|
|
719
719
|
'new.api.prereq.2': '2. URL base de la API (ej: https://api.yourapp.com)',
|
|
@@ -725,11 +725,11 @@ module.exports = {
|
|
|
725
725
|
'new.outdated.hint': 'los proyectos creados ahora no tendrán las últimas mejoras.',
|
|
726
726
|
'new.outdated.upgradeNow': '¿Actualizar a la última versión antes de crear? (requiere suscripción activa)',
|
|
727
727
|
'new.outdated.upgraded': '¡kasy actualizado! Ejecuta kasy new nuevamente.',
|
|
728
|
-
'new.success.title': '¡Proyecto creado con
|
|
728
|
+
'new.success.title': '¡Proyecto creado con éxito!',
|
|
729
729
|
'new.success.featuresInstalled': 'Recursos activados:',
|
|
730
730
|
'new.success.bundleId': 'Identificador de la app (bundle ID)',
|
|
731
731
|
'new.success.bundleId.hint': 'Identificador único de tu app en Android, iOS y Firebase (push).',
|
|
732
|
-
'new.success.nextSteps': '
|
|
732
|
+
'new.success.nextSteps': 'Próximos pasos:',
|
|
733
733
|
'new.success.step.cd': 'Ve a la carpeta del proyecto:',
|
|
734
734
|
'new.success.step.deploy': 'Sube el servidor a Firebase (DB + funciones):',
|
|
735
735
|
'new.success.step.configure': 'Configura claves opcionales cuando las tengas (RevenueCat, Sentry, etc.):',
|
|
@@ -747,7 +747,7 @@ module.exports = {
|
|
|
747
747
|
'new.fcm.failSupabase': 'no generada (permiso de GCP aún propagando); define FIREBASE_SERVICE_ACCOUNT_JSON en los secrets de Supabase',
|
|
748
748
|
'new.fcm.failApi': 'no generada (permiso de GCP aún propagando); ejecuta el comando de nuevo en unos minutos',
|
|
749
749
|
'new.sha1.registering': 'Registrando SHA-1 para Google Sign-In (Android)…',
|
|
750
|
-
'new.sha1.failed': 'SHA-1 no añadido
|
|
750
|
+
'new.sha1.failed': 'SHA-1 no añadido automáticamente: {error}',
|
|
751
751
|
'new.sha1.manual': 'Agregalo manualmente para que Google Sign-In funcione en Android:',
|
|
752
752
|
'new.sha1.skipped.apiFailed': 'SHA-1 no añadido automáticamente. Motivo: {error}',
|
|
753
753
|
'new.sha1.skipped.other': 'SHA-1 no añadido: {reason}',
|
|
@@ -798,7 +798,7 @@ module.exports = {
|
|
|
798
798
|
'reset.prompt.xcodeOpen.skip': 'Dejar Xcode abierto e intentar igual',
|
|
799
799
|
'reset.prompt.xcodeOpen.cancel': 'Cancelar reset',
|
|
800
800
|
'reset.info.xcodeClosed': 'Xcode cerrado.',
|
|
801
|
-
'reset.prompt.reinstallNow': 'App removida. Verifica en el dispositivo y reinstalar ahora?',
|
|
801
|
+
'reset.prompt.reinstallNow': 'App removida. Verifica en el dispositivo y ¿reinstalar ahora?',
|
|
802
802
|
'reset.prompt.clearLauncherCache': '¿Limpiar también la caché del launcher ({pkg})? Soluciona el preview gris de los widgets.',
|
|
803
803
|
'reset.success.launcherCleared': 'Caché del launcher limpiada ({pkg}). Pantalla de inicio intacta.',
|
|
804
804
|
'reset.warn.launcherCacheFailed': 'No se pudo limpiar la caché del launcher.',
|
|
@@ -812,7 +812,7 @@ module.exports = {
|
|
|
812
812
|
'run.updateHint.suffix': 'para ver las novedades',
|
|
813
813
|
'run.spinner.building': 'Iniciando Flutter…',
|
|
814
814
|
'run.spinner.ready': 'Flutter listo — usa r (reload), R (restart), q (salir)',
|
|
815
|
-
'run.spinner.failed': 'Flutter run
|
|
815
|
+
'run.spinner.failed': 'Flutter run falló antes de iniciar',
|
|
816
816
|
'run.stage.gradleFirstTime': 'Compilando Android (1.ª vez tarda 5-15 min — Gradle bajando dependencias)…',
|
|
817
817
|
'run.stage.gradle': 'Compilando Android…',
|
|
818
818
|
'run.stage.xcode': 'Compilando iOS…',
|
|
@@ -820,7 +820,7 @@ module.exports = {
|
|
|
820
820
|
'run.stage.installing': 'Instalando en el dispositivo…',
|
|
821
821
|
'run.stage.syncing': 'Sincronizando archivos con el dispositivo…',
|
|
822
822
|
'run.stage.buildSuccess': 'Build listo — abriendo la app…',
|
|
823
|
-
'run.error.notFlutterProject': 'No se
|
|
823
|
+
'run.error.notFlutterProject': 'No se encontró pubspec.yaml. Ejecuta este comando dentro de un proyecto Flutter.',
|
|
824
824
|
'run.error.flutterNotFound': 'Flutter no encontrado. Verifica que Flutter este instalado y en el PATH.',
|
|
825
825
|
'run.rc.usingTest': 'RevenueCat: usando clave de prueba (test_) — simulador/emulador',
|
|
826
826
|
'run.rc.usingProd': 'RevenueCat: usando claves de producción — dispositivo físico',
|
|
@@ -930,26 +930,26 @@ module.exports = {
|
|
|
930
930
|
|
|
931
931
|
// notifications command
|
|
932
932
|
'cli.command.notifications.description': 'Edita los textos de las notificaciones locales y recordatorios',
|
|
933
|
-
'cli.command.notifications.text.description': 'Define
|
|
933
|
+
'cli.command.notifications.text.description': 'Define títulos y mensajes de notificaciones locales',
|
|
934
934
|
'cli.command.notifications.picker.intro': 'Editar textos de las notificaciones',
|
|
935
935
|
'cli.command.notifications.picker.message': '¿Qué quieres hacer?',
|
|
936
|
-
'notifications.error.notKasyProject': 'No se
|
|
936
|
+
'notifications.error.notKasyProject': 'No se encontró kit_setup.json. Ejecuta dentro de un proyecto Kasy.',
|
|
937
937
|
'notifications.error.noI18n': 'lib/i18n/*.i18n.json no encontrado en este proyecto.',
|
|
938
938
|
'notifications.error.noFeatures': 'lib/core/config/features.dart no encontrado.',
|
|
939
939
|
'notifications.error.notEnabled': 'Notificaciones locales desactivadas. Ejecuta: kasy add local_reminders',
|
|
940
940
|
'notifications.error.cancelled': 'Cancelado.',
|
|
941
941
|
'notifications.prompt.intro': 'Textos de notificación local',
|
|
942
942
|
'notifications.prompt.hint': 'Demo Home = prueba instantanea en Features. Recordatorio = alerta programada en Ajustes.',
|
|
943
|
-
'notifications.prompt.demoTitle': 'Demo Home —
|
|
943
|
+
'notifications.prompt.demoTitle': 'Demo Home — título de la notificación',
|
|
944
944
|
'notifications.prompt.demoBody': 'Demo Home — descripción / cuerpo',
|
|
945
|
-
'notifications.prompt.reminderTitle': 'Recordatorio programado —
|
|
945
|
+
'notifications.prompt.reminderTitle': 'Recordatorio programado — título',
|
|
946
946
|
'notifications.prompt.reminderBody': 'Recordatorio programado — cuerpo',
|
|
947
947
|
'notifications.prompt.required': 'Obligatorio.',
|
|
948
948
|
'notifications.writing': 'Actualizando lib/i18n/*.i18n.json...',
|
|
949
949
|
'notifications.written': 'Actualizado: {langs}',
|
|
950
950
|
'notifications.slang': 'Ejecutando dart run slang...',
|
|
951
951
|
'notifications.slangDone': 'Traducciones regeneradas',
|
|
952
|
-
'notifications.slangFailed': 'dart run slang
|
|
952
|
+
'notifications.slangFailed': 'dart run slang falló — ejecuta manualmente en el proyecto',
|
|
953
953
|
'notifications.done': 'Textos de notificación local actualizados.',
|
|
954
954
|
'notifications.summary.demo': 'Home → Features (demo):',
|
|
955
955
|
'notifications.summary.reminder': 'Ajustes → Recordatorios (programado):',
|
|
@@ -962,7 +962,7 @@ module.exports = {
|
|
|
962
962
|
'add.applying': 'Agregando feature: {module}',
|
|
963
963
|
'add.applyingPatch': 'Aplicando cambios de la feature...',
|
|
964
964
|
'add.patchApplied': 'Patch aplicado',
|
|
965
|
-
'add.patchFailed': 'Patch
|
|
965
|
+
'add.patchFailed': 'Patch falló — revisa la salida anterior',
|
|
966
966
|
'add.pubGet': 'Instalando paquetes de Flutter (flutter pub get)...',
|
|
967
967
|
'add.pubGetDone': 'Dependencias actualizadas',
|
|
968
968
|
'add.pubGetFailed': 'Falló al instalar paquetes de Flutter — ejecuta `flutter pub get` manualmente',
|
|
@@ -980,31 +980,31 @@ module.exports = {
|
|
|
980
980
|
'add.prompt.rcAndroidKey': 'RevenueCat Android API key (deja en blanco para configurar después):',
|
|
981
981
|
'add.prompt.rcIosKey': 'RevenueCat iOS API key (deja en blanco para configurar después):',
|
|
982
982
|
'add.note.facebook': 'Agrega tu Facebook App ID y token en .vscode/launch.json (FB_APP_ID, FB_CLIENT_TOKEN).',
|
|
983
|
-
'new.q.ai_chat.configureNow': 'Configurar el agente de Chat IA ahora?',
|
|
983
|
+
'new.q.ai_chat.configureNow': '¿Configurar el agente de Chat IA ahora?',
|
|
984
984
|
'new.q.ai_chat.configureNow.hint': 'Puedes omitir y ejecutar "kasy add ai_chat" después',
|
|
985
985
|
'add.ai_chat.reconfigure': 'Feature ya activa — reconfigurando solo las credenciales.',
|
|
986
986
|
'add.prompt.aiProvider': 'Proveedor de IA:',
|
|
987
|
-
'add.prompt.aiSystemPrompt': '
|
|
987
|
+
'add.prompt.aiSystemPrompt': 'Instrucción del agente — system prompt (deja en blanco para ninguna):\n Ejemplo: "Eres un asistente de soporte del app Fitsync. Solo responde sobre entrenamientos."\n >',
|
|
988
988
|
'add.prompt.aiApiKey': 'Clave de API (OpenAI o Gemini) — se guarda en el servidor, nunca en el app (deja en blanco para configurar después):',
|
|
989
989
|
'add.prompt.aiEndpoint': 'URL de tu endpoint IA (deja en blanco para configurar después):',
|
|
990
990
|
'add.ai_chat.settingSecret': 'Guardando clave de API como secret en el servidor...',
|
|
991
991
|
'add.ai_chat.secretSet': 'Clave de API guardada como secret',
|
|
992
|
-
'add.ai_chat.secretFailed': 'No se pudo guardar el secret
|
|
992
|
+
'add.ai_chat.secretFailed': 'No se pudo guardar el secret automáticamente — configúralo manualmente (ver instrucciones abajo)',
|
|
993
993
|
'add.ai_chat.skipSecret': 'Clave de API omitida — configura antes del deploy via CLI del servidor',
|
|
994
|
-
'add.ai_chat.deploying': 'Desplegando
|
|
995
|
-
'add.ai_chat.deployed': '
|
|
996
|
-
'add.ai_chat.deployFailed': 'Deploy automático
|
|
997
|
-
'add.ai_chat.nextSteps.firebase': '\n
|
|
998
|
-
'add.ai_chat.nextSteps.firebase.deployFailed': '\n
|
|
999
|
-
'add.ai_chat.nextSteps.supabase': '\n
|
|
1000
|
-
'add.ai_chat.nextSteps.supabase.deployFailed': '\n
|
|
1001
|
-
'add.ai_chat.nextSteps.api': '\n
|
|
994
|
+
'add.ai_chat.deploying': 'Desplegando función IA en el servidor...',
|
|
995
|
+
'add.ai_chat.deployed': 'Función IA desplegada con éxito',
|
|
996
|
+
'add.ai_chat.deployFailed': 'Deploy automático falló — despliega manualmente (ver instrucciones abajo)',
|
|
997
|
+
'add.ai_chat.nextSteps.firebase': '\n Próximos pasos:\n 1. El AI_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 2. Corre el app: kasy run\n',
|
|
998
|
+
'add.ai_chat.nextSteps.firebase.deployFailed': '\n Próximos pasos:\n 1. Deploy manual: firebase deploy --only functions:aiChat\n 2. El AI_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 3. Corre el app: kasy run\n',
|
|
999
|
+
'add.ai_chat.nextSteps.supabase': '\n Próximos pasos:\n 1. El AI_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 2. Corre el app: kasy run\n',
|
|
1000
|
+
'add.ai_chat.nextSteps.supabase.deployFailed': '\n Próximos pasos:\n 1. Deploy manual: supabase functions deploy ai-chat --no-verify-jwt\n 2. El AI_CHAT_ENDPOINT en .vscode/launch.json ya fue pre-llenado.\n 3. Corre el app: kasy run\n',
|
|
1001
|
+
'add.ai_chat.nextSteps.api': '\n Próximos pasos:\n 1. Crea un endpoint en tu servidor que acepte {message, history} y llame tu IA.\n 2. Actualiza AI_CHAT_ENDPOINT en .vscode/launch.json con la URL de tu endpoint.\n 3. Corre el app: kasy run\n',
|
|
1002
1002
|
'cli.command.remove.description': 'Elimina algo que ya no usas (ej: kasy remove sentry)',
|
|
1003
1003
|
'remove.error.noModule': 'Ingresa el nombre de la feature. Uso: kasy remove <feature>',
|
|
1004
1004
|
'remove.error.notKasyProject': 'kit_setup.json no encontrado. Ejecuta este comando dentro de un proyecto Kasy.',
|
|
1005
1005
|
'remove.error.unknownModule': 'Feature desconocida: {module}\nDisponibles: {list}',
|
|
1006
1006
|
'remove.error.notActive': 'La feature "{module}" no está activa en este proyecto.',
|
|
1007
|
-
'remove.confirm': 'Eliminar la feature "{module}"? Esto
|
|
1007
|
+
'remove.confirm': '¿Eliminar la feature "{module}"? Esto borrará archivos y dependencias.',
|
|
1008
1008
|
'remove.cancelled': 'Cancelado.',
|
|
1009
1009
|
'remove.removing': 'Eliminando feature: {module}',
|
|
1010
1010
|
'remove.pubGet': 'Instalando paquetes de Flutter (flutter pub get)...',
|
|
@@ -1014,8 +1014,8 @@ module.exports = {
|
|
|
1014
1014
|
'remove.buildRunnerDone': 'Generación de código completada',
|
|
1015
1015
|
'remove.buildRunnerFailed': 'Generación de código falló — ejecuta `dart run build_runner build` manualmente',
|
|
1016
1016
|
'remove.success': 'Feature "{module}" eliminada exitosamente.',
|
|
1017
|
-
'remove.warn.ci': 'Archivos de CI eliminados. Si
|
|
1018
|
-
'remove.warn.sentry.shared': 'sentry_flutter conservado —
|
|
1017
|
+
'remove.warn.ci': 'Archivos de CI eliminados. Si tenías workflows personalizados, restáuralos desde git.',
|
|
1018
|
+
'remove.warn.sentry.shared': 'sentry_flutter conservado — todavía requerido por features activas (revenuecat/facebook).',
|
|
1019
1019
|
'cli.command.update.description': 'Actualiza partes de tu app a la última versión (ej: kasy update components)',
|
|
1020
1020
|
'cli.command.update.targetArg': 'Objetivo a actualizar (ej.: revenuecat, sentry, components)',
|
|
1021
1021
|
'update.error.noProject': 'kit_setup.json no encontrado. Ejecuta dentro de un proyecto Kasy.',
|
|
@@ -1031,9 +1031,9 @@ module.exports = {
|
|
|
1031
1031
|
'update.howToUpdateComponents': 'Para actualizar componentes base:',
|
|
1032
1032
|
'update.warn.commit': 'Esto sobrescribirá los archivos de la feature "{module}". Asegúrate de haber hecho commit antes.',
|
|
1033
1033
|
'update.warn.commitComponents': 'Esto sobrescribirá archivos de los componentes base. Asegúrate de haber hecho commit antes.',
|
|
1034
|
-
'update.confirm': 'Sobrescribir archivos de la feature "{module}" con la versión más reciente?',
|
|
1035
|
-
'update.confirmComponents': 'Sobrescribir archivos de los componentes base con la versión más reciente?',
|
|
1036
|
-
'update.confirmCore': 'Sobrescribir archivos de core (animaciones, widgets, tema, herramientas dev) con la versión más reciente?',
|
|
1034
|
+
'update.confirm': '¿Sobrescribir archivos de la feature "{module}" con la versión más reciente?',
|
|
1035
|
+
'update.confirmComponents': '¿Sobrescribir archivos de los componentes base con la versión más reciente?',
|
|
1036
|
+
'update.confirmCore': '¿Sobrescribir archivos de core (animaciones, widgets, tema, herramientas dev) con la versión más reciente?',
|
|
1037
1037
|
'update.cancelled': 'Cancelado.',
|
|
1038
1038
|
'update.applying': 'Aplicando actualización de la feature: {module}',
|
|
1039
1039
|
'update.applyingComponents': 'Aplicando actualización de componentes base...',
|
|
@@ -43,7 +43,7 @@ module.exports = {
|
|
|
43
43
|
'cli.command.setup.langName': 'idioma',
|
|
44
44
|
'cli.command.setup.langOption': 'Idioma dos prompts (en, pt, es)',
|
|
45
45
|
'cli.command.setup.backendOption': 'Adapter de backend (firebase, supabase, api)',
|
|
46
|
-
'cli.command.setup.featuresOption': 'Features opcionais separadas por
|
|
46
|
+
'cli.command.setup.featuresOption': 'Features opcionais separadas por vírgula (web,widget,ai_chat,revenuecat,ci)',
|
|
47
47
|
'cli.command.help.paramName': 'comando',
|
|
48
48
|
'cli.command.doctor.description': 'Verifica se o seu computador está pronto para rodar a Kasy',
|
|
49
49
|
'cli.command.modules.description': 'Mostra o que já vem incluso e o que você pode adicionar',
|
|
@@ -79,7 +79,7 @@ module.exports = {
|
|
|
79
79
|
'setup.flutterfire.installing': 'Instalando FlutterFire CLI… (pode levar 1-2 min)',
|
|
80
80
|
'setup.installingNamed': 'Instalando {name}…',
|
|
81
81
|
'setup.warn.hang': 'Se travar, execute manualmente: flutterfire --version',
|
|
82
|
-
'setup.warn.supabase': 'Usando Supabase ou API
|
|
82
|
+
'setup.warn.supabase': 'Usando Supabase ou API própria? O Firebase ainda ajuda com push e remote config.',
|
|
83
83
|
'doctor.title': 'Kasy Doctor',
|
|
84
84
|
'doctor.baseEnvironment': 'Ambiente base',
|
|
85
85
|
'doctor.optionalBackend': 'Ferramentas opcionais de backend',
|
|
@@ -91,7 +91,7 @@ module.exports = {
|
|
|
91
91
|
'doctor.gcpBilling.title': 'Google Cloud Billing (Firebase Blaze)',
|
|
92
92
|
'doctor.gcpBilling.found': '{count} conta(s) de faturamento ativa(s):',
|
|
93
93
|
'doctor.gcpBilling.missing': 'Nenhuma conta de faturamento encontrada. Crie uma antes de rodar `kasy new` com Firebase:',
|
|
94
|
-
'doctor.requiredMissing': '
|
|
94
|
+
'doctor.requiredMissing': 'Dependências obrigatórias ausentes. Corrija os erros acima e execute o doctor novamente.',
|
|
95
95
|
'doctor.requiredPassed': '✓ Verificações obrigatórias de ambiente aprovadas.',
|
|
96
96
|
'modules.backends': 'Backends disponíveis:',
|
|
97
97
|
'modules.featuresBase': 'Sempre incluído:',
|
|
@@ -101,8 +101,8 @@ module.exports = {
|
|
|
101
101
|
'modules.tag.enhances': 'ativa {target}',
|
|
102
102
|
'modules.hint.subscriptionNoRc': 'Dica: a tela de Subscriptions está inclusa mas inativa. Rode `kasy add revenuecat` para habilitar pagamentos reais.',
|
|
103
103
|
'modules.feature.base.authentication.description': 'Cadastro, login e gerenciamento de conta',
|
|
104
|
-
'modules.feature.base.home.description': 'Tela principal do app
|
|
105
|
-
'modules.feature.base.settings.description': 'Tema, idioma, conta e
|
|
104
|
+
'modules.feature.base.home.description': 'Tela principal do app após o login',
|
|
105
|
+
'modules.feature.base.settings.description': 'Tema, idioma, conta e preferências',
|
|
106
106
|
'modules.feature.base.notifications.description': 'Notificações push via Firebase Cloud Messaging (funciona com qualquer backend)',
|
|
107
107
|
'modules.feature.base.subscription.description': 'Tela e modelo de assinatura premium (adicione RevenueCat para habilitar pagamentos reais)',
|
|
108
108
|
'modules.backend.firebase.description': 'Adapter de backend Firebase',
|
|
@@ -116,8 +116,8 @@ module.exports = {
|
|
|
116
116
|
'modules.feature.web.description': 'Suporte Web/PWA',
|
|
117
117
|
'modules.feature.widget.description': 'Widget de tela inicial iOS/Android',
|
|
118
118
|
'modules.feature.ai_chat.description': 'Tela de chat com IA usando OpenAI ou Gemini',
|
|
119
|
-
'modules.feature.feedback.description': 'Pedidos e
|
|
120
|
-
'modules.feature.local_reminders.description': 'Lembretes locais agendados pelo
|
|
119
|
+
'modules.feature.feedback.description': 'Pedidos e votação de features dentro do app',
|
|
120
|
+
'modules.feature.local_reminders.description': 'Lembretes locais agendados pelo usuário (sem servidor)',
|
|
121
121
|
'modules.feature.ci.description': 'CI/CD: GitHub/GitLab (testes + build) + Codemagic (publicação nas lojas)',
|
|
122
122
|
'checks.checking': 'Verificando {name}...',
|
|
123
123
|
'checks.found': '{name} encontrado',
|
|
@@ -151,13 +151,13 @@ module.exports = {
|
|
|
151
151
|
'error.hint.supabaseLogin': 'Você não está logado no Supabase. Execute: supabase login',
|
|
152
152
|
'error.hint.gcloudAuth': 'Você precisa autenticar com gcloud. Execute: gcloud auth login',
|
|
153
153
|
'error.hint.flutterRunFailed': 'Flutter não conseguiu rodar o app. Tente de novo com --verbose para ver a saída completa.',
|
|
154
|
-
'checks.diagnostic.xcodeLicense': '{name} está instalado, mas o Xcode precisa que a
|
|
154
|
+
'checks.diagnostic.xcodeLicense': '{name} está instalado, mas o Xcode precisa que a licença seja aceita. Execute: sudo xcodebuild -license',
|
|
155
155
|
'checks.diagnostic.xcodeCli': '{name} está instalado, mas faltam as Command Line Tools do Xcode. Execute: xcode-select --install',
|
|
156
156
|
'banner.title': 'Kasy CLI · Gerador Flutter SaaS',
|
|
157
157
|
'welcome.firstRun': 'Bem-vindo ao Kasy CLI!',
|
|
158
158
|
'welcome.chooseLanguage': 'Primeiro, escolha seu idioma:',
|
|
159
159
|
'prompt.language.select': 'Escolha seu idioma',
|
|
160
|
-
'prompt.cancelled': 'Comando cancelado pelo
|
|
160
|
+
'prompt.cancelled': 'Comando cancelado pelo usuário.',
|
|
161
161
|
'license.required': '🔑 Chave de ativação necessária para usar o Kasy CLI',
|
|
162
162
|
'license.checking': 'Validando chave de ativação...',
|
|
163
163
|
'license.saved': '✅ Chave validada com sucesso',
|
|
@@ -175,9 +175,9 @@ module.exports = {
|
|
|
175
175
|
'prompt.bundleId.invalid': 'O bundle ID deve seguir o formato com.company.app.',
|
|
176
176
|
'prompt.backend.select': 'Escolha o provedor de backend',
|
|
177
177
|
'prompt.features.select': 'Escolha as features opcionais para incluir',
|
|
178
|
-
'prompt.features.instructions': '
|
|
179
|
-
'prompt.multiselect.instructions': '\
|
|
180
|
-
'prompt.multiselect.warnDisabled': 'Use ↓ para ir a uma opção
|
|
178
|
+
'prompt.features.instructions': 'Espaço para marcar, enter para confirmar',
|
|
179
|
+
'prompt.multiselect.instructions': '\nInstruções:\n ↑/↓: Destacar opção\n ←/→/[space]: Marcar/desmarcar\n a: Marcar/desmarcar todos\n enter/return: Confirmar',
|
|
180
|
+
'prompt.multiselect.warnDisabled': 'Use ↓ para ir a uma opção selecionável, Space para marcar, Enter para confirmar',
|
|
181
181
|
'prompt.firebase.projectId.enter': 'Digite o Firebase Project ID',
|
|
182
182
|
'prompt.firebase.projectId.required': 'Firebase Project ID é obrigatório.',
|
|
183
183
|
'prompt.supabase.url.enter': 'Digite a URL do Supabase',
|
|
@@ -236,7 +236,7 @@ module.exports = {
|
|
|
236
236
|
'new.firebase.billing.stillMissing': 'Ainda não encontrei nenhuma conta de faturamento ativa. Finalize a criação no Console e rode `kasy new` novamente.',
|
|
237
237
|
'new.firebase.create.installTitle': 'Para instalar o gcloud CLI, execute:',
|
|
238
238
|
'new.firebase.create.installCommand': 'Comando',
|
|
239
|
-
'new.firebase.create.installAfter': 'Depois
|
|
239
|
+
'new.firebase.create.installAfter': 'Depois faça login',
|
|
240
240
|
'new.firebase.create.installUrl': 'Ou baixe em',
|
|
241
241
|
'new.firebase.create.authCommand': 'Execute: gcloud auth login',
|
|
242
242
|
'new.firebase.create.gcloudMissing': 'O Google Cloud CLI (gcloud) é necessário para criar o projeto Firebase do zero, e ainda não está instalado. Vou instalar automaticamente agora.',
|
|
@@ -286,9 +286,9 @@ module.exports = {
|
|
|
286
286
|
'new.supabase.projectsRequired': 'Nenhum projeto encontrado nesta organização.',
|
|
287
287
|
'new.supabase.q.dbPassword.existing': 'Senha do banco do projeto (necessária para vincular e aplicar migrations)',
|
|
288
288
|
'new.supabase.existingLinked': 'Projeto pronto para vincular e aplicar migrations.',
|
|
289
|
-
'setup.license.loaded': '✓ Chave de
|
|
290
|
-
'setup.license.saved': '✓ Chave de
|
|
291
|
-
'setup.license.invalid': 'Formato de
|
|
289
|
+
'setup.license.loaded': '✓ Chave de licença carregada da configuração local.',
|
|
290
|
+
'setup.license.saved': '✓ Chave de licença validada e salva.',
|
|
291
|
+
'setup.license.invalid': 'Formato de licença inválido. Esperado XXXX-XXXX-XXXX-XXXX.',
|
|
292
292
|
'setup.error.targetNotEmpty': 'O diretório de destino não está vazio: {path}',
|
|
293
293
|
'setup.error.targetExists': 'O diretório de destino já existe: {path}',
|
|
294
294
|
'setup.error.coreMissing': 'Pasta do core template não encontrada: {path}',
|
|
@@ -297,15 +297,15 @@ module.exports = {
|
|
|
297
297
|
'setup.error.conflictHint': 'Dica: Remova a pasta do projeto e execute novamente, ou use um diretório vazio.',
|
|
298
298
|
'setup.spinner.generating': 'Gerando arquivos do projeto...',
|
|
299
299
|
'setup.success.created': 'Projeto criado com sucesso.',
|
|
300
|
-
'setup.success.complete': '✓ Setup
|
|
300
|
+
'setup.success.complete': '✓ Setup concluído',
|
|
301
301
|
'setup.success.location': 'Local',
|
|
302
|
-
'setup.success.nextSteps': '
|
|
302
|
+
'setup.success.nextSteps': 'Próximos passos',
|
|
303
303
|
'setup.success.stepPubGet': 'flutter pub get',
|
|
304
304
|
'setup.success.stepRun': 'flutter run',
|
|
305
305
|
'validate.title': 'Kasy Validate',
|
|
306
|
-
'validate.success': '✓ Matriz de
|
|
307
|
-
'validate.failed': 'Matriz de
|
|
308
|
-
'validate.error': 'Uma ou mais
|
|
306
|
+
'validate.success': '✓ Matriz de validação aprovada.',
|
|
307
|
+
'validate.failed': 'Matriz de validação falhou.',
|
|
308
|
+
'validate.error': 'Uma ou mais combinações de validação falharam.',
|
|
309
309
|
'validate.projectNotFound': 'Projeto não encontrado',
|
|
310
310
|
'validate.ok': 'ok',
|
|
311
311
|
'validate.fail': 'falhou',
|
|
@@ -331,7 +331,7 @@ module.exports = {
|
|
|
331
331
|
'new.q.preset.content': '📱 Conteúdo — crash reports + analytics + onboarding + AI chat',
|
|
332
332
|
'new.q.preset.full': '🚀 Completo — todas as features',
|
|
333
333
|
'new.q.preset.custom': '⚙️ Personalizar — escolha feature a feature',
|
|
334
|
-
'new.q.preset.none': '○ Nenhum —
|
|
334
|
+
'new.q.preset.none': '○ Nenhum — só o core',
|
|
335
335
|
|
|
336
336
|
'new.firebase.success.deployStep': '• Deploy do backend (de dentro da pasta do projeto):',
|
|
337
337
|
|
|
@@ -525,7 +525,7 @@ module.exports = {
|
|
|
525
525
|
'add.iosRelease.success': 'Arquivos de release iOS adicionados',
|
|
526
526
|
'add.iosRelease.already': 'Arquivos de release iOS já existem',
|
|
527
527
|
|
|
528
|
-
'new.api.q.baseUrl': 'Qual
|
|
528
|
+
'new.api.q.baseUrl': 'Qual é a URL base da sua API?',
|
|
529
529
|
'new.api.q.baseUrl.hint': 'https://api.example.com',
|
|
530
530
|
'new.firebase.banner': '🔥 Novo app Flutter — Firebase',
|
|
531
531
|
'new.firebase.subtitle': 'Projeto completo: auth, Firestore, notificações, login social e muito mais.',
|
|
@@ -541,31 +541,31 @@ module.exports = {
|
|
|
541
541
|
'new.firebase.create.successPush': 'Projeto Firebase criado para FCM + Remote Config.',
|
|
542
542
|
'new.firebase.prereq.1': '1. Firebase CLI instalado (npm i -g firebase-tools) + firebase login',
|
|
543
543
|
'new.firebase.prereq.2': '2. Projeto Firebase criado em console.firebase.google.com',
|
|
544
|
-
'new.firebase.prereq.3': '3. Plano Blaze ativado (
|
|
544
|
+
'new.firebase.prereq.3': '3. Plano Blaze ativado (cartão de crédito — necessário para Cloud Functions)',
|
|
545
545
|
'new.firebase.prereq.4': '4. gcloud CLI instalado + gcloud auth login (usado para ativar APIs automaticamente)',
|
|
546
|
-
'new.firebase.prereq.5': '5. Antes do deploy: ative Secret Manager API e Firebase Storage (ver PREREQUISITES.md ou links
|
|
546
|
+
'new.firebase.prereq.5': '5. Antes do deploy: ative Secret Manager API e Firebase Storage (ver PREREQUISITES.md ou links após gerar)',
|
|
547
547
|
'new.firebase.prereq.doc': ' Checklist completo: PREREQUISITES.md',
|
|
548
548
|
|
|
549
|
-
'new.firebase.q.appName': 'Qual
|
|
550
|
-
'new.firebase.q.appName.hint': 'ex: Meu App
|
|
549
|
+
'new.firebase.q.appName': 'Qual é o nome do seu app?',
|
|
550
|
+
'new.firebase.q.appName.hint': 'ex: Meu App Incrível',
|
|
551
551
|
'new.firebase.q.appName.required': 'O nome do app é obrigatório.',
|
|
552
552
|
|
|
553
|
-
'new.firebase.q.bundleId': '
|
|
553
|
+
'new.firebase.q.bundleId': 'Como você quer o identificador único (Bundle ID) do seu app?',
|
|
554
554
|
'new.firebase.q.bundleId.hint': 'Funciona como um endereço para o seu app, ex: com.minhaempresa.meuapp',
|
|
555
555
|
'new.firebase.q.bundleId.invalid': 'Formato inválido. Use: com.empresa.app',
|
|
556
556
|
'new.firebase.q.bundleId.required': 'O Bundle ID é obrigatório.',
|
|
557
557
|
|
|
558
|
-
'new.firebase.q.projectId': 'Qual
|
|
558
|
+
'new.firebase.q.projectId': 'Qual é o ID do seu projeto Firebase?',
|
|
559
559
|
'new.firebase.q.projectId.hint': 'Encontre no Firebase Console → seu projeto → Configurações',
|
|
560
560
|
'new.firebase.q.projectId.required': 'O Firebase Project ID é obrigatório.',
|
|
561
561
|
|
|
562
562
|
'new.firebase.q.modules': 'Quais features opcionais você quer incluir?',
|
|
563
|
-
'new.firebase.q.modules.hint': '
|
|
563
|
+
'new.firebase.q.modules.hint': 'Espaço para selecionar, Enter para confirmar',
|
|
564
564
|
'new.modules.header.common': '── Comuns (todos os backends) ──',
|
|
565
565
|
'new.modules.header.features': '── Telas e features ──',
|
|
566
566
|
'new.modules.header.feedback': '── Feedback (Firebase + Supabase) ──',
|
|
567
567
|
'new.modules.header.ci': '── CI/CD ──',
|
|
568
|
-
'new.modules.header.monetization': '──
|
|
568
|
+
'new.modules.header.monetization': '── Monetização ──',
|
|
569
569
|
'new.firebase.module.revenuecat': '💰 RevenueCat (assinaturas mobile)',
|
|
570
570
|
'new.firebase.module.stripe': '🌐 Stripe (assinaturas na web)',
|
|
571
571
|
'new.firebase.module.sentry': '🚨 Crash Reports (Sentry)',
|
|
@@ -582,7 +582,7 @@ module.exports = {
|
|
|
582
582
|
'new.firebase.q.secrets.configureNow': 'Configurar as secrets do servidor agora? (webhook RevenueCat, Meta Ads)',
|
|
583
583
|
'new.firebase.q.secrets.configureNow.hint': 'Se não agora, veja o README para os comandos de configuração depois',
|
|
584
584
|
'new.firebase.q.secrets.later': '• Secrets do servidor não configuradas — serão configuradas durante `kasy deploy`.',
|
|
585
|
-
'new.firebase.q.revenuecat.webhookKey': 'Chave secreta do webhook (um valor
|
|
585
|
+
'new.firebase.q.revenuecat.webhookKey': 'Chave secreta do webhook (um valor aleatório foi sugerido — pressione Enter para aceitar ou digite o seu)',
|
|
586
586
|
'new.firebase.q.revenuecat.webhookKey.hint': 'Salve esse valor. No painel RevenueCat, cole como: Bearer <esse-valor>',
|
|
587
587
|
'new.firebase.q.revenuecat.metaToken': 'Meta Access Token (Conversions API, opcional)',
|
|
588
588
|
'new.firebase.q.revenuecat.metaDataset': 'Meta Dataset ID / Pixel ID (opcional)',
|
|
@@ -609,12 +609,12 @@ module.exports = {
|
|
|
609
609
|
'new.firebase.q.mixpanel.token': 'Token do Mixpanel (deixe em branco para configurar depois)',
|
|
610
610
|
'new.firebase.q.facebook.appId': 'App ID do Facebook',
|
|
611
611
|
'new.firebase.q.facebook.appId.required': 'App ID do Facebook é obrigatório.',
|
|
612
|
-
'new.firebase.q.facebook.appId.invalid': 'App ID do Facebook deve ser
|
|
612
|
+
'new.firebase.q.facebook.appId.invalid': 'App ID do Facebook deve ser numérico (ex: 1234567890).',
|
|
613
613
|
'new.firebase.q.facebook.token': 'Token do App Facebook',
|
|
614
614
|
'new.firebase.q.facebook.token.required': 'Token do App Facebook é obrigatório.',
|
|
615
615
|
'new.firebase.q.revenuecat.android.required': 'Chave Android do RevenueCat é obrigatória.',
|
|
616
616
|
'new.firebase.q.revenuecat.ios.required': 'Chave iOS do RevenueCat é obrigatória.',
|
|
617
|
-
'new.firebase.q.revenuecat.metaDataset.invalid': 'Pixel ID deve ser
|
|
617
|
+
'new.firebase.q.revenuecat.metaDataset.invalid': 'Pixel ID deve ser numérico (ex: 1234567890).',
|
|
618
618
|
|
|
619
619
|
'new.firebase.confirm.title': 'Resumo da configuração:',
|
|
620
620
|
'new.firebase.confirm.app': 'App',
|
|
@@ -648,7 +648,7 @@ module.exports = {
|
|
|
648
648
|
'new.firebase.success.alreadyDone': 'Já configurado pela CLI:',
|
|
649
649
|
'new.firebase.success.manualNeeded': 'Configure manualmente (se necessário):',
|
|
650
650
|
'new.firebase.success.apn': '• Chave APN (push iOS): Firebase Console → Config. do Projeto → Cloud Messaging',
|
|
651
|
-
'new.firebase.success.social': '• Ative o login social no Firebase Console → Authentication (Google e Apple já estão no código;
|
|
651
|
+
'new.firebase.success.social': '• Ative o login social no Firebase Console → Authentication (Google e Apple já estão no código; só ative lá)',
|
|
652
652
|
'new.firebase.success.googleSignIn': '• Login com Gmail: 1) Ative em Firebase Console → Auth → Sign-in method → Google. 2) O CLI preenche kGoogleWebClientId (google_auth_options.dart) do google-services.json para Android/iOS. Web usa signInWithPopup.',
|
|
653
653
|
'new.firebase.success.sentry': '• Sentry: Para relatórios de erro em produção. Pegue o DSN em sentry.io. Já no launch.json para dev. Para release: --dart-define=SENTRY_DSN=xxx',
|
|
654
654
|
'new.firebase.success.mixpanel': '• Mixpanel: Para analytics em produção. Já no launch.json para dev. Para release: --dart-define=MIXPANEL_TOKEN=xxx',
|
|
@@ -679,7 +679,7 @@ module.exports = {
|
|
|
679
679
|
'new.firebase.interactive.googleAuthNote': '* Ative o Google Sign-In manualmente (Email/Senha e Anônimo já foram ativados): ',
|
|
680
680
|
'new.firebase.interactive.billingNeeded': 'Plano Blaze ainda não ativo. Ative no link acima e aguarde a detecção automática.',
|
|
681
681
|
'new.firebase.interactive.billingWaiting': 'Verificando status do Blaze...',
|
|
682
|
-
'new.firebase.interactive.billingTimeout': 'Plano Blaze não confirmado
|
|
682
|
+
'new.firebase.interactive.billingTimeout': 'Plano Blaze não confirmado após o tempo limite. Deploy ignorado — rode manualmente quando estiver pronto.',
|
|
683
683
|
'new.firebase.interactive.authWarn': 'Não foi possível ativar Email/Senha e Anônimo automaticamente. Ative manualmente:',
|
|
684
684
|
'new.firebase.localhostWarn': 'Não foi possível autorizar localhost para login web. Se for testar login no navegador, adicione "localhost" em Authorized domains:',
|
|
685
685
|
'new.firebase.existing.apisFailed': 'Não foi possível ativar APIs:',
|
|
@@ -705,21 +705,21 @@ module.exports = {
|
|
|
705
705
|
'new.supabase.prereq.login': ' Se criar manualmente: tenha URL e anon key do projeto prontos',
|
|
706
706
|
'new.supabase.loginRequired': '⚠️ Você precisa estar logado para criar projeto. Execute supabase login primeiro.',
|
|
707
707
|
'new.supabase.loginCommand': ' supabase login',
|
|
708
|
-
'new.supabase.success.done.db': '• Banco: tabelas,
|
|
709
|
-
'new.supabase.success.done.storage': '• Storage: bucket kasy com
|
|
708
|
+
'new.supabase.success.done.db': '• Banco: tabelas, políticas RLS',
|
|
709
|
+
'new.supabase.success.done.storage': '• Storage: bucket kasy com políticas',
|
|
710
710
|
'new.supabase.success.done.webhook': '• Edge Function revenuecat-webhook',
|
|
711
711
|
'new.supabase.success.done.secrets': '• Secrets da Edge Function (se informados)',
|
|
712
712
|
'new.supabase.success.done.launch': '• launch.json com Sentry, Mixpanel, RevenueCat',
|
|
713
713
|
'new.supabase.success.auth': '• Auth: Email já vem ativado. Ative Google, Apple e Facebook em: {authUrl}',
|
|
714
|
-
'new.supabase.success.storage': '• Storage: Bucket kasy criado com
|
|
714
|
+
'new.supabase.success.storage': '• Storage: Bucket kasy criado com políticas (já pronto)',
|
|
715
715
|
'new.supabase.success.fcm': '• Push (FCM): Configure no Firebase Console (plano Blaze). App já pronto para Supabase + FCM. URL: {fcmUrl}',
|
|
716
716
|
'new.supabase.success.deployLater': '• Deploy do backend quando estiver pronto (de dentro da pasta do projeto):',
|
|
717
717
|
|
|
718
|
-
'new.api.prereq.1': '1. Sua API REST rodando e
|
|
718
|
+
'new.api.prereq.1': '1. Sua API REST rodando e acessível',
|
|
719
719
|
'new.api.prereq.2': '2. URL base da API (ex: https://api.yourapp.com)',
|
|
720
720
|
'new.api.prereq.3': '3. Firebase CLI obrigatório para notificações push (FCM)',
|
|
721
721
|
'new.api.success.backendUrl': '• Aponte o BACKEND_URL para sua API (launch.json)',
|
|
722
|
-
'new.api.success.fcm': '• Firebase
|
|
722
|
+
'new.api.success.fcm': '• Firebase é necessário para notificações push (FCM) — configure a chave APNs no console do Firebase',
|
|
723
723
|
'new.api.success.auth': '• Implemente os endpoints de auth social (Google, Apple) no seu backend',
|
|
724
724
|
|
|
725
725
|
'new.outdated.hint': 'projetos criados agora não terão as últimas melhorias.',
|
|
@@ -729,7 +729,7 @@ module.exports = {
|
|
|
729
729
|
'new.success.featuresInstalled': 'Recursos ativados:',
|
|
730
730
|
'new.success.bundleId': 'Identificador do app (bundle ID)',
|
|
731
731
|
'new.success.bundleId.hint': 'Identificador único do seu app no Android, iOS e Firebase (push).',
|
|
732
|
-
'new.success.nextSteps': '
|
|
732
|
+
'new.success.nextSteps': 'Próximos passos:',
|
|
733
733
|
'new.success.step.cd': 'Entre na pasta do projeto:',
|
|
734
734
|
'new.success.step.deploy': 'Suba o servidor pro Firebase (banco + funções):',
|
|
735
735
|
'new.success.step.configure': 'Configure chaves opcionais quando tiver (RevenueCat, Sentry, etc.):',
|
|
@@ -835,7 +835,7 @@ module.exports = {
|
|
|
835
835
|
'doctor.project.appName': 'Nome do app',
|
|
836
836
|
'doctor.project.backend': 'Backend',
|
|
837
837
|
'doctor.project.bundleId': 'Bundle ID',
|
|
838
|
-
'doctor.project.pubGet': '
|
|
838
|
+
'doctor.project.pubGet': 'Dependências instaladas (pubspec.lock presente)',
|
|
839
839
|
'doctor.project.pubGetMissing': 'Execute flutter pub get — pubspec.lock não encontrado',
|
|
840
840
|
'doctor.project.modules': 'Features ativas',
|
|
841
841
|
'doctor.project.noModules': 'Nenhuma feature opcional ativa',
|
|
@@ -948,7 +948,7 @@ module.exports = {
|
|
|
948
948
|
'notifications.writing': 'Atualizando lib/i18n/*.i18n.json...',
|
|
949
949
|
'notifications.written': 'Atualizado: {langs}',
|
|
950
950
|
'notifications.slang': 'Executando dart run slang...',
|
|
951
|
-
'notifications.slangDone': '
|
|
951
|
+
'notifications.slangDone': 'Traduções regeneradas',
|
|
952
952
|
'notifications.slangFailed': 'dart run slang falhou — execute manualmente no projeto',
|
|
953
953
|
'notifications.done': 'Textos de notificação local atualizados.',
|
|
954
954
|
'notifications.summary.demo': 'Home → Features (demo):',
|
|
@@ -957,14 +957,14 @@ module.exports = {
|
|
|
957
957
|
'add.list.title': 'Features do projeto',
|
|
958
958
|
'add.error.noModule': 'Informe o nome da feature ou use --list para ver as disponíveis.',
|
|
959
959
|
'add.error.notKasyProject': 'kit_setup.json não encontrado. Execute este comando dentro de um projeto Kasy.',
|
|
960
|
-
'add.error.unknownModule': 'Feature desconhecida: {module}\
|
|
960
|
+
'add.error.unknownModule': 'Feature desconhecida: {module}\nDisponíveis: {list}',
|
|
961
961
|
'add.alreadyActive': 'A feature "{module}" já está ativa neste projeto.',
|
|
962
962
|
'add.applying': 'Adicionando feature: {module}',
|
|
963
963
|
'add.applyingPatch': 'Aplicando mudanças da feature...',
|
|
964
964
|
'add.patchApplied': 'Patch aplicado',
|
|
965
965
|
'add.patchFailed': 'Patch falhou — verifique a saída acima',
|
|
966
966
|
'add.pubGet': 'Instalando pacotes do Flutter (flutter pub get)...',
|
|
967
|
-
'add.pubGetDone': '
|
|
967
|
+
'add.pubGetDone': 'Dependências atualizadas',
|
|
968
968
|
'add.pubGetFailed': 'Falha ao instalar pacotes do Flutter — execute `flutter pub get` manualmente',
|
|
969
969
|
'add.buildRunner': 'Gerando código (Riverpod/Freezed)...',
|
|
970
970
|
'add.buildRunnerDone': 'Geração de código concluída',
|
|
@@ -984,7 +984,7 @@ module.exports = {
|
|
|
984
984
|
'new.q.ai_chat.configureNow.hint': 'Pode pular e executar "kasy add ai_chat" depois',
|
|
985
985
|
'add.ai_chat.reconfigure': 'Feature já ativa — reconfigurando apenas as credenciais.',
|
|
986
986
|
'add.prompt.aiProvider': 'Provedor de IA:',
|
|
987
|
-
'add.prompt.aiSystemPrompt': 'Instrução do agente — system prompt (deixe em branco para nenhuma):\n Exemplo: "Você
|
|
987
|
+
'add.prompt.aiSystemPrompt': 'Instrução do agente — system prompt (deixe em branco para nenhuma):\n Exemplo: "Você é um assistente de suporte do app Fitsync. Responda apenas sobre treinos."\n >',
|
|
988
988
|
'add.prompt.aiApiKey': 'Chave de API (OpenAI ou Gemini) — fica no servidor, nunca no app (deixe em branco para configurar depois):',
|
|
989
989
|
'add.prompt.aiEndpoint': 'URL do seu endpoint IA (deixe em branco para configurar depois):',
|
|
990
990
|
'add.ai_chat.settingSecret': 'Salvando chave de API como secret no servidor...',
|
|
@@ -993,22 +993,22 @@ module.exports = {
|
|
|
993
993
|
'add.ai_chat.skipSecret': 'Chave de API ignorada — configure antes do deploy via CLI do servidor',
|
|
994
994
|
'add.ai_chat.deploying': 'Fazendo deploy da função IA no servidor...',
|
|
995
995
|
'add.ai_chat.deployed': 'Função IA deployada com sucesso',
|
|
996
|
-
'add.ai_chat.deployFailed': 'Deploy automático falhou —
|
|
997
|
-
'add.ai_chat.nextSteps.firebase': '\n
|
|
998
|
-
'add.ai_chat.nextSteps.firebase.deployFailed': '\n
|
|
999
|
-
'add.ai_chat.nextSteps.supabase': '\n
|
|
1000
|
-
'add.ai_chat.nextSteps.supabase.deployFailed': '\n
|
|
1001
|
-
'add.ai_chat.nextSteps.api': '\n
|
|
996
|
+
'add.ai_chat.deployFailed': 'Deploy automático falhou — faça o deploy manualmente (veja instruções abaixo)',
|
|
997
|
+
'add.ai_chat.nextSteps.firebase': '\n Próximos passos:\n 1. O AI_CHAT_ENDPOINT no .vscode/launch.json já foi preenchido.\n 2. Rode o app: kasy run\n',
|
|
998
|
+
'add.ai_chat.nextSteps.firebase.deployFailed': '\n Próximos passos:\n 1. Deploy manual: firebase deploy --only functions:aiChat\n 2. O AI_CHAT_ENDPOINT no .vscode/launch.json já foi preenchido.\n 3. Rode o app: kasy run\n',
|
|
999
|
+
'add.ai_chat.nextSteps.supabase': '\n Próximos passos:\n 1. O AI_CHAT_ENDPOINT no .vscode/launch.json já foi preenchido.\n 2. Rode o app: kasy run\n',
|
|
1000
|
+
'add.ai_chat.nextSteps.supabase.deployFailed': '\n Próximos passos:\n 1. Deploy manual: supabase functions deploy ai-chat --no-verify-jwt\n 2. O AI_CHAT_ENDPOINT no .vscode/launch.json já foi preenchido.\n 3. Rode o app: kasy run\n',
|
|
1001
|
+
'add.ai_chat.nextSteps.api': '\n Próximos passos:\n 1. Crie um endpoint no seu servidor que aceite {message, history} e chame sua IA.\n 2. Atualize AI_CHAT_ENDPOINT no .vscode/launch.json com a URL do seu endpoint.\n 3. Rode o app: kasy run\n',
|
|
1002
1002
|
'cli.command.remove.description': 'Remove algo que você não usa mais (ex: kasy remove sentry)',
|
|
1003
1003
|
'remove.error.noModule': 'Informe o nome da feature. Uso: kasy remove <feature>',
|
|
1004
1004
|
'remove.error.notKasyProject': 'kit_setup.json não encontrado. Execute este comando dentro de um projeto Kasy.',
|
|
1005
|
-
'remove.error.unknownModule': 'Feature desconhecida: {module}\
|
|
1005
|
+
'remove.error.unknownModule': 'Feature desconhecida: {module}\nDisponíveis: {list}',
|
|
1006
1006
|
'remove.error.notActive': 'A feature "{module}" não está ativa neste projeto.',
|
|
1007
1007
|
'remove.confirm': 'Remover a feature "{module}"? Isso vai deletar arquivos e dependências.',
|
|
1008
1008
|
'remove.cancelled': 'Cancelado.',
|
|
1009
1009
|
'remove.removing': 'Removendo feature: {module}',
|
|
1010
1010
|
'remove.pubGet': 'Instalando pacotes do Flutter (flutter pub get)...',
|
|
1011
|
-
'remove.pubGetDone': '
|
|
1011
|
+
'remove.pubGetDone': 'Dependências atualizadas',
|
|
1012
1012
|
'remove.pubGetFailed': 'Falha ao instalar pacotes do Flutter — execute `flutter pub get` manualmente',
|
|
1013
1013
|
'remove.buildRunner': 'Gerando código (Riverpod/Freezed)...',
|
|
1014
1014
|
'remove.buildRunnerDone': 'Geração de código concluída',
|
|
@@ -1020,20 +1020,20 @@ module.exports = {
|
|
|
1020
1020
|
'cli.command.update.targetArg': 'Alvo para atualizar (ex.: revenuecat, sentry, components)',
|
|
1021
1021
|
'update.error.noProject': 'kit_setup.json não encontrado. Execute dentro de um projeto Kasy.',
|
|
1022
1022
|
'update.error.unknownModule': 'Feature desconhecida: {module}\nDisponíveis: {list}',
|
|
1023
|
-
'update.error.unknownTarget': 'Alvo de atualização desconhecido: {module}\
|
|
1023
|
+
'update.error.unknownTarget': 'Alvo de atualização desconhecido: {module}\nDisponíveis: {list}',
|
|
1024
1024
|
'update.error.notActive': 'A feature "{module}" não está ativa neste projeto.',
|
|
1025
1025
|
'update.alreadyUpToDate': 'Projeto já está atualizado (v{version}).',
|
|
1026
1026
|
'update.status': 'Projeto: v{from} → CLI: v{to}',
|
|
1027
1027
|
'update.noVersion': 'Projeto foi gerado sem rastreamento de versão. Todas as features podem ser atualizadas.',
|
|
1028
1028
|
'update.changesTitle': 'Atualizações disponíveis:',
|
|
1029
|
-
'update.reapplyTitle': 'Sem
|
|
1029
|
+
'update.reapplyTitle': 'Sem mudanças novas — pode reaplicar se precisar:',
|
|
1030
1030
|
'update.howToUpdate': 'Para atualizar uma feature:',
|
|
1031
1031
|
'update.howToUpdateComponents': 'Para atualizar componentes base:',
|
|
1032
|
-
'update.warn.commit': 'Isso vai sobrescrever os arquivos da feature "{module}".
|
|
1033
|
-
'update.warn.commitComponents': 'Isso vai sobrescrever arquivos dos componentes base.
|
|
1032
|
+
'update.warn.commit': 'Isso vai sobrescrever os arquivos da feature "{module}". Faça commit de tudo antes de continuar.',
|
|
1033
|
+
'update.warn.commitComponents': 'Isso vai sobrescrever arquivos dos componentes base. Faça commit de tudo antes de continuar.',
|
|
1034
1034
|
'update.confirm': 'Sobrescrever arquivos da feature "{module}" com a versão mais recente?',
|
|
1035
1035
|
'update.confirmComponents': 'Sobrescrever arquivos dos componentes base com a versão mais recente?',
|
|
1036
|
-
'update.confirmCore': 'Sobrescrever arquivos do core (
|
|
1036
|
+
'update.confirmCore': 'Sobrescrever arquivos do core (animações, widgets, tema, ferramentas de dev) com a versão mais recente?',
|
|
1037
1037
|
'update.cancelled': 'Cancelado.',
|
|
1038
1038
|
'update.applying': 'Aplicando atualização da feature: {module}',
|
|
1039
1039
|
'update.applyingComponents': 'Aplicando atualização dos componentes base...',
|
|
@@ -1046,7 +1046,7 @@ module.exports = {
|
|
|
1046
1046
|
'update.noPatch': 'Feature "{module}" não tem arquivos para atualizar (feature so de configuração).',
|
|
1047
1047
|
'update.noComponentFiles': 'Nenhum arquivo de componente base foi encontrado para atualizar.',
|
|
1048
1048
|
'update.pubGet': 'Instalando pacotes do Flutter (flutter pub get)...',
|
|
1049
|
-
'update.pubGetDone': '
|
|
1049
|
+
'update.pubGetDone': 'Dependências atualizadas',
|
|
1050
1050
|
'update.pubGetFailed': 'Falha ao instalar pacotes do Flutter — execute `flutter pub get` manualmente',
|
|
1051
1051
|
'update.buildRunner': 'Gerando código (Riverpod/Freezed)...',
|
|
1052
1052
|
'update.buildRunnerDone': 'Geração de código concluída',
|
package/package.json
CHANGED
|
@@ -120,9 +120,22 @@ class BottomMenu extends StatelessWidget {
|
|
|
120
120
|
}
|
|
121
121
|
final path = _initialWebPath(Uri.base);
|
|
122
122
|
final segments = Uri.parse(path).pathSegments;
|
|
123
|
-
if (segments.
|
|
123
|
+
if (segments.isEmpty) {
|
|
124
124
|
return null;
|
|
125
125
|
}
|
|
126
|
+
// A single segment is a bottom-bar tab (home/notifications/settings/…).
|
|
127
|
+
// Bart keeps the browser URL in sync with the active tab via
|
|
128
|
+
// history.pushState, so honoring it here means a remount (e.g. toggling the
|
|
129
|
+
// web device preview) or a hard reload restores the tab the user was on
|
|
130
|
+
// instead of snapping back to the first one. Only accept it when it maps to
|
|
131
|
+
// a real tab; anything else falls back to the default tab.
|
|
132
|
+
if (segments.length == 1) {
|
|
133
|
+
final String tab = segments.first;
|
|
134
|
+
final bool isKnownTab = subRoutes().any(
|
|
135
|
+
(r) => r.path.replaceAll('/', '') == tab,
|
|
136
|
+
);
|
|
137
|
+
return isKnownTab ? '/$tab' : null;
|
|
138
|
+
}
|
|
126
139
|
return '/${segments.join('/')}';
|
|
127
140
|
}
|
|
128
141
|
|
|
@@ -104,14 +104,6 @@ class _WebDevicePreviewState extends State<WebDevicePreview>
|
|
|
104
104
|
late final ValueNotifier<AppLocale> _localeNotifier;
|
|
105
105
|
final _screenshotKey = GlobalKey();
|
|
106
106
|
|
|
107
|
-
// Keeps the wrapped app's Element alive across enable/disable. Toggling the
|
|
108
|
-
// preview moves MaterialApp.router between tree positions (in/out of the
|
|
109
|
-
// device frame); without a stable GlobalKey the Router would be rebuilt from
|
|
110
|
-
// scratch and navigation would snap back to the initial route ('/'). The
|
|
111
|
-
// GlobalKey makes Flutter reparent the same Element, preserving the current
|
|
112
|
-
// screen.
|
|
113
|
-
final _appKey = GlobalKey();
|
|
114
|
-
|
|
115
107
|
static const _textScaleSteps = [1.0, 1.3, 1.5];
|
|
116
108
|
|
|
117
109
|
List<DeviceInfo> get _devices => switch (_platform) {
|
|
@@ -418,7 +410,7 @@ class _WebDevicePreviewState extends State<WebDevicePreview>
|
|
|
418
410
|
deviceNotifier: _deviceNotifier,
|
|
419
411
|
frameVisibleNotifier: _frameVisibleNotifier,
|
|
420
412
|
landscapeNotifier: _landscapeNotifier,
|
|
421
|
-
child:
|
|
413
|
+
child: widget.child,
|
|
422
414
|
),
|
|
423
415
|
),
|
|
424
416
|
),
|