Pour une app Mac avec des panneaux appartenant au framework, définissez le secours à deux niveaux : la langue que chaque bundle sélectionne, et ce que chaque message renvoie lorsque sa recherche échoue. Utilisez une localisation de développement en anglais et des valeurs par défaut anglaises explicites pour les messages dont vous êtes propriétaire.

Ce guide met en œuvre ce contrat pour une simple fenêtre de bureau contenant le label appartenant à l'app Workspace et le label appartenant au framework Panel ready. Les labels sont synthétiques. La tâche consiste à garder ces messages lisibles lorsqu'une langue ou une traduction est manquante, tout en préservant la localisation normale lorsque les traductions existent.

Que devrait promettre le contrat de secours ?

Adoptez ce contrat pour les messages appartenant à l'app et ceux appartenant au framework : utilisez une localisation disponible sélectionnée via la correspondance de langues du système ; utilisez l'anglais comme localisation de développement lorsqu'aucune localisation préférée ne correspond ; et renvoyez la valeur par défaut anglaise explicite d'un message si la recherche de sa chaîne échoue. Chaque message doit identifier son bundle propriétaire et sa table de chaînes.

La sélection de la langue prend en compte les langues préférées de l'utilisateur et les localisations disponibles. Une première langue de préférence manquante ne signifie pas nécessairement que l'anglais apparaît immédiatement : une autre langue préférée peut correspondre en premier. Le guide de bundle archivé d'Apple décrit cette séquence de sélection, suivie de la localisation de développement lorsqu'aucune langue préférée ne correspond. La documentation actuelle définit CFBundleDevelopmentRegion comme identifiant de la langue de secours du bundle. Accessing a Bundle's Contents, CFBundleDevelopmentRegion.

Utilisez le tableau de décision suivant lors de la définition des résultats attendus. Il sépare la sélection des ressources de la recherche de message au lieu de traiter chaque traduction manquante comme la même condition.

Condition Contrat pour les messages dont vous êtes propriétaire Ce qu'il faut vérifier
Une langue préférée dispose d'une traduction disponible Afficher cette traduction Bundle, table et clé
La première langue préférée est indisponible, mais une autre langue préférée correspond Permettre à la correspondance de langues du système de sélectionner la localisation disponible Ordre de préférence et ressources fournies
Aucune localisation préférée ne correspond Utiliser les ressources de développement anglaises du bundle Langue de développement et ressources anglaises
La recherche sélectionnée ne peut pas résoudre le message Renvoyer sa valeur par défaut anglaise explicite La defaultValue du message
Une recherche de framework cible accidentellement le bundle de l'app Corriger l'argument bundle Propriété des ressources
Une traduction existe mais contient du texte inapproprié Corriger la traduction Contenu du catalogue et révision

Le tableau combine les règles de sélection des ressources d'Apple avec le comportement de la valeur par défaut documenté de l'initialiseur Swift. C'est une politique d'implémentation dérivée de ces API, pas une fonctionnalité de secours distincte dans les catalogues de chaînes. Une recherche réussie contenant du texte inapproprié ne remplit pas la condition documentée de l'initialiseur pour l'utilisation de sa valeur par défaut : une recherche échouée. String.init(localized:defaultValue:table:bundle:locale:comment:).

Configurer les ressources sources anglaises dans chaque cible propriétaire

Pour cet exemple, utilisez une installation Xcode actuelle, une app SwiftUI macOS ciblant macOS 13 ou version ultérieure, et une cible de framework Swift dynamique embarqué nommée PanelKit. Liez et embarquez ce framework dans l'app. Ce sont des prérequis de projet d'exemple ; le nom du framework n'identifie pas un produit existant.

Définissez l'anglais comme langue de développement pour les deux cibles, et vérifiez que le CFBundleDevelopmentRegion de chaque bundle construit se résout en en. Fournissez les ressources sources anglaises correspondantes dans les deux cibles. Un identifiant de langue de développement décrit la langue de secours ; il ne fournit pas de contenu de message manquant. Apple documente en comme identifiant de langue anglaise. CFBundleDevelopmentRegion.

Créez un catalogue Localizable.xcstrings distinct pour chaque cible. Dans Xcode, choisissez Fichier > Nouveau > Fichier à partir du modèle, sélectionnez Catalogue de chaînes, et nommez-le Localizable. Attribuez un catalogue à la cible de l'app et l'autre à la cible du framework. Garder la propriété des ressources séparée permet de vérifier chaque recherche indépendamment. Apple documente le flux de travail de création de catalogue et prend en charge plusieurs catalogues. Localiser et varier le texte avec un catalogue de chaînes.

