Para una etiqueta reutilizable de macOS, acepta los mensajes localizables como LocalizedStringResource, mantén una ruta verbatim: separada para el texto literal y conserva la interpolación hasta la localización. Este tutorial crea ese contrato para un contador de elementos de escritorio y comprueba la extracción por separado de la visualización.

¿Qué debería garantizar la API de texto reutilizable?

Supongamos que una app para Mac necesita un resumen compacto que muestre un recuento de elementos y una etiqueta de colección sintética, como Sample Set. El componente reutilizable debe distinguir tres entradas: un mensaje escrito por la app que necesita traducción, una clave de localización existente de SwiftUI y un texto que debe aparecer exactamente como se proporciona.

Apple recomienda LocalizedStringResource para representar y pasar cadenas localizables por vistas personalizadas y otro código Swift. Sus directrices actuales muestran propiedades de vistas personalizadas de ese tipo que se muestran mediante Text. Úsalo como contrato principal para los mensajes al diseñar un componente nuevo. Preparar el texto de tu app para la traducción.

La siguiente tabla de decisiones presenta un diseño de API derivado de esos comportamientos documentados. Las etiquetas explícitas de los argumentos permiten revisar la intención de quien llama sin depender de dos sobrecargas de cadena sin etiqueta que compitan entre sí.

Intención de quien llama Punto de entrada propuesto Ruta de representación
Pasar un mensaje traducible con contexto opcional SummaryLabel(localized:) Text(resource)
Pasar una clave de SwiftUI, incluida la interpolación de SwiftUI SummaryLabel(key:) Text(key, tableName:bundle:)
Mostrar una etiqueta exacta SummaryLabel(verbatim:) Text(verbatim:)
Proporcionar texto ya compuesto por quien llama SummaryLabel(text:) Almacenar el Text proporcionado

Mantén LocalizedStringKey disponible cuando el componente necesite específicamente el comportamiento basado en claves de SwiftUI. Apple documenta que un literal de cadena pasado directamente a Text crea una clave de localización, mientras que una variable String normalmente sigue una ruta que omite la localización. Por lo tanto, un contenedor que acepte solo String cambia el significado de llamadas que, de otro modo, parecerían similares. LocalizedStringKey.

Crear un componente completo con puntos de entrada explícitos

Usa un proyecto de app SwiftUI para macOS en Xcode 26 o posterior y, para este ejemplo, configura como macOS 26 la versión mínima de implementación. Sustituye las declaraciones generadas de la app y de la vista de contenido por el programa completo que aparece a continuación; deja una sola declaración @main en el destino. Todas las etiquetas y los recuentos son sintéticos. Se revisó el código conforme a las API documentadas, pero no se compiló aquí porque este entorno no tiene un compilador de Swift.

import Foundation
import SwiftUI

struct SummaryLabel: View {
    private let text: Text

    init(localized resource: LocalizedStringResource) {
        text = Text(resource)
    }

    init(
        key: LocalizedStringKey,
        tableName: String? = nil,
        bundle: Bundle? = nil,
        comment: StaticString? = nil
    ) {
        text = Text(
            key,
            tableName: tableName,
            bundle: bundle,
            comment: comment
        )
    }

    init(verbatim value: String) {
        text = Text(verbatim: value)
    }

    init(text: Text) {
        self.text = text
    }

    var body: some View {
        text
            .font(.callout)
            .padding(8)
    }
}

struct ContentView: View {
    @State private var itemCount = 2
    private let collectionLabel = "Sample Set"

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Stepper(value: $itemCount, in: 0...12) {
                Text("Item count")
            }

            SummaryLabel(
                localized: LocalizedStringResource(
                    "summary.item-count",
                    defaultValue: "\(itemCount) items",
                    comment: "Summary below the item-count control. The integer is the number of items."
                )
            )

            SummaryLabel(
                key: "Collection: \(collectionLabel)"
            )

