¿Qué equivale a NSLocalizedString en Swift?

¿Hay un equivalente Swift de NSLocalizedString(...) ? En Objective-C , solemos usar:

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

¿Cómo puedo lograr lo mismo en Swift? Encontré una función:

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

Sin embargo, es muy largo y no es conveniente en absoluto.

Yo uso la siguiente solución:

1) crear extensión:

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

2) en el archivo Localizable.strings :

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

3) ejemplo de uso:

 myLabel.text = "Hi".localized 

¡disfrutar! 😉

–upd: –

para el caso con comentarios puede usar esta solución:

1) Extensión:

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

2) en el archivo .strings:

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

3) usando:

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

NSLocalizedString existe también en el mundo de Swift.

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

Los tableName , bundle y value están marcados con una palabra clave default que significa que podemos omitir estos parámetros al llamar a la función. En este caso, se usarán sus valores predeterminados.

Esto lleva a la conclusión de que la llamada al método se puede simplificar a:

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

Al usar esta manera, es posible crear una implementación diferente para diferentes tipos (es decir, clases Int o personalizadas como CurrencyUnit, …). También es posible escanear en busca de este método utilizando la utilidad genstrings. Simplemente agregue la bandera de rutina al comando

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

extensión:

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

uso:

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

Una variación de las respuestas existentes:

Swift 4:

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

Luego puede simplemente usarlo con o sin comentarios:

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

Sin embargo, tenga en cuenta que las genstrings no funcionarán con esta solución.

Se creó un pequeño método de ayuda para los casos, donde el “comentario” siempre se ignora. Menos código es más fácil de leer:

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

Simplemente colóquelo en cualquier lugar (fuera de una clase) y Xcode encontrará este método global.

Swift 3 versión:) …

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

Probablemente la mejor manera es esta aquí .

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

y

 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 :(!") } 

puedes usarlo así

 let message: String = .ThisApplicationIsCreated print(message) 

para mí esto es lo mejor porque

  • Las cadenas codificadas están en un archivo específico, por lo que el día que desee cambiarlo es realmente fácil
  • Más fácil de usar que escribir manualmente las cadenas en su archivo cada vez
  • genstrings todavía funcionará
  • puede agregar más extensiones, como un controlador por vista para mantener las cosas ordenadas

En realidad, puede usar dos fases para traducir sus textos en proyectos de Swift:

1) La primera fase está usando la antigua manera de crear todas las cadenas traducibles:

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

1.1) Entonces deberías usar genstrings para generar Localizable.strings:

 $ genstrings *swift 

2) Luego, debes usar esta respuesta .

2.1) Use su opción XCode “Buscar y reemplazar” basada en la expresión regular. En cuanto al ejemplo dado (si no tiene comentarios), la expresión regular será:

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

y reemplazarlo con

 $1.localized 

o (si tiene comentarios)

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

y reemplazarlo con

 $1.localizedWithComment(comment: $2) 

Puedes jugar con expresiones regulares y diferentes combinaciones de extensiones como desees. La forma general es dividir todo el proceso en dos fases. Espero que ayude.

Cuando estás desarrollando un SDK. Necesitas alguna operación adicional.

1) crea Localizable.strings como de costumbre en YourLocalizeDemoSDK.

2) crea la misma Localizable.strings en YourLocalizeDemo.

3) encuentre su ruta de paquete 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)) ayuda a encontrar el paquete en YourLocalizeDemoSDK. Si utiliza Bundle.main en Bundle.main lugar, obtendrá un valor incorrecto (de hecho, será la misma cadena con la clave).

Pero si desea usar la extensión de cadena mencionada por dr OX . Necesitas hacer algo más. La extensión de origen se ve así.

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

Como sabemos, estamos desarrollando un SDK, Bundle.main obtendrá el paquete del paquete de YourLocalizeDemo. Eso no es lo que queremos. Necesitamos el paquete en YourLocalizeDemoSDK. Este es un truco para encontrarlo rápidamente.

Ejecute el código siguiente en una instancia de NSObject en YourLocalizeDemoSDK. Y obtendrá la URL de YourLocalizeDemoSDK.

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

Imprima las dos URL, encontrará que podemos comstackr la base bundleURLofSDK en mainBundleURL. En este caso, será:

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

Y la extensión String será:

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

Espero eso ayude.

Creé mi propia herramienta de genstrings para extraer cadenas usando una función de traducción personalizada

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

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

Analizará todos sus archivos rápidos y exportará las cadenas y comentarios en su código a un archivo .strings.

Probablemente no sea la forma más fácil de hacerlo, pero es posible.

Aunque esto no responde al problema de acortamiento, pero esto me ayudó a organizar los mensajes, creé una estructura para los mensajes de error como a continuación

 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 esta forma puedes organizar los mensajes y hacer que las genstrings funcionen.

Y este es el comando genstrings utilizado

 find ./ -name \*.swift -print0 | xargs -0 genstrings -o .en.lproj 

Útil para el uso en pruebas unitarias:

Esta es una versión simple que se puede extender a diferentes casos de uso (por ejemplo, con el uso de tableNames).

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

Úselo así:

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

O así con un comentario:

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

Cuando tengo una fuente pero varios objectives (traducciones), por ejemplo, para los diferentes géneros gtwigticales que uso (Swift 3)

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

Localización con el idioma predeterminado:

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