İPhone'da iPhone NSLocalizedString
dilini döndürür. NSLocalizedString
Uygulamayı cihazdan farklı bir dilde kullanmak için belirli bir dili kullanmaya zorlamak mümkün mü ?
İPhone'da iPhone NSLocalizedString
dilini döndürür. NSLocalizedString
Uygulamayı cihazdan farklı bir dilde kullanmak için belirli bir dili kullanmaya zorlamak mümkün mü ?
Yanıtlar:
NSLocalizedString()
(ve bunların varyantları) NSUserDefaults
, kullanıcının tercih edilen diller için ayarlarının ne olduğunu belirlemek üzere "AppleLanguages" anahtarına erişir . Bu, bir dizi dil kodu döndürür, ilki telefon tarafından kullanıcı tarafından ayarlanan koddur ve daha sonra tercih edilen dilde bir kaynak yoksa sonraki kodlar yedek olarak kullanılır. (masaüstünde, kullanıcı Sistem Tercihleri'nde özel bir siparişle birden fazla dil belirtebilir)
Kendi dil listenizi ayarlamak için setObject: forKey: yöntemini kullanarak kendi uygulamanız için genel ayarı geçersiz kılabilirsiniz. Bu, genel olarak ayarlanan değere göre önceliklidir ve uygulamanızda yerelleştirme gerçekleştiren herhangi bir koda döndürülür. Bunun kodu şuna benzer:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate
Bu, Almanca'yı uygulamanız için tercih edilen bir dil haline getirecek, İngilizce ve Fransızca'yı yedek olarak yapacak. Bunu, uygulamanızın başlangıcında erkenden aramak istersiniz. Dil / yerel ayar tercihleri hakkında daha fazla bilgiyi buradan edinebilirsiniz: Uluslararasılaştırma Programlama Konuları: Geçerli Dili ve Yerel Ayarı Alma
Son zamanlarda aynı sorunu yaşadım ve tüm NSLocalizedString'imi başlatmak ve yama yapmak istemiyordum ya da yeni dilin çalışması için uygulamayı yeniden başlatmaya zorlamıyordum . Her şeyin olduğu gibi çalışmasını istedim.
Benim çözümüm, ana paketin sınıfını dinamik olarak değiştirmek ve uygun paketi buraya yüklemekti:
Başlık dosyası
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
uygulama
#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
Temel olarak, uygulamanız başladığında ve ilk denetleyicinizi yüklemeden önce şunları aramanız yeterlidir:
[NSBundle setLanguage:@"en"];
Kullanıcınız ayar ekranınızda tercih ettiği dili değiştirdiğinde, onu tekrar arayın:
[NSBundle setLanguage:@"fr"];
Sistem varsayılanlarına sıfırlamak için nil iletmeniz yeterlidir:
[NSBundle setLanguage:nil];
Zevk almak...
Swift sürümüne ihtiyaç duyanlar için:
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)
}
}
Bunu genellikle bu şekilde yaparım, ancak projenizde tüm yerelleştirme dosyalarının olması GEREKİR.
@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
İOS 9'da kullanmayın. Bu, içinden geçen tüm dizeler için sıfır döndürür.
Uygulamayı yeniden başlatmadan ve genstrings ile uyumlu olmadan dil dizelerini güncellemenizi sağlayan başka bir çözüm buldum:
Bu makroyu Prefix.pch dosyasına koyun:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
ve yerelleştirilmiş bir dize kullanımına ihtiyacınız olduğunda:
NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")
Dili ayarlamak için:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
Ardışık dil atlamasıyla bile çalışır:
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, @""));
Daha önce de belirtildiği gibi şunları yapın:
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];
Ancak uygulamayı yeniden başlatmak zorunda kalmamak için main.m
, hemen önce UIApplicationMain
(...) ana yöntemine satırı koyun .
NSAutoreleasePool * pool ..
aksi takdirde birkaç otomatik olarak yayınlanmış nesne sızar.
[[NSBundle mainBundle] URLForResource:withExtension:]
önce ararsanız bu çalışmaz .
Uygulamadan belirli bir dili kullanma hilesi NSLocalizedString
, seçilen dile bağlı olarak belirli bir paketi kullanmaya zorlamaktır.
İşte ios uygulamalarında bu öğrenme ileri yerelleştirme için yazdığım yazı
ve ios uygulamalarında bir örnek uygulama ileri yerelleştirmesinin kodu
Swift 3 için bu çözüm hakkında ne düşünüyorsunuz?
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)
}
}
Basit kullanım:
"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.
Brian Webster'ın belirttiği gibi, dilin "uygulamanızın başlamasının erken bir döneminde" ayarlanması gerekir. Düşündüğümden applicationDidFinishLaunching:
ait AppDelegate
tüm diğer başlatma yapın nerede beri, bunu yapmak için uygun bir yer olmalı.
Ancak William Denniss'in belirttiği gibi, bunun sadece uygulama yeniden başlatıldıktan sonra bir etkisi var gibi görünüyor , bu da işe yaramaz.
Ben olsa da, ana işlev kodu koymak iyi çalışıyor gibi görünüyor:
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;
}
Bu konuda herhangi bir yorum için teşekkür ederiz.
[[NSUserDefaults standardUserDefaults] synchronize];
aradıktan sonra kullanınsetObject:forKey:
En iyi Mauro Delrio'nun yöntemini seviyorum. Ayrıca aşağıdakileri Project_Prefix.pch dosyasına ekledim
#import "Language.h"
#define MyLocalizedString(key, alt) [Language get:key alter:alt]
Bu nedenle, standart yöntemi (NSLocalizedString kullanan) kullanmak isterseniz, tüm dosyalarda hızlı bir sözdizimi ikamesi yapabilirsiniz.
NSLocalizedString()
anahtarın değerini AppleLanguages
standart kullanıcı varsayılanlarından ( [NSUserDefaults standardUserDefaults]
) okur . Çalışma zamanında mevcut tüm yerelleştirmeler arasında uygun bir yerelleştirme seçmek için bu değeri kullanır. Apple, uygulama başlatma sırasında kullanıcı varsayılan sözlüğünü oluşturduğunda, sistem tercihlerinde tercih edilen dil (ler) anahtarını arar ve değeri oradan kopyalar. Bu aynı zamanda örneğin OS X'te dil ayarlarının değiştirilmesinin uygulamaları çalıştırmak için neden hiçbir etkisi olmadığını, yalnızca bundan sonra başlatılan uygulamalar üzerinde de açıklamaktadır. Kopyalandıktan sonra değer, ayarlar değiştiği için güncellenmez. Bu nedenle, dilden sonra değiştirirseniz iOS tüm uygulamaları yeniden başlatır.
Ancak, kullanıcı varsayılanları sözlüğünün tüm değerlerinin üzerine komut satırı bağımsız değişkenleri yazılabilir. NSUserDefaults
Üzerindeki belgelere bakın NSArgumentDomain
. Bu, uygulama tercihleri (.plist) dosyasından yüklenen değerleri de içerir. Test için bir değeri değiştirmek isteyip istemediğinizi bilmek gerçekten çok iyi .
Dili test etmek için değiştirmek isterseniz, muhtemelen kodunuzu değiştirmek istemezsiniz (bu kodu daha sonra kaldırmayı unutursanız ...), bunun yerine Xcode'a uygulamanızı bir komut satırı parametreleriyle başlatmasını söyleyin ( örneğin İspanyolca yerelleştirmeyi kullanın):
Kodunuza dokunmanıza gerek yok. Sadece farklı diller için farklı şemalar oluşturun ve sadece şemayı değiştirerek uygulamayı bir kez bir dilde ve bir başka dilde bir kez hızlı bir şekilde başlatabilirsiniz.
Options
Apple'ın sunduğu daha yeni Xcode sürümlerinde olduğu gibi dili geçersiz kılmadığınızdan emin olun . de.
Kullanmanıza izin veren bir çözüm buldum NSLocalizedString
. Bir NSBundle
arama kategorisi oluşturuyorum NSBundle+RunTimeLanguage
. Arayüz böyle.
// 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
Uygulama böyle.
// 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
Daha NSBundle+RunTimeLanguage.h
sonra, kullanılan dosyalara içe aktarma ekleyin NSLocalizedString
.
Gördüğünüz gibi languageCode'umu bir özellikte saklıyorum AppDelegate
. Bu istediğiniz bir yerde saklanabilir.
Bu konuda sevmediğim tek şey NSLocalizedString
marco'nun yeniden tanımladığı bir Uyarı . Belki birisi bu parçayı düzeltmeme yardımcı olabilir.
#undef NSLocalizedString
hemen ekleyin#define
Yapmanız gereken ilk şey, uygulamanızı en az iki dilde yerelleştirmek (bu örnekte İngilizce ve Fransızca).
Kodunuzda, kullanmak yerine şu şekilde tanımlanmış NSLocalizedString(key, comment)
bir makro kullanın MYLocalizedString(key, comment)
:
#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];
Bu MYLocalizationSystem
singleton:
Kullanıcı uygulama dilini Fransızca olarak değiştirdiğinde, [[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];
}
Bu örnekte bu yöntem, yerelleştirilmiş paketi fr.lproj olarak ayarlar
Yerelleştirilmiş paketi ayarladıktan sonra, bu yöntemle ondan doğru yerelleştirilmiş dizeyi alabilirsiniz:
- (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];
}
Umarım bu size yardımcı olacaktır.
Bu makalede NSWinery.io'dan daha fazla ayrıntı bulacaksınız.
Swift 3 uzantıları:
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
}
}
Kullanımı:
Locale.preferredLanguage = "uk"
label.text = "localizedKey".localized
Tanımlamak için .pch dosyasında :
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")
Belki de bunu tamamlamanız gerekir (#import'tan sonra .pch dosyasında):
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]
Swift 3 çözümü:
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")
Kullanılabilecek bazı dil kodlarına örnekler verin. Bu yardımcı olur umarım
Bunu yapmak istediğiniz yerelleştirilmiş dizeler kümesiyle bir alt paket oluşturabilir ve sonra NSLocalizedStringFromTableInBundle()
bunları yüklemek için kullanabilirsiniz . (Bunun, uygulamada yapabileceğiniz normal kullanıcı arayüzü yerelleştirmesinden ayrı bir içerik olduğunu varsayıyorum.)
benim durumum için iki yerel dosya var, ja ve tr
ve sistemde tercih edilen dil ne en ne de ja ise bunu en
main.m dosyasını düzenleyeceğim
ilk tercih edilen en veya ja olup olmadığını kontrol edeceğim, eğer değilse ikinci tercih edilen dili en olarak değiştireceğim.
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]));
}
}
Bunun gibi bir şey yapabilirsiniz:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];
NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):
Dayanarak Tudorizer en olmaksızın değişiklik diline cevap bırakarak veya yeniden başlatarak uygulamayı.
Makro yerine, belirli bir dil kodunun bulunup bulunmadığını kontrol etmek için tercih edilen dile erişmek için bir sınıf kullanın.
Aşağıda, iOS 9 için çalışan geçerli dil paketini elde etmek için kullanılan bir sınıf bulunmaktadır:
@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
Bir dize dosyasına / image / video / etc'ye başvurmak için yukarıdaki sınıfı kullanın:
// 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")
Aşağıdaki gibi satır içi dili değiştirin veya yeni dile başvuruda bulunan bir dize parametresi almak için yukarıdaki sınıftaki "changeCurrentLanguage" yöntemini güncelleyin.
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
Hızlı 4'te, kütüphaneleri yeniden başlatmaya veya kullanmaya gerek kalmadan çözdüm.
Birçok seçeneği denedikten sonra, çevirmek istediğiniz stringToLocalize (Localizable.String, dizeler dosyası) ilettiğiniz bu işlevi buldum ve çevirmek istediğiniz dil ve döndürdüğü değer Dizeler dosyasında bulunan Dize:
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)
}
Bu işlevi göz önünde bulundurarak, bir Swift dosyasında bu işlevi oluşturdum:
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!)!
}
}
Tüm uygulamadan ve ViewControllers'ın geri kalanının her bir dizesine koymak yerine erişmek için:
NSLocalizedString ("StringToLocalize", comment: “")
Onunla değiştirdim
let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()
NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String
En iyi yol olup olmadığını bilmiyorum, ama çok basit buldum ve benim için çalışıyor, umarım size yardımcı olur!
Bu işlev geçerli dil için yerelleştirilmiş dize almaya çalışır ve bulunmazsa ingilizce dili kullanarak alır.
- (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;
}
Resmi olarak iOS tarafından desteklenmeyen bir dile destek eklemek istedim (sistem ayarları altındaki Dil bölümünde listelenmiyor). Takip ederek Apple'ın Uluslararasılaşma Eğitimi Brian Webster ve geonların tarafından burada ve birkaç ipucu, kod (main.m koymak) bu parça ile geldi:
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]));
}
}
Bu hem Storyboard hem de NSLocalizedString kodu için iyi çalışır. Kod, kullanıcının uygulama içindeki dili daha sonra manuel olarak değiştirme seçeneğine sahip olacağını varsayar.
Tabii ki, uygun Storyboard çevirilerini ve Localizable.strings çevirilerini eklemeyi unutmayın (bunun nasıl yapılacağı için yukarıdaki Apple sayfasına bağlantıya bakın).
İşte bu sorun için iyi bir çözüm ve uygulamanın yeniden başlatılmasını gerektirmez.
https://github.com/cmaftuleac/BundleLocalization
Bu uygulama NSBundle içinde ince ayar yaparak çalışır. Buradaki fikir, NSBundle nesnesi örneğinde localizedStringForKey yöntemini geçersiz kılmanız ve daha sonra bu yöntemi farklı bir dil içeren farklı bir pakette çağırmanızdır. Basit ve zarif, her türlü kaynakla tamamen uyumludur.
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj" ];
ne yaparsanız yapın, en iyi yol belirtilen dil için kısa_adı almaktır, yani: fr, en, nl, de, it, vb ... ve aynısını global bir değere atamaktır.
aşağı açılır bir menü (seçicinin aşağıdan bir dil görünümü ile birlikte göründüğü bir düğmenin kombinasyonu) açılır bir pencere gibi görünmesi için bir seçici görünüm yapın ve istediğiniz dili seçin. kısa adın dahili olarak saklanmasına izin verin. LocalisedString adlı bir .h + .m dosyası oluşturun.
Short_name öğesinin genel değerini LocalisedString.m dosyasında elde edilen değere eşit olacak şekilde ayarlayın. Gerekli dil seçildiğinde NSBundlePath'i gerekli dil için proje alt dizinleri oluşturmak üzere atayın. örneğin, nl.proj, en.proj.
Belirli bir proje klasörü seçildiğinde, ilgili dil için yerelleştirilmiş dizeyi arayın ve dili dinamik olarak değiştirin.
kurallar çiğnenmez.
Swift için, main.swift
uygulamayı çalıştırmadan önce dosyayı geçersiz kılabilir ve UserDefaults dizesini ayarlayabilirsiniz. Bu şekilde, istenen efekti görmek için Uygulamayı yeniden başlatmanız gerekmez.
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))
kaldırılması ile birlikte eşleştirilmiş @UIApplicationMain
sizin de AppDelegate.swift
dosyaya.