2015-09-22 9 views
13

Nella mia applicazione per ogni lingua, le risorse di stringa vengono memorizzate separatamente e vengono visualizzate in base al tipo di ambiente della lingua. Voglio cambiare la lingua nelle impostazioni dell'applicazione. Come mi rendo conto che dopo la selezione della lingua la applichi immediatamente nell'interfaccia utente?C# cambia lingua app in modo programmatico UWP in tempo reale

+0

Set [CurrentUICulture] (https://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.currentuiculture (v = vs.110) aspx) Proprietà quando lancio app. – tao

+0

Lo so. Ma ho bisogno di cambiare la lingua senza riavviare all'istante. Dobbiamo cambiarlo direttamente nell'applicazione in esecuzione. – AlexeySRG

risposta

24

Possiamo usare ApplicationLanguages.PrimaryLanguageOverride per cambiare la lingua durante il runtime senza riavviare l'app.

Ad esempio: Ho due lingue supportate "en" e "fr", il messaggio localizzato verrà visualizzato nel blocco di testo.

  1. Aggiungere utilizzando Windows.Globalization;

  2. modificare la lingua predefinita da "en" a "fr" per

    ApplicationLanguages.PrimaryLanguageOverride = "fr"; 
    
  3. nuovamente accedere alla pagina corrente per aggiornare l'interfaccia utente.

    Frame.Navigate(this.GetType()); 
    

Si noti che, è necessario confrontare il PrimaryLanguageOverride con la cultura di sistema per impostare la lingua per il prossimo lancio app, perché l'impostazione PrimaryLanguageOverride viene mantenuto. E se hai abilitato la cache della pagina, quando applichi una lingua diversa al volo, devi cancellare la cache impostando prima Frame.CacheSize = 0; e poi ripristinarla.

+3

Questa soluzione funziona sempre per me, ma la prima modifica della lingua. Dopo il primo cambio di lingua devo cliccare manualmente su un elemento di navigazione per caricare una pagina con la nuova lingua. Per ogni cambio di lingua dopo quello la pagina si aggiorna automaticamente con la lingua corretta. Questo comportamento si verifica anche quando si modifica CachSize come consigliato. – ThisWillDoIt

+0

@ThisWillDoIt Hai trovato qualche soluzione per questo problema? Altrimenti, segnalarlo come bug potrebbe essere l'idea migliore ...!? – Herdo

+0

Ho un'altra app che funziona correttamente e li ho confrontati l'uno con l'altro. Non ho ancora idea del perché questo comportamento si verifichi nelle app (https://github.com/theWalli/EurekaRemake). Se decido di segnalarlo dopo un altro giro di controllo dalla mia parte, dove sarebbe il posto migliore/ufficiale per farlo? – ThisWillDoIt

2

C'è un page MSDN che descrive la nuova funzionalità di Language da Windows 8.1.

Dopo modificare il

ApplicationLanguages.PrimaryLanguageOverride = "en-US"; 

ho guardato la proprietà resourceContext.Languages[0] al fine di lanciare l'evento PropertyChanged della mia LanguageManager, che era un StaticResources dichiarato in App.xaml con x:Key = Loc.

private void ButtonEn_OnClick(object sender, RoutedEventArgs e) 
    { 
     ApplicationLanguages.PrimaryLanguageOverride = "en-US"; 
     UpdateLang("en-US"); 
    } 

    private async void UpdateLang(string newLang) 
    { 
     var resourceContext = Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView(); 

     while (true) 
     { 
      if (resourceContext.Languages[0] == newLang) 
      { 
       var loc = Application.Current.Resources["Loc"] as LanguagesManager; 
       loc.ChangeLang(); 
       break; 
      } 
      await Task.Delay(100); 
     } 
    } 

Il while (true) era solo per prova, in realtà è meglio per sfuggire da un "backup", perché

Tali requisiti possono variare a seconda del framework di interfaccia utente utilizzata dalla app, e può essere necessario riavviare l'app.

+0

Sì ApplicationLanguages.PrimaryLanguageOverride = "en-US"; dovrebbe essere usato – peterincumbria

3

@ThisWillDoIt e @Herdo

ho aggiunto un ritardo in modo che il tempo di "First" che avrebbe funzionato nella mia situazione:

Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = languageCode; 

await Task.Delay(100); 

Frame.Navigate(this.GetType()); 

Speranza che aiuta il lavoro per voi.

+0

Eccellente! Funziona! Ma perché ??? – Charlie

+0

@Charlie Leggi la risposta di Péter Bozsó sopra la mia, che dovrebbe rispondere alla tua domanda –

5

Qualche aggiunta alla risposta di Alan Yao. C'è un pezzo mancante: Dopo aver impostato la Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride e prima di ri-navigazione verso la pagina corrente, è necessario chiamare queste due funzioni:

Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset(); 
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset(); 

In questo modo non sarà necessario il Task.Delay() soluzione indicata da Michael Woolsey.

Un ultimo passaggio importante: quando si crea un pacchetto Store, è necessario assicurarsi di impostare il valore dell'impostazione "Genera pacchetto app" su "Mai". Motivo da this article:

Perché altrimenti creerà un pacchetto. Significa che taglierà l' l'applicazione in parti diverse per ottimizzare il download. Solo verranno scaricate le parti rilevanti per i dispositivi. Per esempio , se ci sono le risorse in diversa risoluzione, sarà solo scaricare quelli che sono adatti per il dispositivo. Stessa cosa per le lingue , scaricherà solo il file delle risorse relativo alla lingua del dispositivo. Quindi, se provi a cambiare lingua, il numero cadrà ancora nella stessa lingua di base, perché altri non sono installati .

+0

Risposta eccellente, evita i rimedi che interrompono la fluidità dell'interfaccia utente (ritardo sul thread dell'interfaccia utente). – MoDu

0

Purtroppo, nessuna delle risposte precedenti aiutato se NavigationCacheMode insieme al "Required" per la pagina. Ecco il codice che ha risolto il mio problema.

ApplicationLanguages.PrimaryLanguageOverride = language; 
await Task.Delay(300); 
Frame rootFrame = Window.Current.Content as Frame; 
rootFrame.Content = null; 
rootFrame = null;    
rootFrame = new Frame(); 
rootFrame.Navigate(typeof(MainPage), null); 
Window.Current.Content = rootFrame;