            SummaryLabel(verbatim: collectionLabel)

            SummaryLabel(
                text: Text(
                    "Preview",
                    comment: "Heading for a preview of the current item selection."
                ).bold()
            )
        }
        .padding(20)
        .frame(minWidth: 320)
    }
}

@main
struct TextContractDemoApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

El inicializador del recurso separa deliberadamente la clave estable summary.item-count de su mensaje predeterminado, \(itemCount) items. Apple documenta para este inicializador una clave estática, un valor predeterminado localizable, una tabla, una configuración regional, un paquete y un comentario para quien traduce. El valor predeterminado se usa cuando la clave no está en la tabla especificada. Inicializador de LocalizedStringResource.

El inicializador verbatim: establece una garantía igual de clara: mostrar la cadena proporcionada sin localizarla. Funciona tanto con un argumento literal como con una variable. Usa esta ruta para la etiqueta sintética de la colección cuando lo que debe mostrarse es su escritura exacta. Text.init(verbatim:).

El punto de entrada text: permite que quien llama construya texto localizado o con estilo antes de pasarlo al componente. Este componente añade tipografía y espaciado compartidos; quien llama sigue eligiendo la semántica del mensaje. Pasar Text sirve como vía de escape, así que un componente que deba imponer un contrato más acotado puede omitir ese inicializador.

¿En qué se diferencian la extracción y el formato en tiempo de ejecución?

Trata la localización como dos comprobaciones separadas. Durante una compilación, Xcode detecta las expresiones localizables del código fuente y actualiza el catálogo de cadenas. Durante la ejecución, la app resuelve el mensaje y sustituye sus argumentos. La sesión de Apple sobre el catálogo de cadenas describe explícitamente cómo reconocer los literales usados para crear LocalizedStringResource en el punto de llamada de una vista personalizada. También señala el ajuste de compilación Use Compiler to Extract Swift Strings. Detectar catálogos de cadenas.

La interpolación debe llegar a un tipo que admita localización antes de convertirse en una cadena ordinaria ya completada. Apple explica que el generador de interpolación de SwiftUI mantiene separadas la clave de formato y los valores de los argumentos, lo que permite localizar antes de sustituirlos. Convertir una String ya interpolada en una clave no puede reconstruir esos argumentos tipados originales. Novedades de Swift.

Este fragmento de diagnóstico muestra la diferencia; no es una segunda app. Todos los valores usados en el fragmento se definen localmente.

import SwiftUI

let count = 2

// Ordinary String interpolation has already produced "2 items".
let completed: String = "\(count) items"
let exactDisplay = Text(completed)

// Looks up the completed value as a key.
// This does not restore a count placeholder.
let completedValueLookup = Text(LocalizedStringKey(completed))

// Preserves localization-aware interpolation from the beginning.
let messageKey: LocalizedStringKey = "\(count) items"
let interpolatedDisplay = Text(messageKey)

Crear LocalizedStringKey a partir de una variable es una forma documentada de solicitar una búsqueda en tiempo de ejecución. Es útil cuando la variable contiene intencionalmente una clave conocida. Esto no garantiza que Xcode haya extraído en un catálogo todos los valores posibles de esa variable. Mantén explícitamente las claves dinámicas previstas o usa declaraciones literales de recursos para los mensajes finitos que controla tu app. El comportamiento de búsqueda y el valor alternativo se documentan en Text.init(_:tableName:bundle:comment:).

Conserva el mensaje completo, incluida su puntuación y la posición de los marcadores de posición, en una sola expresión localizable. En este ejemplo, mantén unido Collection: \(collectionLabel). Si se construye un mensaje completado con fragmentos localizados por separado, quien llama tendrá que encargarse de su orden y espaciado.

Añadir el catálogo y configurar el comportamiento de pluralización

