← Todos los articulos

El framework Translation de Apple: gratuito, en el dispositivo y más afinado de lo que parece

El framework Translation de Apple traduce texto en el dispositivo, gratis, sin clave de API y sin llamadas de red una vez instalado el idioma1. Está construido sobre modelos de Core ML, viene con el sistema y le da a tu app el mismo motor de traducción que usa la app Traducir. Para las funciones multilingües que antes significaban una factura de traducción en la nube y una pregunta sobre privacidad, el costo vuelve a redondearse a cero. Y como ocurre con el framework Foundation Models6, lo interesante no es el camino feliz: son las aristas que las demos omiten, es decir, la descarga de idioma que bloquea tu primera traducción, el simulador que se niega a funcionar sin decirte por qué y una superficie exclusiva de SwiftUI que condiciona cómo lo adoptas.

En resumen

  • Dos superficies, dos versiones de iOS. translationPresentation muestra el popover de traducción integrado de Apple (iOS 17.4+). TranslationSession, a la que llegas mediante el modificador translationTask, hace traducción programática dentro de tu propia UI (iOS 18+)2.
  • La traducción programática es async. Dentro del closure de translationTask recibes una TranslationSession; la invocas para traducir una cadena o un lote3.
  • El procesamiento por lotes es ciudadano de primera clase. Traduce una lista en una sola solicitud y mantén cada resultado emparejado con su entrada, en lugar de iterar y esperar una traducción por vez3.
  • La UI de traducción es exclusiva de SwiftUI y no funciona en el simulador de iOS. Ambas cosas se descubren fácilmente por las malas; diseña y prueba en consecuencia4.
  • Sin conexión implica una descarga previa. La primera traducción de un par de idiomas descarga los paquetes correspondientes, y eso es un momento de UX real que tienes que resolver, no un detalle5.
  • La combinación que vale la pena conocer: traduce la entrada del usuario con Translation y luego razona sobre ella con Foundation Models, y una función de agente monolingüe en el dispositivo empieza a funcionar en cualquier idioma que el dispositivo pueda instalar.

Dos superficies: el popover del sistema y tu propia UI

El framework te da dos maneras distintas de traducir, y elegir la correcta es casi toda la decisión.

La vía ligera es translationPresentation, disponible desde iOS 17.4. La adjuntas a una vista, enlazas un indicador isPresented y le pasas el texto; cuando el indicador pasa a true, el sistema despliega su propio popover de traducción sobre tu contenido2:

.translationPresentation(isPresented: $showTranslation, text: selectedText)

No escribes nada de lógica de traducción y tampoco ves el resultado: la UI y la interacción son de Apple. Para un “deja que el usuario traduzca este pasaje”, esto es la función completa, y recurrir a algo más pesado es trabajo desperdiciado.

La superficie programática es TranslationSession, disponible desde iOS 18, y llegas a ella mediante el modificador translationTask. El modificador ejecuta un closure asíncrono y te entrega una sesión que invocas tú mismo, de modo que el texto traducido vuelve a tu código y lo presentas a tu manera2:

.translationTask(configuration) { session in
    let response = try await session.translate("Good morning")
    await MainActor.run { translated = response.targetText }
}

La división es limpia. translationPresentation sirve para mostrarle al usuario una traducción dentro de la UI de Apple. TranslationSession sirve para llevar texto traducido a tus datos y a tus vistas. La mayoría de las apps que hacen algo más que un “traduce esto” puntual terminan usando la sesión.

Traducción por lotes: traduce la lista, no el bucle

El detalle que separa una función fluida de una con tirones es el procesamiento por lotes. Si necesitas traducir una lista (mensajes de chat, entradas de catálogo, un conjunto de etiquetas), no recorras la lista esperando (await) cada traducción una por una. TranslationSession acepta un lote de solicitudes y devuelve las respuestas, cada una emparejada con su solicitud, en una sola pasada3:

.translationTask(configuration) { session in
    let requests = items.map { TranslationSession.Request(sourceText: $0.text, clientIdentifier: $0.id) }
    for try await response in session.translate(batch: requests) {
        store[response.clientIdentifier] = response.targetText
    }
}

Lo que importa es el clientIdentifier: vuelve en la respuesta, así que puedes emparejar cada traducción con la fila a la que pertenece sin depender del orden. Además, procesar por lotes le permite al framework planificar el trabajo de manera eficiente en lugar de pagar la sobrecarga de cada llamada a lo largo de un bucle. Para cualquier cosa que vaya más allá de una sola cadena, usa lotes.

La realidad sin conexión que nadie captura en pantalla

Aquí está la arista que convierte una demo impecable en un ticket de soporte. La traducción corre en el dispositivo, pero el idioma tiene que estar en el dispositivo primero. La primera vez que tu app traduce un par origen-destino determinado, el sistema descarga los paquetes de idioma, y esa descarga consume tiempo y requiere conexión de red5. Si lanzas una traducción y presentas el resultado sin contemplar la descarga, tu función parece congelarse en el primer uso con cada idioma nuevo.

