Per un’app Mac con pannelli gestiti dai framework, definisci il fallback a due livelli: quale lingua seleziona ciascun bundle e quale valore restituisce ogni messaggio quando la ricerca non riesce. Usa una localizzazione di sviluppo in inglese e valori predefiniti espliciti in inglese per i messaggi che gestisci.
Questa guida implementa tale contratto per una semplice finestra desktop contenente l’etichetta dell’app Workspace e quella del framework Panel ready. Le etichette sono fittizie. L’obiettivo è mantenere leggibili questi messaggi quando manca una lingua o una traduzione, preservando al contempo il normale comportamento di localizzazione quando le traduzioni sono disponibili.
Quali garanzie dovrebbe offrire il contratto di fallback?
Adotta questo contratto per i messaggi gestiti dall’app e dai framework: usa una localizzazione disponibile selezionata tramite la corrispondenza linguistica del sistema; usa l’inglese come localizzazione di sviluppo quando non corrisponde alcuna lingua preferita; e restituisci il valore predefinito esplicito in inglese di un messaggio se la ricerca della stringa non riesce. Ogni messaggio deve identificare il bundle proprietario e la tabella delle stringhe.
La selezione della lingua tiene conto delle lingue preferite dall’utente e delle localizzazioni disponibili. Se manca la lingua preferita di prima scelta, non è detto che venga usato subito l’inglese: potrebbe corrispondere un’altra lingua preferita. La guida archiviata di Apple sui bundle descrive questa sequenza di selezione, seguita dalla localizzazione di sviluppo se non corrisponde alcuna lingua preferita. La documentazione attuale definisce CFBundleDevelopmentRegion come l’identificatore della lingua di fallback del bundle. Accessing a Bundle’s Contents, CFBundleDevelopmentRegion.
Usa la seguente tabella decisionale per definire i risultati attesi. Distingue la selezione delle risorse dalla ricerca dei messaggi, invece di trattare ogni traduzione mancante come la stessa condizione.
| Condizione | Contratto per i messaggi gestiti dall’app | Cosa verificare |
|---|---|---|
| È disponibile una traduzione per una lingua preferita | Mostra quella traduzione | Bundle, tabella e chiave |
| La lingua preferita di prima scelta non è disponibile, ma corrisponde un’altra lingua preferita | Consenti alla corrispondenza linguistica del sistema di selezionare la localizzazione disponibile | Ordine delle preferenze e risorse incluse |
| Non corrisponde alcuna localizzazione preferita | Usa le risorse di sviluppo in inglese del bundle | Lingua di sviluppo e risorse in inglese |
| La ricerca selezionata non riesce a trovare il messaggio | Restituisci il valore predefinito esplicito in inglese | defaultValue del messaggio |
| Una ricerca nel framework punta per errore al bundle dell’app | Correggi l’argomento del bundle | Proprietà delle risorse |
| Esiste una traduzione, ma il testo non è adatto | Correggi la traduzione | Contenuto del catalogo e revisione |
La tabella combina le regole di selezione delle risorse di Apple con il comportamento documentato del valore predefinito dell’inizializzatore Swift. È una politica di implementazione derivata da queste API, non una funzionalità di fallback distinta dei cataloghi di stringhe. Una ricerca riuscita che restituisce un testo non adatto non soddisfa la condizione documentata dell’inizializzatore per usare il valore predefinito: una ricerca non riuscita. String.init(localized:defaultValue:table:bundle:locale:comment:).
Configurare le risorse sorgente in inglese in ogni target proprietario
Per questo esempio, usa una versione attuale di Xcode, un’app SwiftUI per macOS con una finestra semplice, destinata a macOS 13 o successivo, e un target framework dinamico incorporato chiamato PanelKit. Collega e incorpora il framework nell’app. Questi sono prerequisiti del progetto di esempio; il nome del framework non identifica un prodotto esistente.
Imposta l’inglese come lingua di sviluppo per entrambi i target e verifica che CFBundleDevelopmentRegion del bundle compilato di ciascuno corrisponda a en. Fornisci le risorse sorgente corrispondenti in inglese per entrambi i target. L’identificatore della lingua di sviluppo descrive la lingua di fallback, ma non fornisce il contenuto dei messaggi mancanti. Apple documenta en come identificatore della lingua inglese. CFBundleDevelopmentRegion.
Crea un catalogo Localizable.xcstrings distinto per ogni target. In Xcode, scegli File > New > File from Template, seleziona String Catalog e chiamalo Localizable. Assegna un catalogo al target dell’app e l’altro al target del framework. Mantenere separate le risorse in base alla proprietà consente di verificare ogni ricerca in modo indipendente. Apple documenta la procedura per creare i cataloghi e ne supporta l’uso di più di uno. Localizing and varying text with a string catalog.
Dopo aver aggiunto il codice seguente, scegli Product > Build. Xcode estrae nei cataloghi le chiamate localizzabili riconosciute. Verifica che workspace.title compaia nel catalogo dell’app e panel.ready in quello del framework, con i valori sorgente in inglese previsti. Aggiungi le lingue supportate tramite il pulsante di aggiunta nella barra laterale del catalogo e inserisci le traduzioni dei messaggi pertinenti. Localizing and varying text with a string catalog.
La completezza dei cataloghi e la correttezza delle ricerche in fase di esecuzione richiedono verifiche separate. Una voce tradotta nel catalogo del framework non può aiutare una chiamata che cerca nel bundle dell’app. Apple indica esplicitamente che il codice che carica stringhe al di fuori del bundle principale deve passare il bundle associato a quel target. Preparing your app’s text for translation.
Assegnare a ogni messaggio un bundle, una chiave, una tabella e un valore predefinito
Usa chiavi fittizie stabili e valori predefiniti leggibili in inglese. L’inizializzatore Swift che accetta defaultValue supporta una chiave diversa dal testo sorgente visualizzato. Il valore predefinito viene restituito se la ricerca della stringa localizzata nel bundle non riesce. Il parametro table seleziona la tabella delle stringhe; se omesso, viene selezionata Localizable. String.init(localized:defaultValue:table:bundle:locale:comment:).
Inserire i messaggi del framework nel framework
Aggiungi questo file sorgente Swift completo al target framework dinamico PanelKit. La classe marcatore è definita in quel target, così Bundle(for:) identifica il relativo bundle. Apple documenta questo approccio basato su una classe come alternativa alla macro attuale #bundle. Preparing your app’s text for translation.
import Foundation
private final class PanelBundleAnchor: NSObject {}
public enum PanelText {
public static var resourceBundle: Bundle {
Bundle(for: PanelBundleAnchor.self)
}
public static var ready: String {
String(
localized: "panel.ready",
defaultValue: "Panel ready",
table: "Localizable",
bundle: resourceBundle,
comment: "Status label above the framework panel."
)
}
}
Il framework risolve il proprio messaggio prima di restituire una String all’app. In questo modo si definisce un confine di proprietà chiaro: il framework controlla la chiave, il testo sorgente, la tabella e il bundle delle risorse. L’app riceve il testo da visualizzare.
Visualizzare insieme i messaggi dell’app e del framework
Sostituisci il file generato del punto d’ingresso dell’app con questo esempio completo. Presuppone che il modulo del framework collegato si chiami PanelKit e contenga il file precedente. Mantieni un solo punto d’ingresso nel target dell’app.
import Foundation
import SwiftUI
import PanelKit
@main
struct FallbackDemoApp: App {
var body: some Scene {
WindowGroup {
VStack(alignment: .leading, spacing: 12) {
Text(verbatim: String(
localized: "workspace.title",
defaultValue: "Workspace",
table: "Localizable",
bundle: .main,
comment: "Heading for the main workspace."
))
Text(verbatim: PanelText.ready)
}
.padding(24)
}
}
}
La ricerca dell’app usa esplicitamente .main; quella del framework usa il proprio bundle delle risorse. Entrambe forniscono valori predefiniti in inglese. Ciò segue la selezione del bundle e i parametri del valore predefinito documentati da Apple. Compila ed esegui il progetto in Xcode per convalidare la configurazione completa dei target; questi esempi non sono stati eseguiti qui. String.init(localized:defaultValue:table:bundle:locale:comment:).
Per un’implementazione esistente che usa Bundle.localizedString(forKey:value:table:), fornisci un valore value leggibile e non vuoto quando vuoi ottenere un risultato leggibile per una chiave mancante. Apple documenta che, se la chiave manca, viene restituita la chiave stessa quando value è assente o vuoto, mentre viene restituito value se non è vuoto. Una chiave come panel.ready richiede quindi un fallback esplicito se mostrarne l’identificatore violerebbe il contratto del messaggio. localizedString(forKey:value:table:).
Decidere se i framework possono selezionare lingue diverse
Passare il bundle corretto indica dove cercare. La configurazione delle localizzazioni miste influisce sul rapporto tra la selezione delle localizzazioni e l’app contenitore. Apple espone il valore booleano CFBundleAllowMixedLocalizations, mostrato come Localized resources can be mixed, per recuperare stringhe localizzate dai framework. CFBundleAllowMixedLocalizations.
La spiegazione di questo comportamento sui Swift Forums afferma che, abilitando la chiave nel file Info.plist dell’app, gli altri bundle possono selezionare localizzazioni che vanno oltre quelle supportate dall’app principale. Senza questa opzione, è il bundle principale a limitarne la selezione. Si tratta di una discussione esplicativa meno recente, utile insieme al riferimento attuale di Apple per la chiave. Swift package manager localization.
Per la finestra di esempio, è preferibile che l’app e il framework supportino le stesse lingue e abbiano entrambi risorse di sviluppo in inglese. Escludi dalla configurazione iniziale la selezione indipendente della lingua del framework. Se invece vuoi consentire a un framework di usare traduzioni aggiuntive, imposta il valore booleano CFBundleAllowMixedLocalizations dell’app su YES e verifica esplicitamente tale configurazione. Swift package manager localization.
L’abilitazione di questa chiave non fornisce una traduzione né un valore predefinito per un messaggio mancante. Queste responsabilità restano a carico dei file delle risorse e delle chiamate di ricerca. Analogamente, un valore predefinito fornito nella chiamata gestisce l’esito di una ricerca non riuscita per quella chiamata; non imposta un fallback universale in inglese per ogni controllo di sistema o messaggio del framework.
Evita di usare l’argomento locale di questo inizializzatore String come selettore della lingua di traduzione. Apple documenta esplicitamente che controlla la localizzazione dei valori interpolati, come i numeri, e non cambia la locale usata per cercare la stringa localizzata. Per questo compito, usa la configurazione delle lingue e i controlli di test supportati. String.init(localized:defaultValue:table:bundle:locale:comment:).
Verificare separatamente le lingue e i messaggi mancanti
Esegui i controlli di localizzazione da Product > Scheme > Edit Scheme. Seleziona Run, apri Options, scegli un App Language, chiudi la finestra di dialogo e avvia di nuovo l’app Mac. Apple documenta questa procedura per provare le localizzazioni senza cambiare le impostazioni dell’intero sistema. Durante la verifica di un problema relativo solo alla lingua, lascia invariata la selezione della regione. Testing localizations when running your app.
Usa la seguente matrice di test come supporto diagnostico specifico per il progetto. Per verificare l’instradamento dei bundle, usa temporaneamente marcatori di test in inglese distinti, come App translation sample e Framework translation sample, in una localizzazione supportata diversa da quella sorgente. Si tratta di contenuti diagnostici, non di traduzioni o identificatori di lingua.
- Verifica il comportamento delle risorse sorgente. Seleziona l’inglese e avvia l’app. Aspettati
WorkspaceePanel ready. - Verifica l’instradamento delle risorse tradotte. Seleziona la localizzazione di test supportata. Aspettati i marcatori distinti dei due cataloghi proprietari.
- Verifica il valore predefinito per un messaggio mancante. In una modifica di test usa e getta, cambia la chiave di ricerca del framework in
panel.ready.probe, lascia invariatodefaultValuee assicurati che la voce di prova non venga inclusa nel catalogo di test. Se la ricerca non riesce, aspettatiPanel ready. Ripristina la chiave originale al termine. - Verifica la selezione di una lingua non supportata. Prova un elenco di lingue preferite senza corrispondenze supportate. Controlla che entrambi i bundle gestiti usino le risorse di sviluppo in inglese. Prova anche una lingua non supportata come prima preferenza seguita da una lingua supportata, perché in quel caso il risultato atteso è diverso.
- Verifica le localizzazioni miste, se abilitate. Prova una lingua disponibile solo nel framework. Registra il comportamento previsto e confrontalo con l’impostazione delle localizzazioni miste dell’app.
Il terzo controllo isola una ricerca non riuscita; il quarto isola la corrispondenza linguistica. Verificare solo una riga non tradotta del catalogo può confondere queste condizioni, perché anche la configurazione delle risorse risultante influisce sulla ricerca. Il risultato atteso per una chiave mancante deriva dall’inizializzatore Swift, mentre la selezione delle lingue preferite segue le regole dei bundle. String.init(localized:defaultValue:table:bundle:locale:comment:), Accessing a Bundle’s Contents.
Se i risultati differiscono, controlla il bundle proprietario effettivo. developmentLocalization segnala il valore corrispondente a CFBundleDevelopmentRegion; preferredLocalizations segnala le localizzazioni disponibili, ordinate in base alle preferenze linguistiche. Confronta queste proprietà per Bundle.main e PanelText.resourceBundle. Aiutano a diagnosticare la configurazione, ma per verificare ogni ricerca il controllo finale resta il messaggio visualizzato. developmentLocalization, preferredLocalizations.
Un contratto di fallback utile rende spiegabile ogni risultato: la lingua selezionata deriva dalla corrispondenza dei bundle, il messaggio proviene dalla tabella proprietaria e una ricerca non riuscita restituisce un valore predefinito esplicito e leggibile. Applica queste regole a ogni messaggio gestito dall’app o dai framework, quindi verificale insieme nella finestra desktop in cui le persone li vedono.
Fonti
- Preparing your app’s text for translation — Apple
- Localizing and varying text with a string catalog — Apple
- CFBundleDevelopmentRegion — Apple
- String.init(localized:defaultValue:table:bundle:locale:comment:) — Apple
- localizedString(forKey:value:table:) — Apple
- CFBundleAllowMixedLocalizations — Apple
- Swift package manager localization — Swift Forums
- Testing localizations when running your app — Apple
- developmentLocalization — Apple
- preferredLocalizations — Apple
- Accessing a Bundle’s Contents — Apple Documentation Archive