Enum с локализованной строкой в ​​swift

Я хочу использовать перечисление с локализованной строкой, поэтому мне это нравится, это работает, но проблема этого решения такова: я не могу легко получить значение enum из локализованной строки, у меня должен быть ключ для этого:

let option = DietWithoutResidueOption(rawValue: "NoDiet")

Если нет, я должен вызвать dietWithoutResidueOptionWith метод для получения значения перечисления...:/

Есть лучшее решение для хранения непосредственно localizedString, а не ключей в перечислении?

Спасибо

Перечисление

  enum DietWithoutResidueOption: String {
  case NoDiet = "NoDiet"
  case ThreeDays = "ThreeDays"
  case FiveDays  = "FiveDays"

  private func localizedString() -> String {
    return NSLocalizedString(self.rawValue, comment: "")
  }

  static func dietWithoutResidueOptionWith(#localizedString: String) -> DietWithoutResidueOption {
    switch localizedString {
    case DietWithoutResidueOption.ThreeDays.localizedString():
      return DietWithoutResidueOption.ThreeDays
    case DietWithoutResidueOption.FiveDays.localizedString():
      return DietWithoutResidueOption.FiveDays
    default:
      return DietWithoutResidueOption.NoDiet
    }
  }
}

Localizable.strings

"NoDiet" = "NON, JE N'AI PAS DE RÉGIME";
"ThreeDays" = "OUI, SUR 3 JOURS";
"FiveDays"  = "OUI, SUR 5 JOURS";

вызов

println(DietWithoutResidueOption.FiveDays.localizedString())

Ответ 1

Вы можете использовать любой тип StringLiteralConvertible, Equatable для типа RawValue enum.

Итак, как насчет:

import Foundation

struct LocalizedString: StringLiteralConvertible, Equatable {

    let v: String

    init(key: String) {
        self.v = NSLocalizedString(key, comment: "")
    }
    init(localized: String) {
        self.v = localized
    }
    init(stringLiteral value:String) {
        self.init(key: value)
    }
    init(extendedGraphemeClusterLiteral value: String) {
        self.init(key: value)
    }
    init(unicodeScalarLiteral value: String) {
        self.init(key: value)
    }
}

func ==(lhs:LocalizedString, rhs:LocalizedString) -> Bool {
    return lhs.v == rhs.v
}

enum DietWithoutResidueOption: LocalizedString {
    case NoDiet = "NoDiet"
    case ThreeDays = "ThreeDays"
    case FiveDays  = "FiveDays"

    var localizedString: String {
        return self.rawValue.v
    }

    init?(localizedString: String) {
        self.init(rawValue: LocalizedString(localized: localizedString))
    }
}

Используя это, вы можете построить DietWithoutResidueOption тремя способами:

let option1 = DietWithoutResidueOption.ThreeDays
let option2 = DietWithoutResidueOption(rawValue: "ThreeDays") // as Optional
let option3 = DietWithoutResidueOption(localizedString: "OUI, SUR 3 JOURS")  // as Optional

и извлеките локализованную строку с помощью:

let localized = option1.localizedString

Ответ 2

Попробуйте это, это довольно просто и прямо:

enum ChoicesTitle: String {
    case choice1 = "Choice 1"
    case choice2 = "Choice 2"
    case choice3 = "Choice 3"
    case choice4 = "Choice 4"
    case choice5 = "Choice 5"
    case choice6 = "Choice 6"

    func localizedString() -> String {
        return NSLocalizedString(self.rawValue, comment: "")
    }

    static func getTitleFor(title:ChoicesTitle) -> String {
        return title.localizedString()
    }
}

И вы можете использовать его следующим образом:

let stringOfChoice1: String = ChoicesTitle.getTitleFor(title: .choice1)

Надеюсь, это сработает для вас.

Ответ 3

Хороший подход заключается в создании структуры локализуемых строк со статическими переменными, например:

LocalizableStrings.swift

struct LocalizableStrings {
    static let noDiet  = NSLocalizedString("NoDiet", comment: "")
    static let threeDays  = NSLocalizedString("ThreeDays", comment: "")
    static let fiveDays  = NSLocalizedString("FiveDays", comment: "")
}

Localizable.strings

"NoDiet" = "NON, JE N'AI PAS DE RÉGIME";
"ThreeDays" = "OUI, SUR 3 JOURS";
"FiveDays"  = "OUI, SUR 5 JOURS";

И ваше перечисление будет выглядеть так:

Enum

enum DietWithoutResidueOption {
    case NoDiet,
    ThreeDays,
    FiveDays

    var description : String {
        get {
            switch(self) {
            case .NoDiet:
                return LocalizableStrings.noDiet
            case .ThreeDays:
                return LocalizableStrings.threeDays
            case .FiveDays:
                return LocalizableStrings.fiveDays
            }
        }
    }
}

Так, например, чтобы получить свое описание, вы можете сделать, как показано ниже:

