سؤال

على اي فون NSLocalizedString ترجع السلسلة في اللغة من اي فون.هل من الممكن أن القوة NSLocalizedString إلى استخدام لغة معينة أن يكون التطبيق في لغة مختلفة من الجهاز ؟

هل كانت مفيدة؟

المحلول

NSLocalizedString() (ومتغيراتها) الوصول إلى مفتاح "Applelangyages" NSUserDefaults لتحديد ما هي إعدادات المستخدم للغات المفضلة. يرجع هذا مجموعة من رموز اللغة، مع أول واحد يجري المحدد من قبل المستخدم لهاتفهم، والأشخاص اللاحقة المستخدمة كمساعدة في حالة عدم توفر مورد في اللغة المفضلة. (على سطح المكتب، يمكن للمستخدم تحديد لغات متعددة مع ترتيب مخصص في تفضيلات النظام)

يمكنك تجاوز الإعداد العالمي للتطبيق الخاص بك إذا كنت ترغب في استخدام SetObject: forkey: الطريقة لتعيين قائمة اللغات الخاصة بك. سيؤدي ذلك إلى الأسبقية على القيمة المحددة عالميا وسيتم إرجاعها إلى أي رمز في التطبيق الخاص بك هو أداء التوطين. الرمز الخاص بهذا سيبدو شيئا مثل:

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

هذا من شأنه أن يجعل اللغة الألمانية اللغة المفضلة للتطبيق الخاص بك، مع اللغة الإنجليزية والفرنسية ككسوات. كنت ترغب في الاتصال بهذا في وقت ما في وقت مبكر من بدء تشغيل التطبيق الخاص بك. يمكنك قراءة المزيد عن تفضيلات اللغة / الإعدادات المحلية هنا: موضوعات البرمجة التدويلية: الحصول على اللغة الحالية ودوري

نصائح أخرى

كان لدي نفس المشكلة مؤخرا ولم أرغب في البدء والتصحيح بلدي بالكامل nslocalizedString. ولا قوة التطبيق لإعادة تشغيل اللغة الجديدة للعمل. أردت كل شيء للعمل كما هو.

كان الحل الخاص بي لتغيير فئة الحزمة الرئيسية في ديناميكيا وتحميل الحزمة المناسبة هناك:

الملف الاساسي

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

التنفيذ

#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

لذلك في الأساس، عندما يبدأ تطبيقك وقبل تحميل وحدة التحكم الأولى، ما عليك سوى الاتصال:

[NSBundle setLanguage:@"en"];

عندما يغير المستخدم لغتك المفضلة في شاشة الإعداد الخاصة بك، ما عليك سوى الاتصال به مرة أخرى:

[NSBundle setLanguage:@"fr"];

لإعادة تعيين العودة إلى إعدادات النظام، ما عليك سوى تمرير NIL:

[NSBundle setLanguage:nil];

يتمتع...

بالنسبة لأولئك الذين يحتاجون إلى نسخة سريعة:

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

عادة ما أفعل ذلك بهذه الطريقة، ولكن يجب أن يكون لديك جميع ملفات التوطين في مشروعك.

@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

لا تستخدم على نظام التشغيل iOS 9. هذا إرجاع لا شيء مقابل جميع الأوتار التي تم تمريرها من خلالها.

لقد وجدت حلا آخر يتيح لك تحديث سلاسل اللغة، W / O إعادة تشغيل التطبيق ومتوافق مع Genstrings:

ضع هذا الماكرو في البادئة.PCH:

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

وأين تحتاج إلى أي وقت تحتاج إلى استخدام سلسلة مترجمة:

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

لتعيين استخدام اللغة:

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

يعمل حتى مع وجود لغة متتالية من التنقل مثل:

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

كما قال في وقت سابق، فقط:

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

ولكن لتجنب الاضطرار إلى إعادة تشغيل التطبيق، ضع الخط في الطريقة الرئيسية لل main.m, ، فقط قبل UIApplicationMain(...).

الخدعة لاستخدام لغة محددة عن طريق تحديده من التطبيق هو إجبار NSLocalizedString لاستخدام حزمة محددة اعتمادا على اللغة المحددة،

هنا هو المنشور الذي كتبته لهذاالتعلم التعريب المسبق في تطبيقات iOS

وهنا هو رمز تطبيق نموذج واحد توطين مسبق في تطبيقات iOS

كما يذكر Brian Webster، يجب تعيين اللغة "في وقت مبكر من بدء تشغيل التطبيق الخاص بك". اعتقدت applicationDidFinishLaunching: التابع AppDelegate يجب أن يكون مكان مناسب للقيام بذلك، لأنه حيث أقوم بكل تهيئة أخرى.

ولكن كما يذكر وليام دينيس، يبدو أن هذا له تأثير فقط بعد يتم إعادة تشغيل التطبيق، وهو نوع عديم الفائدة.

يبدو أنه يعمل بشكل جيد إذا وضعت الكود في الوظيفة الرئيسية، على الرغم من:

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

كنت أقدر أي تعليقات على هذا.

ما رأيك في هذا الحل لسارع 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)
    }
}

استخدام بسيط:

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

أنا أحب أفضل طريقة مورو ديلريو. لقد أضفت أيضا ما يلي في project_prefix.pch

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

لذلك إذا كنت ترغب في استخدام الطريقة القياسية (التي تستخدم nslocalizedString)، يمكنك إجراء استبدال بناء الجملة بسرعة في جميع الملفات.

NSLocalizedString() يقرأ قيمة المفتاح AppleLanguages من المعيار المستخدم الافتراضية ([NSUserDefaults standardUserDefaults]).فإنه يستخدم هذه القيمة إلى اختيار مناسب التعريب بين جميع تعريب القائمة في وقت التشغيل.عندما أبل يبني المستخدم التخلف القاموس على إطلاق التطبيق ، فإنها تبدو حتى يفضل اللغة(اللغات) الرئيسية في تفضيلات النظام ثم نسخ قيمة من هناك.وهذا ما يفسر أيضا لماذا على سبيل المثال تغيير إعدادات اللغة في OS X ليس له أي تأثير على تشغيل تطبيقات فقط على تطبيقات بدأ بعد ذلك.نسخ مرة واحدة ، قيمة لا يتم تحديث فقط لأن تغيير إعدادات.هذا هو السبب في دائرة الرقابة الداخلية تشغيل جميع التطبيقات إذا قمت بتغيير ثم اللغة.

ومع ذلك ، كل القيم المستخدم التخلف القاموس يمكن تجاوزها من قبل وسائط سطر الأوامر.انظر NSUserDefaults الوثائق على NSArgumentDomain.هذا يشمل حتى تلك القيم التي يتم تحميلها من تفضيلات التطبيق (.plist) الملف.هذا أمر جيد حقا أن تعرف إذا كنت ترغب في تغيير قيمة مرة واحدة فقط للاختبار.

حتى إذا كنت ترغب في تغيير اللغة فقط للاختبار ، ربما كنت لا ترغب في تغيير التعليمات البرمجية الخاصة بك (إذا كنت قد نسيت أن إزالة هذا الرمز في وقت لاحق ...), بدلا من ذلك قل كسكودي لبدء التطبيق الخاص بك مع معلمات سطر الأوامر (على سبيل المثالاستخدام الإسبانية التعريب):

enter image description here

لا حاجة للمس رمز على الإطلاق.مجرد إنشاء مخططات مختلفة لغات مختلفة و يمكنك بسرعة بدء تشغيل التطبيق مرة واحدة في لغة واحدة ومرة واحدة في واحد آخر فقط عن طريق تحويل المخطط.

لقد توصلت إلى حل يسمح لك باستخدام NSLocalizedString. وبعد أنا خلق فئة من NSBundle يتصل NSBundle+RunTimeLanguage. وبعد الواجهة مثل هذا.

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

التنفيذ هو مثل هذا.

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

من مجرد إضافة استيراد NSBundle+RunTimeLanguage.h في الملفات التي تستخدم NSLocalizedString.

كما ترون أخزن languagecode في ملكية AppDelegate. وبعد يمكن تخزين هذا في أي مكان تريده.

هذا الشيء الوحيد الذي لا أحب فيه هو تحذير من ذلك NSLocalizedString تم إعادة تعريف ماركو. ربما يمكن لشخص ما أن يساعدني في حل هذا الجزء.

نسخة سريعة:

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

شيء صغير :

توطين طلبك

إنه أول ما عليك فعله هو تجميع تطبيقك مع لغتين على الأقل (الإنجليزية والفرنسية في هذا المثال).

تجاوز nslocalizedString.

في التعليمات البرمجية الخاصة بك، بدلا من استخدام NSLocalizedString(key, comment), ، استخدم ماكرو MYLocalizedString(key, comment) المعرفة مثل هذا:#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];

هذه MYLocalizationSystem سوف singleton:

  • تعيين langage عن طريق تحديد الحق nsbundle المحلي المستخدم يسأل عن.
  • إرجاع nsstring المترجمة وفقا لهذه اللغة المحددة سابقا

اضبط لغة المستخدم

عندما تغير المستخدم لغة التطبيق باللغة الفرنسية، اتصل [[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];
}

في هذا المثال هذه الطريقة تعيين حزمة مترجمة إلى fr.lproj

عودة سلسلة مترجمة

بمجرد تعيين الحزمة المترجمة، ستتمكن من الحصول على السلسلة المترجمة المناسبة منه مع هذه الطريقة:

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

ارجوا ان يساعدك هذا.

ستجد المزيد من التفاصيل في هذه المقالة nswinery.io.

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

الاستعمال:

Locale.preferredLanguage = "uk"

label.text = "localizedKey".localized

في file. .pch. للتعريف:

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


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

ربما يجب أن تكمل مع هذا (على ملف .pch بعد #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]

يمكنك إنشاء حزمة فرعية مع مجموعة من السلاسل المحلية التي تريد القيام بذلك معها، ثم استخدمها NSLocalizedStringFromTableInBundle() لتحميلها. (أفترض أن هذا هو المحتوى منفصل عن توطين UI العادي الذي قد تقوم به في التطبيق.)

لدي حالتي لدي اثنين من الملفات المحلية، JA و en

وأود أن أجبره على en إذا كانت اللغة المفضلة في النظام لا en or ar

انا ذاهب لتحرير ملف main.m

سأحقق ما إذا كان المفضل الأول هو EN أو JA، إن لم يكن ثم سأغير اللغة الثانية المفضلة إلى 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]));


    }


}

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

أعطى بعض الأمثلة على رموز اللغة التي يمكن استخدامها. أتمنى أن يساعدك هذا

يمكنك أن تفعل شيئا مثل هذا:

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


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

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

مرتكز على tudorizer الإجابة لتغيير اللغة دون ترك أو إعادة التشغيل تطبيق.

بدلا من ماكرو، استخدم فئة للوصول إلى اللغة المفضلة للتحقق من وجود رمز لغة محددة.

فيما يلي فئة تستخدم للحصول على حزمة اللغة الحالية التي تعمل من أجل 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

استخدم الفئة أعلاه للإشارة إلى ملف / صورة / صورة / فيديو / إلخ:

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

تغيير اللغة الموجودة مثل أدناه أو تحديث طريقة "ChangeCurrentLanguage" في الفصل أعلاه لاتخاذ معلمة سلسلة الرجوع إلى اللغة الجديدة.

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

ستحاول هذه الوظيفة الحصول على سلسلة مترجمة للغة الحالية وإذا لم يتم العثور عليها فسوف تحصل عليه باستخدام اللغة الإنجليزية.

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

أردت إضافة دعم لغة لا تدعم رسميا من قبل iOS (غير المدرجة في قسم اللغة ضمن إعدادات النظام). باتباع البرنامج التعليمي للتدويل وعدد قليل من التلميحات هنا من قبل Brian Webster و Geon، لقد توصلت إلى هذه القطعة من التعليمات البرمجية (ضعها في 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]));
    }
}

هذا يعمل بشكل جيد لكل من كود القصة المصورة و nslocalizedring. يفترض الرمز أن المستخدم سيكون له خيار لتغيير اللغة داخل التطبيق يدويا في وقت لاحق.

بالطبع، لا تنس أن تضيف ترجمات القصة المصورة المناسبة وترجمات Localizable. ترجمات (انظر رابط صفحة Apple أعلاه لكيفية القيام بذلك).

إليك حل لائق لهذه المشكلة، ولا يتطلب إعادة تشغيل التطبيق.

https://github.com/cmaftuleAc/bundlelalization.

يعمل هذا التنفيذ بالتبديل داخل NSBundle. الفكرة هي أن تقوم بتجاوز الطريقة المحلية RestringForkey على مثيل كائن NSBundle، ثم استدعاء هذه الطريقة على حزمة مختلفة مع لغة مختلفة. بسيطة وأنيقة متوافقة تماما مع جميع أنواع الموارد.

في SWIFT 4، قمت بحلها دون الحاجة إلى إعادة تشغيل المكتبات أو استخدامها.

بعد تجربة العديد من الخيارات، وجدت هذه الوظيفة، حيث يمكنك تمرير StringtoLocalize (من Localizable.String، ملف السلاسل) الذي تريد ترجمةه، واللغة التي ترغب في ترجمةها، وما يعوده هو القيمة الخاصة بها هذه السلسلة التي لديك في سلاسل ملف:

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

مع الأخذ في الاعتبار هذه الوظيفة، قمت بإنشاء هذه الوظيفة في ملف 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!)!
    }
}

للوصول من التطبيق بأكمله، وفي كل سلسلة من بقية ViewControllers، بدلا من وضع:

NSLocalizedString ("StringToLocalize", comment: “")

لقد استبدلت بها

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

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

أنا لا أعرف إذا كانت أفضل طريقة، لكنني وجدت أنها بسيطة للغاية، وأنها تعمل من أجلي، وآمل أن يساعدك!

مهما فعلت كل شيء، فإن أفضل طريقة هي أخذ Short_name للغة المحددة، أي: FR، EN، NL، DE، ITC، إلخ ... وتعيين نفسها إلى قيمة عالمية.

قم بإنشاء عرض منتقي للإغلاق مثل القائمة المنسدلة (مزيج من الزر عند النقر الذي يظهر عرض منتقي منه أدناه مع قائمة اللغات) واختر اللغة التي تريدها. دع الاسم القصير يتم تخزينه داخليا. جعل ملف .h + .m المسمى locationisedstring.

اضبط القيمة العالمية على Short_name لتكون مساوية للقيمة التي تم الحصول عليها في localisedstring.m عندما يتم تحديد اللغة المطلوبة تعيين nsbundlevath لإنشاء الدلائل الفرعية للمشروع للغة اللازمة. على سبيل المثال، nl.proj، en.proj.

عند تحديد مجلد Proj المعين، اتصل بالسلسلة المترجمة للغة المعنية وتغيير اللغة بشكل ديناميكي.

لا توجد قواعد مكسورة.

للسريع يمكنك تجاوز main.swift قم بتعيين سلسلة UserDefaults هناك قبل تشغيل التطبيق. بهذه الطريقة لا تضطر إلى إعادة تشغيل التطبيق لرؤية التأثير المرغوب فيه.

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

يقترن مع إزالة @UIApplicationMain في الخاص بك AppDelegate.swift ملف.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top