Après avoir ajouté le code ci-dessous, choisissez Produit > Construire. Xcode extrait les appels localisables reconnus dans les catalogues. Confirmez que workspace.title apparaît dans le catalogue de l'app et panel.ready apparaît dans le catalogue du framework, avec les valeurs sources anglaises prévues. Ajoutez les langues prises en charge à l'aide du bouton d'ajout de la barre latérale du catalogue et saisissez les traductions pour les messages pertinents. Localiser et varier le texte avec un catalogue de chaînes.

L'exhaustivité du catalogue et la correction de la recherche à l'exécution nécessitent des vérifications distinctes. Une entrée traduite dans le catalogue du framework ne peut pas aider un appel qui recherche dans le bundle de l'app. Apple instruit explicitement le code chargeant des chaînes en dehors du bundle principal de passer le bundle associé à cette cible. Préparer le texte de votre app pour la traduction.

Donner à chaque message un bundle, une clé, une table et une valeur par défaut

Utilisez des clés synthétiques stables et des valeurs par défaut anglaises lisibles. L'initialiseur Swift acceptant defaultValue prend en charge une clé différente du texte source affiché. Sa valeur par défaut est renvoyée lorsque la recherche de la chaîne localisée depuis le bundle échoue. Le paramètre table sélectionne la table de chaînes ; l'omettre sélectionne Localizable. String.init(localized:defaultValue:table:bundle:locale:comment:).

Placer les messages du framework dans le framework

Ajoutez ce fichier source Swift complet à la cible de framework dynamique PanelKit. La classe marqueur est définie dans cette cible afin que Bundle(for:) identifie son bundle. Apple documente cette approche basée sur les classes comme alternative à la macro #bundle actuelle. Préparer le texte de votre app pour la traduction.

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."
        )
    }
}

Le framework résout son message avant de renvoyer un String à l'app. Cela établit une frontière de propriété claire : le framework contrôle la clé, le texte source, la table et le bundle de ressources. L'app reçoit le texte d'affichage résultant.

Afficher les messages de l'app et du framework ensemble

Remplacez le fichier de point d'entrée de l'app généré par cet exemple complet. Il suppose que le module de framework lié est nommé PanelKit et contient le fichier précédent. Ne gardez qu'un seul point d'entrée d'app dans la cible de l'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 recherche de l'app utilise explicitement .main ; la recherche du framework utilise son propre bundle de ressources. Les deux fournissent des valeurs par défaut anglaises. Cela suit les paramètres documentés d'Apple pour la sélection de bundle et la valeur par défaut. Construisez et exécutez le projet dans Xcode pour valider la configuration complète des cibles ; ces exemples n'ont pas été exécutés ici. String.init(localized:defaultValue:table:bundle:locale:comment:).

Pour une implémentation existante utilisant Bundle.localizedString(forKey:value:table:), fournissez un value non vide et lisible lorsque vous avez besoin d'un résultat de clé manquante lisible. Apple documente qu'une clé manquante renvoie la clé elle-même lorsque value est absent ou vide, et renvoie value lorsqu'il n'est pas vide. Une clé telle que panel.ready a donc besoin d'un secours explicite si l'exposition de cet identifiant violerait le contrat de message. localizedString(forKey:value:table:).

Décider si les frameworks peuvent sélectionner des langues différentes

Passer le bon bundle répond à la question de l'endroit où rechercher. La configuration de localisation mixte affecte la façon dont la sélection de localisation se rapporte à l'app conteneur. Apple expose le booléen CFBundleAllowMixedLocalizations, affiché comme Les ressources localisées peuvent être mélangées, pour récupérer des chaînes localisées depuis les frameworks. CFBundleAllowMixedLocalizations.

L'explication des forums Swift sur ce comportement indique qu'activer la clé dans le Info.plist de l'app permet aux autres bundles de sélectionner des localisations au-delà de celles prises en charge par l'app principale. Sans cette adhésion, le bundle principal contraint leur sélection. Il s'agit d'une discussion explicative plus ancienne, utile aux côtés de la référence actuelle de la clé d'Apple. Localisation du gestionnaire de paquets Swift.

