关于我:大厂摸鱼 + 业余独立开发,之后会输出深度技术文章 + 独立开发技巧

我的往期技术文章合集:RickeyBoy – Gitbub

我的独立开发 App:iColors – 规划灵感 配色助手

上一篇:

独立开发之 App 世界化全过程(一):为什么要做世界化

独立开发之 App 世界化全过程(二):App 数据翻译

独立开发之 App 世界化全过程(三):Core Data 模型升级

独立开发之 App 世界化全过程(四):Core Data 模型解析

独立开发之 App 世界化全过程(五):提取 App 中文本案牍

独立开发之 App 世界化全过程(六):替换代码中运用的文本

App 内言语环境建立

当咱们做完上面的一切操作之后,App 现在看起来现已大体上适配了世界化了,咱们能够直接看下效果。

修正默许言语

现在咱们能够经过直接设置 App 的默许言语,来检查多言语的效果。能够在真机的设置页面,进行修正:

独立开发之 App 世界化全过程(七):App 内言语环境建立

当然,如果是经过 Xcode 直接进行测验,能够经过修正 Scheme 中的 App Language 设置,来挑选默许的言语:

独立开发之 App 世界化全过程(七):App 内言语环境建立

如果是经过 SwiftUI Preview,能够这样快速测验多言语:

CustomView()
  .environment(.locale, .init(identifier: "en")) // use English
  .environment(.locale, .init(identifier: "zh-Hans")) // 运用中文

iOS 中的言语体系

再进行接下来的内容之前,咱们需求先了解一下 iOS 中的言语体系。在上面的代码中,留意到咱们运用了言语代码 “zh-Hans” 和 “en” 指定对应的言语,来调整 SwiftUI Preview 中需求展现的言语。那么这儿的代码到底是什么意思?

Locale – Apple

Information about linguistic, cultural, and technological conventions for use in formatting data for presentation.

首要咱们需求知道,iOS 中运用 Locale 来记录言语和区域信息。比方 Locale 中,有几个特点,咱们能够获取到对应的信息:

那么怎么初始化一个 Locale 类型呢?一种最简略的方法,便是经过 identifier 来直接创立,比方 “zh-Hans” 就代表简体中文,而 “en” 就代表英文,更多的还有 “fr” 代表法语等等,具体的对应关系能够参阅 ioslocaleidentifiers – Github

支撑 App 内言语挑选

现在言语挑选的逻辑有两个主流的方法,一个是直接在 App 内支撑言语选项,另一个是不支撑 App 内挑选言语,而是直接运用设置中选中的言语。

其实两种方法并没有十分明显的优缺点,支撑 App 内切换的话可能灵活一点,可是完成起来相对难一些。能够根据具体 App 诉求进行挑选。

我这儿首要讲解第一种,即支撑言语在 App 内进行挑选,我的 App 也是用的这种方法。

独立开发之 App 世界化全过程(七):App 内言语环境建立

要完成这样一个言语挑选逻辑,咱们要来自界说一下支撑的言语。就 iColors App 来说,现在就需求支撑三种言语,中文 + 英文,以及运用系统默许的言语。那么经过枚举类型,进行类似于下面的界说即可:

为了便利读者理解,这儿罗列的仅是摘要的简略版别。想要具体运用的话,能够参阅:LanguageManager-SwiftUI – Github 中的代码

public enum Languages: String {
  case en
  case zhHans = "zh-Hans"
  case deviceLanguage
}

留意,这儿 Languages 类型的 rawValue 其实对应的便是前文提到的 Locale 的言语代码。

与此同时,咱们需求经过单例,记录当时挑选的言语即可:

public class LanguageSettings: ObservableObject {
 @Published public var selectedLanguage: Languages = .deviceLanguage
}

当然咱们还需求一个转换逻辑,将咱们界说的 Languages 模型和 iOS 的 Locale 模型相关起来。当咱们挑选 .deviceLanguage 时,直接运用当时默许的 Locale,否则运用咱们挑选的 language:

public class LanguageSettings: ObservableObject {
  @Published public var selectedLanguage: Languages = .deviceLanguage
 
  public var locale: Locale {
    if selectedLanguage == .deviceLanguage {
      return Locale.current
    } else {
      return Locale(identifier: selectedLanguage.rawValue)
    }
  }
}

这样咱们就完成了一个简略的言语挑选逻辑系统,咱们只需求在 App 初始化时将 LanguageSettings 的单例初始化并经过 environment 进行环境变量的相关,并且将 locale 信息设置给整个 App 即可,这样咱们大局的言语就现已设置好了。

@main
struct XXXApp: App {
  @StateObject var settings = LanguageSettings()
 var body: some Scene {
    WindowGroup {
      ContentView()
        .environment(.locale, settings.locale)
        .environmentObject(settings)
    }
  }
}

添加言语挑选页面

有了现在的言语管理结构,那么完成一个言语挑选页面,便是一个十分简略的逻辑了。咱们能够添加一个数组,保存支撑的言语:

public class LanguageSettings: ObservableObject {
 ...
 public let supportedLanguages: [Languages] = [.zh, .en, .deviceLanguage]
}

之后,在言语挑选页面,展现一切支撑的言语,然后在挑选后绑定到当时挑选的言语 selectedLanguage 即可:

struct MeLanguageSelection: View {
  @EnvironmentObject var languageSettings: LanguageSettings
  
  var body: some View {
    VStack {
      // list all choice
      ForEach(languageSettings.supportedLanguages, id: .rawValue) { language in
        CustomChoiceView(language)
          .onTapGesture {
            // binding
            languageSettings.selectedLanguage = language
          }
      }
    }
  }
 
  ...
}