NSLocalizedString ze zmienną Swift

85

Próbuję zlokalizować moją aplikację przy użyciu NSLocalizedString. Kiedy importuję plik XLIFF, większość działa jak urok, ale coś nie działa, a niektóre ciągi nie są zlokalizowane. Zauważyłem, że problem pochodzi z NSLocalizedString zawierającego coś zmiennego wewnątrz, na przykład:

NSLocalizedString(" - \(count) Notifica", comment: "sottotitolo prescrizione per le notifiche al singolare")

lub

NSLocalizedString("Notifica per \(medicina!) della prescrizione \(prescription!)\nMemo: \(memoTextView.text)", comment: "Messaggio della Local Notification")

Może to nie jest poprawna składnia dla tego rodzaju rzeczy. Ktoś może mi wyjaśnić, jak to zrobić szybko? Dziękuję Ci bardzo.

Andorath
źródło
To jest bardzo dobry artykuł o lokalizacji w Swift dla solidnej architektury
Mendy,

Odpowiedzi:

133

Możesz użyć sprintfparametrów formatu w obrębie NSLocalizedString, więc Twój przykład może wyglądać następująco:

let myString = String(format: NSLocalizedString(" - %d Notifica", comment: "sottotitolo prescrizione per le notifiche al singolare"), count)
zisoft
źródło
6
Jak to wygląda w Localizable.string
Van Du Tran
tak samo jak w Obj-C:" - %d Notifica"=" - %d Notifica";
ReDetection
3
Jak zamienić ciąg? Próbowałem użyć %smodyfikatora, który nie działał = \
igrek
12
@igrek Służy %@do zastępowania łańcucha.
Yeehaw,
2
Odniesienie do tych parametrów formatowania to developer.apple.com/library/content/documentation/Cocoa/…
Shaun Dychko
94

W sesji nr 412 WWDC2014 „Lokalizowanie za pomocą Xcode 6” właściwą drogą do tego w języku Swift jest:

String.localizedStringWithFormat(
    NSLocalizedString(" - %d Notifica",
    comment: "sottotitolo prescrizione per le notifiche al singolare"),
    count)
znak
źródło
Dlaczego musisz używać NSLocalizedString (...)? czy to się nie dzieje w implementacji String.localizedStringWithFormat (...)?
Yitzchak
1
Dzięki, już to widziałem po tym, jak zapytałem. Będzie to bardzo pomocne dla innych, więc dzięki
Yitzchak
25

Postępowałem zgodnie z podejściem tworzenia rozszerzenia do String, ponieważ mam wiele ciągów do zlokalizowania.

extension String {
    var localized: String {
        return NSLocalizedString(self, comment:"")
    }
}

Aby użyć go do lokalizacji w kodzie, wykonaj:

self.descriptionView.text = "Description".localized

W przypadku ciągów ze zmiennymi dynamicznymi wykonaj:

self.entryTimeLabel.text = "\("Doors-open-at".localized) \(event.eventStartTime)"

Zadeklaruj ciągi w plikach String dla różnych języków (przykład: arabski i angielski)

wprowadź opis obrazu tutaj wprowadź opis obrazu tutaj

Mam nadzieję, że pomoże!

JaspreetKour
źródło
2
Ale wydaje mi się, że po prostu dołączasz czas do sznurka. Co by było, gdyby twój zlokalizowany ciąg był podobny The doors open at %@ o'clock. Czy Twoje rozwiązanie nadal działałoby?
Houman
Tak, działa idealnie, ponieważ od tyłu mam czas jako String.
JaspreetKour
1
Dziękuję za odniesienie do Localizable.strings. Jednak myślę, że @Houman ma uzasadnione obawy.
Matt,
Nie wiem, dlaczego ludzie chcą porzucić wartość „komentarza”. Daje opis tekstu i jego cel inżynierom lokalizacyjnym, bez których nie mogą rozpoznać zamiaru użycia tego tekstu na przycisku lub jako etykieta itp.
Satyam
7

Wypróbowałem powyższe rozwiązania, ale poniższy kod działał dla mnie

SWIFT 4

extension String {

    /// Fetches a localized String
    ///
    /// - Returns: return value(String) for key
    public func localized() -> String {
        let path = Bundle.main.path(forResource: "en", ofType: "lproj")
        let bundle = Bundle(path: path!)
        return (bundle?.localizedString(forKey: self, value: nil, table: nil))!
    }


    /// Fetches a localised String Arguments
    ///
    /// - Parameter arguments: parameters to be added in a string
    /// - Returns: localized string
    public func localized(with arguments: [CVarArg]) -> String {
        return String(format: self.localized(), locale: nil, arguments: arguments)
    }

}

// variable in a class
 let tcAndPPMessage = "By_signing_up_or_logging_in,_you_agree_to_our"
                                     .localized(with: [tAndc, pp, signin])

// Localization File String
"By_signing_up_or_logging_in,_you_agree_to_our" = "By signing up or logging in, you agree to our \"%@\" and \"%@\" \nAlready have an Account? \"%@\"";
Pratik
źródło
6

Oto rozszerzenie, którego używam w String, dodaje funkcję localizeWithFormat ze zmiennymi argumentami,

extension String:{

     func localizeWithFormat(arguments: CVarArg...) -> String{
        return String(format: self.localized, arguments: arguments)        
     }

     var localized: String{
         return Bundle.main.localizedString(forKey: self, value: nil, table: "StandardLocalizations")
     }
}

Stosowanie:

let siriCalendarText = "AnyCalendar"
let localizedText = "LTo use Siri with my app, please set %@ as the default list on your device reminders settings".localizeWithFormat(arguments: siriCalendarTitle)

Uważaj tylko, aby nie używać tych samych nazw funkcji i właściwości, które ma String. Zwykle używam 3-literowego przedrostka dla wszystkich moich funkcji frameworka.

Wielebny
źródło
-5

Założyłem extensionsię String, ponieważ miałem wiele stringsdo być localized.

extension String {
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
}

Na przykład:

let myValue = 10
let anotherValue = "another value"

let localizedStr = "This string is localized: \(myValue) \(anotherValue)".localized
print(localizedStr)
Santosh
źródło
6
Dużą wadą tego podejścia jest to, że musisz ręcznie wyodrębnić ciągi znaków, aby wysłać je do tłumacza, ponieważ Editor > Export for Localization...ich nie odbierze.
Jason Moore
Biorąc pod uwagę to, co zasugerował @JasonMoore, nie sądzę, że jest to właściwe podejście.
Yuchen Zhong
@JasonMoore całkowicie się z tobą zgadzam. Czy któryś z was znalazł na to rozwiązanie?
gasparuff
nie wiem, dlaczego to rozwiązanie jest obniżone :(. i prawie poniższe gniazdo poniżej rozwiązania jest takie samo, ale ma poprawne
Amr Angry