Ver código fonte

Add Spanish (Mexico) localization and language picker support.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 1 mês atrás
pai
commit
e6f09c0acd

+ 2 - 0
meetings_app.xcodeproj/project.pbxproj

@@ -100,6 +100,7 @@
 				fr,
 				"fr-CA",
 				"es-ES",
+				"es-MX",
 				de,
 				sv,
 				ko,
@@ -107,6 +108,7 @@
 				ru,
 				"zh-Hans",
 				"zh-Hant",
+				"es-MX",
 			);
 			mainGroup = 13AF5D992F83DE22001BE867;
 			minimizedProjectReferenceProxies = 1;

+ 3 - 1
meetings_app/Localization/AppLanguageManager.swift

@@ -8,7 +8,7 @@ enum AppLanguageManager {
     private static let defaultsKey = "settings.appLanguageCode"
 
     /// UI languages shown in Settings → Language (order preserved).
-    private static let supportedLanguageCodes = ["en", "fr", "fr-CA", "es-ES", "de", "sv", "ko", "pt-BR", "ru", "zh-Hans", "zh-Hant"]
+    private static let supportedLanguageCodes = ["en", "fr", "fr-CA", "es-ES", "es-MX", "de", "sv", "ko", "pt-BR", "ru", "zh-Hans", "zh-Hant"]
 
     /// `nil` follows the system language; otherwise uses the selected `.lproj` code.
     static var selectedLanguageCode: String? {
@@ -63,6 +63,8 @@ enum AppLanguageManager {
             return "Français (Canada)"
         case "es-ES":
             return "Español (España)"
+        case "es-MX":
+            return "Español (México)"
         case "de":
             return "Deutsch"
         case "sv":

+ 4 - 0
meetings_app/es-MX.lproj/InfoPlist.strings

@@ -0,0 +1,4 @@
+"CFBundleDisplayName" = "Asistente de IA para Meet de Google";
+"CFBundleName" = "Asistente de IA para Meet de Google";
+"NSMicrophoneUsageDescription" = "Con tu consentimiento, la aplicación grabará el audio de la reunión en esta Mac y lo mostrará en el Asistente de IA después de la reunión.";
+"NSSpeechRecognitionUsageDescription" = "Esta aplicación convierte el audio guardado de tus reuniones en transcripciones de texto para el Asistente de IA.";

+ 452 - 0
meetings_app/es-MX.lproj/Localizable.strings

@@ -0,0 +1,452 @@
+/* AppBrand.name ("Meetings") omitido intencionalmente — el nombre de la aplicación permanece sin cambios en el código. */
+"AI Companion for Meet" = "Asistente de IA para Meet de Google";
+
+/* MARK: - General */
+"OK" = "Aceptar";
+"Cancel" = "Cancelar";
+"Continue" = "Continuar";
+"Apply" = "Aplicar";
+"Reset" = "Restablecer";
+"Save" = "Guardar";
+"Copy" = "Copiar";
+"Copied" = "Copiado";
+"Close" = "Cerrar";
+"Join" = "Unirse";
+"None" = "Ninguno";
+"Link" = "Enlace";
+"Stop" = "Detener";
+"Address" = "Dirección";
+"Title" = "Título";
+"Notes" = "Notas";
+"Start" = "Iniciar";
+"Premium" = "Premium";
+"Popular" = "Popular";
+"Browser" = "Navegador";
+"Meeting" = "Reunión";
+"Error" = "Error";
+"Success" = "Éxito";
+
+/* MARK: - Barra de estado */
+"Meetings status menu" = "Menú de estado de reuniones";
+"Open App" = "Abrir aplicación";
+"Join Meetings" = "Unirse a reuniones";
+"Schedule" = "Agendar";
+"Calendar" = "Calendario";
+"Widgets" = "Widgets";
+"AI Companion" = "Asistente de IA";
+"Settings" = "Configuración";
+"Top meetings" = "Reuniones fijadas";
+"No upcoming meetings" = "No hay reuniones próximas";
+"Sign Out" = "Cerrar sesión";
+"Sign In" = "Iniciar sesión";
+"Quit" = "Salir";
+
+/* MARK: - Pantalla de inicio */
+"Preparing your meetings workspace" = "Preparando tu espacio de trabajo de reuniones";
+"CONNECTING SERVICES" = "CONECTANDO SERVICIOS";
+"READY" = "LISTO";
+"Plan smart, achieve more" = "Planifica inteligentemente, logra más";
+
+/* MARK: - Widgets */
+"Add Widget to Desktop" = "Agregar widget al escritorio";
+"Choose a size and add your Google Meet widget." = "Elige un tamaño y agrega tu widget de Meet de Google.";
+"Tip: Right-click a desktop widget to remove it." = "Consejo: haz clic derecho en un widget del escritorio para eliminarlo.";
+"Removed %@ widget from desktop." = "Widget %@ eliminado del escritorio.";
+"Added %@ widget from desktop." = "Widget %@ agregado desde el escritorio.";
+"Widgets are Premium only. Upgrade to add widgets." = "Los widgets son solo para Premium. Actualiza para agregar widgets.";
+"Remove Widget" = "Eliminar widget";
+"Small" = "Pequeño";
+"Medium" = "Mediano";
+"Quick actions" = "Acciones rápidas";
+"Open Meet" = "Abrir Meet de Google";
+"Upcoming meetings" = "Próximas reuniones";
+"Sign in to see upcoming meetings" = "Inicia sesión para ver las próximas reuniones";
+"Sign in with Google" = "Iniciar sesión con cuenta de Google";
+"Google Meet" = "Meet de Google";
+"Open and join quickly" = "Abrir y unirse rápidamente";
+"Refresh" = "Actualizar";
+
+/* MARK: - Barra lateral y navegación */
+"Planning" = "Planificación";
+"Additional" = "Adicional";
+"Get Premium" = "Obtener Premium";
+"Manage Subscription" = "Administrar suscripción";
+"App for Google Meet" = "Aplicación para Meet de Google";
+
+/* MARK: - Unirse a una reunión */
+"New Instant Meet" = "Nueva reunión instantánea";
+"Start instant Meet in more section with\nGoogle Meet meet." = "Inicia una reunión instantánea de Meet de Google en la sección Más\ncon Meet de Google.";
+"Join with Link" = "Unirse con enlace";
+"Code or meet.google.com/…" = "Código o meet.google.com/…";
+"Join with ID" = "Unirse con ID";
+"Join with URL" = "Unirse con URL";
+"Meeting URL" = "URL de la reunión";
+"Enter meeting URL..." = "Ingresa la URL de la reunión...";
+"Quick Join Meeting" = "Unión rápida a la reunión";
+"Invalid Meet link" = "Enlace de Meet de Google no válido";
+"Enter a valid Google Meet link or meeting code (for example nkd-grps-duv, meet.google.com/nkd-grps-duv, or https://meet.google.com/nkd-grps-duv)." = "Ingresa un enlace válido de Meet de Google o código de reunión (por ejemplo, nkd-grps-duv, meet.google.com/nkd-grps-duv o https://meet.google.com/nkd-grps-duv).";
+"Instant Meeting" = "Reunión instantánea";
+"Connect Google to start Instant Meeting" = "Conecta tu cuenta de Google para iniciar una reunión instantánea";
+"To auto-stop recording when the meeting ends, connect your Google account first." = "Para detener automáticamente la grabación cuando termine la reunión, conecta primero tu cuenta de Google.";
+"Could not create Instant Meeting" = "No se pudo crear la reunión instantánea";
+"Free trial used. Upgrade to continue." = "Prueba gratuita usada. Actualiza para continuar.";
+
+/* MARK: - Navegar por la web */
+"Browse the web" = "Navegar por la web";
+"Enter a web address (for example meet.google.com)." = "Ingresa una dirección web (por ejemplo, meet.google.com).";
+"Invalid address" = "Dirección no válida";
+"Enter a valid http or https URL." = "Ingresa una URL http o https válida.";
+"Browse" = "Navegar";
+"Quick links" = "Enlaces rápidos";
+"Zoom help" = "Ayuda de Zoom";
+"https://example.com or example.com" = "https://example.com o example.com";
+"Enter a valid web address, for example https://example.com" = "Ingresa una dirección web válida, por ejemplo https://example.com";
+"Address not allowed" = "Dirección no permitida";
+"This URL is not permitted with the current in-app browser policy (whitelist)." = "Esta URL no está permitida con la política actual del navegador en la aplicación (lista blanca).";
+"Unable to load page" = "No se pudo cargar la página";
+"Could not load this page in the in-app browser.\n\n%@" = "No se pudo cargar esta página en el navegador de la aplicación.\n\n%@";
+"Page stopped loading" = "La página detuvo la carga";
+"Unable to open browser" = "No se pudo abrir el navegador";
+"Unable to Open Safari" = "No se pudo abrir Safari";
+
+/* MARK: - Agendamiento y calendario */
+"All" = "Todos";
+"Today" = "Hoy";
+"This week" = "Esta semana";
+"This month" = "Este mes";
+"Previous week" = "Semana anterior";
+"Previous month" = "Mes anterior";
+"Custom range" = "Rango personalizado";
+"No meetings match the selected filters." = "Ninguna reunión coincide con los filtros seleccionados.";
+"Adjust the date range and tap Apply." = "Ajusta el rango de fechas y presiona Aplicar.";
+"Premium required. Get Premium now to unlock Calendar." = "Se requiere Premium. Obtén Premium ahora para desbloquear el Calendario.";
+"Premium required. Click to open paywall." = "Se requiere Premium. Haz clic para abrir el muro de pago.";
+"Get Premium to see events" = "Obtén Premium para ver eventos";
+"Connect Google" = "Conectar cuenta de Google";
+"Sign in with Google first to schedule a meeting from Calendar." = "Inicia sesión con cuenta de Google primero para agendar una reunión desde el Calendario.";
+"Select date" = "Seleccionar fecha";
+"Choose a date to schedule your meeting." = "Elige una fecha para agendar tu reunión.";
+"Google schedule" = "Calendario de Google";
+"To show scheduled meetings, connect your Google account. You’ll need a Google OAuth client ID (Desktop) and a redirect URI matching the app’s callback scheme." = "Para mostrar las reuniones agendadas, conecta tu cuenta de Google. Necesitarás un ID de cliente de Google OAuth (Desktop) y un URI de redirección que coincida con el esquema de devolución de llamada de la aplicación.";
+"Actions" = "Acciones";
+"Schedule meeting" = "Agendar reunión";
+"Team sync" = "Sincronización de equipo";
+"Duration (min)" = "Duración (min)";
+"Refresh saved meetings" = "Actualizar reuniones guardadas";
+
+/* MARK: - Configuración */
+"Manage appearance, account, and app options." = "Administra la apariencia, la cuenta y las opciones de la aplicación.";
+"Appearance" = "Apariencia";
+"Account" = "Cuenta";
+"App" = "Aplicación";
+"Notifications" = "Notificaciones";
+"Help & Legal" = "Ayuda y Aviso legal";
+"Dark Mode" = "Modo oscuro";
+"Language" = "Idioma";
+"System Language" = "Idioma del sistema";
+"Rate Us" = "Calificar aplicación";
+"Share App" = "Compartir aplicación";
+"Upgrade" = "Actualizar";
+"Privacy Policy" = "Política de privacidad";
+"Support" = "Soporte";
+"Terms of Services" = "Términos de servicio";
+"AI Language 1" = "Idioma de IA 1";
+"AI Language 2" = "Idioma de IA 2";
+"Google account connected" = "Cuenta de Google conectada";
+"Google account not connected" = "Cuenta de Google no conectada";
+"Signed in" = "Sesión iniciada";
+"Sign in to sync your meetings and calendar." = "Inicia sesión para sincronizar tus reuniones y calendario.";
+"Log out" = "Cerrar sesión";
+"Check out %@ for managing and joining meetings." = "Prueba %@ para administrar y unirte a reuniones.";
+"Meetings App" = "Aplicación de Reuniones";
+
+/* MARK: - Consentimiento de grabación */
+"Record this meeting locally?" = "¿Grabar esta reunión localmente?";
+"With your consent, the app will record meeting audio on this Mac and show it in AI Companion after the meeting." = "Con tu consentimiento, la aplicación grabará el audio de la reunión en esta Mac y lo mostrará en el Asistente de IA después de la reunión.";
+"Allow and Continue" = "Permitir y continuar";
+"Continue Without Recording" = "Continuar sin grabar";
+"Transcription Languages" = "Idiomas de transcripción";
+"Preferred Language 1" = "Idioma preferido 1";
+"Preferred Language 2" = "Idioma preferido 2";
+"Microphone permission denied" = "Permiso de micrófono denegado";
+"Microphone permission required" = "Permiso de micrófono requerido";
+"Enable microphone access in System Settings to record meetings locally." = "Activa el acceso al micrófono en Configuración del Sistema para grabar reuniones localmente.";
+"Could not start recording" = "No se pudo iniciar la grabación";
+"Recording will start when the meeting starts" = "La grabación comenzará cuando empiece la reunión";
+"Meeting recording started (meeting + microphone)" = "Grabación de la reunión iniciada (reunión + micrófono)";
+"System audio unavailable. Recording microphone only." = "Audio del sistema no disponible. Grabando solo el micrófono.";
+"Meeting recording started (microphone only)" = "Grabación de la reunión iniciada (solo micrófono)";
+"Meeting recording saved" = "Grabación de la reunión guardada";
+
+/* MARK: - Asistente de IA */
+"Get notes from your previous meetings" = "Obtén notas de tus reuniones anteriores";
+"Connect your Google account to see your AI Companion meeting history." = "Conecta tu cuenta de Google para ver el historial de reuniones de tu Asistente de IA.";
+"No previous meetings yet for %@. End a meeting to save it here and generate notes." = "Todavía no hay reuniones anteriores para %@. Finaliza una reunión para guardarla aquí y generar notas.";
+"this account" = "esta cuenta";
+"Previous meetings" = "Reuniones anteriores";
+"Recording in progress: %@" = "Grabación en curso: %@";
+"Started: %@" = "Iniciada: %@";
+"Stop Recording" = "Detener grabación";
+"Date: %@" = "Fecha: %@";
+"Saved time: %@" = "Guardada: %@";
+"Get Notes" = "Obtener notas";
+"Premium required. Click to unlock AI Companion notes." = "Se requiere Premium. Haz clic para desbloquear las notas del Asistente de IA.";
+"Play Audio" = "Reproducir audio";
+"Pause Audio" = "Pausar audio";
+"Stopped" = "Detenido";
+"Speaking..." = "Hablando...";
+"Paused" = "Pausado";
+"Playing..." = "Reproduciendo...";
+"Not playing" = "No se está reproduciendo";
+"Checking audio..." = "Verificando audio...";
+"Audio file missing" = "Archivo de audio faltante";
+"Could not play recording" = "No se pudo reproducir la grabación";
+"Failed: %@" = "Error: %@";
+"Failed to play audio" = "Error al reproducir el audio";
+"decode error" = "error de decodificación";
+"Loading..." = "Cargando...";
+"Buffering..." = "Almacenando en búfer...";
+"Finished" = "Finalizado";
+"Transcript not requested" = "Transcripción no solicitada";
+"Transcript processing..." = "Procesando transcripción...";
+"Transcript ready" = "Transcripción lista";
+"Transcript unavailable (tap to retry)" = "Transcripción no disponible (toca para reintentar)";
+"Notes not requested" = "Notas no solicitadas";
+"Preparing notes, please wait..." = "Preparando notas, espera...";
+"Notes ready" = "Notas listas";
+"Notes unavailable (tap to retry)" = "Notas no disponibles (toca para reintentar)";
+"Transcript unavailable" = "Transcripción no disponible";
+"Notes unavailable" = "Notas no disponibles";
+"Could not find recording details for this meeting." = "No se pudieron encontrar los detalles de grabación para esta reunión.";
+"Transcript - %@" = "Transcripción - %@";
+"Notes - %@" = "Notas - %@";
+"Meeting Notes" = "Notas de la reunión";
+"Transcript processing..." = "Procesando transcripción...";
+
+/* MARK: - Muro de pago y StoreKit */
+"Meetings Pro" = "Reuniones Pro";
+"PREMIUM EXPERIENCE" = "EXPERIENCIA PREMIUM";
+"Elevate your meetings workflow" = "Mejora tu flujo de trabajo de reuniones";
+"Unlock automation, premium meeting tools, and priority support for every session." = "Desbloquea automatización, herramientas premium para reuniones y soporte prioritario para cada sesión.";
+"Manage meetings" = "Administrar reuniones";
+"Smart scheduling" = "Agendamiento inteligente";
+"Faster workflow" = "Flujo de trabajo más rápido";
+"Reminder notifications" = "Notificaciones de recordatorio";
+"Monthly" = "Mensual";
+"Bi Yearly" = "Semestral";
+"Yearly" = "Anual";
+"Most Popular" = "Más popular";
+"%@ • Most Popular" = "%@ • Más popular";
+"3 days free trial" = "3 días de prueba gratuita";
+"Cancel anytime" = "Cancela cuando quieras";
+"No lock-in" = "Sin permanencia";
+"Instant access" = "Acceso instantáneo";
+"Unlock all tools" = "Desbloquea todas las herramientas";
+"Secure billing" = "Facturación segura";
+"Handled by Apple" = "Manejado por Apple";
+"Secured by Apple. Cancel anytime." = "Seguro con Apple. Cancela cuando quieras.";
+"Restore Purchase" = "Restaurar compra";
+"Continue with free plan" = "Continuar con el plan gratuito";
+"Already Premium" = "Ya eres Premium";
+"You are already premium. Do you want to continue with this purchase?" = "Ya eres Premium. ¿Quieres continuar con esta compra?";
+"Current plan: %@. Choose a different package to switch." = "Plan actual: %@. Elige otro paquete para cambiar.";
+"Premium is active on this Apple ID." = "Premium está activo en este ID de Apple.";
+"Free for %@, then %@" = "Gratis por %@, luego %@";
+"Billed via App Store" = "Facturado a través de la App Store";
+"%@  •  %@" = "%@  •  %@";
+"Save 0%" = "Ahorra un 0%";
+"Save %@%%" = "Ahorra un %@%%";
+"month" = "mes";
+"year" = "año";
+"%@ free trial" = "Prueba gratuita de %@";
+"Processing..." = "Procesando...";
+"Premium Active" = "Premium activo";
+"Continue with 3 day trail" = "Continuar con la prueba de 3 días";
+"Please Wait" = "Espera";
+"A purchase is already being processed." = "Ya se está procesando una compra.";
+"This Apple ID already has premium access." = "Este ID de Apple ya tiene acceso Premium.";
+"Purchase Complete" = "Compra completada";
+"Premium has been unlocked successfully." = "Premium se ha desbloqueado correctamente.";
+"Purchase Pending" = "Compra pendiente";
+"Your purchase is pending approval. You can continue once it completes." = "Tu compra está pendiente de aprobación. Puedes continuar una vez que se complete.";
+"Product Not Available" = "Producto no disponible";
+"Unable to load this product. Check your StoreKit configuration and product IDs." = "No se pudo cargar este producto. Verifica tu configuración de StoreKit y los IDs de producto.";
+"Already Purchased" = "Ya comprado";
+"This plan is already active on your Apple ID." = "Este plan ya está activo en tu ID de Apple.";
+"Purchase Failed" = "Compra fallida";
+"Restore Purchases" = "Restaurar compras";
+"Purchases restored successfully." = "Compras restauradas correctamente.";
+"No previous premium purchase was found for this Apple ID." = "No se encontró ninguna compra Premium anterior para este ID de Apple.";
+"Restore failed: %@" = "Error al restaurar: %@";
+"Unable to Open Subscriptions" = "No se pudo abrir Suscripciones";
+"The subscriptions URL is invalid." = "La URL de suscripciones no es válida.";
+"%@ tapped." = "%@ presionado.";
+
+/* MARK: - Autenticación */
+"Google Sign-In" = "Inicio de sesión de Google";
+
+/* MARK: - Errores de reconocimiento de voz/transcripción */
+"Speech recognition permission denied. Enable it in System Settings and try again." = "Permiso de reconocimiento de voz denegado. Actívalo en Configuración del Sistema e inténtalo de nuevo.";
+"Speech recognition is restricted on this Mac." = "El reconocimiento de voz está restringido en esta Mac.";
+"Speech recognition authorization is unavailable." = "La autorización de reconocimiento de voz no está disponible.";
+"Speech recognizer is unavailable for the current locale." = "El reconocedor de voz no está disponible para la configuración regional actual.";
+"Speech recognizer is unavailable for %@." = "El reconocedor de voz no está disponible para %@.";
+"No audio was available to transcribe." = "No había audio disponible para transcribir.";
+
+/* MARK: - Errores de transacción de StoreKit */
+"Unable to load products: %@" = "No se pudieron cargar los productos: %@";
+"Product ID not found in StoreKit response. Requested: %@. Loaded IDs: %@" = "ID de producto no encontrado en la respuesta de StoreKit. Solicitado: %@. IDs cargados: %@";
+"Purchase verification failed." = "Error de verificación de compra.";
+"Unknown purchase state." = "Estado de compra desconocido.";
+"none" = "ninguno";
+
+/* MARK: - Textos de precios del muro de pago */
+"%@ one-time purchase" = "Compra única de %@";
+"%@/month" = "%@/mes";
+"%@/6 months" = "%@/6 meses";
+"%@/year (3 days free trial)" = "%@/año (3 días de prueba gratuita)";
+"day" = "día";
+"week" = "semana";
+"period" = "período";
+"1 %@" = "1 %@";
+"%d %@s" = "%d %@";
+
+/* MARK: - Toasts y retroalimentación rápida */
+"Meeting added successfully." = "Reunión agregada correctamente.";
+"An issue occurred. Please try again." = "Ocurrió un problema. Inténtalo de nuevo.";
+"Failed to load transcript." = "Error al cargar la transcripción.";
+"Failed to generate notes." = "Error al generar las notas.";
+
+/* MARK: - Alertas del navegador */
+"Try Again" = "Reintentar";
+"The in-app browser closed this page unexpectedly. You can try loading it again in this same window." = "El navegador de la aplicación cerró esta página inesperadamente. Puedes intentar cargarla de nuevo en esta misma ventana.";
+
+/* MARK: - Errores de agendamiento y calendario */
+"Couldn't load schedule." = "No se pudo cargar el calendario.";
+"Couldn't refresh schedule." = "No se pudo actualizar el calendario.";
+"Couldn't connect Google account." = "No se pudo conectar la cuenta de Google.";
+"Couldn't logout Google account." = "No se pudo cerrar la sesión de la cuenta de Google.";
+"Couldn't load schedule" = "No se pudo cargar el calendario";
+"Couldn't determine Meet meeting code from URL." = "No se pudo determinar el código de reunión de Meet de Google a partir de la URL.";
+"Refreshing…" = "Actualizando…";
+"Connect Google to see meetings" = "Conecta tu cuenta de Google para ver reuniones";
+"Connect to load schedule" = "Conéctate para cargar el calendario";
+"Loading…" = "Cargando…";
+"Loading schedule…" = "Cargando calendario…";
+"Start date must be on or before end date." = "La fecha de inicio debe ser anterior o igual a la fecha de finalización.";
+"Invalid custom date range" = "Rango de fechas personalizado no válido";
+"No meetings" = "No hay reuniones";
+"No meetings for selected filters" = "No hay reuniones para los filtros seleccionados";
+"No meetings on %@" = "No hay reuniones el %@";
+"1 meeting on %@" = "1 reunión el %@";
+"%d meetings on %@" = "%d reuniones el %@";
+"All day" = "Todo el día";
+"Duration: all day" = "Duración: todo el día";
+"Duration: %dh %dm" = "Duración: %dh %dm";
+"Duration: %dh" = "Duración: %dh";
+"Duration: %dm" = "Duración: %dm";
+"%@ - %@" = "%@ - %@";
+"Scheduled Meeting" = "Reunión agendada";
+
+/* MARK: - Ventana emergente de creación de reunión */
+"Please enter a title." = "Por favor, ingresa un título.";
+"Duration must be a positive number of minutes." = "La duración debe ser un número positivo de minutos.";
+"Invalid start time." = "Hora de inicio no válida.";
+
+/* MARK: - Recordatorios y notificaciones */
+"Reminders" = "Recordatorios";
+"1 Day Before" = "1 día antes";
+"12 Hours Before" = "12 horas antes";
+"1 Hour Before" = "1 hora antes";
+"Starts in 1 day" = "Comienza en 1 día";
+"Starts in 12 hours" = "Comienza en 12 horas";
+"Starts in 1 hour" = "Comienza en 1 hora";
+
+/* MARK: - Errores de OAuth de Google */
+"Missing Google OAuth Client ID." = "Falta el ID de cliente de OAuth de Google.";
+"Missing Google OAuth Client Secret." = "Falta el secreto de cliente de OAuth de Google.";
+"Invalid OAuth callback URL." = "URL de devolución de llamada de OAuth no válida.";
+"Google did not return an authorization code." = "La cuenta de Google no devolvió un código de autorización.";
+"Token exchange failed: %@" = "Error en el intercambio de tokens: %@";
+"Could not open browser for Google sign-in." = "No se pudo abrir el navegador para iniciar sesión en Google.";
+"Google sign-in timed out." = "Tiempo de espera agotado para el inicio de sesión con cuenta de Google.";
+"No stored Google tokens found." = "No se encontraron tokens de la cuenta de Google almacenados.";
+
+/* MARK: - Errores del Asistente de IA/transcripción */
+"Recording not found." = "Grabación no encontrada.";
+"Local meeting audio is missing." = "Falta el audio local de la reunión.";
+"Generated transcript was empty." = "La transcripción generada estaba vacía.";
+"(No transcript entries found.)" = "(No se encontraron entradas de transcripción.)";
+"No conference record found for this meeting." = "No se encontró ningún registro de conferencia para esta reunión.";
+"No transcript found for this meeting." = "No se encontró ninguna transcripción para esta reunión.";
+"Unable to create audio composition tracks." = "No se pudieron crear las pistas de composición de audio.";
+"Unable to create audio export session." = "No se pudo crear la sesión de exportación de audio.";
+"Audio mix export failed." = "Error en la exportación de la mezcla de audio.";
+"No display available for system audio capture." = "No hay ninguna pantalla disponible para la captura de audio del sistema.";
+"Cannot add audio writer input." = "No se puede agregar la entrada del escritor de audio.";
+
+/* MARK: - Errores de la API de Google */
+"Google Meet returned an invalid response." = "Meet de Google devolvió una respuesta no válida.";
+"Google Meet API error (%d): %@" = "Error de la API de Meet de Google (%d): %@";
+"Failed to parse Google Meet response: %@" = "Error al analizar la respuesta de Meet de Google: %@";
+"Google Calendar returned an invalid response." = "Calendario de Google devolvió una respuesta no válida.";
+"Google Calendar API error (%d): %@" = "Error de la API de Calendario de Google (%d): %@";
+"Failed to parse Google Calendar events: %@" = "Error al analizar los eventos de Calendario de Google: %@";
+
+/* MARK: - Errores de OpenAI */
+"OpenAI API key is missing. Set OPENAI_API_KEY in the environment or app key vault." = "Falta la clave de API de OpenAI. Establece OPENAI_API_KEY en el entorno o en el almacén de claves de la aplicación.";
+"Notes generation returned an invalid response." = "La generación de notas devolvió una respuesta no válida.";
+"Notes generation failed (%d): %@" = "Error en la generación de notas (%d): %@";
+"Notes generation returned empty text." = "La generación de notas devolvió un texto vacío.";
+"OpenAI transcription returned an invalid response." = "La transcripción de OpenAI devolvió una respuesta no válida.";
+"OpenAI transcription failed (%d): %@" = "Error en la transcripción de OpenAI (%d): %@";
+"OpenAI transcription returned no text." = "La transcripción de OpenAI no devolvió texto.";
+
+/* MARK: - Navegación y navegador en la aplicación */
+"Open sites in the in-app browser (back, forward, reload, address bar). OAuth and “Continue in browser” flows stay inside the app." = "Abre sitios en el navegador de la aplicación (atrás, adelante, recargar, barra de direcciones). Los flujos de OAuth y de «Continuar en el navegador» permanecen dentro de la aplicación.";
+"Open in app browser" = "Abrir en el navegador de la aplicación";
+"Meet help" = "Ayuda de Meet de Google";
+"Go" = "Ir";
+"Back" = "Atrás";
+"Forward" = "Adelante";
+"Reload" = "Recargar";
+
+/* MARK: - Etiquetas de calendario y agendamiento */
+"Google Calendar" = "Calendario de Google";
+"Untitled meeting" = "Reunión sin título";
+"Created event missing start/end." = "El evento creado no tiene inicio/fin.";
+"Created event missing Meet/HTML link." = "El evento creado no tiene enlace Meet de Google/HTML.";
+
+/* MARK: - Cuenta de Google */
+"Google account" = "Cuenta de Google";
+"%@, Google account" = "%@, cuenta de Google";
+"Google User" = "Usuario de Google";
+
+/* MARK: - Unirse a Zoom (partes no utilizadas) */
+"Meeting ID" = "ID de reunión";
+"Enter meeting ID..." = "Ingresa el ID de la reunión...";
+"Meeting Passcode" = "Código de acceso de la reunión";
+"Enter meeting passcode..." = "Ingresa el código de acceso de la reunión...";
+
+/* MARK: - Muro de pago (beneficios alternativos) */
+"Virtual backgrounds" = "Fondos virtuales";
+"Tools for productivity" = "Herramientas de productividad";
+"24/7 support" = "Soporte 24/7";
+
+/* MARK: - Oradores de la transcripción */
+"You" = "Tú";
+
+/* MARK: - Errores del llavero */
+"Failed to read OAuth tokens from Keychain." = "Error al leer los tokens de OAuth del Llavero.";
+"Keychain returned an invalid token payload." = "El Llavero devolvió una carga útil de token no válida.";
+"Failed to update OAuth tokens in Keychain." = "Error al actualizar los tokens de OAuth en el Llavero.";
+"Failed to save OAuth tokens to Keychain." = "Error al guardar los tokens de OAuth en el Llavero.";
+"Failed to delete OAuth tokens from Keychain." = "Error al eliminar los tokens de OAuth del Llavero.";
+"Unable to allocate audio buffer." = "No se pudo asignar el búfer de audio.";
+"Invalid revoke response." = "Respuesta de revocación no válida.";
+"Token revoke failed with status %d." = "Error en la revocación del token con estado %d.";
+
+/* MARK: - Diagnóstico de errores */
+"Keychain: %d (%@)" = "Llavero: %d (%@)";
+"OSStatus: %d" = "OSStatus: %d";
+"Item: service=%@, account=%@" = "Elemento: servicio=%@, cuenta=%@";

+ 17 - 0
meetings_app/es-MX.lproj/Main.strings

@@ -0,0 +1,17 @@
+/* Class = "NSMenuItem"; title = "AI Companion for Meet"; ObjectID = "1Xt-HY-uBw"; */
+"1Xt-HY-uBw.title" = "Asistente de IA para Meet de Google";
+
+/* Class = "NSMenu"; title = "AI Companion for Meet"; ObjectID = "uQy-DD-JDr"; */
+"uQy-DD-JDr.title" = "Asistente de IA para Meet de Google";
+
+/* Class = "NSMenuItem"; title = "About AI Companion for Meet"; ObjectID = "5kV-Vb-QxS"; */
+"5kV-Vb-QxS.title" = "Acerca de Asistente de IA para Meet de Google";
+
+/* Class = "NSMenuItem"; title = "Hide AI Companion for Meet"; ObjectID = "Olw-nP-bQN"; */
+"Olw-nP-bQN.title" = "Ocultar Asistente de IA para Meet de Google";
+
+/* Class = "NSMenuItem"; title = "Quit AI Companion for Meet"; ObjectID = "4sb-4s-VLi"; */
+"4sb-4s-VLi.title" = "Salir de Asistente de IA para Meet de Google";
+
+/* Class = "NSMenuItem"; title = "AI Companion for Meet Help"; ObjectID = "FKE-Sm-Kum"; */
+"FKE-Sm-Kum.title" = "Ayuda de Asistente de IA para Meet de Google";