Notre Team d’application n’a pas besoin de compter sur nous, les développeurs (et de prendre notre temps précieux) lors du déploiement de nouvelles traductions dans notre application. Nous pouvons également éviter l’approbation de l’App Store lors de la mise à jour du contenu localisé de notre application. Voyons comment nous pouvons réaliser ces avantages dans notre application iOS grâce à la fonctionnalité over-the-air de Phrase. Nous allons ajouter Phrase over-the-air à une application fonctionnelle, en reliant tout sur la console Phrase et notre projet XCode.
Notre application
Nous reprenons là où nous nous étions arrêtés dans notre précédent article, localisation application iOS avec Phrase. Dans ce tutoriel, nous avons pris une application et l’avons connectée à Phrase pour rationaliser notre flux de travaux de localisation. Nous supposons que vous avez lu cet article, et/ou que vous avez déjà connecté Phrase à votre application. Sinon, nous vous recommandons vivement de consulter cet article avant de continuer.

Notre petite application de démonstration liste des morceaux de musique électronique ainsi que leurs artistes et dates de sortie. C’est une application simple à deux écrans avec un UITableViewController qui présente une liste de tous nos morceaux, et dispose d’un écran de détails pour afficher les informations d’un morceau unique.
🔗 Ressource » Si vous souhaitez faire le travail en parallèle, vous pouvez récupérer le Starter projet sur Github. Le projet terminé se trouve près du bas de l’article.
Préparation
D’accord, commençons à préparer notre application pour les traductions over-the-air. Dans notre application iOS, nous allons déplacer nos chaînes localisées des storyboards vers un bon vieux Localizable.strings. Nous ajouterons ensuite le support de traduction over-the-air à notre projet Phrase. Pour compléter notre préparation, nous installerons le SDK iOS de Phrase, qui synchronise les traductions de notre application avec notre projet Phrase over-the-air.
Déplacer les traductions de notre application des Storyboards vers Localizable.strings
Les traductions Phrase over-the-air fonctionneront parfaitement avec les fichiers storyboard .strings. Cependant, pour garder les choses simples ici, mettons toutes nos chaînes traduisibles dans un seul fichier Localizable.strings. Il s’agit d’un simple remaniement de Main.strings à Localizable.strings, alors allons-y.
📖 Aller plus loin » Si vous souhaitez en savoir plus sur la localisation des storyboards iOS, consultez notre guide, iOS i18n : Internationaliser les storyboards dans Xcode
Commençons par les titres des éléments de navigation de notre écran. Nous pouvons simplement remplacer les titres définis dans nos storyboards en définissant le champ title dans nos contrôleurs de vue. Notre écran d’accueil, qui présente la liste de nos artistes, est connecté à TrackListViewController. Mettons à jour ce contrôleur maintenant.
class TrackListViewController : UIViewController {
// ...
override func viewDidLoad() {
super.viewDidLoad()
title = NSLocalizedString("trackListTitle", comment: "")
// ...
}
}
Nous utilisons le NSLocalizedString habituel pour récupérer notre traduction depuis Localizable.strings. Assurons-nous que la chaîne de traduction existe dans la version anglaise de Localizable.strings.
"copyright" = "Droit d’auteur © %@ %@." « Tous droits réservés. » "trackListTitle" = "Short Circuit";
Avec cela en place, notre application aura exactement le même aspect lorsqu’elle sera exécutée en anglais. Nous ajouterons nos paramètres régionaux non anglais un peu plus tard. Terminons d’abord de déplacer nos traductions hors de nos storyboards.
Pour nos étiquettes, nous devons nous assurer que nous disposons d’outlets depuis nos storyboards vers leurs contrôleurs respectifs.
Après avoir connecté nos étiquettes, nous répétons simplement le même processus d’appel à NSLocalizedString pour leur fournir les chaînes traduites. Et, bien sûr, nous ajoutons nos nouvelles chaînes dans notre fichier anglais Localizable.strings.
Notre TrackDetailsViewController, qui aide à afficher les informations d’un seul morceau, ressemblerait à ceci après que nous ayons déplacé nos traductions de storyboard :
import UIKit
classe TrackDetailsViewController : UIViewController {
@IBOutlet weak var trackNameHeaderLabel: UILabel!
@IBOutlet weak var artistNameHeaderLabel: UILabel!
// ...
var track : Track?
override func viewDidLoad() {
super.viewDidLoad()
title = NSLocalizedString("trackDetailsTitle", comment: "")
if let track = track {
trackNameHeaderLabel.text =
getLocalizedHeaderText(clé: "trackNameHeader")
artistNameHeaderLabel.text =
getLocalizedHeaderText(clé: "artistNameHeader")
releaseDateHeaderLabel.text =
getLocalizedHeaderText(key: "releaseDateHeader")
// ...
}
}
fileprivate func getLocalizedHeaderText(key: String) -> String {
return NSLocalizedString(key, comment: "")
.localizedUppercase
}
}
La fonction getLocalizedHeaderText est simplement un petit utilitaire que nous utilisons pour fournir un formatage en majuscules localisé à notre texte d’étiquette traduit.
Après avoir ajouté nos chaînes de traduction à notre Localizable.strings, notre application a exactement le même aspect qu’auparavant.

