web-dev-qa-db-fra.com

Quel est l'équivalent de NSLocalizedString dans Swift?

Existe-t-il un équivalent Swift de NSLocalizedString(...)? Dans Objective-C, nous utilisons généralement:

NSString *string = NSLocalizedString(@"key", @"comment");

Comment puis-je obtenir le même résultat dans Swift? J'ai trouvé une fonction:

func NSLocalizedString(
    key: String,
    tableName: String? = default,
    bundle: NSBundle = default,
    value: String = default,
    #comment: String) -> String

Cependant, c'est très long et pas pratique du tout.

206
RaffAl

La NSLocalizedString existe aussi dans le monde des Swift.

func NSLocalizedString(
    key: String,
    tableName: String? = default,
    bundle: NSBundle = default,
    value: String = default,
    #comment: String) -> String

Les paramètres tableName, bundle et value sont marqués d'undefaultmot clé, ce qui signifie que nous pouvons omettre ces paramètres lors de l'appel de la fonction. Dans ce cas, leurs valeurs par défaut seront utilisées.

Cela conduit à la conclusion que l'appel de méthode peut être simplifié pour:

NSLocalizedString("key", comment: "comment")
264
RaffAl

J'utilise la solution suivante:

1) créer une extension:

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

2) dans Localizable.strings fichier:

"Hi" = "Привет";

3) exemple d'utilisation:

myLabel.text = "Hi".localized

prendre plaisir! ;)

--upd: -

pour les cas avec commentaires, vous pouvez utiliser cette solution:

1) extension:

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

2) dans le fichier .strings:

/* with !!! */
"Hi" = "Привет!!!";

3) en utilisant:

myLabel.text = "Hi".localized(withComment: "with !!!")
352
dr OX

Une variante des réponses existantes:

Swift 4:

extension String {

    func localized(withComment comment: String? = nil) -> String {
        return NSLocalizedString(self, comment: comment ?? "")
    }

}

Vous pouvez ensuite simplement l'utiliser avec ou sans commentaire:

"Goodbye".localized()
"Hello".localized(withComment: "Simple greeting")

Notez cependant que genstrings ne fonctionnera pas avec cette solution.

14
José

En utilisant cette méthode, il est possible de créer une implémentation différente pour différents types (par exemple, Int ou des classes personnalisées comme CurrencyUnit, ...). Il est également possible de rechercher cette méthode à l'aide de l'utilitaire genstrings . Ajoutez simplement l'indicateur de routine à la commande

genstrings MyCoolApp/Views/SomeView.Swift -s localize -o .

extension: 

import UIKit

extension String {
    public static func localize(key: String, comment: String) -> String {
        return NSLocalizedString(key, comment: comment)
    }
}

usage:

String.localize("foo.bar", comment: "Foo Bar Comment :)")
11
Kay

Création d'une petite méthode d'assistance pour les cas, où "commentaire" est toujours ignoré. Moins de code est plus facile à lire:

public func NSLocalizedString(key: String) -> String {
    return NSLocalizedString(key, comment: "")
}

Il suffit de le placer n'importe où (en dehors d'une classe) et Xcode trouvera cette méthode globale.

7
JOM

Swift 3 version:) ...

import Foundation

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

Le meilleur moyen est probablement celui-ci ici .

fileprivate func NSLocalizedString(_ key: String) -> String {
    return NSLocalizedString(key, comment: "")
}

et

import Foundation
extension String {
    static let Hello = NSLocalizedString("Hello")
    static let ThisApplicationIsCreated = NSLocalizedString("This application is created by the swifting.io team")
    static let OpsNoFeature = NSLocalizedString("Ops! It looks like this feature haven't been implemented yet :(!")
}

vous pouvez ensuite l'utiliser comme ça

let message: String = .ThisApplicationIsCreated
print(message)

pour moi c'est le meilleur parce que

  • Les chaînes codées en dur sont dans un fichier spécifique, donc le jour où vous voulez le changer est très facile
  • Plus facile à utiliser que de taper manuellement les chaînes de votre fichier à chaque fois
  • genstrings fonctionnera toujours
  • vous pouvez ajouter plus d'extensions, comme un contrôleur par vue pour garder les choses en ordre
5
Robin Dorpe

En réalité, vous pouvez utiliser deux phases pour traduire vos textes dans des projets Swift:

1) La première phase utilise l'ancienne méthode pour créer toutes vos chaînes traduisibles:

NSLocalisedString("Text to translate", comment: "Comment to comment")

1.1) Ensuite, vous devez utiliser genstrings pour générer Localizable.strings:

$ genstrings *Swift

2) Ensuite, vous devriez utiliser cette réponse .

2.1) Utilisez votre option "Rechercher et remplacer" XCode en fonction de l'expression régulière . Comme pour l'exemple donné (si vous n'avez pas de commentaires), l'expression régulière sera:

NSLocalizedString\((.*)\, comment:\ \"\"\) 

et le remplacer par

$1.localized

ou (si vous avez des commentaires)

NSLocalizedString\((.*)\, comment:\ (.*)\)

et le remplacer par

$1.localizedWithComment(comment: $2)

Vous êtes libre de jouer avec regex et différentes combinaisons d’extensions à votre guise. La manière générale est de diviser tout le processus en deux phases. J'espère que cela pourra aider.

4
GYFK

Lorsque vous développez un SDK. Vous avez besoin d'une opération supplémentaire.

1) créez Localizable.strings comme d'habitude dans YourLocalizeDemoSDK.

2) créez le même Localizable.strings dans YourLocalizeDemo.

