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.
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'undefault
mot 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")
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 !!!")
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.
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 :)")
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.
Swift 3 version:) ...
import Foundation
extension String {
var localized: String {
return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
}
}
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
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.
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.
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.
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
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")
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: "")
}
}
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.