Pour la fenêtre d'exemple, privilégiez une couverture linguistique prise en charge correspondante entre l'app et le framework, avec des ressources de développement anglaises dans les deux. Laissez la sélection de langue indépendante du framework en dehors du contrat initial. Si votre comportement prévu est plutôt de laisser un framework utiliser des traductions supplémentaires, définissez le booléen CFBundleAllowMixedLocalizations de l'app sur YES et testez cette configuration explicitement. Localisation du gestionnaire de paquets Swift.

L'activation de cette clé ne fournit ni traduction ni valeur par défaut de message manquant. Ces responsabilités incombent toujours aux fichiers de ressources et aux appels de recherche. De même, une valeur par défaut fournie à votre propre appel définit le résultat de recherche échouée de cet appel ; elle n'établit pas de secours anglais universel pour chaque contrôle système ou message de framework.

Évitez d'utiliser l'argument locale de cet initialiseur String comme commutateur de langue de traduction. Apple documente explicitement qu'il contrôle la localisation des valeurs interpolées, telles que les nombres, et ne change pas la locale utilisée pour rechercher la chaîne localisée. Utilisez la configuration de langue prise en charge et les contrôles de test pour cette tâche. String.init(localized:defaultValue:table:bundle:locale:comment:).

Tester les langues manquantes séparément des messages manquants

Exécutez les vérifications de localisation via Produit > Schéma > Modifier le schéma. Sélectionnez Exécuter, ouvrez Options, choisissez une Langue de l'app, fermez la boîte de dialogue, et relancez l'app Mac. Apple documente ce flux de travail pour exercer les localisations sans changer les paramètres de l'ensemble du système. Maintenez la sélection de région inchangée lors de l'investigation d'un problème de langue uniquement. Tester les localisations lors de l'exécution de votre app.

Utilisez la matrice de test suivante comme aide diagnostique propre au projet. Pour les vérifications de routage de bundle, utilisez temporairement des marqueurs de test anglais distincts tels que App translation sample et Framework translation sample dans une localisation non source prise en charge. Ce sont du contenu de diagnostic, pas des traductions ou des identifiants de langue.

  1. Vérifier le comportement source. Exécutez avec l'anglais sélectionné. Attendez-vous à Workspace et Panel ready.
  2. Vérifier le routage des ressources traduites. Sélectionnez la localisation de test prise en charge. Attendez-vous aux marqueurs distincts des deux catalogues propriétaires.
  3. Vérifier une valeur par défaut de message manquant. Dans une modification de test jetable, changez la clé de recherche du framework en panel.ready.probe, laissez defaultValue inchangé, et empêchez cette entrée de test d'être incluse dans le catalogue de test. Attendez-vous à Panel ready lorsque la recherche échoue. Rétablissez la clé originale par la suite.
  4. Vérifier la sélection de langue non prise en charge. Exercez une liste de préférences sans correspondance de langue prise en charge. Vérifiez que les deux bundles propriétaires utilisent leurs ressources de développement anglaises. Testez également une première préférence non prise en charge suivie d'une préférence prise en charge, car ce cas a un résultat attendu différent.
  5. Vérifier la localisation mixte si activée. Exercez une langue disponible uniquement dans le framework. Enregistrez le comportement prévu et testez le réglage de localisation mixte de l'app par rapport à celui-ci.

La troisième vérification isole une recherche échouée ; la quatrième isole la correspondance de langues. Tester seulement une ligne de catalogue non traduite peut brouiller ces conditions car la configuration de ressources résultante affecte également la recherche. Le résultat de clé manquante attendu provient de l'initialiseur Swift, tandis que la sélection de langue préférée suit les règles de bundle. String.init(localized:defaultValue:table:bundle:locale:comment:), Accessing a Bundle's Contents.

Lorsque les résultats diffèrent, inspectez le bundle propriétaire réel. developmentLocalization signale la valeur correspondant à CFBundleDevelopmentRegion ; preferredLocalizations signale les localisations disponibles ordonnées selon les préférences de langue. Comparez ces propriétés sur Bundle.main et PanelText.resourceBundle. Elles aident à diagnostiquer la configuration, mais les messages affichés restent la vérification finale de chaque recherche. developmentLocalization, preferredLocalizations.

Un contrat de secours utile rend chaque résultat explicable : la langue sélectionnée provient de la correspondance de bundle, le message provient de sa table propriétaire, et une recherche échouée renvoie une valeur par défaut lisible explicite. Appliquez ces règles à chaque message d'app et de framework dont vous êtes propriétaire, puis vérifiez-les ensemble dans la fenêtre de bureau où les utilisateurs les rencontrent.

Sources