3) trouvez votre chemin Bundle de YourLocalizeDemoSDK.

Swift4:

// if you use NSLocalizeString in NSObject, you can use it like this
let value = NSLocalizedString("key", tableName: nil, bundle: Bundle(for: type(of: self)), value: "", comment: "")

Bundle(for: type(of: self)) vous aide à trouver le paquet dans YourLocalizeDemoSDK. Si vous utilisez plutôt Bundle.main, vous obtiendrez une valeur erronée (en fait, ce sera la même chaîne que la clé).

Mais si vous voulez utiliser l’extension String mentionnée par dr OX . Vous devez en faire plus. L'extension Origin ressemble à ceci.

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

Comme nous le savons, nous développons un SDK, Bundle.main recevra le bundle du bundle YourLocalizeDemo. Ce n'est pas ce que nous voulons. Nous avons besoin du paquet dans YourLocalizeDemoSDK. C'est un truc pour le trouver rapidement.

Exécutez le code ci-dessous dans une instance de NSObject dans YourLocalizeDemoSDK. Et vous obtiendrez l'URL de YourLocalizeDemoSDK.

let bundleURLOfSDK = Bundle(for: type(of: self)).bundleURL
let mainBundleURL = Bundle.main.bundleURL

Imprimez les deux URL, vous constaterez que nous pouvons créer une base bundleURLofSDK sur mainBundleURL. Dans ce cas, ce sera:

let bundle = Bundle(url: Bundle.main.bundleURL.appendingPathComponent("Frameworks").appendingPathComponent("YourLocalizeDemoSDK.framework")) ?? Bundle.main

Et l'extension de chaîne sera:

extension String {
    var localized: String {
        let bundle = Bundle(url: Bundle.main.bundleURL.appendingPathComponent("Frameworks").appendingPathComponent("YourLocalizeDemoSDK.framework")) ?? Bundle.main
        return NSLocalizedString(self, tableName: nil, bundle: bundle, value: "", comment: "")
    }
}

J'espère que ça aide.

2
Liam

J'ai créé mon propre outil genstrings pour extraire des chaînes à l'aide d'une fonction de traduction personnalisée

extension String {

    func localizedWith(comment:String) -> String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: comment)
    }

}

https://Gist.github.com/Maxdw/e9e89af731ae6c6b8d85f5fa60ba848c

Il analysera tous vos fichiers Swift et exportera les chaînes et les commentaires de votre code dans un fichier .strings.

Ce n’est probablement pas la façon la plus simple de le faire, mais c’est possible.

1
Max

Bien que cela ne réponde pas au problème de raccourcissement, mais cela m'a aidé à organiser les messages, j'ai créé une structure pour les messages d'erreur comme ci-dessous.

struct Constants {
    // Error Messages
    struct ErrorMessages {
        static let unKnownError = NSLocalizedString("Unknown Error", comment: "Unknown Error Occured")
        static let downloadError = NSLocalizedString("Error in Download", comment: "Error in Download")
    }
}

let error = Constants.ErrorMessages.unKnownError

De cette façon, vous pouvez organiser les messages et faire fonctionner les chaînes de caractères.

Et ceci est la commande genstrings utilisée

find ./ -name \*.Swift -print0 | xargs -0 genstrings -o .en.lproj
1
anoop4real

Utile pour les tests unitaires:

C'est une version simple qui peut être étendue à différents cas d'utilisation (par exemple, avec l'utilisation de noms de table).

public func NSLocalizedString(key: String, referenceClass: AnyClass, comment: String = "") -> String 
{
    let bundle = NSBundle(forClass: referenceClass)
    return NSLocalizedString(key, tableName:nil, bundle: bundle, comment: comment)
}

Utilisez-le comme ceci:

NSLocalizedString("YOUR-KEY", referenceClass: self)

Ou comme ceci avec un commentaire:

NSLocalizedString("YOUR-KEY", referenceClass: self, comment: "usage description")
1
GatoCurioso

Localisation avec langue par défaut:

extension String {
func localized() -> String {
       let defaultLanguage = "en"
       let path = Bundle.main.path(forResource: defaultLanguage, ofType: "lproj")
       let bundle = Bundle(path: path!)

       return NSLocalizedString(self, tableName: nil, bundle: bundle!, value: "", comment: "")
    }
}
0
researcher

Lorsque vous traduisez, par exemple en anglais, où une phrase est identique, dans une autre langue où elle est différente (en raison du sexe, de la conjugaison ou de la déclinaison d'un verbe)la forme la plus simpleNSString dans Swift, cela fonctionne dans tous les cas, les trois arguments sont un. Par exemple, l'expression anglaise "previous was", est traduite différemment en russe pour "weight" ("предыдущ ий был") et pour "taille" ("предыдущ ая был а ").

Dans ce cas, vous avez besoin de deux traductions différentes pour une source (en termes d'outil XLIFF recommandé dans WWDC 2018). Vous ne pouvez pas y parvenir avec deux arguments NSLocalizedString, où "previous was" seront les mêmes pour la "clé" et la traduction anglaise (c'est-à-dire pour la valeur). Le seul moyen est d'utiliser la forme à trois arguments

NSLocalizedString("previousWasFeminine", value: "previous was", comment: "previousWasFeminine")

NSLocalizedString("previousWasMasculine", value: "previous was", comment: "previousWasMasculine")

où les clés ("previousWasFeminine" et "previousWasMasculine") sont différentes.

Je sais que le conseil général est de traduire la phrase dans son ensemble, cependant, elle prend parfois trop de temps et est peu pratique.

0
Vadim Motorine