Trátalo de forma deliberada. El framework te permite consultar la disponibilidad de idiomas y preparar (descargar) un par antes del momento en que lo necesitas, así puedes mostrar un estado de “preparando la traducción” o descargar por adelantado en un momento más tranquilo en vez de trabarte a mitad de la interacción5. El modelo mental: trata la primera traducción de un par de idiomas como una descarga de recursos por única vez, porque eso es exactamente lo que es. Diseña la UX contando con que la descarga existe, y el beneficio de “gratis y sin conexión” se nota; ignórala y ese beneficio queda escondido detrás de un bloqueo.

Dos datos más que cuestan una tarde si los aprendes tarde. Las superficies de UI de traducción son modificadores de SwiftUI, así que una pantalla de UIKit tiene que alojar una vista SwiftUI (mediante UIHostingController) para llegar a ellas, aunque también se puede construir una TranslationSession directamente para trabajo sin UI4. Y el framework no funciona en el simulador de iOS ni de iPadOS: la traducción se prueba en un dispositivo real4. Ninguna de las dos está documentada de forma prominente, y contra ambas es fácil chocarse de frente.

Combinar traducción con Foundation Models

La síntesis que vale la pena llevarse conecta este framework con el resto del stack en el dispositivo. Casi todo el trabajo lingüístico local asume que la entrada viene en un idioma que tu lógica y el modelo del sistema manejan bien. Los usuarios reales no colaboran. El framework Translation cierra esa brecha: traduce la entrada del usuario al idioma en el que razona tu función, ejecuta el trabajo de Foundation Models sobre el texto traducido y después traduce el resultado de vuelta.

La forma es un paréntesis: traducir hacia adentro, razonar, traducir hacia afuera.

// 1. translate the user's text into English (session configured for their language -> en)
let english = try await inboundSession.translate(userText).targetText
// 2. reason on-device, monolingually, in English
let summary = try await LanguageModelSession()
    .respond(to: "Summarize in one line: \(english)").content
// 3. translate the result back (a session configured for en -> their language)
let localized = try await outboundSession.translate(summary).targetText

Una función de clasificación de tickets de soporte, un resumidor de notas, un extractor de intenciones: cada uno se escribe una sola vez, en un solo idioma, y funciona en cualquier idioma que el dispositivo pueda instalar, con solo encerrar la llamada a Foundation Models entre dos traducciones. Las dos direcciones usan dos configuraciones de sesión (del idioma del usuario al inglés, y luego del inglés de vuelta), porque cada sesión se configura para un único par de idiomas. Ambas capas corren en el dispositivo, ambas son gratuitas y nada sale del teléfono, de modo que la versión multilingüe no cuesta más privacidad ni más factura en la nube que la monolingüe. Esa composición (traducir hacia adentro, razonar, traducir hacia afuera) es el patrón que vuelve genuinamente global a una función pequeña que corre en el dispositivo, y solo es posible porque ambas mitades se ejecutan localmente y gratis.

Cuándo no usarlo

La traducción en el dispositivo es gratuita y privada, lo que la convierte en la opción predeterminada correcta para traducir dentro de una app. Es la herramienta equivocada en unos pocos casos que conviene admitir.

  • Necesitas la mejor calidad de traducción posible o la mayor cobertura de idiomas. Los modelos locales son buenos, no los mejores disponibles, y el conjunto de idiomas instalables es finito. Para traducciones de alto riesgo (legales, médicas, contenido publicado), un servicio de traducción en la nube dedicado sigue ganando en calidad y amplitud.
  • No puedes tolerar la descarga del primer uso. Para una función que debe funcionar al instante en el primer arranque y sin red, el requisito de descarga puede descalificar por sí solo a la traducción local, salvo que la descargues por adelantado durante el proceso de bienvenida.
  • Tu app es de UIKit sin espacio para alojar SwiftUI, o tu flujo tiene que correr en el simulador (una prueba de UI automatizada, por ejemplo). Las restricciones de “solo SwiftUI” y “nada de simulador” son duras, no sugerencias.

El framework es una de las victorias más discretas del conjunto de herramientas en el dispositivo: un motor de traducción genuinamente gratuito y privado que la mayoría de las apps podría adoptar en una tarde. La habilidad requerida es la misma que premia el resto de este stack. Reconoce qué superficie encaja (el popover del sistema o tu propia sesión), agrupa en lotes cuando tengas una lista y diseña contemplando la descarga en lugar de fingir que no está. Haz eso y la traducción deja de ser una dependencia en la nube para convertirse en una capacidad local que compones con todo lo demás que el dispositivo hace gratis.

Preguntas frecuentes

¿El framework Translation de Apple es gratuito y funciona en el dispositivo?

Sí. La traducción corre en el dispositivo y es gratuita, sin que nada salga del teléfono, lo que la convierte en la opción predeterminada correcta para traducir dentro de una app. La contrapartida es que la calidad de traducción y la cobertura de idiomas son buenas, pero no las mejores de su categoría, así que el trabajo de alto riesgo puede seguir necesitando un servicio en la nube.

¿Por qué la primera traducción se cuelga o pide una descarga?

La traducción corre en el dispositivo, pero el par de idiomas tiene que estar en el dispositivo primero. La primera vez que traduces un par origen-destino determinado, el sistema descarga los paquetes de idioma, lo que requiere tiempo y conexión de red5. Consulta la disponibilidad y prepara (descarga por adelantado) el par antes del momento en que lo necesitas, así puedes mostrar un estado de “preparando” en lugar de trabarte a mitad de la interacción.

¿Cuáles son las dos formas de agregar traducción a una app?

El popover del sistema mediante un modificador de presentación de SwiftUI, o tu propia UI impulsada por una TranslationSession construida directamente para trabajo sin UI4. Como las superficies son modificadores de SwiftUI, una pantalla de UIKit llega a ellas alojando una vista SwiftUI mediante UIHostingController.

¿El framework Translation de Apple funciona en el simulador?

No. El framework no funciona en el simulador de iOS ni de iPadOS, así que la traducción se prueba en un dispositivo real4. Esta restricción es dura, no una sugerencia, y también descarta la traducción dentro de pruebas de UI automatizadas en el simulador.

¿Cómo hago que una función con Foundation Models funcione en cualquier idioma?

Enciérrala entre traducciones: traduce la entrada del usuario al idioma en el que razona tu lógica, ejecuta el trabajo de Foundation Models sobre el texto traducido y después traduce el resultado de vuelta. Las dos direcciones usan dos configuraciones de TranslationSession (del idioma del usuario al inglés, y luego del inglés de vuelta), porque cada sesión se configura para un único par de idiomas. Ambas capas corren en el dispositivo y son gratuitas, así que la versión multilingüe no cuesta ni privacidad ni factura en la nube.

¿Cuándo no debería usar traducción en el dispositivo?

Cuando necesitas la mejor calidad posible o la mayor cobertura de idiomas (contenido legal, médico o publicado), cuando una función debe funcionar al instante en el primer arranque sin red y no puedes descargar por adelantado, o cuando tu flujo tiene que correr en el simulador o es de UIKit sin espacio para alojar SwiftUI. Estas últimas restricciones son límites duros.



  1. Apple Developer, framework “Translation”. Un framework propio de Apple para traducción en el dispositivo provista por el sistema, construida sobre modelos de Core ML, que traduce localmente sin llamadas de red una vez instalados los recursos de idioma. 

  2. Apple Developer, “translationPresentation(isPresented:text:attachmentAnchor:arrowEdge:replacementAction:)” (iOS 17.4+) presenta la UI de traducción integrada del sistema sobre una vista; “translationTask(_:action:)” (iOS 18+) ejecuta un closure asíncrono que provee una TranslationSession para traducción programática dentro de tu propia interfaz. 

  3. Apple Developer, TranslationSession y TranslationSession.Request. translate(_:) procesa una sola cadena; la API por lotes recibe un arreglo de solicitudes, cada una con un clientIdentifier que vuelve en la respuesta correspondiente para que los resultados puedan reasociarse con sus entradas con independencia del orden. 

  4. Las APIs de traducción del framework Translation se exponen a través de modificadores de vista de SwiftUI (translationTask, translationPresentation) y no tienen punto de entrada en UIKit; una pantalla de UIKit aloja una vista SwiftUI (por ejemplo, mediante UIHostingController) para usarlas. El framework también exige un dispositivo físico y no funciona en el simulador de iOS. Consulta la documentación del framework Translation y “Translating text within your app”

  5. Apple Developer, “Translating text within your app” y LanguageAvailability. La primera traducción de un par de idiomas origen-destino descarga los recursos de idioma necesarios; el framework expone verificaciones de disponibilidad de idiomas y una forma de preparar (descargar) un par por adelantado para que las apps puedan gestionar el momento de la descarga en lugar de trabarse en el primer uso. 

  6. Análisis relacionado del autor sobre cómo componer capacidades en el dispositivo: Apple Foundation Models: el framework de LLM en el dispositivo, LLMs en el dispositivo con Foundation Models de Apple y Adopción de la API de Writing Tools. El patrón de traducir hacia adentro, razonar y traducir hacia afuera encierra una llamada monolingüe a Foundation Models entre dos traducciones para volver multilingüe una función local sin que nada salga del dispositivo. 

Artículos relacionados

Image Playground API: hoja de SwiftUI, creador de imágenes programático y control de estilo

Image Playground ofrece dos caminos a las apps: el modificador imagePlaygroundSheet de SwiftUI y la API programática Ima…

11 min de lectura

Genmoji y NSAdaptiveImageGlyph: Emoji en línea en iOS 18+

Genmoji llega como NSAdaptiveImageGlyph en texto con atributos. En UITextView con TextKit 2: habilita supportsAdaptiveIm…

10 min de lectura

Claude Code Auto Mode Is Not a Security Boundary

Anthropic closed a working auto-mode bypass as Informative: the classifier is best-effort, not a guarantee. What actuall…

10 min de lectura