Nous pouvons maintenant retirer complètement nos fichiers de traduction de storyboard de notre projet XCode. Nous le faisons en sélectionnant le fichier storyboard dans le navigateur de projet et en décochant chaque paramètre régional sous l’en-tête Localisations dans le inspecteur de fichier.
📖 Aller plus loin » Si vous travaillez beaucoup avec des storyboards iOS, vous voudrez peut-être consulter notre article, Automatiser la localisation des storyboards iOS.
Mise à jour de nos traductions avec Phrase
Nous devons maintenant mettre à jour nos traductions Localizable.strings pour nos langues non-source (non-anglaises dans mon cas). Nous le faisons afin que nos utilisateurs non-anglophones puissent voir nos étiquettes de mise à jour dans leur langue. Nous pouvons, bien sûr, utiliser notre flux de travaux habituel Phrase pour traduire nos étiquettes.
Tout d’abord, nous allons charger notre nouvelle source en faisant un $ phrase push depuis la ligne de commande.
Nos nouvelles clés de traduction devraient maintenant apparaître sur la console web de Phrase . Une fois que nos traducteurs ont traduit les clés dans tous les paramètres régionaux que notre application prend en charge, nous pouvons $ phrase pull depuis la ligne de commande pour obtenir nos fichiers Localizable.strings mis à jour. Maintenant, lorsque nous exécutons notre application dans un paramètre linguistique non source (arabe dans mon cas), nous voyons que nos vues sont traduites comme prévu.

📖 Aller plus loin » Vous pouvez en savoir plus sur le flux de travaux de base de Phrase avec iOS dans localisation application iOS avec Phrase.
Maintenant que nous avons déplacé nos chaînes de traduction de storyboard vers des fichiers Localizable.strings, nous pouvons passer à la configuration des traductions over-the-air dans notre projet Phrase.
Ajout d’une distribution over-the-air dans Phrase
Préparons notre projet Phrase pour les traductions over-the-air. Dans notre console web Phrase, ouvrons le menu déroulant de notre organisation dans la barre de navigation supérieure et sélectionnons Intégrations.

Cela ouvrira notre page Intégrations Phrase. Ici, nous pouvons trouver la ligne over-the-air (OTA) et cliquer sur son bouton Configurer.

Nous devrions maintenant voir la page over-the-air nous invitant à créer une distribution. Une distribution est une configuration OTA de projet qui cible une ou plusieurs plateformes et dispose d’options de secours.

Cliquons sur le bouton Créer distribution pour ouvrir la boîte de dialogue Ajouter distribution.