DietWithoutResidueOption.NoDiet.description

Преимущество этого подхода состоит в том, что вы помещаете ключи ваших локализуемых строк в один файл. Так, например, если вы измените ключ NoDiet в вашем файле Localizable.strings, вам нужно только обновить файл LocalizableStrings.swift, а не все места, где у нас есть ключ NoDiet в виде строки. Кроме того, вы рискуете ошибиться в написании ключа NoDiet в каком-то файле, где он используется, и ваш код будет компилироваться без ошибок, в то же время, используя статическую переменную из LocalizableStrings.swift, вы можете избежать этого, поскольку ваш код не будет компилироваться и Вы увидите сообщение об ошибке, в котором говорится, где находится ошибка.

Ответ 4

это поздний ответ, но я только что поболтал с инженерами Apple на эту тему, которую они рекомендуют сделать так:

    enum LocalizedStrings {
        case title

        var localized: String {
            switch self {
            case .title:
                return NSLocalizedString("My Title", comment: "My Comment")
            }
        }
    }

В вашем случае решение будет не сильно отличаться от исходного кода:

    enum DietWithoutResidueOption {
        case NoDiet
        case ThreeDays
        case FiveDays

        var localizedString: String {
            switch self {
            case .NoDiet:
                return NSLocalizedString("NoDiet", comment: "Some comment")
            case .ThreeDays:
                return NSLocalizedString("ThreeDays", comment: "Some comment")
            case .FiveDays:
                return NSLocalizedString("FiveDays", comment: "Some comment")
            }
        }

        static func dietWithoutResidueOptionWith(localizedString: String) -> DietWithoutResidueOption {
            switch localizedString {
            case DietWithoutResidueOption.ThreeDays.localizedString:
                return DietWithoutResidueOption.ThreeDays
            case DietWithoutResidueOption.FiveDays.localizedString:
                return DietWithoutResidueOption.FiveDays
            default:
                return DietWithoutResidueOption.NoDiet
            }
        }
    }

Причина в том, что они не хотят, чтобы вы передавали переменные в NSLocalizedString(). Это как-то связано с оптимизацией и разбором строк. Представьте, что Xcode генерирует файл localizable.strings самостоятельно в какой-то момент, но он не может найти строки, потому что они передаются как переменные.

Ответ 5

Альтернатива Ohter:

Enum

enum Title : String {

  case CEO = "CEOKey"
  case CTO = "CTOKey"
  case CFO = "CFOKey"

  private static let allTitles = [CEO, CTO, CFO]

  var localizedString: String {
    return NSLocalizedString(self.rawValue, comment: "")
  }

  init!(rawValue: String) {
    var keys =  Title.allTitles
    var filtered = keys.filter { $0.rawValue == rawValue }

    self = filtered.first!
  }

  init!(localizedString: String) {
    var keys =  Title.allTitles
    var filtered = keys.filter { $0.localizedString == localizedString }

    self = filtered.first!
  }
}

Localizable.strings

"CEOKey" = "Chief Executive Officer";
"CTOKey" = "Chief Technical Officer";
"CFOKey" = "Chief Financial Officer";

Заканчивать перечисление:

let option1 = Title.CFO
let option2 = Title(rawValue: "CTOKey") // init from key
let option3 = Title(localizedString: NSLocalizedString("CEOKey", comment: ""))  // init from value

Извлечь локализованные строки:

println("option1 localized string : \(option1.localizedString)")
println("option2 localized string : \(option2.localizedString)")
println("option3 localized string : \(option3.localizedString)")

Вход

option1 localized string : Chief Financial Officer
option2 localized string : Chief Technical Officer
option3 localized string : Chief Executive Officer

Этот код генерирует исключение, если локализованные строки или ключи не найдены

Ответ 6

Попробуйте этот протокол, который я создал, и вы можете импортировать, используйте его, как показано ниже.

https://github.com/Wei18/Self-Study-Protocol/blob/master/Localizable.swift

enum SomeKey: String, Localizable {
  case MenuGreeting = "lb_menu_greeting"
  case HaveBook = "I have %@ books"
}

// Sample
let menuGreeting: String = SomeKey.MenuGreeting.localized()
let iHaveBoxes: String = SomeKey.HaveBook.localized([3])

/*
// You also can make it with html.
SomeKey.CustomCase.localizedHTML()
SomeKey.CustomCase.localizedHTML([])
*/

Ответ 7

Это мой пример

enum Localization: String {
    case appName = "app_name"
    case appOk = "app_ok"
    case appError = "app_error"
    case placeholderNoContent = "placeholder_no_content"
    case homeTitle = "home_title"

    public func localized(args: CVarArg...) -> String {
        let localizedString = NSLocalizedString(self.rawValue, comment: "")
        return String.init(format: localizedString, args)
    }
}

использование

self.homeTitleLabel = Localization.homeTitle.localized()

Это перечисление Localization можно легко использовать со строковыми форматами.