SwiftUI Tutorial on Localization

SwiftUI本地化教程

2021-02-17 01:50 Lingua Greca

本文共2556个字,阅读需26分钟

阅读模式 切换至中文

At the WWDC 2019, Apple surprised the developer community by introducing SwiftUI, a modern, declarative API for building user interfaces for all Apple platforms. Ever since, the tech giant from Cupertino has continuously improved the framework, making it a compelling solution for building out production apps. In light of this popularity, the following SwiftUI tutorial seeks to outline the key steps in localizing iOS apps built with SwiftUI. To keep things straightforward, we will be building a simple application along the way. At the time of writing, we are using the Xcode 12.3. Make sure you use the latest version when referring to this tutorial. Basic Setup Localizing UI Strings Localizing Interpolated Strings in SwiftUI Handling Plurals in SwiftUI Localization Adding Translations Testing Localization Exporting Localizations Importing Localizations Calling It a Day! Basic Setup To get the ball rolling, open Xcode and create a new iOS project. We will call ours ‘SwiftUILocalization’. This is just a simple application that will help us get a better understanding of how to approach localization in SwiftUI. Our app’s base language will be English while supporting French and Chinese at the same time. Once you have created the project, from the project navigator, select the project name, and click on the Info tab. Under Localizations, click the plus symbol to add the languages and regions you want to support, in our case, Simplified Chinese and French. In the sheet that comes next, select the resource file you want to localize – LaunchScreen.storyboard in our case – and click Finish. This is a basic setup that applies to localizing iOS apps built with UIKit as well. Localization in SwiftUI works automatically, out of the box. Quite amazing, right? This is possible because most SwiftUI views and view modifiers take up LocalizedStringKey struct as an argument. More on this later on. Let us move on to create a string file called ‘Localizable’ that will hold the text we want to localize. Choose File → New → File …, select Strings File under Resources, and click Next. Name it Localizable, then click on Create. Localizing UI Strings In ContentView.swift, we have a text view whose string would need to be localized eventually. The ‘Hello, World!’ string inside the text view is the key that would be used to look up the translated version of the text in the Localizable.strings file. Usually, if the LocalizedStringKey API did not find any matching text for the key, it would display the key in the text view for an app that supports localization. This comes as a result of LocalizedStringKey struct conforming to the ExpressibleByStringInterpolation protocol, which in turn inherits from the ExpressibleByStringLiteral protocol. This allows you to use a string literal, like ‘Hello, World!’, in a text view, that is turned into an instance of LocalizedStringKey struct automatically. Basically, you can either use Text("Hello, World!") or Text(LocalizedStringKey("Hello, World!")) and you will still achieve the same result. Note that if you initialize the text view with a string literal, it will use the init(_:tableName:bundle:comment:) initializer, which interprets the string as the key and uses it to search the table you provide for a matching pair. It would use the default table Localizable.strings if you provided none. However, if you initialized the text view with a variable name, the view would use the init(_:) initializer, which does not localize the string. You can specify the table name for the localization file, the bundle containing the string file (it would use the main bundle if you did not provide one), and the comment containing the contextual information about the key-value pair for your localizers in the text view initialization above. If your app is pretty large, with many chunks of content for localization, you can decide to split it into different .strings files, and indicate the file name as the table name. In the Localizable.strings file (English), add the following: In your text view, use the newly added key to initialize the view, run the app, and you will get ‘Hello, World!’ displayed on the screen. Do not forget to add the semicolon at the end of your key-value pair in your .strings file, otherwise, Xcode will trigger a build error with invalid input. Your ContentView.swift file should look like this so far: Localizing Interpolated Strings in SwiftUI SwiftUI supports string interpolation out of the box since LocalizedStringKey conforms to the ExpressibleByStringInterpolation protocol that allows us to inject dynamic data into our string value. Here is an example for a better understanding. Let’s say we want to display something like ‘My name is John’ in the text view, where the name is dynamic, perhaps returned from an API call to the backend. However, in our example, we will just have a variable name of String type. Add the following to your Localizable.strings (English) file. In the ContentView.swift file, introduce a new variable name for the type string var name = "John". Your ContentView.swift file will then look as follows: When you run the app, you should see ‘My name is John’ displayed on the screen. Now, let us experiment a little bit. Assign an integer value of six to the name variable, and try to run the app again. What do you notice? The key is displayed on the screen. The reason for this is because %@ is a specifier for an object (which includes strings). We will have to use a different specifier for int to get it working as it should be. In your Localizable.strings file, change the specifier to for title-name from %@ to %lld so that the line looks like as follows: Try running the app again, and everything will look good again. To learn more about String formatters, kindly check out format specifiers. Handling Plurals in SwiftUI Localization In order to create a plural variant of the localizable strings you pass to LocalizedStringKey, you need to add a stringsdict file to your project. Adding plural variants comes in handy when you want to render something like ‘one apple’ in your view when you have only one apple and ‘ten apples’ when you have ten of those. Let us add a stringsdict file to our project. Choose File → New → File … and make sure you are in the right target operating system (iOS in this case). Select Stringsdict File under Resources and click Next. In the sheet that appears, type in Plurals as the file name and click Create. Now, let us edit the file we just added. Localized String Key is the key that we will be passing to the LocalizedStringKey struct. Change this to fruit-count %lld. Change the NSStringLocalizedFormatKey value %#@VARIABLE@ to %#@apple@, and change the VARIABLE dictionary below to ‘apple’. Expand the ‘apple’ dictionary and add lld string formatter as the value to the NSStringFormatValueTypeKey. This string format specifier will vary depending on the type of data you are dealing with. In our case, we are handling Int, that is why we use lld. We now have to define our plural variants by entering our formatted strings in the ‘zero’ to ‘other’ categories we have. We are only concerned with two cases, ‘one’ and ‘other’. For ‘one’, add the value %lld apple, and for ‘other’, add the value %lld apples. Go ahead and remove the other categories you are not using. If you have done everything correctly, your modified file should look as shown below. Let us test to see if everything works as expected. However, before we do that, we will be introducing the use of VStack in our view body to help us render two text views. Introduce a new variable appleCount of type Int. Inside the VStack closure, add another text view i.e Text("fruit-count \(appleCount)"). Your code structure should now look as follows: Try testing the app. It seems that it does not work as expected, what could have been the cause? Well, the reason why we had fruit-count 2, which is our key displayed in the second text view, is that we named our stringsdict file ‘Plurals’. The default lookup table name is usually ‘Localizable.stringsdict’. If we had named our stringsdict file ‘Localizable.stringsdict,’ everything would have worked as expected. To get it working, we have to specify the Plurals as the tableName without the extension part in our second text view initialization, i.e. Text("fruit-count \(appleCount)", tableName: "Plurals") Test again, and everything will work fine. Great work so far! Let us move forward and add a twist to it. Suppose you wanted to display other types of fruit, like orange and mangos, i.e. display something like ‘2 apples,’ ‘1 mango,’ or ‘3 oranges’. Open the Plurals.stringsdict file, and change NSStringLocalizedFormatKey to %#@apple@, %#@mango@ and, %#@orange@, the way we want it rendered (‘2 apples,’ ‘1 mango,’ and ‘3 oranges’). Duplicate the ‘apple’ variant into ‘mango’ and ‘orange,’ and make the necessary changes. And since we will be passing in three variables in our string interpolation in our text view, we need to add two more %lld string format specifiers to our Localized String Key, i.e. fruit-count %lld %lld %lld. The newly modified file should look like this: All good to go. Inside our code, we need to introduce two more variables to keep the count of mango and orange. Update your code to the one below. Test out your code once again, and everything should work as expected. It has been quite a learning journey so far, you are doing really great having gotten here! For more information on adding plural variants to your localization, check out this Xcode Help doc. Adding Translations We now have our app fully prepared for localization. Click on the Localizable.strings file that we created at the very beginning. From the file inspector, choose Localize. A pop-up would ask you if you want to localize the file with the base language English. Click on Localize. You also have to check the boxes for the other languages, Chinese and French. Once done, you will have three files under the Localizable.strings folder for the base language English, as well as for Chinese and French. Do the same thing for the Plurals.stringsdict file. For localizing the text content, you should handle the process very carefully because if app localization is done wrongly, it will defeat its purpose. You simply do not want to end up losing users who might feel offended by the content of your app in their native language. That is why we will not be providing translation to the localizable strings in this article. For learning purposes, you can go ahead, and translate the content yourself, but in real life, this is where you should rely on professional translators. You can use Google Translate or any other machine translation service to translate the texts into Chinese and French, respectively. You only need to change the value and not the key while providing the localized texts for Chinese and French. For example, in your Localizable.strings file, you only need to translate My name is in "title-name %@" = "My name is %@"; to Chinese and French in the Localizable.strings(Chinese, Specified) and Localizable.strings(French)files respectively. You also have to do the same for the Plurals.stringsdict file. You will only have to translate apple, mango, and orange to Chinese and French in your Plurals.stringsdict(Chinese, Specified) and Plurals.stringsdict(French) files respectively. At this point, you have fully localized your application. Cheers to the good work so far! Testing Localization SwiftUI is so powerful that you can, actually, preview your app localization on the fly, without having to run it on a simulator or physical device, which definitely helps to cut your development time. This is particularly helpful when you have many languages and regions you need to support and want to get a feel for their look on the UI. For this purpose, Apple introduced environment variables – one of them dedicated to languages and regions. Let us try to use this environment variable for languages and regions in the preview. Add .environment(\.locale, .init(identifier: "zh-Hans")) where zh-Hans is the locale identifier for Chinese, specified to the ContentView instance. Click on the Resume button on the canvas to refresh the canvas if no change is reflected after adding the environment variable. The good thing is that you can test for both the Chinese and French at the same time from the preview. All you need to do is to use Group in SwiftUI to group your views. Create a new instance of ContentView and add an environment variable with the ‘fr’ identifier. Your ContentView_Previews struct will then look as follows: You can now test out for Chinese and French in the preview simultaneously. Quite impressive, right? Note that changing this language identifier in your environment variable will only be reflected in the preview in the canvas. However, if you want to test if your localization is working well in a simulator or real device, then follow the steps below. Select Edit Scheme → Run → Options and change the Application Language to any language you want to test for. You can also select the app region. After you edit your settings, run the app again. Exporting Localizations The next step is to export localizations by selecting the languages you want to support, and send them off to your localizers. Follow the steps below. In the Project navigator, choose the project, then Editor → Export for Localization. In the dialog box, enter a folder name, select a location where you want it exported, and uncheck English because we do not want to translate that, and finally, click Export. Xcode creates an Xcode Localization Catalog folder (with .xcloc extension) for each of the languages. Each of these folders contains the resources and assets you marked localizable. You can then send the catalog folder to your localizers to start work immediately. The .xcloc folder contains the .xliff (standard XML Localization Interchange File Format ) file with the extracted strings that our localizers can start translating. Importing Localizations Once your localizers are done with localizing the contents in your catalog folder, they will send it back to you, and all you need to do is import it back to your project. Xcode handles everything for you. In the Project navigator, choose the project, then choose Editor → Import Localizations. If you have more than one .xcloc folder and they are contained in one folder for all the languages, select the folder, and then import the individual .xcloc folders back to your project. Once imported, your app is fully localized. Calling It a Day! Well done! If you have gotten this far, you have done an amazing job, following all the steps of our SwiftUI tutorial on localization. Now that you have your app ready for localization, you can let Phrase do the heavy lifting. Sing up for a 14-day trial, and if you have any questions along the way, leave a message or comment anytime below! For more information on iOS app localization, kindly refer to the following articles: How to Make the Most of Your Mobile App Localization Automate iOS Storyboard Localization Advanced iOS OTA Translations with Phrase iOS iOS app localization (iOS app l10n) iOS internationalization (iOS i18n) iOS localization (ios l10n)
在2019年的WWDC上,苹果推出了SwiftUI,这是一个现代化的声明性API,用于为所有苹果平台构建用户界面,这让开发者社区感到惊讶。从那以后,这家来自库比蒂诺的科技巨头不断改进这个框架,使之成为构建生产应用程序的一个引人注目的解决方案。 鉴于这种流行,下面的SwiftUI教程试图概述使用SwiftUI构建的iOS应用程序本地化的关键步骤。为了使事情简单明了,我们将在此过程中构建一个简单的应用程序。在撰写本文时,我们使用的是Xcode12.3。请确保在参考本教程时使用最新版本。 基本设置 正在本地化UI字符串 SwiftUI中内插字符串的本地化 SwiftUI本地化中复数的处理 正在添加翻译 测试定位 正在导出本地化 正在导入本地化 今天到此为止! 基本设置 要开始工作,请打开Xcode并创建一个新的iOS项目。我们将把我们称为‘快速本地化’。这只是一个简单的应用程序,它将帮助我们更好地理解如何在SwiftUI中实现本地化。我们的应用程序的基本语言将是英语,同时支持法语和中文。 创建项目后,从project navigator中选择项目名称,然后单击Info选项卡。在“本地化”下,单击加号以添加要支持的语言和地区,在本例中为简体中文和法语。 在接下来的工作表中,选择要本地化的资源文件--在我们的示例中是launchscreen.storyboard--然后单击Finish。这是一个基本的设置,也适用于本地化使用UIKit构建的iOS应用程序。 SwiftUI的本地化自动工作,开箱即用。相当惊人,对吧?这是可能的,因为大多数SwiftUI视图和视图修饰符采用LocalizedStringKey结构作为参数。稍后会有更多关于这方面的内容。 让我们继续创建一个名为'Localizable'的字符串文件,它将保存我们想要本地化的文本。选择File New File…,在Resources下选择Strings File,然后单击Next。将其命名为Localizable,然后单击Create。 正在本地化UI字符串 在ContentView.swift中,我们有一个文本视图,其字符串最终需要本地化。 文本视图中的“Hello,World!”字符串是用于查找localizable.strings文件中文本的翻译版本的键。通常,如果LocalizedStringKey API没有找到键的任何匹配文本,它将在支持本地化的应用程序的文本视图中显示键。 这是由于LocalizedStringKey结构符合ExpressibleByStringInterpolation协议,后者又继承自ExpressibleByStringLiteral协议。这允许您在文本视图中使用字符串文本,如'Hello,World!‘,该文本视图将自动转换为LocalizedStringKey结构的实例。基本上,您可以使用文本(“Hello,World!”) 或文本(LocalizedStringKey(“Hello,World!”)) 而且你还是会达到同样的结果。 请注意,如果您使用字符串文字初始化文本视图,它将使用init(_:tableName:bundle:comment:)初始值设定项,该初始值设定项将字符串解释为键,并使用它在您提供的表中搜索匹配对。如果您没有提供,它将使用默认表localizable.strings。但是,如果使用变量名初始化文本视图,则视图将使用init(_:)初始值设定项,该初始值设定项不会本地化字符串。 您可以指定本地化文件的表名,包含字符串文件的包(如果您没有提供主包,它将使用主包),以及包含与上述文本视图初始化中的本地化器的键-值对相关信息的注释。 如果您的应用程序非常大,有许多用于本地化的内容块,您可以决定将其拆分为不同的。strings文件,并将文件名指示为表名。在localizable.strings文件(英文)中,添加以下内容: 在你的文本视图中,使用新添加的键初始化视图,运行app,你会得到屏幕上显示的‘你好,世界!’。不要忘记在。strings文件中键-值对的末尾添加分号,否则,Xcode将触发无效输入的构建错误。 到目前为止,您的ContentView.swift文件应该如下所示: SwiftUI中内插字符串的本地化 SwiftUI支持开箱即用的字符串插值,因为LocalizedStringKey符合ExpressibleByStringInterpolation协议,该协议允许我们将动态数据注入到字符串值中。 下面是一个更好理解的例子。假设我们希望在文本视图中显示类似'My name is John'的内容,其中的名称是动态的,可能是从对后端的API调用返回的。然而,在我们的示例中,我们将只拥有一个字符串类型的变量名。将以下内容添加到Localizable.strings(英文)文件中。 在contentView.swift文件中,为类型字符串var name=“john”引入一个新的变量名。您的ContentView.swift文件将如下所示: 当你运行应用程序时,你应该会看到屏幕上显示‘我的名字是约翰’。现在,让我们做一点实验。给name变量分配一个整数值6,然后再次尝试运行应用程序。你注意到什么了?按键显示在屏幕上。这是因为%@是一个对象(其中包括字符串)的说明符。我们将不得不为int使用一个不同的说明符以使其正常工作。在Localizable.strings文件中,将title-name的说明符从%@更改为%lld,使该行看起来如下所示: 尝试再次运行应用程序,一切都将再次看起来良好。要了解更多关于字符串格式化程序的信息,请查看格式说明符。 SwiftUI本地化中复数的处理 为了创建传递给LocalizedStringKey的可本地化字符串的复数变体,需要向项目中添加一个stringsdict文件。当你想在视图中呈现“一个苹果”(当你只有一个苹果)和“十个苹果”(当你有十个苹果)时,添加复数变体会很有用。 让我们向项目中添加一个stringsdict文件。选择File New File…并确保您在正确的目标操作系统(本例中为iOS)。在Resources下选择Stringsdict File,然后单击Next。在显示的工作表中,键入复数作为文件名,然后单击“创建”。 现在,让我们编辑刚才添加的文件。LocalizedStringKey是我们将传递给LocalizedStringKey结构的键。将其更改为水果计数%lld。 将NSSringLocalizedFormatKey值%#@VARIABLE@更改为%#@apple@,并将下面的变量字典更改为“apple”。展开'apple'字典并将lld string FormatValueTypeKey作为值添加到NSSringFormatValueTypeKey中。此字符串格式说明符将根据您所处理的数据类型而有所不同。在我们的例子中,我们处理的是Int,这就是为什么我们使用lld。 我们现在必须通过在“零”到“其他”类别中输入格式化字符串来定义复数变体。我们只关注两个案例,“一个”和“另一个”。对于“one”,添加值%lld apple,对于“other”,添加值%lld apples。继续删除其他不使用的类别。如果您已经正确地完成了所有操作,那么您修改后的文件应该如下所示。 让我们测试一下,看看是否一切都按预期运行。然而,在此之前,我们将介绍在视图主体中使用VStack来帮助我们呈现两个文本视图。引入一个int类型的新变量appleCount。在VStack闭包中,添加另一个文本视图,即text(“fruit-count\(appleCount)”)。 您的代码结构现在应该如下所示: 尝试测试应用程序。看来它并不像预期的那样起作用,这可能是什么原因造成的呢?好吧,我们之所以有fruit-count 2(它是我们在第二个文本视图中显示的关键字),是因为我们将stringsdict文件命名为“plurals”。默认的查找表名称通常为“Localizable.StringsDict”。如果我们将我们的stringsdict文件命名为“Localizable.stringsdict”,那么一切都将按预期工作。为了使它正常工作,我们必须在第二个文本视图初始化中指定复数作为表名,而不使用扩展部分,即再次测试text(“fruit-count\(appleCount)”,tableName:“Plurals”),然后一切都将正常工作。 到目前为止工作很出色!让我们向前迈进,为它增添一丝曲折。假设您想要显示其他类型的水果,如橘子和芒果,即显示类似于“2个苹果”,“1个芒果”或“3个橘子”的内容。 打开Plurals.Stringsdict文件,并将NSSringLocalizedFormatKey更改为%#@Apple@,%#@mango@和%#@Orange,即我们希望它呈现的方式(“2个苹果”,“1个芒果”和“3个橙子”)。将“apple”的变体复制成“mango”和“orange”,并进行必要的更改。 由于我们将在文本视图中的字符串插值中传入三个变量,我们需要向本地化的字符串键添加两个%lld字符串格式说明符,即fruit-count%lld%lld%lld。 新修改的文件应该如下所示: 一切准备就绪。在我们的代码内部,我们需要再引入两个变量来保持mango和Orange的计数。请将您的代码更新为下面的代码。 再次测试您的代码,所有的事情都应该像预期的那样工作。到目前为止,这是一次相当的学习之旅,你在这里做得真的很棒!有关在本地化中添加多个变体的更多信息,请查看这个Xcode帮助文档。 正在添加翻译 我们现在已经为本地化做好了充分的准备。单击我们在最开始创建的localizable.strings文件。在“文件检查器”中,选择“本地化”。弹出窗口将询问您是否希望将文件本地化为基本语言英语。单击Localize。 您还必须勾选其他语言的复选框,中文和法文。完成后,在Localizable.strings文件夹下将有三个文件,分别用于基本语言英语,汉语和法语。对plurals.stringsdict文件执行相同的操作。 对于本地化文本内容,您应该非常小心地处理这个过程,因为如果应用程序本地化做得不对,就会破坏其目的。你只是不想失去那些可能会因为你的应用程序的母语内容而感到冒犯的用户。这就是为什么我们在本文中将不提供对可本地化字符串的转换。出于学习的目的,你可以自己翻译内容,但在现实生活中,这是你应该依靠专业翻译的地方。 你可以使用谷歌翻译或任何其他机器翻译服务将文本分别翻译成中文和法文。在提供中文和法文本地化文本的同时,您只需要更改值而不需要更改键。例如,在您的localizable.strings文件中,您只需要翻译My name is in“title-name%@”=“My name is%@”;分别为Localizable.strings(中文,指定)和Localizable.strings(法语)文件中的中文和法语。 您还必须对plurals.stringsdict文件执行同样的操作。您只需将apple,mango和orange分别在Plurals.stringsdict(中文,指定)和Plurals.stringsdict(法语)文件中翻译成中文和法语。至此,您已经完全本地化了应用程序。为到目前为止的好工作干杯! 测试定位 SwiftUI功能强大,实际上,你可以实时预览应用程序的本地化,而无需在模拟器或物理设备上运行,这无疑有助于缩短开发时间。 当您需要支持多种语言和地区,并且希望在UI上感受它们的外观时,这尤其有用。为此,苹果引入了环境变量--其中一个是专门针对语言和地区的。让我们尝试在预览中对语言和地区使用这个环境变量。 添加。environment(\.locale,init(identifier:“zh-Hans”)),其中zh-Hans是中文的区域设置标识符,指定给ContentView实例。单击画布上的Resume按钮,如果添加环境变量后没有反映任何变化,则刷新画布。好的方面是,你可以从预览中同时测试中文和法文。您只需要在SwiftUI中使用Group来对您的视图进行分组即可。创建一个ContentView的新实例,并添加一个带有'fr'标识符的环境变量。 您的ContentView_Previews结构将如下所示: 您现在可以在预览中同时测试中文和法语。相当令人印象深刻,对吧? 注意,在您的环境变量中更改此语言标识符将只反映在画布中的预览中。但是,如果您想测试您的本地化是否在模拟器或真实设备中工作良好,那么按照下面的步骤操作。 选择“编辑方案”“运行选项”,并将应用程序语言更改为要测试的任何语言。您还可以选择应用程序区域。编辑设置后,再次运行应用程序。 正在导出本地化 下一步是通过选择您想要支持的语言导出本地化,并将它们发送给您的本地化程序。请按照以下步骤进行操作。 在Project navigator中,选择项目,然后选择Editor Export for Localization。 在对话框中,输入文件夹名称,选择要导出文件夹的位置,取消选中English,因为我们不想翻译English,最后单击Export。 Xcode为每种语言创建一个Xcode本地化目录文件夹(扩展名为。xcloc)。这些文件夹中的每个都包含您标记为可本地化的资源和资产。然后可以将目录文件夹发送到本地化程序,以便立即开始工作。xcloc文件夹包含。xliff(标准XML本地化交换文件格式)文件,其中包含我们的本地化程序可以开始翻译的提取的字符串。 正在导入本地化 一旦您的本地化程序完成了对目录文件夹中内容的本地化,他们就会将其发送回您,而您所需要做的就是将其导入回您的项目中。Xcode为您处理一切。在Project navigator中,选择项目,然后选择Editor Import Localizations。如果您有多个。xcloc文件夹,并且它们包含在所有语言的一个文件夹中,请选择该文件夹,然后将各个。xcloc文件夹导入回项目。一旦导入,你的应用程序就完全本地化了。 今天到此为止! 干得好!如果您已经做到了这一点,那么您已经完成了一项了不起的工作,遵循了我们SwiftUI本地化教程的所有步骤。既然您已经为本地化准备好了您的应用程序,那么您就可以让短语来完成繁重的任务了。唱起来14天的试用,如果你有任何问题,随时在下面留言或评论! 想了解更多iOS app本地化的信息,敬请参考以下文章: 如何最大限度地利用移动应用程序本地化 自动化iOS情节提要本地化 带有短语的高级iOS OTA翻译 iOS iOS应用本地化(iOS应用l10n) iOS国际化(iOS i18n) iOS本地化(iOS l10n)

以上中文文本为机器翻译,存在不同程度偏差和错误,请理解并参考英文原文阅读。

阅读原文