View in English

  • Global Nav Open Menu Global Nav Close Menu
  • Apple Developer
Search
Cancel
  • Apple Developer
  • News
  • Discover
  • Design
  • Develop
  • Distribute
  • Support
  • Account
Only search within “”

Quick Links

5 Quick Links

Vidéos

Ouvrir le menu Fermer le menu
  • Collections
  • Sujets
  • Toutes les vidéos
  • À propos

Plus de vidéos

  • À propos
  • Résumé
  • Transcription
  • Code
  • Code-along : explorez la localisation avec Xcode

    Découvrez comment localiser votre app dans d'autres langues à l'aide de Xcode. Nous vous guiderons pas à pas tout au long du processus de création d'un catalogue de chaînes, de traduction de texte et d'échange de fichiers avec des traducteurs externes. Vous découvrirez les bonnes pratiques pour fournir le contexte nécessaire aux traducteurs et comment Xcode peut vous aider à transmettre ces informations automatiquement. Pour les projets plus importants, nous explorerons également les techniques permettant de gérer la complexité et de simplifier la gestion des chaînes à l'aide du code Swift sécurisé.

    Chapitres

    • 0:00 - Introduction
    • 0:38 - Premiers pas
    • 5:33 - Contexte de traduction
    • 9:33 - Gérer la complexité
    • 20:49 - Étapes suivantes

    Ressources

    • Expanding Your App to New Markets
    • Localizing Landmarks
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC23

    • Discover String Catalogs
  • Rechercher dans cette vidéo…

    Bonjour ! Je suis Andreas, de l’équipe de localisation. Au cours de cette session, nous allons explorer la localisation avec Xcode.

    Aucune connaissance préalable n’est requise. Nous allons découvrir comment configurer une app pour la localisation. Puis, nous verrons comment fournir le contexte approprié aux personnes impliquées dans la traduction de l’app. Enfin, nous aborderons certaines difficultés que vous pouvez rencontrer lorsque le projet prend de l’ampleur, ainsi que les nouvelles fonctionnalités utiles à cet effet. Allons-y.

    Il s’agit d’une session de « code-along ». Autrement dit, vous pouvez appliquer les étapes de cette vidéo à l’exemple de projet lié dans la description. Téléchargez le projet Landmarks et commencez à le traduire avec moi. J’ai ouvert le projet dans Xcode. Cette version de Landmarks fonctionne très bien en anglais, mais n’a pas encore de traduction. Pour commencer, ajoutons un catalogue de chaînes avec le menu Files.

    Utilisons le nom par défaut Localizable, mais enregistrons-le dans le groupe Ressources. C’est aussi là que se trouve le catalogue de ressources. Maintenant que le catalogue de chaînes a été ajouté, générons le projet. Lorsqu’il existe un catalogue de chaînes, Xcode détecte les chaînes localisables après chaque build et les y ajoute automatiquement. Les chaînes du catalogue restent synchronisées avec le code sans que nous n’ayons rien à faire. Comment Xcode sait-il quelles chaînes nous voulons localiser ? La plupart des API SwiftUI rendent les chaînes localisables par défaut. Cela inclut les vues comme Texte et Bouton. Dans le reste du code, String(localized:) rend les chaînes disponibles pour la traduction.

    Je vais utiliser l’éditeur adjoint pour déterminer d’où les chaînes du catalogue de chaînes ont été extraites.

    Celle-ci vient d’une boîte de dialogue de confirmation.

    Cette autre chaîne est utilisée comme titre d’un LabeledContent, et celle-ci comme titre de navigation. Et celle-là vient d’un texte utilisant une variable interpolée. Comme vous le voyez, presque toute l’API SwiftUI est localisable. Vous avez peut-être remarqué que cette chaîne représente un certain nombre d’éléments. L’espace réservé %lld sera remplacé par le nombre de points de repère à l’exécution. Nous voulons que cette chaîne varie en fonction de ce nombre. Par exemple, elle peut indiquer : « 1 élément » et « 2 éléments ».

    Pour ce faire, dans le menu contextuel, sélectionnons Vary by Plural.

    Désormais, nous pouvons écrire les phrases pour un et plusieurs éléments.

    À l’exécution, le système choisit la chaîne correspondant au nombre. C’était facile.

    La localisation implique diverses langues. Comme je parle allemand, je peux écrire certaines des traductions directement dans le catalogue de chaînes. Fermons l’assistant. Pour ajouter une langue au projet, cliquons sur le bouton + dans la barre du bas et sélectionnons Allemand. Je peux désormais commencer à ajouter des traductions.

    Comme vous le voyez, l’état passe de NEW à TRANSLATED à mesure que je traduis, et active une coche verte à droite.

    Parallèlement, le pourcentage global de traduction de la barre latérale est passé à 8 %.

    Comme je suis meilleur développeur que traducteur, je fais appel à un expert linguistique. Je préférerais qu’il termine la traduction allemande restante.

    Pour lui envoyer ce que j’ai jusqu’à présent, dans le menu Product de Xcode, je sélectionne Export Localizations. Comme je traduis l’app en allemand, j’aimerais n’exporter que cette langue.

    Cela créera un fichier de catalogue de localisation avec toutes les traductions allemandes actuelles, ainsi que les chaînes anglaises non traduites. Ce paquet contient un fichier XLIFF standard, avec lequel les services de traduction peuvent facilement travailler. Quand ils auront terminé, ils renverront le catalogue de localisation traduit.

    Pour le réimporter dans le projet, je retourne dans le menu Product et je sélectionne Import Localizations. Xcode met un moment à compiler le projet, mais toutes les chaînes sont ensuite marquées comme traduites, et l’allemand est à 100 %. Vous pouvez en faire de même. L’exemple de projet contient le fichier de.xcloc traduit que vous pouvez importer dans Xcode comme je l’ai fait. Voyons ce que ça donne. J’aimerais exécuter l’application en allemand. Dans l’éditeur de schéma, je modifie le schéma, je sélectionne Run et j’accède à Options.

    Remplaçons ici la langue de l’app par l’allemand pour le prochain débogage.

    Maintenant, je compile et j’exécute l’app sur mon Mac.

    Elle est entièrement traduite en allemand. J’adore !

    Vous savez désormais comment configurer la localisation d’une app. Voyons de plus près comment fournir plus de contexte aux traducteurs pour garantir des traductions de haute qualité. L’éditeur adjoint de Xcode permet de voir le code juste à côté du catalogue de chaînes. Lors de la traduction, les traducteurs voient rarement le code ou l’app en fonctionnement. Pour que leurs traductions soient de bonne qualité, ils ont besoin de contexte.

    Ce contexte est ajouté sous forme de commentaire. Soit directement dans le code, soit dans la colonne de commentaires du catalogue de chaînes. Sans commentaire, il peut être difficile de comprendre le but d’une chaîne. Par exemple, « Landmarks » n’est qu’un seul mot. Faisons-nous référence au nom de l’app ou à des points de repère sur une carte ? Cette clé de chaîne indique « %@ is contained in %@ ». Comment le traducteur peut-il savoir ce que représente %@ ? Cela a un impact sur la façon dont la chaîne sera traduite. Un commentaire doit indiquer l’élément d’interface où se trouve la chaîne, comme une barre d’onglets, un bouton ou un sous-titre.

    Il est aussi utile de décrire les éléments d’interface environnants. Par exemple, indiquez que la première chaîne est une entrée de la barre latérale. Et que la deuxième chaîne est le sous-titre d’un point de repère dans une liste. Enfin, un commentaire doit expliquer le type de contenu lié à chaque espace réservé. Ici, le premier espace réservé est le nom d’un point de repère, et le second le nom d’une collection dont il fait partie. Sans commentaire, il serait impossible de traduire cela correctement. C’est pourquoi il est essentiel de fournir un commentaire clair.

    Depuis l’an dernier, les catalogues de chaînes suivent d’où provient une chaîne dans le code. Cette année, nous utilisons cette information pour vous aider. Voyons la génération automatique de commentaires dans Xcode 26.

    Xcode utilise un modèle sur l’appareil pour analyser le code et peut écrire des commentaires pour vous. Voyons cela de plus près. Jusqu’à présent, nous n’avons fourni des commentaires que pour certaines chaînes du code. Vu l’importance des commentaires, améliorons le contexte dont disposeront les traducteurs. Ici, nous avons une chaîne sans commentaire. Elle semble être utilisée dans un bouton. Dans le menu contextuel, je sélectionne Generate Comment. Après avoir analysé la chaîne, Xcode indique qu’il s’agit d’un libellé figurant sur un bouton pour annuler la suppression d’une collection. Très pertinent !

    Comme la chaîne n’a pas de commentaire, je laisse Xcode en générer un pour nous.

    Il crée « Libellé affiché au-dessus de l’emplacement d’un point de repère ». Très bien. Notez qu’il est possible d’y apporter des modifications. Votre entrée remplace toujours un commentaire généré. J’aime fournir plus de contexte quand cela est possible. J’ajoute donc que cette chaîne apparaît dans l’inspecteur.

    Je trouve cette fonctionnalité très utile, et je veux que Xcode génère un commentaire pour toute nouvelle chaîne extraite du code. Pour ce faire, j’ouvre Settings et j’accède à Editing.

    Je coche « Automatically generate string catalog comment ». Désormais, lorsque Xcode détectera l’ajout de chaînes localisables dans le code, il générera automatiquement un commentaire. Il est donc très facile de fournir aux traducteurs le contexte dont ils ont besoin.

    Pour aider les développeurs d’outils de traduction à signaler la génération d’un commentaire par Xcode, le fichier XLIFF exporté utilise l’annotation « auto-generated ».

    Pour en savoir plus sur l’interopérabilité avec d’autres outils et sur les fonctionnalités d’un catalogue de chaînes, consultez « Discover String Catalogs ».

    Lorsque votre projet prend de l’ampleur et gagne en complexité, d’autres fonctionnalités Xcode et API de localisation vous aident à rester organisé. Par exemple, quand la taille d’un projet augmente et que plusieurs développeurs travaillent dessus, nous divisons parfois la base de code en extensions, frameworks et paquets Swift. Chacun d’eux peut contenir un ou plusieurs catalogues de chaînes. Dans ce cas, nous devons utiliser un autre paramètre sur l’API de localisation : bundle. Cela indique au système où trouver la chaîne à l’exécution. Bundle.main fait toujours référence à l’app principale. Si nous n’incluons pas le paramètre bundle, .main est utilisé par défaut.

    La nouveauté de cette année est la macro #bundle. Elle renvoie au bundle qui contient les ressources pour la cible actuelle. À savoir l’app principale, si le code s’exécute dans l’app principale. Elle trouve automatiquement les ressources du framework ou du paquet Swift. Elle fonctionne sur les anciennes versions du système d’exploitation et s’occupe de tout.

    Une autre façon d’organiser les chaînes est de regrouper les chaînes liées, par exemple, les chaînes liées à un écran, à une fonctionnalité ou à un flux utilisateur. Nous appelons les groupes de chaînes « Table ». Chaque catalogue de chaînes représente une table.

    Par défaut, toutes les chaînes sont extraites dans la table « Localizable ». C’est le nom du fichier par défaut généré lorsque vous créez un catalogue de chaînes. Vous pouvez le modifier. Le paramètre tableName vous permet d’ajouter les chaînes dans le catalogue de chaînes de votre choix. Par exemple, l’utilisation du nom de table Discover les place automatiquement dans Discover.xcstrings. Bien que l’application Landmarks fonctionne très bien lors de la création de collections privées, je veux développer une fonctionnalité pour découvrir plus de contenu. Ce contenu provient soit d’amis que je suis, soit d’un flux organisé. Développons cette fonctionnalité dans un nouveau framework.

    Pour commencer, j’ouvre le menu File et j’ajoute une cible. Je cherche « framework ».

    Comme ce framework concerne la découverte de points de repère, je l’appelle « DiscoverKit ».

    Je lance un tout nouvel écran, et je veux mettre toutes ses chaînes dans un tableau séparé. Ajoutons un fichier à DiscoverKit, sélectionnons String Catalog et appelons-le Discover.

    J’ouvre le code dans l’éditeur à droite, en maintenant enfoncés Maj et Option pendant que je clique sur le nouveau fichier Swift.

    Et je ferme le navigateur pour avoir un peu plus d’espace.

    Développons cette fonctionnalité dans la couche du modèle avec une enum. Cette enum définit si le contenu vient d’un ami ou d’un flux organisé. Une de ses propriétés permet d’exposer un titre localisé. Implémentons-la. Je commence par utiliser String(localized: ) afin d’exposer la chaîne pour la traduction. Puis, j’utilise l’argument Table pour une meilleure organisation. Comme il s’agit d’un framework, je dois également utiliser l’argument bundle. Faisons de même pour l’autre cas.

    Notre enum est terminée. Importons maintenant SwiftUI et ajoutons une vue pour afficher du contenu à l’écran.

    Je n’ai pas encore de logique métier. Je vais donc montrer un espace réservé indiquant qu’il y aura 42 nouvelles publications.

    C’est maintenant au tour de Xcode de travailler. Je remplace le schéma par le nouveau framework et lance le build.

    Une fois le build terminé, les nouvelles chaînes apparaissent dans le catalogue.

    Et elles ont déjà un commentaire. Parfait !

    Pour le reste du travail sur l’interface utilisateur, voyons un nouveau processus dans Xcode 26. Depuis le début des catalogues de chaînes, ils permettent l’extraction des chaînes à partir du code. Cette année, ils vous aident à écrire le code en générant des symboles pour les chaînes ajoutées manuellement. Continuons à créer notre vue avec ce nouveau processus. Mon objectif est d’ajouter un titre et un sous-titre de navigation. L’intégralité de cette vue est en cours de développement. En séparant les clés de chaîne de leur valeur, je peux itérer la formulation exacte sans avoir besoin de mettre à jour le code.

    Je clique sur le bouton + dans le catalogue de chaînes pour ajouter une chaîne. De nombreux projets préfèrent utiliser des clés en majuscules pour indiquer une signification sémantique des chaînes. C’est aussi ce que je vais faire. La clé doit être « TITLE » et la valeur « Discover Landmarks ». Comme j’ai ajouté cette chaîne manuellement, j’écris le commentaire moi-même.

    L’inspecteur d’attributs m’indique comment utiliser la chaîne dans le code. C’est très utile ! Je fais ce qu’il me dit !

    Pour afficher un titre dans la barre de navigation, j’utilise le modificateur de vue .navigationTitle.

    Pour sa valeur, je saisis un point de début, puis je commence à taper le nom de la table. Xcode saisit automatiquement le reste du nom pour moi, et toutes les chaînes manuelles de cette table sont également suggérées.

    Facile ! Notez que je n’ai pas eu à saisir un nom de bundle et de table cette fois-ci.

    Faisons la même chose pour le sous-titre de navigation. Je vais ajouter une chaîne au catalogue et l’appeler SUBTITLE.

    Elle doit résumer combien de publications proviennent d’amis et combien proviennent d’un flux organisé. Pour cela, j’ai besoin d’un espace réservé, ce que permettent les spécificateurs de format. Je commence par taper %, et Xcode m’en suggère quelques-uns. Comme je veux un nombre, je choisis un espace réservé correspondant à un entier.

    Cet espace réservé représentera le nombre de publications d’amis, d’où le nom friendsPosts.

    J’ajoute un autre espace réservé pour les publications de flux organisés.

    Ajoutons un commentaire.

    Cette chaîne peut maintenant être utilisée dans le code. Cette fois, j’utilise le modificateur navigationSubtitle.

    Je commence à taper .Discover pour trouver la bonne table, et la saisie automatique prend le relais.

    J’ai eu beaucoup moins à saisir ! Comme vous le voyez, Xcode m’a suggéré les bons types. Cette nouvelle fonctionnalité facilite le traitement des chaînes manuelles. Il me suffit d’utiliser la saisie automatique et le compilateur pour charger ces ressources localisées. Si je veux modifier les valeurs de mes chaînes ultérieurement, je peux les mettre à jour dans le catalogue de chaînes sans avoir à modifier le code. Vous est-il déjà arrivé de vouloir harmoniser en une seule action un terme pour lequel vous aviez utilisé différentes orthographes ?

    Pour générer un nom de symbole parfaitement adapté à Swift, Xcode utilise la clé et la valeur de la chaîne. Les chaînes sans espace réservé sont accessibles comme toute autre propriété statique. Si une chaîne contient un espace réservé, Xcode génère une fonction à la place et utilise le nom de l’espace réservé comme libellé d’argument. Les symboles générés sont des variables statiques ou des fonctions de type LocalizedStringResource. C’est impressionnant, car vous pouvez les utiliser partout où une ressource LocalizedStringResource est utilisée. Cela inclut les vues SwiftUI telles que Texte ou Bouton, ou les modificateurs de vue comme .navigationSubtitle() Si vous n’utilisez pas SwiftUI, la chaîne String(localized: ) de Foundation fonctionne aussi avec LocalizedStringResource.

    Les vues personnalisées et autres déclarations utilisant LocalizedStringResource peuvent désormais être appelées à l’aide d’un symbole généré.

    Vos symboles sont directement accessibles sur LocalizedStringResource si vous utilisez le nom de table par défaut Localizable. Lorsque vous utilisez un autre nom de table, les symboles générés sont imbriqués dans l’espace de noms de cette table. Vous pouvez y accéder dans le code commençant par le nom de votre table. La génération de symboles est activée par défaut pour les projets créés par Xcode 26. Pour l’utiliser dans un projet existant, activez le réglage Generate String Catalog Symbols.

    Comme nous l’avons vu, Xcode offre deux approches différentes pour gérer vos chaînes : les extraire du code ou les référencer à l’aide d’une API type-safe. Cela soulève la question : quelle approche choisir ? Nous recommandons l’extraction des chaînes. Comme vous écrivez les chaînes là où vous développez l’interface utilisateur, vous pouvez lire et comprendre le code plus rapidement. Cette approche permet d’utiliser la génération de commentaires de Xcode, ce qui vous fait gagner du temps tout en donnant plus de contexte utile aux traducteurs. Plus le projet prend de l’ampleur, plus il est important d’avoir plus de contrôle sur l’organisation des chaînes. Dans ce cas, nous recommandons d’utiliser des symboles générés. Cela vous permet de séparer les clés de leurs valeurs, afin de pouvoir itérer le texte sans modifier le code. De plus, la saisie automatique de Xcode permet de référencer facilement les chaînes dans toutes les tables. Enfin, les symboles générés contribuent à éviter le code répétitif dans les frameworks et les paquets.

    Les deux approches ont leurs avantages. Nous vous laissons la liberté de choisir celle qui convient le mieux à votre projet. C’est pourquoi nous avons ajouté une fonctionnalité de refactoring permettant de passer facilement de l’une à l’autre. Testons-la dans le framework DiscoverKit. Je pense que le texte de l’espace réservé de la pile de navigation se prête bien à la génération d’un symbole. Dans le menu contextuel, je sélectionne Refactor > Convert Strings to Symbols.

    Une interface utilisateur d’aperçu affiche les emplacements exacts où le symbole sera utilisé à la place de la chaîne. En cliquant sur la section en surbrillance, je peux comparer le symbole avec le code d’origine.

    Remplaçons le nom de la clé par feedTitle pour améliorer la sémantique. Je peux aussi ajouter un nom à l’argument 1. Appelons-le newPosts. Ça me semble pas mal. Je confirme le refactoring.

    Après avoir réfléchi aux deux approches, je veux utiliser des symboles générés pour toutes les chaînes de cette table. Sélectionnons les chaînes restantes, puis Refactor > Convert Strings to Symbols.

    Les noms des symboles me conviennent. Je clique donc sur Convert.

    Le tour est joué : nous avons refactorisé toute la table en une fois. Je vous invite à explorer par vous-même ces fonctionnalités de localisation dans Xcode. Commencez par utiliser l’extraction de chaînes pour localiser votre projet. Fournissez des commentaires pertinents aux traducteurs en les écrivant vous-même ou avec la fonctionnalité de Xcode. Si votre projet prend de l’ampleur, envisagez d’utiliser des symboles générés pour conserver un contrôle précis sur vos chaînes.

    Pour plus de détails sur les catalogues de chaînes, consultez la vidéo « Discover String Catalogs ». Merci de votre attention. J’espère que ces nouvelles fonctionnalités vous seront utiles.

    • 1:34 - Localizable strings

      // import SwiftUI
      Text("Featured Landmark", comment: "Big headline in the hero image of featured landmarks.")
      
      Button("Keep") { }
      
      // import Foundation
      String(localized: "New Collection", comment: "Default name for a new user-created collection.")
    • 6:00 - Adding a comment

      Text("Delete",
      comment: "Delete button shown in an alert asking for confirmation to delete the collection.")
      
      String(localized: "Shared by Friends", comment: "Subtitle of post that was shared by friends.")
    • 9:13 - XLIFF file

      // Field for automatically generated comments in the XLIFF
      
      <trans-unit id="Grand Canyon" xml:space="preserve">
      <source>Grand Canyon</source>
      <target state="new">Grand Canyon</target>
      <note from="auto-generated">Suggestion for searching landmarks</note>
      </trans-unit>
    • 9:58 - Localized String in the main app and a Swift Package or Framework

      // Localized String in the main app:
      Text("My Collections", 
      comment: "Section title above user-created collections.")
      
      // Localized String in a Swift Package or Framework
      Text("My Collections", 
      bundle: #bundle, 
      comment: "Section title above user-created collections.")
    • 10:56 - Localized String with a tableName parameter

      // Localized String in the main app:
      Text("My Collections",
      tableName: "Discover",
      comment: "Section title above user-created collections.")
      
      // Localized String in a Swift Package or Framework
      Text("My Collections",
      tableName: "Discover",
      bundle: #bundle, 
      comment: "Section title above user-created collections.")
    • 17:31 - Symbol usage

      // Symbol usage in SwiftUI
      Text(.introductionTitle)
      
      .navigationSubtitle(.subtitle(friendsPosts: 42))
      
      
      // Symbol usage in Foundation
      String(localized: .curatedCollection)
      
      
      // Working with generated symbols in your own types
      struct CollectionDetailEditingView: View {
          let title: LocalizedStringResource
          
          init(title: LocalizedStringResource) {
              self.title = title
          }
      }
      CollectionDetailEditingView(title: .editingTitle)
    • 0:00 - Introduction
    • Dans ce code pour tous les niveaux de compétences, apprenez à configurer votre app pour la localisation, à travailler avec des professionnels de la traduction et à gérer les complexités au fur et à mesure que votre projet se développe.

    • 0:38 - Premiers pas
    • Nous vous montrons comment localiser une app SwiftUI nommée « Landmarks » à l’aide de Xcode. Le processus commence par l’ajout d’un catalogue de chaînes qui détecte automatiquement les chaînes localisables après chaque build. Vous pouvez localiser le catalogue de chaînes vous-même ou collaborer avec un professionnel de la traduction via des fichiers XLIFF.

    • 5:33 - Contexte de traduction
    • Lorsque vous fournissez des fichiers pour traduction, le contexte est crucial pour assurer la précision. Vous pouvez ajouter des commentaires directement dans le code ou dans le catalogue de chaînes. Xcode 26 introduit la génération automatique de commentaires, qui utilise un modèle sur l’appareil pour analyser votre code et suggérer des commentaires.

    • 9:33 - Gérer la complexité
    • Au fur et à mesure que votre projet se développe, vous pouvez l’organiser en lots ou en frameworks. Vous pouvez spécifier des paramètres de lots et de tables lorsque vous utilisez les API de localisation pour identifier les chaînes. Xcode 26 introduit également un nouveau processus qui génère automatiquement des symboles pour les chaînes, ce qui permet de séparer les clés de chaîne des valeurs. Vous pouvez choisir et passer facilement d’un processus à l’autre : extraction de chaînes à partir du code ou à l’aide des symboles générés.

    • 20:49 - Étapes suivantes
    • Pour localiser votre app, vous pouvez commencer par extraire des chaînes et, à mesure que votre projet devient plus complexe, passer aux symboles générés pour une meilleure gestion des chaînes.

Developer Footer

  • Vidéos
  • WWDC25
  • Code-along : explorez la localisation avec Xcode
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • App Store
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Fonts
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Open Source
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Sample Code
    • Tutorials
    • Downloads
    • Forums
    • Videos
    Open Menu Close Menu
    • Support Articles
    • Contact Us
    • Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Get the Apple Developer app.
    Copyright © 2025 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines