Sur iPhone NSLocalizedString
renvoie la chaîne dans la langue de l'iPhone. Est-il possible de forcer NSLocalizedString
à utiliser une langue spécifique pour que l'application soit dans une langue différente de celle de l'appareil?
Sur iPhone NSLocalizedString
renvoie la chaîne dans la langue de l'iPhone. Est-il possible de forcer NSLocalizedString
à utiliser une langue spécifique pour que l'application soit dans une langue différente de celle de l'appareil?
Réponses:
NSLocalizedString()
(et ses variantes) accédez à la clé "AppleLanguages" NSUserDefaults
pour déterminer quels sont les paramètres de l'utilisateur pour les langues préférées. Cela renvoie un tableau de codes de langue, le premier étant celui défini par l'utilisateur pour son téléphone, et les suivants utilisés comme solutions de rechange si une ressource n'est pas disponible dans la langue préférée. (sur le bureau, l'utilisateur peut spécifier plusieurs langues avec une commande personnalisée dans les Préférences Système)
Vous pouvez remplacer le paramètre global de votre propre application si vous le souhaitez en utilisant la méthode setObject: forKey: pour définir votre propre liste de langues. Cela aura priorité sur la valeur définie globalement et sera renvoyé à tout code de votre application qui effectue la localisation. Le code pour cela ressemblerait à quelque chose comme:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate
Cela ferait de l'allemand la langue préférée pour votre application, avec l'anglais et le français comme solutions de rechange. Vous voudriez l'appeler quelque temps au début du démarrage de votre application. Vous pouvez en savoir plus sur les préférences de langue / paramètres régionaux ici: Rubriques de programmation d'internationalisation: obtenir la langue et les paramètres régionaux actuels
J'ai eu le même problème récemment et je ne voulais pas démarrer et corriger l'intégralité de ma NSLocalizedString ni forcer l'application à redémarrer pour que la nouvelle langue fonctionne. Je voulais que tout fonctionne tel quel.
Ma solution était de changer dynamiquement la classe du bundle principal et d'y charger le bundle approprié:
En tête de fichier
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
la mise en oeuvre
#import <objc/runtime.h>
static const char _bundle=0;
@interface BundleEx : NSBundle
@end
@implementation BundleEx
-(NSString*)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
NSBundle* bundle=objc_getAssociatedObject(self, &_bundle);
return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName];
}
@end
@implementation NSBundle (Language)
+(void)setLanguage:(NSString*)language
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
object_setClass([NSBundle mainBundle],[BundleEx class]);
});
objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
Donc, fondamentalement, lorsque votre application démarre et avant de charger votre premier contrôleur, appelez simplement:
[NSBundle setLanguage:@"en"];
Lorsque votre utilisateur change sa langue préférée dans votre écran de configuration, il vous suffit de l'appeler à nouveau:
[NSBundle setLanguage:@"fr"];
Pour rétablir les valeurs par défaut du système, passez simplement nil:
[NSBundle setLanguage:nil];
Prendre plaisir...
Pour ceux qui ont besoin d'une version Swift:
var bundleKey: UInt8 = 0
class AnyLanguageBundle: Bundle {
override func localizedString(forKey key: String,
value: String?,
table tableName: String?) -> String {
guard let path = objc_getAssociatedObject(self, &bundleKey) as? String,
let bundle = Bundle(path: path) else {
return super.localizedString(forKey: key, value: value, table: tableName)
}
return bundle.localizedString(forKey: key, value: value, table: tableName)
}
}
extension Bundle {
class func setLanguage(_ language: String) {
defer {
object_setClass(Bundle.main, AnyLanguageBundle.self)
}
objc_setAssociatedObject(Bundle.main, &bundleKey, Bundle.main.path(forResource: language, ofType: "lproj"), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
Je fais généralement cela de cette façon, mais vous DEVEZ avoir tous les fichiers de localisation dans votre projet.
@implementation Language
static NSBundle *bundle = nil;
+(void)initialize
{
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString *current = [[languages objectAtIndex:0] retain];
[self setLanguage:current];
}
/*
example calls:
[Language setLanguage:@"it"];
[Language setLanguage:@"de"];
*/
+(void)setLanguage:(NSString *)l
{
NSLog(@"preferredLang: %@", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];
bundle = [[NSBundle bundleWithPath:path] retain];
}
+(NSString *)get:(NSString *)key alter:(NSString *)alternate
{
return [bundle localizedStringForKey:key value:alternate table:nil];
}
@end
Ne l'utilisez pas sur iOS 9. Cela renvoie zéro pour toutes les chaînes qui y sont passées.
J'ai trouvé une autre solution qui vous permet de mettre à jour les chaînes de langue, sans redémarrer l'application et compatible avec genstrings:
Mettez cette macro dans Prefix.pch:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
et partout où vous avez besoin d'une utilisation de chaîne localisée:
NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")
Pour définir l'utilisation de la langue:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
Fonctionne même avec un saut de langue consécutif comme:
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"fr"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"it"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
Comme dit précédemment, faites simplement:
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];
Mais pour éviter d'avoir à redémarrer l'application, mettez la ligne dans la méthode principale de main.m
, juste avant UIApplicationMain
(...).
NSAutoreleasePool * pool ..
Cela peut sembler évident pour les non-débutants, mais vous devez insérer cette ligne après ou quelques objets libérés automatiquement fuiront.
[[NSBundle mainBundle] URLForResource:withExtension:]
avant.
L'astuce pour utiliser une langue spécifique en la sélectionnant dans l'application consiste à forcer l' NSLocalizedString
utilisation d'un ensemble spécifique en fonction de la langue sélectionnée,
voici le post que j'ai écrit pour cette localisation avancée de l'apprentissage dans les applications ios
et voici le code d'un exemple de localisation avancée de l' application dans les applications ios
Que pensez-vous de cette solution pour Swift 3?
extension String {
func localized(forLanguage language: String = Locale.preferredLanguages.first!.components(separatedBy: "-").first!) -> String {
guard let path = Bundle.main.path(forResource: language == "en" ? "Base" : language, ofType: "lproj") else {
let basePath = Bundle.main.path(forResource: "Base", ofType: "lproj")!
return Bundle(path: basePath)!.localizedString(forKey: self, value: "", table: nil)
}
return Bundle(path: path)!.localizedString(forKey: self, value: "", table: nil)
}
}
Utilisation simple:
"report".localized(forLanguage: "pl") //forced language
"report".localized() //default language selected by user in settings, in case when your app doesnt support selected lanaguage, the default one is selected, here is an english.
Comme le mentionne Brian Webster, la langue doit être définie "quelque temps au début du démarrage de votre application". J'ai pensé que applicationDidFinishLaunching:
le AppDelegate
devrait être un endroit approprié pour le faire, car c'est là que je fais toutes les autres initialisations.
Mais comme William Denniss le mentionne, cela ne semble avoir d'effet qu'après le redémarrage de l'application, ce qui est en quelque sorte inutile.
Cela semble bien fonctionner si je mets le code dans la fonction principale, cependant:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Force language to Swedish.
[[NSUserDefaults standardUserDefaults]
setObject:[NSArray arrayWithObject:@"sv"]
forKey:@"AppleLanguages"];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
J'apprécierais tout commentaire à ce sujet.
[[NSUserDefaults standardUserDefaults] synchronize];
après avoir appelésetObject:forKey:
J'aime mieux la méthode de Mauro Delrio. J'ai également ajouté ce qui suit dans mon Project_Prefix.pch
#import "Language.h"
#define MyLocalizedString(key, alt) [Language get:key alter:alt]
Donc, si vous souhaitez utiliser la méthode standard (qui utilise NSLocalizedString), vous pouvez effectuer une substitution de syntaxe rapide dans tous les fichiers.
NSLocalizedString()
lit la valeur de la clé à AppleLanguages
partir des valeurs par défaut de l'utilisateur standard ( [NSUserDefaults standardUserDefaults]
). Il utilise cette valeur pour choisir une localisation appropriée parmi toutes les localisations existantes au moment de l'exécution. Quand Apple crée le dictionnaire des valeurs par défaut de l'utilisateur au lancement de l'application, il recherche la clé de langue préférée dans les préférences système et copie la valeur à partir de là. Cela explique également par exemple pourquoi la modification des paramètres de langue dans OS X n'a aucun effet sur l'exécution des applications, uniquement sur les applications démarrées par la suite. Une fois copiée, la valeur n'est pas mise à jour simplement parce que les paramètres changent. C'est pourquoi iOS redémarre toutes les applications si vous changez de langue.
Cependant, toutes les valeurs du dictionnaire par défaut de l'utilisateur peuvent être remplacées par des arguments de ligne de commande. Voir la NSUserDefaults
documentation sur le NSArgumentDomain
. Cela inclut même les valeurs chargées à partir du fichier de préférences de l'application (.plist). C'est vraiment bon de savoir si vous voulez changer une valeur une seule fois pour le tester .
Donc, si vous voulez changer la langue juste pour les tests, vous ne voudrez probablement pas modifier votre code (si vous oubliez de supprimer ce code plus tard ...), dites plutôt à Xcode de démarrer votre application avec des paramètres de ligne de commande ( par exemple utiliser la localisation espagnole):
Pas besoin de toucher à votre code. Il suffit de créer différents schémas pour différentes langues et vous pouvez rapidement démarrer l'application une fois dans une langue et une fois dans une autre en changeant simplement le schéma.
Options
comme dans les versions Xcode plus récentes qu'Apple propose ainsi que.
J'ai trouvé une solution qui vous permet d'utiliser NSLocalizedString
. Je crée une catégorie d' NSBundle
appel NSBundle+RunTimeLanguage
. L'interface est comme ça.
// NSBundle+RunTimeLanguage.h
#import <Foundation/Foundation.h>
@interface NSBundle (RunTimeLanguage)
#define NSLocalizedString(key, comment) [[NSBundle mainBundle] runTimeLocalizedStringForKey:(key) value:@"" table:nil]
- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName;
@end
L'implémentation est comme ça.
// NSBundle+RunTimeLanguage.m
#import "NSBundle+RunTimeLanguage.h"
#import "AppDelegate.h"
@implementation NSBundle (RunTimeLanguage)
- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSString *path= [[NSBundle mainBundle] pathForResource:[appDelegate languageCode] ofType:@"lproj"];
NSBundle *languageBundle = [NSBundle bundleWithPath:path];
NSString *localizedString=[languageBundle localizedStringForKey:key value:key table:nil];
return localizedString;
}
@end
Ensuite, ajoutez simplement l'importation NSBundle+RunTimeLanguage.h
dans les fichiers qui utilisent NSLocalizedString
.
Comme vous pouvez le voir, je stocke mon languageCode dans une propriété de AppDelegate
. Cela pourrait être stocké où vous le souhaitez.
Cette seule chose que je n'aime pas, c'est un avertissement que NSLocalizedString
marco a redéfini. Peut-être que quelqu'un pourrait m'aider à réparer cette partie.
#undef NSLocalizedString
juste avant #define
pour désactiver l'avertissement
C'est la première chose que vous devez faire est de localiser votre application avec au moins deux langues (anglais et français dans cet exemple).
Dans votre code, au lieu d'utiliser NSLocalizedString(key, comment)
, utilisez une macro MYLocalizedString(key, comment)
définie comme ceci:
#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];
Ce MYLocalizationSystem
singleton:
Lorsque l'utilisateur a changé la langue de l'application en français, appelez [[MYLocalizationSystem sharedInstance] setLanguage:@"fr"];
- (void)setLanguage:(NSString *)lang
{
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj"];
if (!path)
{
_bundle = [NSBundle mainBundle];
NSLog(@"Warning: No lproj for %@, system default set instead !", lang);
return;
}
_bundle = [NSBundle bundleWithPath:path];
}
Dans cet exemple, cette méthode définit le bundle localisé sur fr.lproj
Une fois que vous avez défini le bundle localisé, vous pourrez obtenir la bonne chaîne localisée de lui avec cette méthode:
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value
{
// bundle was initialized with [NSBundle mainBundle] as default and modified in setLanguage method
return [self.bundle localizedStringForKey:key value:value table:nil];
}
J'espère que ceci vous aidera.
Vous trouverez plus de détails dans cet article de NSWinery.io
Extensions Swift 3:
extension Locale {
static var preferredLanguage: String {
get {
return self.preferredLanguages.first ?? "en"
}
set {
UserDefaults.standard.set([newValue], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
}
}
}
extension String {
var localized: String {
var result: String
let languageCode = Locale.preferredLanguage //en-US
var path = Bundle.main.path(forResource: languageCode, ofType: "lproj")
if path == nil, let hyphenRange = languageCode.range(of: "-") {
let languageCodeShort = languageCode.substring(to: hyphenRange.lowerBound) // en
path = Bundle.main.path(forResource: languageCodeShort, ofType: "lproj")
}
if let path = path, let locBundle = Bundle(path: path) {
result = locBundle.localizedString(forKey: self, value: nil, table: nil)
} else {
result = NSLocalizedString(self, comment: "")
}
return result
}
}
Usage:
Locale.preferredLanguage = "uk"
label.text = "localizedKey".localized
Dans le fichier .pch à définir:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")
Vous devriez peut-être compléter avec ceci (sur le fichier .pch après #import):
extern NSBundle* bundle; // Declared on Language.m
#ifdef NSLocalizedString
#undef NSLocalizedString
// Delete this line to avoid warning
#warning "Undefining NSLocalizedString"
#endif
#define NSLocalizedString(key, comment) \
[bundle localizedStringForKey:(key) value:@"" table:nil]
Solution Swift 3:
let languages = ["bs", "zh-Hant", "en", "fi", "ko", "lv", "ms", "pl", "pt-BR", "ru", "sr-Latn", "sk", "es", "tr"]
UserDefaults.standard.set([languages[0]], forKey: "AppleLanguages")
Donné quelques exemples de codes de langue qui peuvent être utilisés. J'espère que cela t'aides
Vous pouvez créer un sous-ensemble avec l'ensemble de chaînes localisées avec lesquelles vous souhaitez effectuer cette opération, puis les utiliser NSLocalizedStringFromTableInBundle()
pour les charger. (Je suppose qu'il s'agit d'un contenu distinct de la localisation normale de l'interface utilisateur que vous effectuez sur l'application.)
pour mon cas j'ai deux fichiers localisés, ja et en
et je voudrais le forcer à en si la langue préférée dans le système n'est ni en ni ja
je vais éditer le fichier main.m
je vais vérifier si la première préférence est en ou ja, sinon je changerai la deuxième langue préférée en en.
int main(int argc, char *argv[])
{
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSString *lang = [[NSLocale preferredLanguages] objectAtIndex:0];
if (![lang isEqualToString:@"en"] && ![lang isEqualToString:@"ja"]){
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[NSLocale preferredLanguages]];
[array replaceObjectAtIndex:1 withObject:@"en"];
[[NSUserDefaults standardUserDefaults] setObject:array forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
Vous pouvez faire quelque chose comme ça:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];
NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):
Basé sur la réponse de Tudorizer pour changer de langue sans quitter ni redémarrer l'application.
Au lieu d'une macro, utilisez une classe pour accéder à la langue préférée afin de vérifier si un code de langue spécifique est présent.
Vous trouverez ci-dessous une classe utilisée pour obtenir le pack de langue actuel qui fonctionne pour iOS 9:
@implementation OSLocalization
+ (NSBundle *)currentLanguageBundle
{
// Default language incase an unsupported language is found
NSString *language = @"en";
if ([NSLocale preferredLanguages].count) {
// Check first object to be of type "en","es" etc
// Codes seen by my eyes: "en-US","en","es-US","es" etc
NSString *letterCode = [[NSLocale preferredLanguages] objectAtIndex:0];
if ([letterCode rangeOfString:@"en"].location != NSNotFound) {
// English
language = @"en";
} else if ([letterCode rangeOfString:@"es"].location != NSNotFound) {
// Spanish
language = @"es";
} else if ([letterCode rangeOfString:@"fr"].location != NSNotFound) {
// French
language = @"fr";
} // Add more if needed
}
return [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]];
}
/// Check if preferred language is English
+ (BOOL)isCurrentLanguageEnglish
{
if (![NSLocale preferredLanguages].count) {
// Just incase check for no items in array
return YES;
}
if ([[[NSLocale preferredLanguages] objectAtIndex:0] rangeOfString:@"en"].location == NSNotFound) {
// No letter code for english found
return NO;
} else {
// Tis English
return YES;
}
}
/* Swap language between English & Spanish
* Could send a string argument to directly pass the new language
*/
+ (void)changeCurrentLanguage
{
if ([self isCurrentLanguageEnglish]) {
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
} else {
[[NSUserDefaults standardUserDefaults] setObject:@[@"en"] forKey:@"AppleLanguages"];
}
}
@end
Utilisez la classe ci-dessus pour référencer un fichier de chaîne / image / vidéo / etc:
// Access a localized image
[[OSLocalization currentLanguageBundle] pathForResource:@"my_image_name.png" ofType:nil]
// Access a localized string from Localizable.strings file
NSLocalizedStringFromTableInBundle(@"StringKey", nil, [OSLocalization currentLanguageBundle], @"comment")
Modifiez la langue en ligne comme ci-dessous ou mettez à jour la méthode "changeCurrentLanguage" dans la classe ci-dessus pour prendre un paramètre de chaîne référençant la nouvelle langue.
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
Dans swift 4, je l'ai résolu sans avoir besoin de redémarrer ou d'utiliser des bibliothèques.
Après avoir essayé de nombreuses options, j'ai trouvé cette fonction, où vous passez la chaîneToLocalize (de Localizable.String, le fichier de chaînes) que vous souhaitez traduire, et la langue dans laquelle vous souhaitez la traduire, et ce qu'elle renvoie est la valeur de cette chaîne que vous avez dans le fichier Strings:
func localizeString (stringToLocalize: String, language: String) -> String
{
let path = Bundle.main.path (forResource: language, ofType: "lproj")
let languageBundle = Bundle (path: path!)
return languageBundle! .localizedString (forKey: stringToLocalize, value: "", table: nil)
}
Compte tenu de cette fonction, j'ai créé cette fonction dans un fichier Swift:
struct CustomLanguage {
func createBundlePath () -> Bundle {
let selectedLanguage = //recover the language chosen by the user (in my case, from UserDefaults)
let path = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj")
return Bundle(path: path!)!
}
}
Pour accéder à partir de l'application entière, et dans chaque chaîne du reste de ViewControllers, au lieu de mettre:
NSLocalizedString ("StringToLocalize", comment: “")
Je l'ai remplacé par
let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()
NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String
Je ne sais pas si c'est le meilleur moyen, mais je l'ai trouvé très simple, et ça marche pour moi, j'espère que ça vous aide!
Cette fonction essaiera d'obtenir une chaîne localisée pour la langue actuelle et si elle n'est pas trouvée, elle l'obtiendra en utilisant la langue anglaise.
- (NSString*)L:(NSString*)key
{
static NSString* valueNotFound = @"VALUE_NOT_FOUND";
static NSBundle* enBundle = nil;
NSString* pl = [NSLocale preferredLanguages][0];
NSString* bp = [[NSBundle mainBundle] pathForResource:pl ofType:@"lproj"];
NSBundle* b = [NSBundle bundleWithPath:bp];
NSString* s = [b localizedStringForKey:key value:valueNotFound table:nil];
if ( [s isEqualToString:valueNotFound] ) {
if ( !enBundle ) {
bp = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
enBundle = [NSBundle bundleWithPath:bp];
}
s = [enBundle localizedStringForKey:key value:key table:nil];
}
return s;
}
Je voulais ajouter la prise en charge d'une langue qui n'est pas officiellement prise en charge par iOS (non répertoriée dans la section Langue sous les paramètres système). En suivant le tutoriel d'internationalisation d'Apple et quelques conseils ici de Brian Webster et geon, j'ai trouvé ce morceau de code (mettez-le dans main.m):
int main(int argc, char * argv[]) {
@autoreleasepool {
// Grab regional settings locale, for Slovenian this is either sl_SI or en_SI
NSLocale *locale = [NSLocale currentLocale];
NSString *ll = [locale localeIdentifier]; // sl_SI
// Grab the first part of language identifier
NSArray *comp = [ll componentsSeparatedByString:@"_"];
NSString *ll1 = @"en";
if (comp.count > 0) {
ll1 = comp[0]; // sl, en, ...
}
// Check if we already saved language (user can manually change it inside app for example)
if (![[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"]) {
// Slovenian (Slovenia), Slovenia
if ([ll isEqualToString:@"sl_SI"] || [ll isEqualToString:@"en_SI"]) {
ll1 = @"sl-SI"; // This is the part of localized path for Slovenian language that Xcode generates
}
// Add more unsupported languages here...
[[NSUserDefaults standardUserDefaults] setObject:ll1 forKey:@"SelectedLanguage"]; // Save language
}
else {
// Restore language as we have previously saved it
ll1 = [[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"];
}
// Overwrite NSLocalizedString and StoryBoard language preference
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:ll1, @"en", @"fr", nil] forKey:@"AppleLanguages"];
// Make sure settings are stored to disk
[[NSUserDefaults standardUserDefaults] synchronize];
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
Cela fonctionne bien pour le code Storyboard et NSLocalizedString. Le code suppose que l'utilisateur aura la possibilité de changer manuellement la langue dans l'application ultérieurement.
Bien sûr, n'oubliez pas d'ajouter les traductions de Storyboard et les traductions de Localizable.strings appropriées (voir le lien vers la page Apple ci-dessus pour savoir comment faire).
Voici une solution décente à ce problème, et elle ne nécessite pas de redémarrage de l'application.
https://github.com/cmaftuleac/BundleLocalization
Cette implémentation fonctionne en modifiant l'intérieur de NSBundle. L'idée est que vous remplacez la méthode localizedStringForKey sur l'instance de l'objet NSBundle, puis appelez cette méthode sur un bundle différent avec un langage différent. Simple et élégant entièrement compatible avec tous les types de ressources.
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj" ];
quoi que vous fassiez tous, la meilleure façon est de prendre le short_name pour la langue spécifiée, c'est-à-dire: fr, en, nl, de, it, etc ... et de l'attribuer à une valeur globale.
faire apparaître une vue de sélecteur comme un menu déroulant (combinaison d'un bouton au clic duquel une vue de sélecteur apparaît ci-dessous avec une liste de langues) et sélectionner la langue souhaitée. laissez le nom court être stocké en interne. créez un fichier .h + .m nommé LocalisedString.
Définissez la valeur globale de short_name pour qu'elle soit égale à la valeur obtenue dans LocalisedString.m Lorsque la langue requise est sélectionnée, affectez NSBundlePath pour créer des sous-répertoires de projet pour la langue requise. par exemple, nl.proj, en.proj.
Lorsque le dossier proj particulier est sélectionné, appelez la chaîne localisée pour la langue respective et changez la langue dynamiquement.
pas de règles enfreintes.
Pour Swift, vous pouvez remplacer le main.swift
fichier et y définir la chaîne UserDefaults avant l'exécution de l'application. De cette façon, vous n'avez pas à redémarrer l'application pour voir l'effet souhaité.
import Foundation
import UIKit
// Your initialisation code here
let langCultureCode: String = "LANGUAGE_CODE"
UserDefaults.standard.set([langCultureCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
jumelé avec la suppression de @UIApplicationMain
dans votre AppDelegate.swift
fichier.