Primero, añade un catálogo de cadenas mediante File > New > File from Template, selecciona String Catalog y llámalo Localizable. Luego elige Product > Build. Apple documenta que la compilación rellena el catálogo a partir de las API localizables y lo actualiza cuando cambian los mensajes del código fuente. Localizar y variar el texto con un catálogo de cadenas.

Para el ejemplo, inspecciona la entrada summary.item-count y su entero interpolado. Haz clic con Control en la entrada y elige Vary by Plural. En la localización de origen en inglés, establece One en %lld item y Other en %lld items, conservando el marcador de posición del entero que proporciona Xcode. Añade las formas requeridas al incorporar otras localizaciones; las categorías de plural dependen del idioma. Localizar y variar el texto con un catálogo de cadenas.

La interpolación proporciona el recuento, pero por sí sola no crea la forma singular del texto. El tutorial guiado de Apple muestra cómo añadir variantes plurales en el catálogo y cómo el sistema selecciona la variante correspondiente en tiempo de ejecución. Por eso, una compilación correcta y un mensaje extraído solo son parte de la verificación. Tutorial guiado: Explorar la localización con Xcode.

Usa esta pequeña matriz de aceptación después de configurar las formas plurales de origen. Estos son los resultados esperados del programa ilustrativo, no resultados de una ejecución comprobada.

Comprobación Resultado esperado
Compilar e inspeccionar summary.item-count Una entrada de mensaje con una sustitución de entero
Establecer el recuento en 0 0 items
Establecer el recuento en 1 1 item
Establecer el recuento en 2 2 items
Inspeccionar la fila de etiqueta exacta Sample Set permanece literal
Inspeccionar el mensaje de la colección La etiqueta es un argumento dentro del mensaje completo

Diagnosticar por separado las entradas que faltan y los errores de visualización

Si falta un mensaje en el catálogo, inspecciona primero el tipo de su origen. Un parámetro String puede haber borrado la expresión localizable antes de que llegara al componente. Comprueba el destino del catálogo, compila el esquema que incluye ese punto de llamada y verifica Use Compiler to Extract Swift Strings. Apple describe la extracción como una operación que se realiza para el esquema y la plataforma actuales, así que inspecciona la configuración que compila realmente el mensaje. Detectar catálogos de cadenas.

Si hay una entrada, pero la app muestra una clave o un texto alternativo, inspecciona la configuración de búsqueda. El inicializador de Text basado en claves busca en la tabla y el paquete especificados; si se omiten los valores, se seleccionan la tabla predeterminada y el paquete principal. Si falta una clave o una tabla, se muestra la representación de cadena de la clave. Por eso, un valor alternativo legible puede ocultar una búsqueda incompleta. Text.init(_:tableName:bundle:comment:).

Al trasladar el componente a un framework o paquete, decide dónde deben estar los mensajes. Los mensajes propios del componente necesitan el paquete de recursos del componente; los recursos propios de quien llama deben conservar la información de búsqueda que se les proporcionó. Las directrices actuales de Apple permiten pasar #bundle a las API de localización para identificar el paquete del destino que contiene el código. Las tablas con nombre también necesitan catálogos con el nombre correspondiente. Preparar el texto de tu app para la traducción.

Por último, no des por sentado que todas las interpolaciones que acepta SwiftUI también pueden usarse en un recurso de Foundation. LocalizedStringKey tiene sus propios métodos de interpolación, incluidas variantes con formato y con formateador. Elige el tipo de mensaje antes de componer la expresión y consulta las operaciones de interpolación compatibles cuando un argumento no compile. LocalizedStringKey.StringInterpolation.

Un componente de texto reutilizable está listo cuando quien llama puede expresar claramente su intención y verificarla en ambas etapas: la compilación genera el mensaje previsto en el catálogo y la app para Mac en ejecución muestra la sustitución, la forma plural o la etiqueta exacta correctas. Mantén esas comprobaciones junto al contrato de la API cada vez que cambie el componente.

Fuentes