it-swarm.com.de

So erzwingen Sie, dass NSLocalizedString eine bestimmte Sprache verwendet

Auf dem iPhone NSLocalizedString gibt den String in der Sprache des iPhones zurück. Ist es möglich, NSLocalizedString zu zwingen, eine bestimmte Sprache zu verwenden, damit die App in einer anderen Sprache als das Gerät angezeigt wird?

257
CodeFlakes

NSLocalizedString() (und Varianten davon) greifen auf die Taste "AppleLanguages" in NSUserDefaults zu, um die Einstellungen des Benutzers für bevorzugte Sprachen zu bestimmen. Dies gibt eine Reihe von Sprachcodes zurück, wobei der erste der vom Benutzer für sein Telefon festgelegte ist und die nachfolgenden als Ersatz verwendet werden, wenn eine Ressource nicht in der bevorzugten Sprache verfügbar ist. (Auf dem Desktop kann der Benutzer mehrere Sprachen mit einer benutzerdefinierten Reihenfolge in den Systemeinstellungen angeben.)

Sie können die globale Einstellung für Ihre eigene Anwendung überschreiben, indem Sie die Methode setObject: forKey: verwenden, um Ihre eigene Sprachliste festzulegen. Dies hat Vorrang vor dem global festgelegten Wert und wird an jeden Code in Ihrer Anwendung zurückgegeben, der die Lokalisierung durchführt. Der Code dafür würde ungefähr so ​​aussehen:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate

Dies würde Deutsch zur bevorzugten Sprache für Ihre Bewerbung machen, mit Englisch und Französisch als Fallbacks. Möglicherweise möchten Sie dies zu einem frühen Zeitpunkt beim Start Ihrer Anwendung aufrufen. Weitere Informationen zu den Sprach-/Gebietsschemaeinstellungen finden Sie hier: Themen zur Internationalisierungsprogrammierung: Abrufen der aktuellen Sprache und des Gebietsschemas

254
Brian Webster

Ich hatte vor kurzem das gleiche Problem und wollte nicht mein gesamtes NSLocalizedString starten und patchen und auch nicht den Neustart der App erzwingen, damit die neue Sprache funktioniert. Ich wollte, dass alles so funktioniert, wie es ist.

Meine Lösung bestand darin, die Klasse des Hauptpakets dynamisch zu ändern und das entsprechende Paket dort zu laden:

Header-Datei

@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end

Implementierung

#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

Rufen Sie also beim Starten Ihrer App und vor dem Laden Ihres ersten Controllers einfach Folgendes auf:

[NSBundle setLanguage:@"en"];

Wenn Ihr Benutzer seine bevorzugte Sprache in Ihrem Einstellungsbildschirm ändert, rufen Sie sie einfach erneut auf:

[NSBundle setLanguage:@"fr"];

Übergeben Sie zum Zurücksetzen auf die Systemstandards einfach nil:

[NSBundle setLanguage:nil];

Genießen...

Für diejenigen, die eine Swift version brauchen:

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)
    }
}
142
Gilad Novik

Normalerweise mache ich das so, aber Sie MÜSSEN alle Lokalisierungsdateien in Ihrem Projekt haben.

@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
137
Mauro Delrio

Nicht unter iOS 9 verwenden. Dies gibt null für alle Zeichenfolgen zurück, die durchlaufen werden.

Ich habe eine andere Lösung gefunden, mit der Sie die Sprachstrings aktualisieren können, ohne die App neu zu starten und die mit Genstrings kompatibel ist:

Fügen Sie dieses Makro in die Prefix.pch ein:

#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]

und wo immer Sie eine lokalisierte Zeichenfolge benötigen, verwenden Sie:

NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")

So stellen Sie die Sprache ein:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];

Funktioniert auch mit aufeinanderfolgendem Sprachsprung wie:

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, @""));
41
Tudor

Wie bereits gesagt, machen Sie einfach Folgendes:

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

Um jedoch einen Neustart der App zu vermeiden, setzen Sie die Zeile in die Hauptmethode von main.m, kurz vor UIApplicationMain (...).

31

Der Trick, eine bestimmte Sprache durch Auswahl in der App zu verwenden, besteht darin, das NSLocalizedString zu zwingen, abhängig von der ausgewählten Sprache ein bestimmtes Bundle zu verwenden.

hier ist der Beitrag, den ich dazu geschrieben habe Erlernen der erweiterten Lokalisierung in iOS-Apps

und hier ist der Code einer Beispiel-App erweiterte Lokalisierung in iOS-Apps

31
object2.0

Wie Brian Webster erwähnt, muss die Sprache "irgendwann früh im Start der Anwendung" eingestellt werden. Ich dachte applicationDidFinishLaunching: von AppDelegate sollte ein geeigneter Ort dafür sein, da ich dort alle anderen Initialisierungen vornehme.

Aber wie William Denniss erwähnt, scheint das nur einen Effekt zu haben nach die App wird neu gestartet, was irgendwie nutzlos ist.

Es scheint gut zu funktionieren, wenn ich den Code in die Hauptfunktion stecke:

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;
}

Ich würde mich über Kommentare dazu freuen.

12
geon

Was halten Sie von dieser Lösung für 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)
    }
}

Einfache Bedienung:

"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.

NSLocalizedString() liest den Wert für den Schlüssel AppleLanguages aus den Standardbenutzerstandards ([NSUserDefaults standardUserDefaults]). Dieser Wert wird verwendet, um zur Laufzeit eine geeignete Lokalisierung unter allen vorhandenen Lokalisierungen auszuwählen. Wenn Apple) beim Start der App das Benutzerwörterbuch mit den Standardeinstellungen erstellt, sucht der Benutzer in den Systemeinstellungen nach dem/den Schlüssel (n) der bevorzugten Sprache (n) und kopiert den Wert von dort. Dies erklärt beispielsweise auch, warum die Sprache geändert wird Die Einstellungen in OS X wirken sich nicht auf die Ausführung von Apps aus, sondern nur auf die danach gestarteten Apps. Nach dem Kopieren wird der Wert nicht aktualisiert, nur weil sich die Einstellungen ändern. Deshalb startet iOS alle Apps neu, wenn Sie die Sprache ändern.

alle Werte des Benutzer-Standardwörterbuchs kann jedoch durch Befehlszeilenargumente überschrieben werden. Siehe NSUserDefaults Dokumentation zu NSArgumentDomain. Dies schließt auch die Werte ein, die aus der App-Voreinstellungsdatei (.plist) geladen werden. Das ist wirklich gut zu wissen wenn Sie einen Wert nur einmal zum Testen ändern möchten.

Wenn Sie also die Sprache nur zum Testen ändern möchten, möchten Sie wahrscheinlich Ihren Code nicht ändern (wenn Sie vergessen, diesen Code später zu entfernen ...), sondern Xcode anweisen, Ihre App mit Befehlszeilenparametern zu starten ( zB spanische Lokalisierung verwenden):

enter image description here

Sie müssen Ihren Code überhaupt nicht berühren. Erstellen Sie einfach verschiedene Schemata für verschiedene Sprachen und Sie können die App schnell einmal in einer Sprache und einmal in einer anderen starten, indem Sie einfach das Schema wechseln.

11
Mecki

Mir gefällt die Methode von Mauro Delrio am besten. Ich habe auch das folgende in meinem Project_Prefix.pch hinzugefügt

#import "Language.h"    
#define MyLocalizedString(key, alt) [Language get:key alter:alt]

Wenn Sie also jemals die Standardmethode (die NSLocalizedString verwendet) verwenden möchten, können Sie in allen Dateien eine schnelle Syntaxersetzung vornehmen.

11
dnaxxx

Ich habe eine Lösung gefunden, mit der Sie NSLocalizedString verwenden können. Ich erstelle eine Kategorie von NSBundle call NSBundle+RunTimeLanguage. Die Schnittstelle ist wie folgt.

// 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

Die Implementierung ist wie folgt.

// 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

Als nur Import hinzufügen NSBundle+RunTimeLanguage.h in die Dateien, die NSLocalizedString verwenden.

Wie Sie sehen, speichere ich meinen languageCode in einer Eigenschaft von AppDelegate. Dies kann an einem beliebigen Ort gespeichert werden.

Das einzige, was ich nicht mag, ist eine Warnung, die NSLocalizedString marco neu definiert hat. Vielleicht könnte mir jemand helfen, diesen Teil zu reparieren.

10
qman64

Schnelle Version:

NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()
9
daaniaal

In einer Nussschale :

Lokalisieren Sie Ihre Anwendung

Zunächst müssen Sie Ihre App in mindestens zwei Sprachen (Englisch und Französisch in diesem Beispiel) lokalisieren.

Überschreiben Sie NSLocalizedString

Verwenden Sie in Ihrem Code anstelle von NSLocalizedString(key, comment) ein Makro MYLocalizedString(key, comment), das wie folgt definiert ist: #define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];

Dieser MYLocalizationSystem Singleton wird:

  • Stellen Sie die Sprache ein, indem Sie den richtigen lokalisierten NSBundle-Benutzer angeben
  • Gibt den lokalisierten NSString gemäß dieser zuvor festgelegten Sprache zurück

Benutzersprache einstellen

Wenn der Benutzer die Anwendungssprache auf Französisch geändert hat, rufen Sie [[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];
}

In diesem Beispiel hat diese Methode localized bundle auf fr.lproj gesetzt

Gibt eine lokalisierte Zeichenfolge zurück

Sobald Sie das lokalisierte Bundle festgelegt haben, können Sie mit dieser Methode die richtige lokalisierte Zeichenfolge von ihm abrufen:

- (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];
}

Hoffe das wird dir helfen.

Weitere Details finden Sie in diesem Artikel von NSWinery.io

8
user3465357

Swift 3-Erweiterungen:

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
    }
}

Verwendung:

Locale.preferredLanguage = "uk"

label.text = "localizedKey".localized
6
ChikabuZ

Vielleicht solltest du folgendes ergänzen (in der .pch-Datei nach #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]
4
D33pN16h7

In der Datei . Pch definieren:

#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]


#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")
4
MrPiliffo

Swift 3 Lösung:

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

Gab einige Beispiele von Sprachcodes, die verwendet werden können. Hoffe das hilft

3
Jeremy Bader

Sie können ein Unterbündel mit den lokalisierten Zeichenfolgen erstellen, mit denen Sie dies tun möchten, und dann NSLocalizedStringFromTableInBundle() verwenden, um sie zu laden. (Ich gehe davon aus, dass dies nicht der normalen UI-Lokalisierung entspricht, die Sie möglicherweise in der App vornehmen.)

3
Sixten Otto

für meinen fall habe ich zwei lokalisierte dateien, ja und en

und ich würde es gerne erzwingen, wenn die bevorzugte Sprache im System weder en noch ja ist

ich werde die Datei main.m bearbeiten

ich überprüfe, ob die erste bevorzugte Sprache "en" oder "ja" ist. Wenn nicht, ändere ich die zweite bevorzugte Sprache in "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]));


    }


}
3
chings228

Basierend auf Tudorizer Antwort, um die Sprache zu ändern, ohne das Programm zu verlassen oder neu zu starten

Verwenden Sie anstelle eines Makros eine Klasse für den Zugriff auf die bevorzugte Sprache, um zu überprüfen, ob ein bestimmter Sprachcode vorhanden ist.

Im Folgenden finden Sie eine Klasse, mit der Sie das aktuelle Sprachpaket für iOS 9 erhalten:

@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

Verwenden Sie die obige Klasse, um auf eine String-Datei/image/video/etc zu verweisen:

// 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")

Ändern Sie die Sprache in der folgenden Zeile oder aktualisieren Sie die Methode "changeCurrentLanguage" in der obigen Klasse, um einen Zeichenfolgenparameter zu übernehmen, der auf die neue Sprache verweist.

[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
2
Antonioni

Sie können so etwas tun:

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];


NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];

NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):
2
JERC

In Swift 4 habe ich das Problem behoben, ohne dass ein Neustart oder die Verwendung von Bibliotheken erforderlich war.

Nachdem ich viele Optionen ausprobiert hatte, fand ich diese Funktion, bei der Sie den Wert für stringToLocalize (von Localizable.String, die zu übersetzende Strings-Datei) und die Sprache, in die Sie sie übersetzen möchten, übergeben Die Zeichenfolge, die Sie in der Zeichenfolgendatei haben:

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

Unter Berücksichtigung dieser Funktion habe ich diese Funktion in einer Swift Datei erstellt:

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!)!
    }
}

So greifen Sie über die gesamte App und in jeder Zeichenfolge der übrigen ViewController zu, anstatt Folgendes zu setzen:

NSLocalizedString ("StringToLocalize", comment: “")

Ich habe es durch ersetzt

let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()

NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String

Ich weiß nicht, ob es der beste Weg ist, aber ich fand es sehr einfach, und es funktioniert bei mir, ich hoffe, es hilft dir!

1
ainareta685

Ich wollte Unterstützung für eine Sprache hinzufügen, die von iOS nicht offiziell unterstützt wird (nicht im Abschnitt Sprache unter den Systemeinstellungen aufgeführt). Indem ich dem Apples Internationalization Tutorial und ein paar Hinweisen von Brian Webster und Geon folgte, kam ich auf diesen Code (in 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]));
    }
}

Dies funktioniert sowohl für Storyboard- als auch für NSLocalizedString-Code. Der Code setzt voraus, dass der Benutzer die Möglichkeit hat, die Sprache später in der App manuell zu ändern.

Vergessen Sie natürlich nicht, die richtigen Storyboard-Übersetzungen und Localizable.strings-Übersetzungen hinzuzufügen (siehe Link zu Apple Seite oben, um zu erfahren, wie das geht).

1
frin

Diese Funktion versucht, eine lokalisierte Zeichenfolge für die aktuelle Sprache zu erhalten. Wird sie nicht gefunden, wird die englische Sprache verwendet.

- (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;
}
1
Cherpak Evgeny

Hier ist eine anständige Lösung für dieses Problem, und es ist kein Neustart der Anwendung erforderlich.

https://github.com/cmaftuleac/BundleLocalization

Diese Implementierung funktioniert durch Optimierung in NSBundle. Die Idee ist, dass Sie die Methode localizedStringForKey für die Instanz des NSBundle-Objekts überschreiben und diese Methode dann für ein anderes Bundle mit einer anderen Sprache aufrufen. Einfach und elegant, voll kompatibel mit allen Arten von Ressourcen.

1

was auch immer Sie alle tun, der beste Weg ist, den Kurznamen für die angegebene Sprache zu nehmen, d. h .: fr, en, nl, de, it, etc ... und diesen einem globalen Wert zuzuweisen.

erstellen Sie eine Auswahlansicht, die wie ein Dropdown-Menü angezeigt wird (Kombination einer Schaltfläche, auf die von unten eine Auswahlansicht mit einer Liste von Sprachen angezeigt wird), und wählen Sie die gewünschte Sprache aus. Lassen Sie den Kurznamen intern speichern. Erstellen Sie eine .h + .m-Datei mit dem Namen LocalisedString.

Setzen Sie den globalen Wert von short_name auf den in LocalisedString.m erhaltenen Wert. Wenn die gewünschte Sprache ausgewählt ist, weisen Sie NSBundlePath zu, um Projekt-Unterverzeichnisse für die gewünschte Sprache zu erstellen. für zB nl.proj, en.proj.

Wenn der jeweilige proj-Ordner ausgewählt ist, rufen Sie den lokalisierten String für die jeweilige Sprache auf und ändern Sie die Sprache dynamisch.

keine Regeln gebrochen.

0
Abhijeet

Für Swift) können Sie die Datei main.Swift Überschreiben und den UserDefaults-String dort festlegen, bevor Sie die App ausführen. Auf diese Weise müssen Sie die App nicht neu starten, um den gewünschten Effekt zu sehen.

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))

gepaart mit dem Entfernen von @UIApplicationMain in Ihrer AppDelegate.Swift - Datei.

0
Andreas