ios - multi - ¿Cuál es el equivalente de NSLocalizedString en Swift?
swift create localizable strings (14)
Al usar de 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 este método invocando usando 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 :)")
¿Hay un equivalente Swift de NSLocalizedString(...)
? En Objective-C
, usualmente usamos:
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.
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 se muestra 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 manera usted puede organizar los mensajes y hacer que las cadenas de texto funcionen.
Y este es el comando genstrings utilizado
find ./ -name /*.swift -print0 | xargs -0 genstrings -o .en.lproj
Cuando estás desarrollando un SDK. Necesitas alguna operación extra.
1) cree Localizable.strings como de costumbre en YourLocalizeDemoSDK.
2) crea las mismas cadenas de cadenas localizables en YourLocalizeDemo.
3) encuentra la ruta de tu 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 utilizar 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ás la URL de YourLocalizeDemoSDK.
let bundleURLOfSDK = Bundle(for: type(of: self)).bundleURL
let mainBundleURL = Bundle.main.bundleURL
Imprima los dos url, verá que podemos construir bundleURLofSDK base en mainBundleURL. En este caso, será:
let bundle = Bundle(url: Bundle.main.bundleURL.appendingPathComponent("Frameworks").appendingPathComponent("YourLocalizeDemoSDK.framework")) ?? Bundle.main
Y la extensión de 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.
Cuando se traduce, diga desde el inglés, donde una frase es la misma, a otro idioma donde es diferente (debido al género, las conjugaciones del verbo o la declinación), la forma más simple de NSString en Swift que funciona en todos los casos son los tres argumentos uno . Por ejemplo, la frase en inglés "anterior era", se traduce de manera diferente al ruso para el caso de "peso" ("предыдущ ий был") y para "waist" ("предыдущ ая был а ").
En este caso, necesita dos traducciones diferentes para una Fuente (en términos de la herramienta XLIFF recomendada en WWDC 2018). No se puede lograr con dos argumentos NSLocalizedString, donde "anterior era" será el mismo tanto para la "clave" como para la traducción al inglés (es decir, para el valor). La única forma es usar la forma de los tres argumentos.
NSLocalizedString("previousWasFeminine", value: "previous was", comment: "previousWasFeminine")
NSLocalizedString("previousWasMasculine", value: "previous was", comment: "previousWasMasculine")
donde las teclas ("previousWasFeminine" y "previousWasMasculine") son diferentes.
Sé que el consejo general es traducir la frase como un todo, sin embargo, a veces es demasiado lento e inconveniente.
El NSLocalizedString
también existe en el mundo 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 utilizarán sus valores por defecto.
Esto lleva a la conclusión de que la llamada al método se puede simplificar para:
NSLocalizedString("key", comment: "comment")
En realidad, puedes usar dos fases para traducir tus textos en proyectos Swift:
1) La primera fase está utilizando la forma antigua de crear todas sus cadenas traducibles:
NSLocalisedString("Text to translate", comment: "Comment to comment")
1.1) Entonces debería usar genstrings para generar Localizable.strings:
$ genstrings *swift
2) Después, debes usar esta answer .
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)
Eres libre de 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.
He creado mi propia clase de herramienta 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 swift y exportará las cadenas y los comentarios en su código a un archivo .strings.
Probablemente no sea la forma más fácil de hacerlo, pero es posible.
Localización con 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: "")
}
}
Probablemente la mejor manera es esta here .
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 :(!")
}
entonces puedes usarlo así
let message: String = .ThisApplicationIsCreated
print(message)
para mi esto es lo mejor porque
- Las cadenas codificadas están en un archivo específico, por lo que el día que quiera cambiarlo es muy 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 todo limpio
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.
Una variación de las respuestas existentes:
Swift 4:
extension String {
func localized(withComment comment: String? = nil) -> String {
return NSLocalizedString(self, comment: comment ?? "")
}
}
Entonces puedes simplemente usarlo con o sin comentario:
"Goodbye".localized()
"Hello".localized(withComment: "Simple greeting")
Tenga en cuenta que las genstrings
no funcionarán con esta solución.
Versión Swift 3:) ...
import Foundation
extension String {
var localized: String {
return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
}
}
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 puedes 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) utilizando:
myLabel.text = "Hi".localized(withComment: "with !!!")
Útil para uso en pruebas unitarias:
Esta es una versión simple que puede extenderse 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)
}
Úsalo así:
NSLocalizedString("YOUR-KEY", referenceClass: self)
O así, con un comentario:
NSLocalizedString("YOUR-KEY", referenceClass: self, comment: "usage description")