ios swift xcode localization localizable.strings

ios - ¿Cómo puedo configurar la dirección localizada dentro de la aplicación?(RTL si el usuario selecciona árabe, LTR es el idioma seleccionado es el inglés)



swift xcode (4)

Mi aplicación debe ser compatible con el idioma árabe (de derecha a izquierda) e inglés (de izquierda a derecha). Necesito establecer la interfaz de usuario y, en función del idioma seleccionado por el usuario, de mi aplicación.

Implementaré la interfaz de usuario con NSLayoutConstraint para que pueda actualizar la interfaz de usuario automáticamente, según las restricciones iniciales y finales.

Ahora mi pregunta es ¿cómo puedo lograr esto? Como el idioma de mi dispositivo es inglés y de mi aplicación, el usuario selecciona árabe (limitado solo a mi aplicación), así que mi flujo, interfaz de usuario, animaciones, etc. deben estar de derecha a izquierda.

Aquí está la muestra de ajuste para la dirección de la interfaz de usuario

Gracias


En la línea inferior puede cambiar el idioma desde dentro de la aplicación. Pero, se necesita un trabajo extra. Estoy enumerando un fondo de limitaciones para cada versión de iOS y luego proporciono la solución. porque mientras explica la solución, necesita comprender la razón detrás de ella.

Actualizar (iOS 9+)

Clave de la solución: semanticContentAttribute

Algunos dicen que de esta manera no es oficial y puede causar problemas de eficiencia.

La dirección de la interfaz de usuario se puede forzar ahora sin cerrar la aplicación:

UIView.appearance().semanticContentAttribute = .forceRightToLeft

Nota, las barras en iOS 9 no pueden ser forzadas a RTL (Navegación y TabBar). Mientras se obliga con iOS 10.

Lo único restante que no puede ser forzado RTL en iOS 10 es el botón de retroceso predeterminado.

Cambiar la aplicación del idioma junto con forzar el diseño no obliga automáticamente al sistema a utilizar el archivo de cadena localizado asociado con el idioma.

Por debajo de iOS 9

Respuesta corta:

Cambiar el idioma de la aplicación no forzará la dirección del diseño según el idioma seleccionado sin reiniciar la aplicación.

Línea guía de Apple:

Apple no proporciona eso porque no prefieren permitir que el usuario cambie el idioma desde la aplicación. Apple empuja a los desarrolladores a usar el lenguaje del dispositivo. Y no cambiarlo desde dentro de la aplicación en absoluto.

Workarwound:

Algunas aplicaciones que admiten el idioma árabe indican al usuario, en la página de configuración donde el usuario puede cambiar el idioma, que el diseño no tendrá efecto sin un reinicio de la aplicación. enlace de la tienda para la aplicación de muestra

Código de ejemplo para cambiar el idioma de la aplicación a árabe:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"ar", @"en", nil] forKey:@"AppleLanguages"];

Eso no tendrá efecto sin un reinicio

Cómo cambiar el idioma de la aplicación sin reiniciar la aplicación

La solución es proporcionar su propia solución de localización:

  1. Utiliza la Base Internacionalización pero no localiza guiones gráficos.
  2. Cree un archivo de cadenas y localícelo en todos los idiomas y base para (inglés).
  3. Coloque la función de cambio de idioma en un ViewController que comienza antes que cualquier otro ViewController incluso antes que el principal. O use un unwindSegue para volver al controlador de vista raíz después de cambiar el idioma.
  4. Establezca cadenas para sus vistas en el método viewDidLoad para todos los controladores de vista.

No satisfaga los puntos 5 y 6 si no es compatible con iOS 9

  1. Establezca las restricciones para sus vistas en el método viewDidLoad para todos los controladores de vista.

  2. Cuando configura las restricciones, use la derecha / izquierda de acuerdo con el idioma seleccionado en lugar de al inicio / al final .

Ejemplo de clase de idioma (Swift): Inicializa un objeto de esta clase en tu clase individual.

