Mon application doit prendre en charge les langues arabe (de droite à gauche) et anglaise (de gauche à droite), je dois définir l'interface utilisateur et en fonction de la langue de sélection de l'utilisateur de mon application.
Je vais implémenter l'interface utilisateur avec NSLayoutConstraint afin qu'il puisse la mettre à jour automatiquement, en fonction des contraintes de début et de fin.
Maintenant, ma question est: comment puis-je y parvenir? Comme la langue de mon appareil est l'anglais et que l'utilisateur de mon application sélectionne l'arabe (uniquement pour mon application), mon flux, mon interface utilisateur, mes animations, etc. doivent être placés de droite à gauche.
voici l'exemple d'échantillon pour ui Direction
Merci
En bout de ligne, vous pouvez changer la langue depuis l’application. Mais, un un travail supplémentaire est nécessaire. J'énumère de l'information sur les limites de chaque version d'iOS, puis fournit la solution. parce que tout en expliquant la solution, vous devez comprendre la raison derrière celle-ci.
Clé de la solution: semanticContentAttribute
Certains disent que cette façon de faire n'est pas officielle et peut causer des problèmes d'efficacité.
La direction de l'interface utilisateur peut être forcée maintenant sans fermer l'application:
UIView.appearance().semanticContentAttribute = .forceRightToLeft
Notez que les barres dans iOS 9 ne peuvent pas être forcées à RTL (Navigation et TabBar). Bien qu'il soit forcé avec iOS 10.
La dernière chose qui ne peut pas être forcée dans RTL dans iOS 10 est le bouton Précédent par défaut.
Changer la langue de l'application avec forcer la mise en page ne le fait pas oblige automatiquement le système à utiliser le fichier de chaîne localisé associé à la langue.
Réponse courte:
Changer la langue de l'application ne force pas la direction de la mise en page en fonction de la langue sélectionnée sans redémarrage de l'application.
Guide de Apple:
Apple ne fournit pas cela parce qu'ils ne préfèrent pas autoriser l'utilisateur pour changer la langue de l'intérieur de l'application. Apple pousse les développeurs à utiliser la langue de l'appareil. et ne pas le changer de l'intérieur de l'application du tout.
Workarwound:
Certaines applications qui prennent en charge la langue arabe note l'utilisateur, dans le page de paramètres où l'utilisateur peut changer de langue, que la mise en page ne prendra pas en compte sans un redémarrage de l'application. le magasin lien pour exemple d'application
Exemple de code pour changer la langue de l'application en arabe:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"ar", @"en", nil] forKey:@"AppleLanguages"];
Cela ne prendra pas effet sans redémarrage
La solution consiste à fournir votre propre solution de localisation:
ViewController
qui commence avant toute autre ViewController
même avant votre principale. OU utilise une unwindSegue
pour revenir au contrôleur de vue racine après avoir changé de langue.viewDidLoad
pour tous les contrôleurs de vue.Ne répondez pas aux points 5 et 6 si vous ne supportez pas iOS 9
Définissez les contraintes pour vos vues dans la méthode viewDidLoad
pour tous les contrôleurs de vue.
Lorsque vous définissez les contraintes, utilisez right/left en fonction de la langue sélectionnée au lieu de lead/fin.
Exemple de classe de langue (Swift): Initialisez un objet de cette classe dans votre classe singlton.
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: "")
}
}
Exemple de classe de langue (Objective-c): Un échantillon de Swift fournit une solution complète. désolé vous avez besoin de le convertir vous-même.
@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
utilisez Marges de disposition directionnelle (iOS 11.0+)
et définissez Vues sur
De droite à gauche
UIView.appearance().semanticContentAttribute = .forceRightToLeft
De gauche à droite
UIView.appearance().semanticContentAttribute = .forceLeftToRight