No iPhone, NSLocalizedString
retorna a sequência no idioma do iPhone. É possível forçar o NSLocalizedString
uso de um idioma específico para ter o aplicativo em um idioma diferente do dispositivo?
No iPhone, NSLocalizedString
retorna a sequência no idioma do iPhone. É possível forçar o NSLocalizedString
uso de um idioma específico para ter o aplicativo em um idioma diferente do dispositivo?
Respostas:
NSLocalizedString()
(e variantes dos mesmos) acessam a tecla "AppleLanguages" NSUserDefaults
para determinar quais são as configurações do usuário para os idiomas preferidos. Isso retorna uma matriz de códigos de idioma, sendo o primeiro o definido pelo usuário para o telefone e os subsequentes usados como fallbacks se um recurso não estiver disponível no idioma preferido. (na área de trabalho, o usuário pode especificar vários idiomas com um pedido personalizado em Preferências do sistema)
Você pode substituir a configuração global do seu próprio aplicativo, se desejar, usando o método setObject: forKey: para definir sua própria lista de idiomas. Isso terá precedência sobre o valor definido globalmente e será retornado para qualquer código em seu aplicativo que esteja executando a localização. O código para isso seria algo como:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate
Isso tornaria o alemão o idioma preferido para o seu aplicativo, com inglês e francês como substitutos. Você gostaria de chamar isso algum dia no início da inicialização do seu aplicativo. Você pode ler mais sobre as preferências de idioma / localidade aqui: Tópicos de programação de internacionalização: obtendo o idioma e o local atuais
Tive o mesmo problema recentemente e não queria iniciar e corrigir todo o meu NSLocalizedString nem forçar o aplicativo a reiniciar para que o novo idioma funcionasse. Eu queria que tudo funcionasse como está.
Minha solução foi alterar dinamicamente a classe do pacote principal e carregar o pacote apropriado lá:
Arquivo de cabeçalho
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
Implementação
#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
Então, basicamente, quando seu aplicativo iniciar e antes de carregar seu primeiro controlador, basta ligar para:
[NSBundle setLanguage:@"en"];
Quando o usuário alterar o idioma preferido na tela de configurações, basta chamá-lo novamente:
[NSBundle setLanguage:@"fr"];
Para redefinir os padrões do sistema, basta passar nulo:
[NSBundle setLanguage:nil];
Aproveitar...
Para quem precisa de uma versão 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)
}
}
Normalmente faço isso dessa maneira, mas você DEVE ter todos os arquivos de localização no seu projeto.
@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
Não use no iOS 9. Isso retorna nulo para todas as strings passadas por ele.
Encontrei outra solução que permite atualizar as seqüências de idiomas, sem reiniciar o aplicativo e compatível com os geradores:
Coloque essa macro no Prefix.pch:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
e sempre que você precisar de uma string localizada, use:
NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")
Para definir o idioma, use:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
Funciona mesmo com salto de idioma consecutivo, como:
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, @""));
Como dito anteriormente, basta fazer:
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];
Mas para evitar ter que reiniciar o aplicativo, coloque a linha no método principal de main.m
, pouco antes UIApplicationMain
(...).
NSAutoreleasePool * pool ..
ou alguns objetos liberados automaticamente vazarão.
[[NSBundle mainBundle] URLForResource:withExtension:]
antes.
O truque para usar um idioma específico, selecionando-o no aplicativo, é forçar o NSLocalizedString
uso de um pacote específico, dependendo do idioma selecionado,
aqui está o post que escrevi para esta localização de avanço de aprendizado em aplicativos iOS
e aqui está o código de uma localização avançada de exemplo de aplicativo em aplicativos iOS
O que você acha dessa solução para o 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)
}
}
Uso simples:
"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.
Como Brian Webster menciona, o idioma precisa ser definido "em algum momento no início da inicialização do aplicativo". Pensei applicationDidFinishLaunching:
do AppDelegate
deve ser um local adequado para fazê-lo, já que é onde eu faço todos os outros inicialização.
Mas, como William Denniss menciona, isso parece ter efeito apenas depois que o aplicativo é reiniciado, o que é meio inútil.
Parece funcionar bem se eu colocar o código na função principal, no entanto:
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;
}
Eu gostaria de receber comentários sobre isso.
[[NSUserDefaults standardUserDefaults] synchronize];
após ligarsetObject:forKey:
Eu gosto do melhor método de Mauro Delrio. Também adicionei o seguinte no meu Project_Prefix.pch
#import "Language.h"
#define MyLocalizedString(key, alt) [Language get:key alter:alt]
Portanto, se você quiser usar o método padrão (que usa NSLocalizedString), poderá fazer uma substituição rápida da sintaxe em todos os arquivos.
NSLocalizedString()
lê o valor da chave AppleLanguages
nos padrões padrão do usuário ( [NSUserDefaults standardUserDefaults]
). Ele usa esse valor para escolher uma localização apropriada entre todas as localizações existentes no tempo de execução. Quando a Apple cria o dicionário de padrões do usuário no lançamento do aplicativo, eles pesquisam o (s) idioma (s) preferido (s) nas preferências do sistema e copiam o valor a partir daí. Isso também explica, por exemplo, por que a alteração das configurações de idioma no OS X não afeta a execução de aplicativos, apenas nos aplicativos iniciados a partir de então. Uma vez copiado, o valor não é atualizado apenas porque as configurações são alteradas. É por isso que o iOS reinicia todos os aplicativos se você alterar o idioma.
No entanto, todos os valores do dicionário de padrões do usuário podem ser substituídos pelos argumentos da linha de comando. Veja a NSUserDefaults
documentação no NSArgumentDomain
. Isso inclui até mesmo os valores carregados no arquivo de preferências do aplicativo (.plist). É muito bom saber se você deseja alterar um valor apenas uma vez para o teste .
Portanto, se você deseja alterar o idioma apenas para teste, provavelmente não deseja alterar seu código (se esquecer de removê-lo mais tarde ...), em vez disso, diga ao Xcode para iniciar seu aplicativo com parâmetros de linha de comando ( por exemplo, use a localização em espanhol):
Não é necessário tocar no seu código. Basta criar esquemas diferentes para idiomas diferentes e você pode iniciar o aplicativo rapidamente uma vez em um idioma e outra em outro, apenas alternando o esquema.
Options
como nas versões mais recentes do Xcode, que a Apple oferece: também.
Eu vim com uma solução que permite que você use NSLocalizedString
. Eu crio uma categoria de NSBundle
chamada NSBundle+RunTimeLanguage
. A interface é assim.
// 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
A implementação é assim.
// 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
Do que apenas adicionar importação NSBundle+RunTimeLanguage.h
nos arquivos que usam NSLocalizedString
.
Como você pode ver, eu armazeno meu languageCode em uma propriedade de AppDelegate
. Isso pode ser armazenado em qualquer lugar que você desejar.
A única coisa de que não gosto é um aviso que o NSLocalizedString
marco redefiniu. Talvez alguém possa me ajudar a consertar essa parte.
#undef NSLocalizedString
pouco antes #define
para desativar o aviso
É a primeira coisa que você precisa fazer para localizar seu aplicativo com pelo menos dois idiomas (inglês e francês neste exemplo).
No seu código, em vez de usar NSLocalizedString(key, comment)
, use uma macro MYLocalizedString(key, comment)
definida assim:
#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];
Este MYLocalizationSystem
singleton:
Quando o usuário alterou o idioma do aplicativo em francês, ligue para [[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];
}
Neste exemplo, esse método define o pacote localizado como fr.lproj
Depois de definir o pacote localizado, você poderá obter a string localizada correta com este método:
- (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];
}
Espero que isso ajude você.
Você encontrará mais detalhes neste artigo em NSWinery.io
Swift 3 extensões:
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
}
}
Uso:
Locale.preferredLanguage = "uk"
label.text = "localizedKey".localized
No arquivo .pch para definir:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")
Talvez você deva complementar isso (no arquivo .pch apó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]
Solução 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")
Deu alguns exemplos de códigos de idioma que podem ser usados. Espero que isto ajude
Você pode criar um subconjunto com o conjunto de cadeias localizadas com as quais deseja fazer isso e usá NSLocalizedStringFromTableInBundle()
-las para carregá-las. (Suponho que esse conteúdo seja separado da localização normal da interface do usuário que você pode estar fazendo no aplicativo.)
para o meu caso, eu tenho dois arquivos localizados, ja e en
e eu gostaria de forçá-lo a en se o idioma preferido no sistema nem en ou ja
vou editar o arquivo main.m
vou verificar se o primeiro preferido é en ou ja; caso contrário, alterarei o segundo idioma preferido para 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]));
}
}
Você pode fazer algo assim:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];
NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):
Com base na resposta do Tudorizer para alterar o idioma sem sair ou reiniciar o aplicativo.
Em vez de uma macro, use uma classe para acessar o idioma preferido para verificar se um código de idioma específico está presente.
Abaixo está uma classe usada para obter o pacote de idiomas atual que está funcionando no 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
Use a classe acima para referenciar um arquivo / imagem / vídeo / 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")
Altere o idioma in-line como abaixo ou atualize o método "changeCurrentLanguage" na classe acima para obter um parâmetro de string referente ao novo idioma.
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
No swift 4, eu o resolvi sem precisar reiniciar ou usar as bibliotecas.
Depois de tentar muitas opções, encontrei esta função, na qual você transmite a stringToLocalize (de Localizable.String, o arquivo de strings) que deseja traduzir e o idioma em que deseja traduzi-lo, e o que ele retorna é o valor para essa String que você possui no arquivo 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)
}
Levando em conta essa função, criei essa função em um arquivo 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!)!
}
}
Para acessar de todo o aplicativo e em cada sequência do restante dos ViewControllers, em vez de colocar:
NSLocalizedString ("StringToLocalize", comment: “")
Eu substituí-o por
let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()
NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String
Não sei se é o melhor caminho, mas achei muito simples e funciona para mim, espero que ajude!
Esta função tentará obter uma string localizada para o idioma atual e, se não for encontrada, a obterá no idioma inglês.
- (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;
}
Eu queria adicionar suporte para um idioma que não é oficialmente suportado pelo iOS (não listado na seção Idioma nas configurações do sistema). Seguindo o Tutorial de internacionalização da Apple e algumas dicas aqui de Brian Webster e Geon, vim com esse pedaço de código (coloque-o em 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]));
}
}
Isso funciona bem para o código do Storyboard e do NSLocalizedString. O código pressupõe que o usuário terá a opção de alterar manualmente o idioma dentro do aplicativo posteriormente.
Obviamente, não esqueça de adicionar traduções apropriadas do Storyboard e traduções Localizable.strings (consulte o link para a página da Apple acima para saber como fazer isso).
Aqui está uma solução decente para esse problema e não requer a reinicialização do aplicativo.
https://github.com/cmaftuleac/BundleLocalization
Essa implementação funciona aprimorando o NSBundle. A idéia é que você substitua o método localizedStringForKey na instância do objeto NSBundle e chame esse método em um pacote diferente com um idioma diferente. Simples e elegante totalmente compatível com todos os tipos de recursos.
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj" ];
faça o que fizer, a melhor maneira é usar o short_name para o idioma especificado, ou seja: fr, en, nl, de, it, etc ... e atribuir o mesmo a um valor global.
faça com que uma exibição de selecionador apareça como um menu suspenso (combinação de um botão ao clicar no qual uma exibição de selecionador aparece abaixo com uma lista de idiomas) e selecione o idioma desejado. deixe o nome abreviado ser armazenado internamente. crie um arquivo .h + .m chamado LocalisedString.
Defina o valor global de short_name como igual ao valor obtido em LocalisedString.m Quando o idioma necessário for selecionado, atribua o NSBundlePath para criar subdiretórios do projeto para o idioma necessário. por exemplo, nl.proj, en.proj.
Quando a pasta específica do projetor for selecionada, chame a sequência localizada para o respectivo idioma e altere o idioma dinamicamente.
sem regras quebradas.
Para o Swift, você pode substituir o main.swift
arquivo e definir a string UserDefaults antes de executar o aplicativo. Dessa forma, você não precisa reiniciar o aplicativo para ver o efeito desejado.
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))
emparelhado com a remoção do @UIApplicationMain
seu AppDelegate.swift
arquivo.