class LanguageDetails: NSObject { var language: String! var bundle: Bundle! let LANGUAGE_KEY: String = "LANGUAGE_KEY" override init() { super.init() // user preferred languages. this is the default app language(device language - first launch app language)! language = Bundle.main.preferredLocalizations[0] // the language stored in UserDefaults have the priority over the device language. language = Common.valueForKey(key: LANGUAGE_KEY, default_value: language as AnyObject) as! String // init the bundle object that contains the localization files based on language bundle = Bundle(path: Bundle.main.path(forResource: language == "ar" ? language : "Base", ofType: "lproj")!) // bars direction if isArabic() { UIView.appearance().semanticContentAttribute = .forceRightToLeft } else { UIView.appearance().semanticContentAttribute = .forceLeftToRight } } // check if current language is arabic func isArabic () -> Bool { return language == "ar" } // returns app language direction. func rtl () -> Bool { return Locale.characterDirection(forLanguage: language) == Locale.LanguageDirection.rightToLeft } // switches language. if its ar change it to en and vise-versa func changeLanguage() { var changeTo: String // check current language to switch to the other. if language == "ar" { changeTo = "en" } else { changeTo = "ar" } // change language changeLanguageTo(lang: changeTo) Log.info("Language changed to: /(language)") } // change language to a specfic one. func changeLanguageTo(lang: String) { language = lang // set language to user defaults Common.setValue(value: language as AnyObject, key: LANGUAGE_KEY) // set prefered languages for the app. UserDefaults.standard.set([lang], forKey: "AppleLanguages") UserDefaults.standard.synchronize() // re-set the bundle object based on the new langauge bundle = Bundle(path: Bundle.main.path(forResource: language == "ar" ? language : "Base", ofType: "lproj")!) // app direction if isArabic() { UIView.appearance().semanticContentAttribute = .forceRightToLeft } else { UIView.appearance().semanticContentAttribute = .forceLeftToRight } Log.info("Language changed to: /(language)") } // get local string func getLocale() -> NSLocale { if rtl() { return NSLocale(localeIdentifier: "ar_JO") } else { return NSLocale(localeIdentifier: "en_US") } } // get localized string based on app langauge. func LocalString(key: String) -> String { let localizedString: String? = NSLocalizedString(key, bundle: bundle, value: key, comment: "") // Log.ver("Localized string ''/(localizedString ?? "not found")'' for key ''/(key)''") return localizedString ?? key } // get localized string for specific language func LocalString(key: String, lan: String) -> String { let bundl:Bundle! = Bundle(path: Bundle.main.path(forResource: lan == "ar" ? lan : "Base", ofType: "lproj")!) return NSLocalizedString(key, bundle: bundl, value: key, comment: "") } }

Ejemplo de clase de idioma (Objective-c): Swift sample proporciona una solución completa. lo siento, necesitas convertirlo tú mismo.

@implementation LanguageDetails @synthesize language; @synthesize bundle; #define LANGUAGE_KEY @"LANGUAGE_KEY" // language var is also the strings file name ar or en - (id)init { if (self = [super init]) { language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]; if (![language isEqualToString:@"ar"]) language = @"en"; language = [Common valueForKey:LANGUAGE_KEY defaultValue:language]; bundle = [NSBundle mainBundle]; } return self; } - (BOOL)rtl { return [NSLocale characterDirectionForLanguage:language] == NSLocaleLanguageDirectionRightToLeft; } - (void)changeLanguage { if ([language isEqualToString:@"ar"]) language = @"en"; else language = @"ar"; [Common setValue:language forKey:LANGUAGE_KEY]; } - (void)changeLanguageTo:(NSString *)lang { language = lang; [Common setValue:language forKey:LANGUAGE_KEY]; } - (NSString *) LocalString:(NSString *)key { return NSLocalizedStringFromTableInBundle(key, language, bundle, nil); } @end


@ashwin, estaba tratando de hacer exactamente lo mismo que tú.

Esperaba encontrar que podía convertir mi aplicación en un lenguaje RTL (de derecha a izquierda) simplemente cambiando algo en la lista de información, la lista de aplicaciones o quién sabe qué. La idea es que alguien con un dispositivo LTR pueda tener mi aplicación en RTL, cambiándola dentro de la aplicación y sin necesidad de reiniciarla.

Parece que no hay tal cosa (me alegraría saber si alguien no está de acuerdo con esto). Sin embargo, he encontrado algunas opciones que no son tan malas.

