作者:Erica Sadun,原文鏈接,原文日期:2016-08-29
譯者:Darren妈经;校對(duì):shanks;定稿:千葉知風(fēng)
我在很多地方都表達(dá)了我對(duì)流的喜愛(ài)捧书。我在 Swift Cookbook 中介紹了一些〈蹬荩現(xiàn)在,我將通過(guò) Pearson 的內(nèi)容更新計(jì)劃更新 Swift 3 的相關(guān)內(nèi)容经瓷,正好我有一些要說(shuō)的爆哑。我想在文章中添加一些有趣的新配方。
今天舆吮,讓我們談?wù)劇恨D(zhuǎn)換流』揭朝。你寫 print(..., to:)
時(shí)傳遞的傳統(tǒng)流,只是一個(gè)你傳遞給stdout色冀、stderr或文件的一個(gè)目標(biāo)而已潭袱。轉(zhuǎn)換流會(huì)從根本上改變流經(jīng)它的文本。你可以限制文本為全部小寫呐伞,或者做拼寫檢查敌卓,甚至打印到你的平臺(tái)的本地通知系統(tǒng)。
因此我決定創(chuàng)建一個(gè)翻譯流伶氢。如截圖所示趟径,當(dāng)你打印流的時(shí)候,會(huì)把英文文本轉(zhuǎn)換成其他語(yǔ)言癣防。
如圖所示蜗巧,我的解決方案充分利用了 Swift 標(biāo)準(zhǔn)庫(kù)內(nèi)置的 print 函數(shù)。Swift 允許打印到流蕾盯。當(dāng)使用我的 ItalianStream.shared
流時(shí)幕屹, 打印到控制臺(tái)的內(nèi)容被自動(dòng)翻譯成了我在流中提供的語(yǔ)言。
在我的實(shí)現(xiàn)中级遭,我希望能夠做到幾個(gè)關(guān)鍵點(diǎn):
- 所有特定的翻譯功能都需要從打印流中分離望拖,這樣我可以在不打亂實(shí)現(xiàn)的情況下交換不同 API 提供的輸入和輸出。
- 我希望能使用多種語(yǔ)言挫鸽。
- 我需要提供一個(gè)可重用的
var
成員说敏,用于需要打印的流。
為了實(shí)現(xiàn)這些目標(biāo)丢郊,我決定大量使用泛型和面向協(xié)議盔沫。我希望能夠用一個(gè)泛型化的流類型來(lái)跟蹤任意的語(yǔ)言医咨,這反過(guò)來(lái)將為打印提供一個(gè)共享的流實(shí)例。這可能聽起來(lái)有點(diǎn)繞架诞。
標(biāo)準(zhǔn)庫(kù)內(nèi)置的 TextOutputStream
協(xié)議剛好滿足了一個(gè)需求拟淮,一個(gè)接收一個(gè)字符串并做一些處理的方法。下面的代碼翻譯了字符串并打印了出來(lái)谴忧。
/// A text output stream that performs translation in
/// the process of printing
public struct TranslationStream<Language: EnglishTranslationProvider>: TextOutputStream {
/// Writes the contents of the string to stdout after
/// passing the string through an automatic translator
public func write(_ string: String) {
guard let translation = Language.translate(string) else { return }
print(translation)
}
}
比較 tricky 的是我的 TranslationStream
結(jié)構(gòu)是泛型很泊。它需要一個(gè)遵循 EnglishTraslationProvider
協(xié)議的類型,允許其從 provider 請(qǐng)求翻譯俏蛮。這是協(xié)議的內(nèi)容:
/// A provider of string translations from English
public protocol EnglishTranslationProvider {
/// Returns a shared instance of the provider
static var shared: TranslationStream<Self> { get }
/// Returns a translated string
static func translate(_ string: String) -> String?
}
每個(gè)語(yǔ)言翻譯的 provider 提供一個(gè) shared
翻譯流給 TranslationStream
類型供 打印時(shí)使用(就像在 ItalianStream.shared
的截圖中所看到的那樣 )撑蚌,以及一個(gè) translate
方法來(lái)返回字符串翻譯后的版本。例如搏屑,這是法語(yǔ) provider 類型的實(shí)現(xiàn):
/// A stream type that automatically translates from English to French
public struct FrenchStream: EnglishTranslationProvider {
/// Returns a shared instance of the provider
public static var shared = TranslationStream<FrenchStream>()
/// Returns a translated string
public static func translate(_ string: String) -> String? {
return FrenchStream.translate(string, language: "fr")
}
}
很簡(jiǎn)單吧争涌?這真的不難。它實(shí)現(xiàn)了兩個(gè)必要的成員辣恋,另一方面作為在協(xié)議擴(kuò)展中聲明的默認(rèn) translate
方法的代理亮垫。我的具體實(shí)現(xiàn)用了兩個(gè)字符的語(yǔ)言代碼,并通過(guò) Google 翻譯成英語(yǔ)伟骨。我在這里并沒(méi)有包含實(shí)際的translate(_ string:, language:)
方法饮潦,因?yàn)橛泻芏嘁资褂玫?API可供選擇,它們一般都需要 API key 和費(fèi)用携狭。
我試圖讓本文的重點(diǎn)是『哇继蜡,6666,你可以在打印流時(shí)轉(zhuǎn)換文本逛腿∠〔ⅲ』,而不是『哦单默,翻譯了碘举。』搁廓。我認(rèn)為翻譯流是展示這個(gè)特定的 Swift 特性的好方式引颈。
在下面的截圖中,我把(第20行)打印到了用戶的通知欄境蜕。
本文由 SwiftGG 翻譯組翻譯蝙场,已經(jīng)獲得作者翻譯授權(quán),最新文章請(qǐng)?jiān)L問(wèn) http://swift.gg粱年。