Pour notre projet actuel, nous pouvons donner à la distribution un nom de notre choix, sélectionner le projet Phrase associé à notre application iOS, et cocher la case de la plateforme ios. Nous pouvons laisser les options de secours par défaut telles qu’elles sont, car elles conviennent à nos besoins. Cliquons sur le bouton Enregistrer pour créer la distribution.
💡Pour votre information » Vous pouvez modifier les paramètres de votre distribution à tout moment en revenant à la page over-the-air.
Ajout de notre première version OTA
Pour travailler avec le SDK iOS sans voir de résultat d’échec lorsque nous essayons de mettre à jour nos traductions dans l’application, nous devons disposer d’une version OTA. Une version est essentiellement un instantané de nos traductions Phrase que nous pouvons tester et déployer dans notre application iOS over-the-air. Nous parlerons des versions plus tard. Pour l’instant, créons une première version pour commencer à utiliser le SDK.
Nous commencerons par cliquer sur le bouton Créer une version en bas de notre page de distribution.

Libérez-moi
Cela ouvre la boîte de dialogue Ajouter une version. Nous pouvons ajouter une description pour nous aider à identifier la version plus tard, laisser tout le reste tel quel, et cliquer sur Enregistrer.

Nous devrions maintenant voir une entrée sous Versions près du bas de notre page de distribution.
Maintenant que nous avons une distribution OTA et une première version, nous pouvons configurer OTA dans notre application iOS.
Installation du SDK iOS de Phrase
Nous aurons besoin du SDK Phrase installé pour utiliser OTA. Nous pouvons le faire via CocoaPods, Carthage, ou manuellement.
Pour installer le SDK via CocoaPods, il faut que CocoaPods soit installé sur notre Mac. Vous pouvez voir les instructions d’installation sur le site Web de CocoaPods. En supposant que nous avons CocoaPods installé, nous pouvons naviguer vers le répertoire racine du projet (celui qui contient notre fichier .xcodeproj) et exécuter la commande suivante depuis le terminal.
$ pod init
Cela créera un Podfile dans notre répertoire racine. Ouvrons ce fichier dans notre éditeur de code préféré et ajouter une ligne pour qu’il ressemble à ceci :
target 'phraseapp-demo' do use_frameworks! # Pods for phraseapp-demo pod 'PhraseSDK' end
Avec cette modification enregistrée, nous pouvons exécuter ce qui suit depuis notre terminal :
$ pod install
Si tout s’est bien passé, nous devrions avoir reçu une sortie indiquant que Phrase a été installé. Après cela, nous pouvons fermer toutes les fenêtres XCode que nous avons ouvertes et ouvrir le fichier .xcworkspace que CocoaPods a ajouté à la racine de notre projet après l’installation de Phrase.
Configurer Phrase dans notre application iOS
Avec le SDK installé, nous allons le connecter à notre application. Tout d’abord, jetons un coup d’œil rapide à deux méthodes principales proposées par le SDK Phrase :
Phrase.shared.setup(distributionID:environmentSecret:timeout:) initialise l’objet singleton Phrase partagé, prenant nos informations d’identification et un paramètre de délai d’attente optionnel.
Phrase.shared.updateTranslations(translationResult:) met à jour manuellement les traductions dans l’application, en récupérant les plus récentes depuis les serveurs Phrase si une nouvelle version existe. updateTranslations prend une fermeture d’échappement optionnelle, translationResult, que nous pouvons fournir si nous voulons agir lorsque la demande de mettre à jour est terminée.
Ok, allons ajouter une classe OTATranslations qui fournit un léger wrapper autour de PhraseApp.
import PhraseSDK
class OTATranslations {
static let shared = OTATranslations()
private init() {
#if DEBUG
Phrase.shared.debugMode = true
#endif
let config : PList? = loadConfig()
if let config = config {
#if DEBUG
let environmentTokenKey : String = "devToken"
#else
let environmentTokenKey : String = "prodToken"
#endif
Phrase.shared.setup(
distributionID : config.getValue(withKey : "distributionID"),
environmentSecret : config.getValue(withKey : environmentTokenKey),
timeout: config.getValue(withKey: "timeout")
)
}
}
func updateTranslations(onUpdateComplete: (() -> Void)? = nil) {
do {
try Phrase.shared.updateTranslations { result in
switch result {
case .success(let updated):
si mis à jour {
printIfDebug("Translations mises à jour avec succès")
onUpdateComplete?()
} else {
printIfDebug("Aucune nouvelle traduction trouvée")
}
case .failure:
printIfDebug("Échec de la mise à jour des traductions")
}
}
} catch {
printIfDebug("Erreur lors de la mise à jour des traductionsa: \(error)")
}
}
fileprivate func loadConfig() -> PList? {
do {
return try PList(pListResource: "PhraseApp")
} catch {
printIfDebug(
printIfDebug("Erreur de chargement de la configuration Phrase depuis plist, \(error)")
}
return nil
}
}
💡FYI »
Phrase.shared.debugModeest un indicateur qui rend le SDK Phrase plus verbeux, en affichant plus de détails dans la console, lorsqu’il est activé. Nous l’activons lorsque nous exécutons une version de débogage de notre application.
💡FYI » La fonctionprintIfDebug(_:)est un helper personnalisé qui affiche simplement la chaîne donnée dans la console si l’indicateur#DEBUGest activé.
Nous fournissons un simple objet singleton OTATranslations.shared à utiliser dans notre application. Notre objet est initialisé en tirant les valeurs de configuration de Phrase d’un PhraseApp.plist et en les fournissant à PhraseApp.setup. Pour que cela fonctionne, nous devons créer la classe PhraseApp.plist dans notre projet XCode. Faisons-le maintenant. Cela devrait ressembler un peu à ce qui suit.

Voici une version texte si vous voulez ⌘-C.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<clé>distributionID</clé>
<chaîne>votre_distribution_id</chaîne>
<clé>devToken</clé>
<chaîne>votre_secret_de_developpement_de_distribution</chaîne>
<clé>prodToken</clé>
<chaîne>votre_secret_de_production_de_distribution</chaîne>
<clé>timeout</clé>
<integer>10</integer>
</dict>
</plist>
✋🏽 Attention » Vous voudrez peut-être ajouter votre fichier
PhraseApp.plistà votre.gitignorepour protéger vos clés.
💡Pour info » La classePListque nous utilisons pour charger les valeurs de notre fichier.plistest une classe utilitaire personnalisée.
Les valeurs pour notre distributionID, devToken, et prodToken peuvent être trouvées sur la page de distribution OTA dans la console web de Phrase. Nous pouvons naviguer vers l’onglet Vue d’ensemble du tableau de bord de notre projet, puis cliquer sur le bouton Voir les distributions sous la section over-the-air. Cela ouvre la page over-the-air, et de là, nous pouvons trouver et cliquer sur la distribution OTA de notre projet dans la liste Distributions. Une fois sur la page de la distribution spécifique, nous pouvons trouver les valeurs Identifiant de distribution, secret de développement et secret de production à copier et coller dans notre fichier .plist. Bien sûr, nous utilisons « jeton » au lieu de « secret » dans notre .plist, mais vous l’avez probablement déjà compris.
Copiez et collez vos identifiants et jetons secrets
Ok, maintenant que nous avons connecté le SDK Phrase à notre classe OTATranslations, utilisons-le dans notre AppDelegate.swift.
import UIKit
@UIApplicationMain
class AppDelegate : UIResponder, UIApplicationDelegate {
var window: UIWindow ?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
OTATranslations.shared.updateTranslations()
return true
}
}
Dans la méthode application(_:didFinishLaunchingWithOptions:) de notre AppDelegate, qui s’exécute au démarrage de notre application, nous mettons manuellement à jour nos traductions over-the-air. Cela récupère toutes les nouvelles traductions en arrière-plan. Cependant, notre configuration actuelle ne mettra pas à jour l’interface utilisateur immédiatement. Les mises à jour de traduction qui sont récupérées lors de ce lancement d’application apparaîtront à l’utilisateur lors de son suivant lancement d’application. C’est souvent le comportement que nous voulons : avoir de nouvelles chaînes de traduction qui apparaissent pendant que l’utilisateur utilise l’application pourrait être une expérience utilisateur étrange et potentiellement déstabilisante.
Rafraîchir manuellement l’interface utilisateur après avoir récupéré de nouvelles traductions
Cependant, en fonction de nos exigences, nous pourrions avoir besoin de rafraîchir l’interface utilisateur de l’application immédiatement après avoir récupéré une mise à jour de traduction. Nous pouvons le faire en utilisant le paramètre de fermeture de rappel que nous avons fourni dans updateTranslations(onUpdateComplete:).
import UIKit
@UIApplicationMain
class AppDelegate : UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any] ?) -> Bool {
OTATranslations.shared.updateTranslations() {
AppDelegate.reloadRootViewController()
}
return true
}
static func reloadRootViewController() {
DispatchQueue.main.async {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController =
storyboard.instantiateInitialViewController()
}
Ici, nous fournissons l’argument onUpdateComplete à updateTranslations en tant que fermeture d’échappement. Cette fonction de rappel sera appelée lorsqu’il y aura de nouvelles traductions qui ont été récupérées avec succès. Lorsque cela se produit, nous appelons notre méthode personnalisée AppDelegate.reloadViewController(). Cela rechargera effectivement notre application et montrera à l’utilisateur nos traductions les plus récentes.
✋🏽 Attention » Soyez vigilant lors du rechargement du contrôleur de vue racine de l’application. Si l’utilisateur a déjà commencé à faire quelque chose dans votre application, il se peut que son flux soit interrompu – et que ses données non enregistrées soient perdues – lorsque le rechargement se produit. Pour réduire les chances que cela se produise, vous voudrez peut-être utiliser une configuration de
timeoutrelativement basse lors de la configuration du SDKPhraseApp. De cette façon, si la demande de traduction prend du temps, elle s’annulera simplement et ne déclenchera pas le rechargement. Alternativement, et de façon plus fiable, vous pourriez faire apparaître un indicateur de chargement bloquant pendant la requête. Cela empêcherait l’utilisateur d’interagir avec votre application pendant le chargement de la traduction, évitant ainsi la perte de données mentionnée ci-dessus.
La liberté des traductions iOS over-the-air avec Phrase
Nous avons pratiquement terminé d’intégrer les traductions OTA dans notre application. Après avoir publié cette version de notre application sur l’App Store, nous sommes libres d’envoyer des traductions à nos utilisateurs sans passer à nouveau par l’approbation de l’App Store. Tout ce que nous avons à faire est de nous rendre sur notre console web Phrase, et
- Mettre à jour nos traductions des paramètres régionaux, puis
- Créer une nouvelle version pour notre distribution OTA (tout comme nous l’avons fait auparavant), et
- Publiez la version.

N’oubliez pas de publier votre version après l’avoir revue
C’est vraiment aussi simple que ça. Une fois que nous publions notre version dans la console web de Phrase, nos utilisateurs commenceront à recevoir les traductions mises à jour. Tous les utilisateurs qui ont la version de l’application connectée au SDK PhraseApp récupéreront les nouvelles traductions over-the-air. Pas besoin de publier une nouvelle version de l’application, pas besoin d’attendre l’approbation de l’App Store. Douce liberté.
🔗 Ressource » Vous pouvez voir et télécharger le code terminé pour le projet iOS que nous avons construit ici depuis notre dépôt Github.
Pour en savoir plus
Si vous souhaitez approfondir l’internationalisation et la localisation iOS, consultez certains de nos autres articles sur le sujet.
Et voilà, c’est terminé
Connecter notre application aux traductions over-the-air de Phrase ne prend qu’un jour ou deux. Cela peut nous faire économiser des dizaines et des dizaines d’heures alors que nous publions de nouvelles traductions directement à nos utilisateurs de l’application. Avec OTA, nous avons également l’avantage de sauter l’approbation de l’App Store (juste pour mettre à jour le texte). Et Phrase vous offre bien plus que OTA: Phrase peut vraiment rationaliser le processus de localisation pour votre application. Jetez un œil à tous les produits de Phrase et inscrivez-vous pour un essai gratuit de 14 jours.
J’espère que vous commencez à voir le potentiel des traductions over-the-air, et que vous avez apprécié ce petit guide pour faire fonctionner OTA dans votre application iOS. Nous ajouterons plus de contenu OTA dans les jours à venir, alors restez à l’écoute, et bonne programmation :)