  1. Resulta que puede forzar que una vista específica sea LTR o RTL. Por lo tanto, puede establecer esta propiedad en cada vista de su aplicación. La forma en que lo hagas depende de ti.

    self.view.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;

Referencia: UISemanticContentAttribute

  1. Siempre puede voltear las vistas horizontalmente hasta obtener la configuración deseada.

[view setTransform:CGAffineTransformMakeScale(1, 1)];

Aquí hay un código que podría ayudarte.

void reloadRTLViewAndSubviews(UIView *view) { reloadRTLViews(@[view]); reloadRTLViews([view subviews]); } void reloadRTLViews(NSArray *views) { if (isRTL()) { [views enumerateObjectsUsingBlock:^(UIView* view, NSUInteger idx, BOOL * stop) { [view setTransform:CGAffineTransformMakeScale(-1, 1)]; }]; } else { [views enumerateObjectsUsingBlock:^(UIView* view, NSUInteger idx, BOOL * stop) { [view setTransform:CGAffineTransformMakeScale(1, 1)]; }]; } } BOOL isRTL() { return isRTL_app(); } BOOL isRTL_device() { BOOL isRTL = ([NSLocale characterDirectionForLanguage:[[NSLocale preferredLanguages] objectAtIndex:0]] == NSLocaleLanguageDirectionRightToLeft); return isRTL; } BOOL isRTL_scheme() { BOOL isRTL = ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:[UIView new].semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft); return isRTL; } BOOL isRTL_app() { NSString *languageIdentifier = [AppDataManager sharedManager].languageIdentifier; NSArray *rtl_languages = @[@"ar"]; BOOL isRTL; if ((languageIdentifier == nil) || (languageIdentifier.length == 0)) { isRTL = (isRTL_device() || isRTL_scheme()); } else if ([rtl_languages containsObject:languageIdentifier]) { isRTL = YES; } else { isRTL = NO; } return isRTL; } BOOL deviceLanguageDirectionEqualAppLanguageDirection() { if ((isRTL_device() || isRTL_scheme()) && isRTL())//All RTL { return YES; } else if (!(isRTL_device() || isRTL_scheme()) && !isRTL())//All LTR { return YES; } return NO;//RTL-LTR or LTR-RTL } void transformViews(NSArray *views) { [views enumerateObjectsUsingBlock:^(UIView* view, NSUInteger idx, BOOL * stop) { [view setTransform:CGAffineTransformMakeScale(-1, 1)]; }]; }

Por lo tanto, si tuviera que cambiar un UIViewController para estar en RTL, puede hacer toda la configuración para que sea suficiente para:

reloadRTLViewAndSubviews(self.view);

Nota: esta no es la forma en que debe ser y las pautas de Apple dicen que el idioma debe cambiarse desde la configuración de iOS. Pero esta solución funciona si se debe cambiar el idioma dentro de la aplicación y está implicado un cambio de dirección de idioma entre LTR y RTL. Y tampoco es necesario reiniciar la aplicación.

Espero que haya ayudado.


Use esta línea de código, hará su magia y cambiará el diseño sin cerrar la aplicación. De derecha a izquierda

UIView.appearance().semanticContentAttribute = .forceRightToLeft

Y para voltear de derecha a izquierda.

UIView.appearance().semanticContentAttribute = .forceLeftToRight

y si desea cambiar el diseño del campo de texto o el cambio de texto, use este código porque enfrenté este problema. Los textos de textfield no estaban cambiando de diseño. Verifique este código para cambiar el diseño del texto del campo de texto.

extension UITextField { open override func awakeFromNib() { super.awakeFromNib() if UserDefaults.languageCode == "ar" { if textAlignment == .natural { self.textAlignment = .right } } } }


usar márgenes de diseño direccional (iOS 11.0+)

y establece Vistas a

De derecha a izquierda

UIView.appearance().semanticContentAttribute = .forceRightToLeft

De izquierda a derecha

UIView.appearance().semanticContentAttribute = .forceLeftToRight