# General Translation Knowledge Base: ¿Cómo localizo una app de iOS con String Catalogs?
URL: https://generaltranslation.com/es/kb/localize-ios-app.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Agrega tus idiomas en Xcode, escribe el texto visible para el usuario con API localizables como Text de SwiftUI y String(localized:), y compila para que Xcode recopile esas cadenas en un String Catalog (.xcstrings). Traduce en Xcode, mediante XLIFF o con la CLI de General Translation si quieres que los catálogos se actualicen con cada lanzamiento y compartan terminología con tu sitio web y tu app de Android.
Category: Internacionalización
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

Un String Catalog reúne una misma tabla de cadenas en todos los idiomas dentro de un único archivo JSON, y Xcode lo sincroniza con tu código en cada compilación. Así, solo te quedan dos tareas: incorporar al catálogo todas las cadenas visibles para el usuario y volver a incluir en él traducciones de calidad.

## Configurar la localización en Xcode

### Añade tus idiomas

En el editor del proyecto, selecciona el proyecto, abre **Info** y haz clic en el botón de añadir que hay debajo de **Localizations** (también encontrarás uno en la barra lateral del editor de String Catalog). Cada entrada tiene un ID de idioma, como `de`, `ja` o `en-IN` ([Apple: Adding support for languages and regions](https://developer.apple.com/documentation/xcode/adding-support-for-languages-and-regions)). Elige una variante regional solo cuando el texto cambie, como ocurre con `pt-BR` y `pt-PT`. (Consulta [códigos de configuración regional](/docs/platform/core/guides/locale-codes)).

### Añade un String Catalog y compila

Elige **File &gt; New &gt; File from Template**, filtra por &quot;string&quot; y selecciona **String Catalog**. El nombre predeterminado es `Localizable.xcstrings`. Después, elige **Product &gt; Build**: Xcode detecta las cadenas localizables de tu código, las añade al catálogo y lo actualiza en cada compilación posterior ([Apple: Localizing and varying text with a string catalog](https://developer.apple.com/documentation/xcode/localizing-and-varying-text-with-a-string-catalog)).

Los String Catalogs llegaron con Xcode 15 ([notas de la versión](https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes)). En tiempo de compilación se compilan a archivos `.strings` y `.stringsdict`, por lo que adoptarlos no te obliga a subir tu versión mínima de despliegue ([WWDC23: Discover String Catalogs](https://developer.apple.com/videos/play/wwdc2023/10155/)).

### Escribe texto con API localizables

Xcode solo extrae las cadenas que se pasan a API localizables. En SwiftUI, los literales de cadena de las vistas son valores [`LocalizedStringKey`](https://developer.apple.com/documentation/swiftui/localizedstringkey) y se extraen automáticamente. En el resto del código, usa `String(localized:)` ([Apple: Preparing your app&#39;s text for translation](https://developer.apple.com/documentation/xcode/preparing-your-apps-text-for-translation)):

```swift
import SwiftUI

struct CartView: View {
    let itemCount: Int
    let couponCode: String

    var body: some View {
        VStack {
            // Los literales de cadena en las vistas de SwiftUI son valores LocalizedStringKey,
            // así que Xcode los añade al String Catalog al compilar.
            Text("Your cart")

            // La interpolación se convierte en un especificador de formato (%lld) que puedes variar en función del plural.
            Text("\(itemCount) items")

            // Un comentario indica a los traductores dónde y cómo se usa el texto.
            Text("Checkout", comment: "Button that starts payment for the items in the cart.")

            // Una variable String se muestra tal cual. Text(verbatim:) lo deja explícito.
            Text(verbatim: couponCode)
        }
    }
}

// Fuera de las vistas de SwiftUI, crea texto localizable con String(localized:).
let emptyCartMessage = String(
    localized: "Your cart is empty",
    comment: "Shown when the cart has no items."
)
```

El error más habitual es `Text(someString)`: una variable `String` no se busca en el catálogo. Para pasar texto localizable entre vistas, usa `LocalizedStringResource`, que es lo que recomienda Apple y que además incluye un comentario y un nombre de tabla.

Los comentarios son importantes porque &quot;Checkout&quot;, sin más contexto, podría ser un sustantivo o un verbo. Agrégalos con el parámetro `comment:`, o haz Control-clic en una clave del catálogo y elige **Generate Comment** para que Xcode genere uno a partir del código que la rodea.

Para encontrar texto que nunca llegó al catálogo, abre **Product &gt; Scheme &gt; Edit Scheme &gt; Run &gt; Options** y activa **Show non-localized strings**; así, esas cadenas se renderizan en mayúsculas al ejecutar la app ([Apple: Preparing your interface for localization](https://developer.apple.com/documentation/xcode/preparing-your-interface-for-localization)). (Consulta [¿Cómo encuentro cadenas hardcodeadas que no están traducidas?](/kb/find-hardcoded-strings)).

## Gestionar plurales, dispositivos e Info.plist

Haz Control-clic en una clave con un número interpolado y elige **Vary by Plural**. Xcode añade las categorías de plural que necesita cada idioma: `one` y `other` para el inglés, y `one`, `few`, `many` y `other` cuando añades el ruso. **Vary by Device** asigna a una clave un valor distinto según el dispositivo, como &quot;Tap to learn more&quot; en iPhone y &quot;Click to learn more&quot; en Mac.

Por debajo del editor, el catálogo es JSON, así que las diferencias se ven con claridad en los pull requests. Este es un pequeño extracto con un plural en inglés y una traducción al español:

```json title="Localizable.xcstrings"
{
  "sourceLanguage" : "en",
  "strings" : {
    "%lld items" : {
      "comment" : "Number of items in the shopping cart.",
      "localizations" : {
        "en" : {
          "variations" : {
            "plural" : {
              "one" : {
                "stringUnit" : {
                  "state" : "translated",
                  "value" : "%lld item"
                }
              },
              "other" : {
                "stringUnit" : {
                  "state" : "translated",
                  "value" : "%lld items"
                }
              }
            }
          }
        }
      }
    },
    "Checkout" : {
      "comment" : "Button that starts payment for the items in the cart.",
      "localizations" : {
        "es" : {
          "stringUnit" : {
            "state" : "translated",
            "value" : "Pagar"
          }
        }
      }
    }
  },
  "version" : "1.0"
}
```

El texto del sistema en `Info.plist`, como el nombre para mostrar de la app y las descripciones de uso de las solicitudes de permisos, se guarda en un catálogo aparte. Agrega un archivo `InfoPlist.xcstrings` al destino y Xcode lo completará con las claves localizables conocidas de `Info.plist` en cada compilación.

## Seguimiento de los estados de las cadenas

Cada traducción del catálogo tiene un estado, que se muestra en la columna **State** del editor:

* **New:** aún no se ha traducido a ese idioma.
* **Needs Review:** el texto de origen cambió después de la traducción o alguien la marcó para revisión; elige **Mark as Reviewed** para conservar el valor actual.
* **Translated:** una marca de verificación verde; no hay nada más que hacer.
* **Stale:** Xcode ya no encuentra la cadena en el código. Las cadenas sin traducir que desaparecen del código se eliminan; las traducidas se conservan y se marcan como obsoletas hasta que las borres.

Las cadenas que añades manualmente, como las claves generadas en tiempo de ejecución, pueden configurarse con gestión manual para que las compilaciones nunca las actualicen ni las eliminen.

## Migrar desde .strings y .stringsdict

Para convertir un proyecto existente, elige **Edit &gt; Convert &gt; To String Catalog** (o haz Control-clic en un archivo y elige **Migrate to String Catalog**). La migración se realiza por archivo y por destino, y los catálogos pueden convivir con los archivos heredados mientras migras. Si en un mismo destino hay un catálogo y un archivo `.strings` o `.stringsdict` con el mismo nombre, se produce un error de compilación, así que termina cada tabla antes de pasar a la siguiente. Al migrar `InfoPlist.strings`, se conservan sus comentarios, si los tiene.

## Elige cómo traducir

Estas son las formas de incorporar traducciones al catálogo:

| Enfoque                                                                                 | Quién traduce                     | Contexto que recibe el traductor                                                                         | Repetible en cada lanzamiento                                                            | Lo que queda a tu cargo                                                                                                                          |
| --------------------------------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| Escribir en el editor del catálogo                                                      | Tú o un compañero bilingüe        | Toda la app                                                                                              | No                                                                                       | Cada cadena en cada idioma, a mano                                                                                                               |
| Agente de programación de Xcode (Xcode 27)                                              | El agente que habilites en Xcode  | Dónde se usa cada cadena, cadenas similares, necesidades de plural, guías de estilo lingüístico de Apple | Se ejecuta bajo demanda en Xcode                                                         | Configuración inicial del agente, revisar las cadenas traducidas automáticamente, mantener los términos sincronizados con tus apps web y Android |
| Exportar `.xcloc` y XLIFF a traductores o a un sistema de gestión de traducciones (TMS) | Traductores profesionales         | Comentarios, además de las capturas de pantalla que añadas a la carpeta `Notes`                          | Automatizable con `xcodebuild`                                                           | Un ciclo de ida y vuelta por lanzamiento, y la espera que implica                                                                                |
| CLI de General Translation                                                              | El servicio de traducción de GT   | Comentarios del catálogo, más el glosario y los Custom Prompts compartidos                               | Ejecuta [`gt translate`](/docs/cli/reference/commands/translate) antes de la compilación | Revisar en el panel de control o en Xcode y luego probar la app                                                                                         |
| Script de traducción automática o un LLM sobre el JSON                                  | Un modelo o una API de traducción | Lo que envíe tu script                                                                                   | Sí                                                                                       | Variaciones, sustituciones, categorías de plural por idioma, especificadores de formato, estados y revisión                                      |

**Exportación.** **Product &gt; Export Localizations** crea un Xcode Localization Catalog (una carpeta `.xcloc`) por idioma, con un archivo XLIFF dentro ([Apple: Exporting localizations](https://developer.apple.com/documentation/xcode/exporting-localizations)). Activa el ajuste de compilación **Use Compiler to Extract Swift Strings** para que la exportación incluya todas las cadenas de Swift. Vuelve a importar las traducciones con **Product &gt; Import Localizations**, o automatiza ambos sentidos con `xcodebuild -exportLocalizations` y `xcodebuild -importLocalizations` ([Apple: Importing localizations](https://developer.apple.com/documentation/xcode/importing-localizations)).

**Novedades de Xcode 27.** Los agentes de Xcode ahora pueden traducir String Catalogs: Xcode añade los idiomas, crea los String Catalogs que falten y proporciona al agente contexto para cada cadena ([Xcode 27 release notes](https://developer.apple.com/documentation/xcode-release-notes/xcode-27-release-notes), [WWDC26: Translate your app using agents in Xcode](https://developer.apple.com/videos/play/wwdc2026/213/)). El editor del catálogo incorpora un botón **Generate Translations**, la salida del agente recibe el estado **Machine Translated** y el XLIFF exportado la marca con `state-qualifier="leveraged-mt"`. Un comentario de localización con «do not translate» ahora marca una cadena como **Don&#39;t Translate** en el catálogo y con `translate="no"` en el XLIFF. Puedes hacer que `AGENTS.md` o `CLAUDE.md` remitan a un archivo `TRANSLATION.md` con un glosario y una lista de cadenas que el agente no debe traducir ([Apple: Localizing your app using agents](https://developer.apple.com/documentation/xcode/localizing-your-app-using-agents)).

Usa el editor del catálogo para uno o dos idiomas que domines. Usa el agente de Xcode si quieres traducción automática dentro de Xcode. Elige General Translation cuando te importe contar con un comando repetible en el repositorio y una terminología compartida entre productos; seguirás usando Xcode y las API de localización nativas de Apple. Opta por una exportación XLIFF cuando el trabajo esté a cargo de traductores profesionales o de un [TMS](/kb/what-is-a-translation-management-system) que ya utilices.

## Prueba todos los idiomas

Elige **Product &gt; Scheme &gt; Edit Scheme**, selecciona **Run**, luego **Options**, y configura **App Language** y **App Region** para la próxima ejecución ([Apple: Testing localizations](https://developer.apple.com/documentation/xcode/testing-localizations-when-running-your-app)). En ese mismo menú **App Language** aparecen pseudoidiomas: **Double-Length** para la expansión del texto, **Right-to-Left** para diseños reflejados, **Accented** y **Tall** para glifos más altos, y **Bounded String** para el truncamiento. (Consulta [¿Qué es la pseudolocalización?](/kb/pseudo-localization)). Para las vistas previas de SwiftUI, usa `.environment(\.locale, .init(identifier: "de"))`.

Los metadatos de la App Store (nombre, descripción, capturas de pantalla) se localizan por separado en [App Store Connect](https://developer.apple.com/help/app-store-connect/manage-app-information/localize-app-information).

## Traduce String Catalogs con General Translation

Si quieres que la traducción se ejecute como un comando repetible y que la terminología sea coherente en tu app de iOS, tu sitio web y tu app de Android, la CLI de General Translation, `gt`, traduce los archivos `.xcstrings` en el mismo documento (`gt` 2.21.0 o posterior). Agrega una entrada `xcstrings` a `gt.config.json` que apunte directamente a cada catálogo:

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "ja"],
  "files": {
    "xcstrings": {
      "include": ["Resources/Localizable.xcstrings", "Resources/InfoPlist.xcstrings"]
    }
  }
}
```

Todas las configuraciones regionales se encuentran en el mismo archivo, por lo que las rutas de `include` no llevan el marcador de posición `[locale]`, y el `sourceLanguage` del catálogo debe coincidir con `defaultLocale`; de lo contrario, la ejecución se detiene antes de subir nada. Inicia sesión con [`npx gt login`](/docs/cli/reference/commands/login), define `GT_PROJECT_ID` ([credenciales de la CLI](/docs/cli/guides/configuring#credentials)) y, si se trata de una app existente, importa el origen y las traducciones revisadas con [`npx gt upload`](/docs/cli/reference/commands/upload). Después, ejecuta [`npx gt translate`](/docs/cli/reference/commands/translate) para generar las actualizaciones. En CI, guarda como `GT_API_KEY` una clave de API del proyecto con los permisos **Files &gt; Write** y **Translation queue &gt; Enabled**.

La CLI sube solo la parte correspondiente al idioma de origen y vuelve a fusionar cada configuración regional de destino en el archivo, sin alterar el resto de configuraciones regionales ni la estructura del catálogo. Al procesar String Catalogs, usa las categorías de plural del idioma de destino para traducir las variaciones y conserva los especificadores de formato y las sustituciones. (Consulta la [referencia de `.xcstrings`](/docs/cli/reference/formats/xcstrings-files)). Si usas el formato heredado, las claves `dotStrings` y `dotStringsdict` traducen en su lugar archivos `.strings` y [`.stringsdict`](/docs/cli/reference/formats/dot-stringsdict-files).

Revisa el catálogo en Xcode o usa el [editor de archivos sin procesar](/docs/platform/dashboard/guides/reviewing-translations) del panel de control. Si editas traducciones en Xcode, ejecuta [`npx gt save-local`](/docs/cli/reference/commands/save-local) para que las ejecuciones posteriores las conserven. Asigna un mismo [grupo de contexto](/docs/platform/dashboard/guides/defining-context-for-translations) a tus proyectos de iOS, web y [Android](/docs/cli/reference/formats/android-strings-files), y los términos del glosario, como los nombres de tus planes, se mantendrán iguales en todas las superficies.

Ramp usa GT para más de 11 configuraciones regionales en su panel de control, su página de inicio y su app de iOS: un ejemplo de cómo una misma plataforma de traducción puede dar servicio tanto a productos web como nativos. (Consulta los [despliegues en producción](https://generaltranslation.com/enterprise)).

## Puntos clave

* Compila una vez después de añadir `Localizable.xcstrings`: Xcode extrae los literales de SwiftUI y el texto de `String(localized:)`, pero no los `Text` creados a partir de una variable `String`.
* Usa **Vary by Plural** para las cantidades; Xcode añade las categorías de cada idioma, como las cuatro del ruso.
* Las cadenas traducidas que se eliminan del código no desaparecen, sino que pasan al estado **Stale**, así que conviene limpiarlas de forma deliberada.
* Xcode 27 incorpora la traducción mediante agentes, un estado **Machine Translated** y `leveraged-mt` en el XLIFF exportado.
* La CLI de General Translation traduce el catálogo en el mismo documento con `"xcstrings": { "include": [...] }` y [`npx gt translate`](/docs/cli/reference/commands/translate), y genera las variaciones en los idiomas de destino sin alterar las demás configuraciones regionales ni la estructura del catálogo.

## Related questions

- [¿Qué es la pseudolocalización?](https://generaltranslation.com/es/kb/pseudo-localization.mdx): La pseudolocalización es una prueba que sustituye tu texto de origen por una versión alterada (con acentos, alrededor de un 40 % más larga y entre corchetes) para que las cadenas codificadas de forma fija, el truncamiento, las fuentes rotas y las oraciones concatenadas salgan a la luz antes de que exista ninguna traducción. Android incluye para ello las pseudoconfiguraciones regionales en-XA y ar-XB.
- [¿Cómo encuentro cadenas codificadas de forma fija que no están traducidas?](https://generaltranslation.com/es/kb/find-hardcoded-strings.mdx): Ejecuta en CI un linter que marque los literales de cadena visibles para el usuario, como la regla no-literal-string de eslint-plugin-i18next para JSX, la comprobación HardcodedText de Android Lint o el linter HardCodedString de erb_lint para Rails. Después, recorre la app con una pseudoconfiguración regional para detectar el texto que las comprobaciones estáticas no pueden rastrear.
- [¿Cómo doy soporte a idiomas RTL (right-to-left) en CSS?](https://generaltranslation.com/es/kb/right-to-left-css.mdx): Coloca dir="rtl" y lang en el elemento html, ya que lang por sí solo no cambia la dirección, y luego sustituye el CSS físico, como margin-left, por propiedades lógicas, como margin-inline-start. Las filas flex, las columnas de grid y la alineación de texto predeterminada se invierten solas; translateX(), left y right, no.
- [General Translation frente a un TMS (Crowdin, Lokalise, Phrase)](https://generaltranslation.com/es/kb/general-translation-vs-tms.mdx): Elige General Translation cuando los desarrolladores quieran que la generación de traducciones, el contexto derivado del código y la revisión estén vinculados a los lanzamientos del producto. Conserva tus catálogos y tu biblioteca de renderizado actuales, o escribe JSX inline sin claves de traducción. Un TMS encaja con programas centrados en proveedores lingüísticos, editores CAT e intercambio de XLIFF; sus integraciones pueden automatizar las transferencias de archivos.

## Previous and next questions

- Previous question: [¿Cómo hago que un sitio web sea multilingüe?](https://generaltranslation.com/es/kb/make-website-multilingual.mdx)
- Next question: [¿Cómo traduzco archivos JSON de i18n?](https://generaltranslation.com/es/kb/translate-json-files.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/es/kb/sitemap.md) for every article.
