NSLocalizedString com variável swift

86

Estou tentando localizar meu aplicativo usando NSLocalizedString. Quando eu importo o arquivo XLIFF, a maioria funciona bem, mas algo não funciona e algumas strings não são localizadas. Percebi que o problema é de NSLocalizedString contendo algo variável como:

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

ou

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

Talvez esta não seja a sintaxe correta para esse tipo de coisa. Alguém pode me explicar como fazer isso rapidamente? Muito obrigado.

Andorath
fonte
Este é um artigo muito bom sobre localização em Swift para uma arquitetura robusta
Mendy

Respostas:

138

Você pode usar os sprintfparâmetros de formato de NSLocalizedString, para que seu exemplo seja parecido com este:

let myString = String(format: NSLocalizedString(" - %d Notifica", comment: "sottotitolo prescrizione per le notifiche al singolare"), count)
zisoft
fonte
6
Como se parece no Localizable.string
Van Du Tran
o mesmo que em Obj-C:" - %d Notifica"=" - %d Notifica";
ReDetecção de
3
Como faço para substituir uma string? Tentei usar o %smodificador que não funcionou = \
igrek
12
@igrek Use %@para substituir uma string.
Yeehaw
3
A referência para esses parâmetros de formatação é developer.apple.com/library/content/documentation/Cocoa/…
Shaun Dychko
96

Na Sessão # 412 do WWDC2014 "Localizing with Xcode 6", a maneira adequada para fazer isso em Swift é a seguinte:

String.localizedStringWithFormat(
    NSLocalizedString(" - %d Notifica",
    comment: "sottotitolo prescrizione per le notifiche al singolare"),
    count)
Marca
fonte
Por que você precisa usar NSLocalizedString (...)? isso não acontece na implementação de String.localizedStringWithFormat (...)?
Yitzchak
1
Obrigado, eu já vi depois que perguntei. Será muito útil para os outros, então obrigado
Yitzchak
25

Eu segui a abordagem de criação de extensão para String, pois tenho muitas strings para localizar.

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

Para usá-lo para localização no código, faça:

self.descriptionView.text = "Description".localized

Para strings com variáveis ​​dinâmicas, siga:

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

Declare as strings em arquivos String para diferentes idiomas (exemplo: árabe e inglês)

insira a descrição da imagem aqui insira a descrição da imagem aqui

Espero estar ajudando!

JaspreetKour
fonte
2
Mas me parece que você está apenas prendendo o tempo na corda. E se sua string localizada fosse assim The doors open at %@ o'clock. Sua solução ainda funcionaria?
Houman
Sim, está funcionando perfeitamente, pois estou recebendo tempo como String de volta.
JaspreetKour
1
Obrigado por incluir uma referência a Localizable.strings. No entanto, acho que @Houman tem uma preocupação válida.
Matt
Não sei por que as pessoas querem abandonar o valor de "comentário". Ele fornece a descrição do texto e sua finalidade aos engenheiros de localização, sem os quais eles não conseguem perceber a intenção de usar aquele texto em um botão ou como um rótulo etc.
Satyam
8

Eu tentei as soluções acima, mas o código abaixo funcionou para mim

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
fonte
7

Aqui está uma extensão que uso em String, ela adiciona uma função localizeWithFormat com argumentos variáveis,

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")
     }
}

Uso:

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)

Apenas tome cuidado para não usar os mesmos nomes de função e propriedade que String possui. Eu normalmente uso um prefixo de 3 letras para todas as minhas funções de framework.

o reverendo
fonte
-5

Eu criei um extensionto Stringporque tinha muitos stringspara ser localized.

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

Por exemplo:

let myValue = 10
let anotherValue = "another value"

let localizedStr = "This string is localized: \(myValue) \(anotherValue)".localized
print(localizedStr)
Santosh
fonte
6
A grande desvantagem dessa abordagem é que você precisa extrair manualmente as strings para enviar ao tradutor, pois Editor > Export for Localization...não vai pegá-las.
Jason Moore
Considerando o que @JasonMoore sugeriu, não acho que essa seja a abordagem certa.
Yuchen Zhong
@JasonMoore concordo totalmente com você. Algum de vocês encontrou uma solução para isso?
gasparuff de
eu não sabia por que essa solução foi reduzida :(. e quase a solução do ninho abaixo é a mesma, mas aumentou
Amr Angry