{"id":8674,"date":"2016-12-15T07:31:13","date_gmt":"2016-12-15T05:31:13","guid":{"rendered":"https:\/\/phraseapp.com\/blog\/?p=1779"},"modified":"2023-05-22T09:39:04","modified_gmt":"2023-05-22T07:39:04","slug":"app-localization-the-ultimate-guide-to-app-store-optimization","status":"publish","type":"post","link":"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/","title":{"rendered":"Implementing App Store Localization for Higher Downloads"},"content":{"rendered":"\n<div id=\"acf\/text-block_7a16f91e2afdedab87d6ca4809bcd4c6\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>Successful iOS apps appeal to as wide an audience as possible. Achieving this appeal will invariably include a look at <a href=\"https:\/\/phrase.com\/blog\/posts\/ios-tutorial-internationalization-localization\/\">iOS localization<\/a>: adapting the app\u2019s user experience to the language, culture, and other specifics of a country or region.<\/p>\n<p>While developers are increasingly getting better at localizing apps, not everyone may pay attention to localizing App Store pages\u2014and herein lies a great opportunity: Localized App Store pages rank higher in App Store search results and have better download rates.<\/p>\n<p>This tutorial will go over localizing your App Store page step by step, including the app&#8217;s name, description, screenshots, and other metadata. We\u2019ll cover both manual and automated localization. Let&#8217;s get it started!<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_69_1 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Overview<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#our-app-store-localization-project\" title=\"Our App Store localization project\">Our App Store localization project<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#how-to-localize-app-details\" title=\"How to localize app details\">How to localize app details<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#adding-supported-locales\" title=\"Adding supported locales\">Adding supported locales<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#localizing-app-details\" title=\"Localizing app details\">Localizing app details<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#how-to-localize-screenshots\" title=\"How to localize screenshots\">How to localize screenshots<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#automating-localization-through-fastlane\" title=\"Automating localization through fastlane\">Automating localization through fastlane<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#a-note-about-development-environments\" title=\"A note about development environments\">A note about development environments<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#the-setup\" title=\"The setup\">The setup<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#localizing-app-store-details\" title=\"Localizing App Store details\">Localizing App Store details<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#adding-other-locales\" title=\"Adding other locales\">Adding other locales<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#automating-screenshot-localization\" title=\"Automating screenshot localization\">Automating screenshot localization<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#setting-up-ui-tests\" title=\"Setting up UI tests\">Setting up UI tests<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#setting-up-snapshot\" title=\"Setting up snapshot\">Setting up snapshot<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#generating-screenshots\" title=\"Generating screenshots\">Generating screenshots<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#deploying-to-the-app-store\" title=\"Deploying to the App Store\">Deploying to the App Store<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/phrase.com\/blog\/posts\/app-localization-the-ultimate-guide-to-app-store-optimization\/#well-done\" title=\"Well done!\">Well done!<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"our-app-store-localization-project\"><\/span>Our App Store localization project<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>To learn all about localizing App Store pages, we will use a mobile app called &#8220;Motivate Me,&#8221; a simple SwiftUI application that shows random motivational quotes when you tap a button:<\/p>\n<table style=\"width: 100%; border-collapse: collapse; border-style: none;\">\n<tbody>\n<tr>\n<td style=\"width: 50%;\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-52946 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-en-1-472x1024.png\" alt=\"Localizing iOS App Store pages en screenshot | Phrase\" width=\"472\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-en-1-472x1024.png 472w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-en-1-138x300.png 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-en-1-768x1665.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-en-1-709x1536.png 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-en-1-945x2048.png 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-en-1.png 1179w\" sizes=\"(max-width: 472px) 100vw, 472px\" \/><\/td>\n<td style=\"width: 50%;\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-52964 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-fr-2-472x1024.png\" alt=\"Localizing iOS App Store pages fr 2 screenshot | Phrase\" width=\"472\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-fr-2-472x1024.png 472w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-fr-2-138x300.png 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-fr-2-768x1665.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-fr-2-709x1536.png 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-fr-2-945x2048.png 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-fr-2.png 1179w\" sizes=\"(max-width: 472px) 100vw, 472px\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><span class=\"ez-toc-section\" id=\"how-to-localize-app-details\"><\/span>How to localize app details<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Let\u2019s start by looking at how to localize additional supported locales for our App Store page, and how to add text translations and localize our screenshots.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"adding-supported-locales\"><\/span>Adding supported locales<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Visit <a href=\"https:\/\/appstoreconnect.apple.com\/\">App Store Connect<\/a>, select your project, and click <em>App Information<\/em>. This screen shows the basic information of your App Store product.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-52975 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-information-1024x493.png\" alt=\"App information | Phrase\" width=\"1024\" height=\"493\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-information-1024x493.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-information-300x144.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-information-768x370.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/app-information.png 1484w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>On the <em><span class=\"notion-enable-hover\" data-token-index=\"1\">Localizable Information <\/span><\/em>section, you&#8217;ll see the base language, English(U.S.), selected in the drop-down near the upper-right of the page. To localize our App Store page to another language, we need to click on this drop-down and click the language we would like to support.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-52981 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/language-selector.png\" alt=\"Language selector | Phrase\" width=\"293\" height=\"412\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/language-selector.png 293w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/language-selector-213x300.png 213w\" sizes=\"(max-width: 293px) 100vw, 293px\" \/><\/p>\n<p>The drop-down has 2 sections. The first is a list of languages we already have localizations for. The second is a list of languages so far unsupported by our <span class=\"discussion-id-dd117090-fcfa-4fc0-ad2d-e518a62fa981 notion-enable-hover\" data-token-index=\"1\">App Store<\/span> page. We will add French localization to our App Store listing, so let\u2019s select <em><span class=\"notion-enable-hover\" data-token-index=\"3\">French<\/span><\/em> from the list.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-52987 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/language-french-selector.png\" alt=\"Language french selector | Phrase\" width=\"605\" height=\"427\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/language-french-selector.png 605w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/language-french-selector-300x212.png 300w\" sizes=\"(max-width: 605px) 100vw, 605px\" \/><\/p>\n<p><em>French<\/em> will now show in the list of localized languages. The <em>Primary Language<\/em> section now shows a drop-down that allows selecting the App Store page\u2019s primary or default language. This will be the language shown when a user with an unsupported locale views our App Store page or when our page isn\u2019t localized.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"localizing-app-details\"><\/span>Localizing app details<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>French is now selected as the active locale, shown in blue next to a downward arrow. All the information currently displayed is what a user of the active locale will see when they visit our page. Let\u2019s change the <em>Subtitle<\/em> to something in French, along with the <em>Name<\/em>, and click the <em>Save<\/em> button.<\/p>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb<\/em> You don\u2019t always have to translate literally. It sometimes makes sense to choose different words or phrases to appeal better to the audience of the active locale.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-52993 size-large aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/french-app-information-1024x566.png\" alt=\"French app information | Phrase\" width=\"1024\" height=\"566\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/french-app-information-1024x566.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/french-app-information-300x166.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/french-app-information-768x425.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/french-app-information.png 1235w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>Let&#8217;s move on to another section of the app page where we can localize more information in our App Store listing.<\/p>\n<p>Click on the latest build version we have for our app, in our case <em>1.0<\/em>. The screen that opens displays more information that appears on our store page. Just past the <em>Screenshots<\/em> section, we should see details for <em>Promotional Text<\/em>, <em>Description<\/em>, <em>Keywords<\/em>, etc. We can localize them by following the same steps we did for the <em>App Information<\/em> section.<\/p>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb <\/em>We will come back to screenshot localization shortly.<\/p>\n<p>Click the active language drop-down, switch to any other supported language, and change the details. We can save the changes and repeat the process for other languages.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-52999 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/more-app-details-1024x543.png\" alt=\"More app details | Phrase\" width=\"1024\" height=\"543\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/more-app-details-1024x543.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/more-app-details-300x159.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/more-app-details-768x407.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/more-app-details-1536x815.png 1536w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/more-app-details.png 1546w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb <\/em>Localization on the App Store generally follows this same workflow. Change the active language to the one you want to localize \u279e make changes \u279e click the Save button. Whenever you see the language selector, you know localization is possible for that section.<\/p>\n<p>That&#8217;s it! Very simple and straightforward.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"how-to-localize-screenshots\"><\/span>How to localize screenshots<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Screenshots give a visual representation of how our application will look on our user&#8217;s device. Screenshots are very important for conversion rates. So they should look good and help potential users envision themselves using our app.<\/p>\n<p>Let\u2019s scroll back up on the Version Information page to get to the <em>iOS Previews and Screenshots<\/em> section. We can drag and drop the image files to upload the screenshots we want to show for our base language.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53005 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/screenshots-1024x579.png\" alt=\"Screenshots | Phrase\" width=\"1024\" height=\"579\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/screenshots-1024x579.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/screenshots-300x170.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/screenshots-768x434.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/screenshots.png 1423w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>When we switch the language to French we see the screenshots section is empty for that locale. We can then design localized screenshots that fit our French audience. Once they\u2019re ready, we can drag and drop them to the dedicated section and click the <em><span class=\"notion-enable-hover\" data-token-index=\"1\">Save<\/span><\/em> button. And, as you may have guessed, we can repeat this process for each language our app supports.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53016 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/drag-and-drop-1024x685.png\" alt=\"Drag and drop | Phrase\" width=\"1024\" height=\"685\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/drag-and-drop-1024x685.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/drag-and-drop-300x201.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/drag-and-drop-768x514.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/drag-and-drop.png 1155w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>That\u2019s it for App Store localization. Not too bad, right? Now our app can conquer the world!<\/p>\n<p>Well, for a few languages, this workflow isn\u2019t too bad. But what happens when we have 10+, 20+, or 30+ locales we want to support? I know you are yawning already because that sounds like a tedious task. You&#8217;re probably asking yourself if there is an easier way, right? Well, yes! We are about to learn how to do this more efficiently with the power of automation.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"automating-localization-through-fastlane\"><\/span>Automating localization through fastlane<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><a href=\"https:\/\/fastlane.tools\/\">Fastlane<\/a> is a simple, powerful tool that can streamline the process of localizing apps. With fastlane, we can automate many of the tedious and time-consuming tasks associated with localization, such as translating text, updating screenshots, and submitting updates to the App Store. We can also use the tool to easily create and submit new versions of our app, with all the necessary localization changes. All this can be done from the command line, which saves significant time and effort. It\u2019s also relatively cheap: We don&#8217;t need complex cloud infrastructure to use it, just our local machine. Let\u2019s see how to use fastlane to automate App Store localization.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"a-note-about-development-environments\"><\/span>A note about development environments<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Fastlane setup can differ depending on your development environment. Luckily fastlane has very good <a href=\"https:\/\/docs.fastlane.tools\/\">documentation<\/a> that is constantly updated. You need to follow <a href=\"https:\/\/docs.fastlane.tools\/getting-started\/ios\/setup\/\">these steps<\/a> to set up the best environment to run your automation.<\/p>\n<p>The environment we&#8217;re using for this article is:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">- macOS Ventura 13.1\n- ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) &#91;arm64-darwin22]\n- fastlane 2.211.0\n- Swift version 5.7.2\n- Xcode Version 14.2<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_e83300c9325a0bf44491b681c847d294\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<h3><span class=\"ez-toc-section\" id=\"the-setup\"><\/span>The setup<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>After installing fastlane, with the help of the <a href=\"https:\/\/docs.fastlane.tools\/getting-started\/ios\/setup\/\">setup instructions<\/a>, we&#8217;re ready for some automation. Let\u2019s open our project folder from the command line and start fastlane with the following command:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">% fastlane init<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_8ae6944a7156f4fde4fecbf42dae8cef\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53024 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-init-1024x247.png\" alt=\"Fastlane init | Phrase\" width=\"1024\" height=\"247\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-init-1024x247.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-init-300x72.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-init-768x185.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-init-1536x371.png 1536w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-init.png 1566w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>The command presents a prompt that asks us how we will start using fastlane. Let\u2019s choose option 3, <em>Automate App Store distribution<\/em>, for this tutorial.<\/p>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb <\/em>Choosing one option doesn\u2019t lock us in. We can always add more automation tasks later.<\/p>\n<p>Fastlane will present a series of prompts about our developer account and app details. Once we\u2019re done answering all the prompts, we should see some new files that fastlane generated: A <code>fastlane<\/code> folder containing all we need to automate our App Store listing. Notice that fastlane localizes store data by default, placing stubs in our app\u2019s base language, e.g. under <code>fastlane\/metadata\/en-US<\/code>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53030 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-folders.png\" alt=\"Fastlane folders |\u00a0Phrase\" width=\"408\" height=\"719\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-folders.png 408w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-folders-170x300.png 170w\" sizes=\"(max-width: 408px) 100vw, 408px\" \/><\/p>\n<p><span class=\"discussion-id-9b100ea1-553d-44cb-8dac-7f9430c22d3d notion-enable-hover\" data-token-index=\"0\">If we don&#8217;t see the <\/span><code><span class=\"discussion-id-9b100ea1-553d-44cb-8dac-7f9430c22d3d notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">fastlane\/metadata<\/span><\/code><span class=\"discussion-id-9b100ea1-553d-44cb-8dac-7f9430c22d3d notion-enable-hover\" data-token-index=\"2\"> folder<\/span>, we can use the following command to generate it:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">% fastlane deliver download_metadata\\\\\n  --username {{App Store username}}\\\\\n  --app_identifier {{bundle id}}\\\\\n  --force <span class=\"hljs-literal\">true<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_2767a9f860efb5c966c96d1072f71019\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<h3><span class=\"ez-toc-section\" id=\"localizing-app-store-details\"><\/span>Localizing App Store details<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The fastlane subfolders and file names are self-explanatory and descriptive. They often map one-to-one with the info we see in App Store Connect. For example, fastlane\u2019s <code>first_name.txt<\/code> file corresponds to the app contact\u2019s <strong>First name<\/strong> field in App Store Connect. We will highlight all the mandatory files that need to be populated before fastlane can do its job.<\/p>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb <\/em>We will use the term \u201clane\u201d moving forward. A lane is a set of actions you want fastlane to take. Without a lane, <a href=\"https:\/\/docs.fastlane.tools\/advanced\/lanes\/#private-lanes\">fastlane<\/a> can\u2019t work so always make sure there is at least one lane. The generated Fastfile comes with a lane already provided and that is what we\u2019ll be using throughout this tutorial.<\/p>\n<ul>\n<li><code>Appfile<\/code>: stores useful information that is used across all fastlane tools, like our <em>Apple ID<\/em> or the application <em>Bundle Identifier.<\/em> This info is used to deploy our lanes faster and is tailored to our project needs. [<a href=\"https:\/\/docs.fastlane.tools\/advanced\/Appfile\/#appfile\">Official Appfile documentation<\/a>]<\/li>\n<li><code>Fastfile<\/code>: stores the automation configuration that is used to run fastlane. [<a href=\"https:\/\/docs.fastlane.tools\/advanced\/Fastfile\/\">Official Fastfile documentation<\/a>].<\/li>\n<li><code>copyright.txt<\/code>: the copyright of the app e.g. Phrase inc @ 2023<\/li>\n<li><code>primary_category.txt<\/code>: the primary category of our application e.g. LIFESTYLE<\/li>\n<li><code>review_information<\/code>: found in the metadata folder, its information Apple&#8217;s testers will use to access our application. The required files in the review information related to your team\u2019s point of contact for testers: <code>email_address.txt<\/code>, <code>frist_name.txt<\/code>, <code>last_name.txt<\/code>, and <code>phone_number.txt<\/code>. Fastlane requires that these files have data before you can push updates to the App Store.<\/li>\n<li><code>name.txt<\/code>: the name of our app.<\/li>\n<li><code>subtitle.txt<\/code>: the subtitle of our application. This is normally a tagline or something short to describe our application.<\/li>\n<\/ul>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb<\/em> Keep in mind that <code>name.txt<\/code> and <code>subtitle.txt<\/code> have a thirty (30) character limit each.<\/p>\n<p>Let&#8217;s update the required fastlane files:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/metadata\/en-US\/copyright.txt<\/span>\n\nPhrase inc @ <span class=\"hljs-number\">2023<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/metadata\/en-US\/primary_category.txt<\/span>\n\nLIFESTYLE<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/metadata\/en-US\/review_information\/email_address.txt<\/span>\n\nmyemail@gmail.com<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/metadata\/en-US\/review_information\/frist_name.txt<\/span>\n\nJohn<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/metadata\/en-US\/review_information\/last_name.txt<\/span>\n\nDoe<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/metadata\/en-US\/review_information\/phone_number.txt<\/span>\n\n+<span class=\"hljs-number\">233000000000<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/metadata\/en-US\/name.txt<\/span>\n\nMotivate Me<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/metadata\/en-US\/subtitle.txt<\/span>\n\nFor your daily dose of motivation<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_16cc97ed0079ba81a89dfecc5618b34d\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>\ud83d\uddd2\ufe0f <em>Note \u00bb <\/em>The initial files generated are based on the default language of our App Store listing, which is en-US in this case.<\/p>\n<p>With the required metadata entered, let\u2019s run the <code>deliver<\/code> command to upload this data to our App Store page:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">% fastlane deliver<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_cce8111389dc60bc67dd748293ee88ea\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>This should use the info in <code>fastlane\/metadata<\/code> to update our App Store listing.<\/p>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb <\/em>The command has other important features that we won\u2019t cover in the scope of this tutorial. Check out the <a href=\"https:\/\/docs.fastlane.tools\/actions\/deliver\/\">documentation<\/a> to learn everything <code>fastlane deliver<\/code> has to offer.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"adding-other-locales\"><\/span>Adding other locales<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>There are 2 main ways to add locales when working with fastlane. We can duplicate the metadata folder of our base language, e.g. <code>en-US<\/code>, and rename it to the locale we want to support, e.g. <code>fr-FR<\/code> for French &#8211; France. After that, we can enter French translations in the new <code>fr-FR<\/code> folder. The next time we run <code>fastlane deliver<\/code>, fastlane will automatically add the locale to our supported locales in our App Store listing.<\/p>\n<p>Alternatively, we can add another locale in App Store Connect and run the <code>fastlane deliver download_metadata<\/code> command. This will create all the metadata in our local project for all supported locales. We can then edit the localized files and run <code>fastlane deliver<\/code> to upload our changes.<\/p>\n<p>An example of localizing subtitles for English and French would be:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\"># fastlane\/metadata\/en-US\/subtitle.txt\n\nFor your daily dose of motivation<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\"># fastlane\/metadata\/fr-FR\/subtitle.txt\n\nMotivation au quotidien<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_a6424d2fcaa8745db64c7bae308e2cea\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<h2><span class=\"ez-toc-section\" id=\"automating-screenshot-localization\"><\/span>Automating screenshot localization<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Manually taking screenshots and uploading them individually for all locales can be a pain. Fastlane has a screenshot automation tool called <em><a href=\"https:\/\/docs.fastlane.tools\/actions\/snapshot\/\">snapshot<\/a><\/em> to make this a lot easier. Screenshots are generated by integrating fastlane into the automated UI tests of our project. It takes a few steps to set up, but once it&#8217;s done, it&#8217;s smooth sailing.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"setting-up-ui-tests\"><\/span>Setting up UI tests<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The backbone of automating screenshots is using UI Tests. You can skip this section if you already have UI Tests set up for your project. Fastlane will take snapshots of our UI tests and use that as screenshots of your App Store listing. We will create a UI Test target that will be used to run our UI tests.<\/p>\n<p>The first step is to create a UI Test Target. Click <em>File<\/em> \u279e <em>New<\/em> \u279e <em>Target.<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53040 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/create-target.png\" alt=\"Create target | Phrase\" width=\"678\" height=\"689\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/create-target.png 678w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/create-target-295x300.png 295w\" sizes=\"(max-width: 678px) 100vw, 678px\" \/><\/p>\n<p>In the Template sheet that appears, search <em><span class=\"notion-enable-hover\" data-token-index=\"1\">&#8220;UI Test&#8221;<\/span><\/em> \u279e Select <em><span class=\"notion-enable-hover\" data-token-index=\"3\">UI Testing Bundle<\/span><\/em> \u279e Click the <em><span class=\"notion-enable-hover\" data-token-index=\"5\">Next<\/span><\/em> button.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53046 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/ui-testing-bundle.png\" alt=\"UI testing bundle | Phrase\" width=\"733\" height=\"523\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/ui-testing-bundle.png 733w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/ui-testing-bundle-300x214.png 300w\" sizes=\"(max-width: 733px) 100vw, 733px\" \/><\/p>\n<p>On the Create Target sheet that appears make any edits if necessary and click the <em><span class=\"notion-enable-hover\" data-token-index=\"1\">Finish<\/span><\/em> button.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53052 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/create-target-sheet.png\" alt=\"Create target sheet | Phrase\" width=\"730\" height=\"523\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/create-target-sheet.png 730w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/create-target-sheet-300x215.png 300w\" sizes=\"(max-width: 730px) 100vw, 730px\" \/><\/p>\n<p>If all went well, Xcode will create a folder with two files using the <em><span class=\"notion-enable-hover\" data-token-index=\"1\">Product Name<\/span><\/em> from the <em><span class=\"notion-enable-hover\" data-token-index=\"3\">Create Target<\/span><\/em> sheet.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53058 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/target-files.png\" alt=\"Target files | Phrase\" width=\"271\" height=\"81\" \/><\/p>\n<p>Next, we will verify that our target is ready to run our tests. For our target to be able to run UI Tests, it has to be present in the Test scheme. Click <em><span class=\"notion-enable-hover\" data-token-index=\"1\">Product<\/span><\/em> \u279e <em><span class=\"notion-enable-hover\" data-token-index=\"3\">Scheme<\/span><\/em> \u279e <span class=\"notion-enable-hover\" data-token-index=\"5\"><em>Edit Scheme<\/em>.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53064 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/edit-scheme.jpg\" alt=\"Edit scheme | Phrase\" width=\"571\" height=\"606\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/edit-scheme.jpg 571w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/edit-scheme-283x300.jpg 283w\" sizes=\"(max-width: 571px) 100vw, 571px\" \/><\/p>\n<p>Select <em><span class=\"notion-enable-hover\" data-token-index=\"1\">Test<\/span><\/em> on the left panel. This will show relevant information related to testing. The target we created should be shown and should be <em><span class=\"notion-enable-hover\" data-token-index=\"3\">checked <\/span><\/em><span role=\"img\" aria-label=\"\u2611\ufe0f\">\u2611\ufe0f<\/span>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53070 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/test-scheme.png\" alt=\"Test scheme | Phrase\" width=\"936\" height=\"507\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/test-scheme.png 936w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/test-scheme-300x163.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/test-scheme-768x416.png 768w\" sizes=\"(max-width: 936px) 100vw, 936px\" \/><\/p>\n<p>All set! Now we can confidently run our UI tests. In the newly created folder with our UI Tests, select the one that ends in <code>UITests<\/code>, in our case <code>Motivate_MeUITests<\/code>.<\/p>\n<p>To run the UI Test, click the <em>Run<\/em> icon next to a function, or a class to run all its test functions. After a successful test, a green c<em>heckmark<\/em> \u2705 will appear next to each passed test.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53076 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/run-ui-test.png\" alt=\"Run UI test | Phrase\" width=\"784\" height=\"609\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/run-ui-test.png 784w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/run-ui-test-300x233.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/run-ui-test-768x597.png 768w\" sizes=\"(max-width: 784px) 100vw, 784px\" \/><\/p>\n<h3><span class=\"ez-toc-section\" id=\"setting-up-snapshot\"><\/span>Setting up snapshot<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>With our UI tests properly set up, we can introduce fastlane&#8217;s <a href=\"https:\/\/docs.fastlane.tools\/actions\/snapshot\/\">snapshot<\/a> to help us with generating localized screenshots.<\/p>\n<p>Run <code>fastlane snapshot init<\/code> in your project folder. This command will create 2 files under the <code>.fastlane<\/code> folder, <code>Snapfile<\/code> and <code>SnapshotHelper.swift<\/code>. The <code>Snapfile<\/code> configures configuration snapshot. <code>SnapshotHelper<\/code> has functions needed for fastlane to capture screenshots during testing.<\/p>\n<p>Now you need to add the newly created <code>SnapshotHelper.swift<\/code> to your UI Test target. Click on the UI Test Target folder, in our case <em>Motivate MeUITests<\/em> \u279e Click <em>Add files to &#8220;Project Name..&#8221;.<\/em> On the sheet that appears, locate the <code>SnapshotHelper.swift<\/code> and select it. Check <em>UI Test target<\/em> if it&#8217;s not checked \u279e click <em>Add<\/em>. The <code>SnapshotHelper.swift<\/code> should be visible in your <em>UI Test Target<\/em> folder.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53084 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/add-snapshot-helper.png\" alt=\"Add snapshot helper | Phrase\" width=\"436\" height=\"541\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/add-snapshot-helper.png 436w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/add-snapshot-helper-242x300.png 242w\" sizes=\"(max-width: 436px) 100vw, 436px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53090 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/add-snapshot-sheet.png\" alt=\"Add snapshot sheet | Phrase\" width=\"803\" height=\"588\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/add-snapshot-sheet.png 803w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/add-snapshot-sheet-300x220.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/add-snapshot-sheet-768x562.png 768w\" sizes=\"(max-width: 803px) 100vw, 803px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53096 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/snapshot-helper-added.png\" alt=\"Snapshot helper added | Phrase\" width=\"262\" height=\"95\" \/><\/p>\n<p><em><span class=\"notion-enable-hover\" data-token-index=\"0\"><span role=\"img\" aria-label=\"\ud83d\uddd2\ufe0f\">\ud83d\uddd2\ufe0f<\/span> Note \u00bb <\/span><\/em><span class=\"notion-enable-hover\" data-token-index=\"0\">(Objective C only) Add the bridging header to your test class. The bridging header is named after your test target with <\/span><code><span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">-Swift.h<\/span><\/code><span class=\"notion-enable-hover\" data-token-index=\"2\"> appended.<\/span><\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Objective-C\" data-shcb-language-slug=\"objectivec\"><span><code class=\"hljs language-objectivec\"><span class=\"hljs-comment\">\/\/ Motivate_MeUITests-Swift.h<\/span>\n\nimport <span class=\"hljs-string\">\"MYUITests-Swift.h\"<\/span>\n\n<span class=\"hljs-comment\">\/\/ Rest of test<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Objective-C<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">objectivec<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_47e6e4d6d9e32d43147cbe6c0108f521\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>The most important function for capturing screenshots for fastlane is <code>snapshot(IndexNameOfScreen)<\/code>. It&#8217;s what tells fastlane to take a screenshot of the current state of our UI test. Here are the signatures for Swift and Objective C:<\/p>\n<ul>\n<li>Swift: <code>snapshot(\"01YourScreen\")<\/code><\/li>\n<li>Objective C: <code>[Snapshot snapshot:@\"01YourScreen\" timeWaitingForIdle:10];<\/code><\/li>\n<\/ul>\n<p>Let\u2019s update our test to make use of snapshot. In the code below we take a snapshot every time a button is pressed and this tells fastlane when to capture a screenshot.<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Swift\" data-shcb-language-slug=\"swift\"><span><code class=\"hljs language-swift\"><span class=\"hljs-comment\">\/\/  Motivate_MeUITests.swift<\/span>\n\n<span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Motivate_MeUITests<\/span>: <span class=\"hljs-title\">XCTestCase<\/span> <\/span>{\n\n <span class=\"hljs-keyword\">var<\/span> app: <span class=\"hljs-type\">XCUIApplication!<\/span>\n\n <span class=\"hljs-keyword\">override<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">setUpWithError<\/span><span class=\"hljs-params\">()<\/span><\/span> <span class=\"hljs-keyword\">throws<\/span> {\n     <span class=\"hljs-comment\">\/\/ UI tests must launch the application that they test.<\/span>\n    app = <span class=\"hljs-type\">XCUIApplication<\/span>()\n\n    <span class=\"hljs-comment\">\/\/ Important for fastlane to capture test results.<\/span>\n    <span class=\"hljs-comment\">\/\/ Without this line fastlane won't work<\/span>\n    setupSnapshot(app) \n\n    app.launch()\n }\n\n <span class=\"hljs-comment\">\/\/ Put teardown code here. This method is called after<\/span>\n <span class=\"hljs-comment\">\/\/ the invocation of each test method in the class.<\/span>\n <span class=\"hljs-keyword\">override<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">tearDownWithError<\/span><span class=\"hljs-params\">()<\/span><\/span> <span class=\"hljs-keyword\">throws<\/span> {\n \n }\n\n <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">testGenerateRandomQuote<\/span><span class=\"hljs-params\">()<\/span><\/span> <span class=\"hljs-keyword\">throws<\/span> {\n    <span class=\"hljs-keyword\">let<\/span> randomQuoteButton = app.buttons.element(boundBy: <span class=\"hljs-number\">0<\/span>)\n    snapshot(<span class=\"hljs-string\">\"01-Quote\"<\/span>)\n\n    randomQuoteButton.tap()\n    snapshot(<span class=\"hljs-string\">\"02-Quote\"<\/span>)\n\n    randomQuoteButton.tap()\n    snapshot(<span class=\"hljs-string\">\"03-Quote\"<\/span>)\n\n    randomQuoteButton.tap()\n    snapshot(<span class=\"hljs-string\">\"04-Quote\"<\/span>)\n\n    randomQuoteButton.tap()\n    snapshot(<span class=\"hljs-string\">\"05-Quote\"<\/span>)\n }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Swift<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">swift<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_917c846a1aa5a02a9d44ba77a3e7cf8e\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>\ud83d\uddd2\ufe0f <em>Note \u00bb<\/em> <code>snapshot(IndexNameOfScreen)<\/code> is the recommended naming convention to follow; it makes it easy to identify screenshots.<\/p>\n<p>Click the <em>Run<\/em> icon next to the test function(i.e <code>testGenerateRandomQuote()<\/code> in our case), or the <em>Run<\/em> icon next to the class(i.e <code>Motivate_MeUITests<\/code> in our case) to run all its test functions. After a successful test, a green c<em>heckmark<\/em> \u2705 will appear next to each passed test.<\/p>\n<p>Remember our Motivate Me application? This is what we\u2019ll be using to demonstrate screenshot automation.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53102 size-medium\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/motivate-me-146x300.jpg\" alt=\"Motivate me | Phrase\" width=\"146\" height=\"300\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/motivate-me-146x300.jpg 146w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/motivate-me-500x1024.jpg 500w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/motivate-me-768x1573.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/motivate-me-750x1536.jpg 750w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/motivate-me.jpg 868w\" sizes=\"(max-width: 146px) 100vw, 146px\" \/><\/p>\n<h3><span class=\"ez-toc-section\" id=\"generating-screenshots\"><\/span>Generating screenshots<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In our fastlane folder, we should notice there has been an additional file added.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53108 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/snapfile-1024x345.png\" alt=\"Snapfile | Phrase\" width=\"1024\" height=\"345\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/snapfile-1024x345.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/snapfile-300x101.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/snapfile-768x259.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/snapfile.png 1134w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb <\/em>If you don&#8217;t see this file, run <code>fastlane snapshot init<\/code>.<\/p>\n<p>The <code>Snapfile<\/code> has configuration details for snapshot capturing. Here is the sample <code>Snapfile<\/code> for our test application:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/Snapfile<\/span>\n\ndevices(&#91;\n <span class=\"hljs-string\">\"iPhone 13 Pro\"<\/span>,\n <span class=\"hljs-string\">\"iPhone 13 Pro Max\"<\/span>,\n <span class=\"hljs-string\">\"iPhone 8 Plus\"<\/span>,\n <span class=\"hljs-string\">\"iPhone SE (3rd generation)\"<\/span>,\n <span class=\"hljs-string\">\"iPad Pro (12.9-inch) (6th generation)\"<\/span>,\n <span class=\"hljs-string\">\"iPad Pro (11-inch) (4th generation)\"<\/span>\n])\n\nlanguages(&#91;\n <span class=\"hljs-string\">\"en-US\"<\/span>,\n <span class=\"hljs-string\">\"fr-FR\"<\/span>,\n])\n\nscheme(<span class=\"hljs-string\">\"Your Test Scheme\"<\/span>)\n\noutput_directory(<span class=\"hljs-string\">\".\/fastlane\/screenshots\"<\/span>)\n\nclear_previous_screenshots(<span class=\"hljs-literal\">true<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_9d132486674c23c5cc8fdee2d0df2633\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>The most important things here are the devices to generate the screenshots on, the locales supported, and the scheme used to run the tests. Devices are particularly important because the generated images should match Apple&#8217;s resolution guidelines. You can use this <a href=\"https:\/\/appradar.com\/blog\/ios-app-screenshot-sizes-and-guidelines-for-the-apple-app-store\">guideline<\/a> to help you choose.<\/p>\n<p>\ud83d\uddd2\ufe0f <em>Note \u00bb <\/em>There&#8217;s a lot more fastlane can do with screenshots, such as framing them. Visit <a href=\"https:\/\/docs.fastlane.tools\/actions\/snapshot\/\">fastlane&#8217;s documentation on snapshot<\/a> to learn more.<\/p>\n<p>Run this command to generate snapshots:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">fastlane snapshot<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_16258e1132c035b406e17d0f9982e27c\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>You&#8217;ll have to wait for a while for fastlane to do its magic. After everything is successful, fastlane will open a report of all the generated screenshots. You should also see a screenshots folder at the location specified in your <code><span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">Snapfile<\/span><\/code>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53114 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-snap-cli-1024x475.png\" alt=\"Fastlane snap CLI | Phrase\" width=\"1024\" height=\"475\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-snap-cli-1024x475.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-snap-cli-300x139.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-snap-cli-768x356.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-snap-cli.png 1332w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53120 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/generated-snapshots-1024x591.jpg\" alt=\"Generated snapshots scaled | Phrase\" width=\"1024\" height=\"591\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/generated-snapshots-1024x591.jpg 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/generated-snapshots-300x173.jpg 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/generated-snapshots-768x444.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/generated-snapshots-1536x887.jpg 1536w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/generated-snapshots-2048x1183.jpg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"deploying-to-the-app-store\"><\/span>Deploying to the App Store<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Now that we have all we need to fully localize our App Store, it&#8217;s time to deploy our changes.<\/p>\n<p>In our <code>Fastfile<\/code>, we should add the action to capture and upload our generated screenshots in our lane.<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-comment\"># fastlane\/Fastfile<\/span>\n\nplatform <span class=\"hljs-symbol\">:ios<\/span> <span class=\"hljs-keyword\">do<\/span>\n    desc <span class=\"hljs-string\">\"Description of what the lane does\"<\/span>\n    lane <span class=\"hljs-symbol\">:custom_lane<\/span> <span class=\"hljs-keyword\">do<\/span>\n        capture_screenshots\n        upload_to_app_store\n     <span class=\"hljs-keyword\">end<\/span>\n<span class=\"hljs-keyword\">end<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_7ecefaf621724eb204e59b932103a1e8\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>Run the deliver command to upload your screenshots and App Store details.<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">fastlane deliver<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_4729b287228796121b45fff8f574fa0f\" class=\"pxblock pxblock--text alignfull spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53128 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-deliver-1024x464.png\" alt=\"Fastlane deliver | Phrase\" width=\"1024\" height=\"464\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-deliver-1024x464.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-deliver-300x136.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-deliver-768x348.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-deliver-1536x696.png 1536w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/fastlane-deliver.png 1846w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>After completion, you should see a screen similar to this. Fastlane does a good job of pointing out errors in case you have any.<\/p>\n<p>And if you visit App Store Connect, you should see the screenshots fastlane uploaded.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-53134 size-large\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/final-upload-1024x785.jpg\" alt=\"Final upload | Phrase\" width=\"1024\" height=\"785\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/final-upload-1024x785.jpg 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/final-upload-300x230.jpg 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/final-upload-768x588.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/final-upload-1536x1177.jpg 1536w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/05\/final-upload-2048x1569.jpg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>\ud83d\udd17 <em>Resource \u00bb\u00a0 <code>fastlane deliver<\/code> updates your App Store details so you can submit them for review if everything looks right. Fastlane can also deploy to your application and even submit it for review. Read all about <a href=\"https:\/\/docs.fastlane.tools\/getting-started\/ios\/appstore-deployment\/\">fastlane deployment in the official documentation<\/a>.<\/em><\/p>\n<h2><span class=\"ez-toc-section\" id=\"well-done\"><\/span>Well done!<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>We hope that this tutorial has shown you that localizing your App Store page is not too hard, and for all super-optimizers, we hope our coverage of fastlane has shown you a good way to automate the process. With a localized App Store page, you can <a href=\"https:\/\/phrase.com\/blog\/posts\/increase-app-downloads\/\">increase app downloads<\/a>\u2014resulting in greater revenue.<\/p>\n<p>To make the most of it, consider streamlining your app translation process with a specialized software localization tool such as <a href=\"https:\/\/phrase.com\/platform\/strings\/\">Phrase Strings<\/a>. Designed to automate manual and repetitive tasks, it can help you efficiently manage translation strings for your mobile app and continually release updated translations over the air.<\/p>\n<p>With a strong API and native integrations with GitHub, GitLab, Bitbucket, and other tools, Phrase Strings provides a comprehensive strings editor that enables translators to access all the content you&#8217;ve pushed for translation from one location. Once the translation is complete, you can effortlessly retrieve the translated content and incorporate it back into your project.<\/p>\n<p>As your software product grows, you can seamlessly connect Phrase Strings with a cutting-edge translation management system (TMS) to unlock the full power of traditional CAT tools and machine translation capabilities.<\/p>\n<p>Check out all\u00a0<a href=\"https:\/\/phrase.com\/roles\/developers\/\">Phrase features for developers<\/a> and see for yourself how they can streamline your software localization workflows from day one.<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n\n<div id=\"acf\/blog-cta-block_48379acaed8c0fe80a836949eba31461\" class=\"pxblock pxblock--blog-cta bg--green image--orientation-landscape\">\n\t<div class=\"block-container\">\n\t\t\t\t\t<div class=\"image image--align-middle\">\n\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1260\" height=\"992\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero.png\" class=\"attachment-original size-original\" alt=\"String Management UI visual | Phrase\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero.png 1260w, https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero-300x236.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero-1024x806.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero-768x605.png 768w\" sizes=\"(max-width: 1260px) 100vw, 1260px\" \/>\t\t\t<\/div>\n\t\t\t\t<div class=\"content\">\n\t\t\t<p class=\"subhead\">Phrase Strings<\/p>\n<p class=\"secondary h6\">Take your web or mobile app global without any hassle<\/p>\n<div class=\"text--copy\">\n<p class=\"small\">Adapt your software, website, or video game for global audiences with the leanest and most realiable software localization platform.<\/p>\n<p><a class=\"btn btn--outline\" href=\"https:\/\/phrase.com\/platform\/strings\/\">Explore Phrase Strings<\/a><\/p>\n<\/div>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Optimize your iOS app&#8217;s appeal by implementing App Store localization strategies to rank higher, increase downloads, and reach a wider audience.<\/p>\n","protected":false},"author":61,"featured_media":53156,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_stopmodifiedupdate":true,"_modified_date":"","_searchwp_excluded":"","footnotes":""},"categories":[40],"class_list":["post-8674","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-localization"],"acf":[],"_links":{"self":[{"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/posts\/8674"}],"collection":[{"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/users\/61"}],"replies":[{"embeddable":true,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/comments?post=8674"}],"version-history":[{"count":10,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/posts\/8674\/revisions"}],"predecessor-version":[{"id":93904,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/posts\/8674\/revisions\/93904"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/media\/53156"}],"wp:attachment":[{"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/media?parent=8674"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/categories?post=8674"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}