Migrar Localizable.strings a un String Catalog (.xcstrings)

Actualizado el · LocalePilot

Desde Xcode 15, Apple empuja a todo el mundo hacia los String Catalogs: un único archivo JSON para todos los idiomas, con plurales y variaciones por dispositivo. La migración se hace en dos clics; lo que hay que revisar es el diff que viene después.

¿Tienes prisa? Convierte archivos .strings sueltos en un catálogo directamente en el navegador: gratis, sin registro, no se sube nada.

Antes de migrar

Dos precauciones que evitan la mayoría de las sorpresas:

  • Un árbol de Git limpio, en una rama dedicada. Todo lo que hay que revisar después está en el diff, así que lo quieres aislado.
  • Un build que pase antes de la migración. Xcode rellena el catálogo analizando tu código durante el build. Si el proyecto no compila, el catálogo queda incompleto y no sabrás por qué.

La migración en sí

En el navegador del proyecto, haz clic derecho en Localizable.strings y luego en Migrate to String Catalog. Xcode lista los archivos y targets afectados; el texto exacto puede cambiar entre versiones de Xcode, la idea no.

Los archivos fr.lproj/Localizable.strings, de.lproj/Localizable.strings… se sustituyen por un único Localizable.xcstrings que contiene todos los idiomas. Los comentarios de los archivos .strings pasan a ser el comentario de cada clave.

Cómo es el archivo

Un String Catalog es JSON. Una clave simple:

{
  "sourceLanguage" : "en",
  "strings" : {
    "welcome_user" : {
      "comment" : "Home screen greeting",
      "localizations" : {
        "fr" : {
          "stringUnit" : {
            "state" : "translated",
            "value" : "Bon retour, %@ !"
          }
        }
      }
    }
  },
  "version" : "1.0"
}

Y un plural, guardado en variations:

"items_left" : {
  "localizations" : {
    "fr" : {
      "variations" : {
        "plural" : {
          "one" : { "stringUnit" : { "state" : "translated", "value" : "%lld article restant" } },
          "other" : { "stringUnit" : { "state" : "translated", "value" : "%lld articles restants" } }
        }
      }
    }
  }
}

Fíjate en el formato: un espacio antes de cada dos puntos, como lo escribe Xcode. Una herramienta que reescriba el archivo como JSON «estándar» producirá un diff enorme sin cambiar ni una sola traducción.

Qué revisar en el diff

Claves marcadas como Stale. Después de un build, Xcode marca las claves que ya no encuentra en tu código. No están necesariamente muertas: una clave construida en tiempo de ejecución (NSLocalizedString(variable, comment: ""), una clave leída de un archivo de configuración) es invisible para el análisis. Compruébalo antes de borrar.

Claves nuevas extraídas del código. El build puede añadir cadenas que nunca pusiste en Localizable.strings, normalmente literales Text("…") de SwiftUI, que son localizables por defecto. Llegan sin traducir, así que es normal que baje el porcentaje que Xcode muestra para cada idioma.

Estados. Cada valor tiene un estado: translated, needs_review o new para una cadena que nadie ha traducido todavía. Dentro de tres meses, así sabrás qué se revisó de verdad.

Especificadores de formato. Una cadena de SwiftUI como Text("\(count) items left") produce la clave %lld items left. Si tu antiguo .strings usaba %d para la misma frase, ahora tienes dos claves casi duplicadas; quédate con la que tu código usa realmente.

¿Y las versiones anteriores de iOS?

No necesitas iOS 17. El catálogo es un formato fuente: durante el build, Xcode lo compila en archivos .strings normales dentro del bundle de la app. Tu deployment target no cambia.

Editar el catálogo fuera de Xcode

El editor de Xcode sirve para unas pocas cadenas. Para revisar un idioma completo, traducir en bloque o verificar placeholders, una herramienta dedicada ayuda. LocalePilot abre los archivos .xcstrings y los vuelve a escribir con el estilo de Xcode: un catálogo sin cambios sale idéntico byte a byte, una edición solo cambia sus propias líneas y un valor editado pasa al estado translated. Los plurales y las variaciones por dispositivo se pueden editar; las claves con sustituciones (%#@count@) y las marcadas con shouldTranslate: false se conservan tal cual, para que las edites en Xcode.

Preguntas frecuentes

¿Los String Catalogs requieren iOS 17?

No. Xcode compila el catálogo en archivos de localización normales durante el build; el deployment target de tu app no cambia.

¿Qué significa Stale en un String Catalog?

Xcode no encontró la clave en tu código en el último build. Asegúrate de que no se construye en tiempo de ejecución antes de borrarla.

¿Cómo deshago la migración?

Migra en una rama dedicada con un commit justo antes: revertir en Git recupera los archivos .strings.