С# изменение языка приложения программно UWP в реальном времени
В моем приложении для каждой языковой строки ресурсы хранятся отдельно и отображаются в зависимости от типа языковой среды. Я хочу изменить язык в настройках приложения. Как я понимаю, что после того, как выбор языка мгновенно применит его в пользовательском интерфейсе?
Ответы
Ответ 1
Мы можем использовать ApplicationLanguages.PrimaryLanguageOverride для изменения языка во время выполнения без перезапуска приложения.
Например: у меня есть два языка с поддержкой "en" и "fr", локализованное сообщение будет отображаться в текстовом блоке.
-
Добавить с помощью Windows.Globalization;
-
Измените язык по умолчанию с "en" на "fr" на
ApplicationLanguages.PrimaryLanguageOverride = "fr";
-
Перейдите на текущую страницу, чтобы обновить интерфейс.
Frame.Navigate(this.GetType());
Обратите внимание, что вам нужно сравнить PrimaryLanguageOverride с культурой системы, чтобы установить язык для следующего запуска приложения, поскольку параметр PrimaryLanguageOverride сохраняется. И если у вас включен кеш страницы, когда вы применяете другой язык "на лету", вам нужно очистить кеш, установив Frame.CacheSize = 0;
сначала, а затем верните его.
Ответ 2
Некоторое дополнение к ответу Алана Яо. Там один недостающий кусок:
После установки Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride
и перед повторной навигацией к текущей странице вы должны вызвать эти две функции:
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
Таким образом вам не понадобится обходное решение Task.Delay()
, упомянутое Майклом Вулси.
Еще один важный последний шаг: при создании пакета Store вы должны установить для параметра "Создать набор приложений" значение "Никогда". Причина из в этой статье:
Потому что в противном случае он создаст пакет. Это значит, что он режет ваше приложение в разные части, чтобы оптимизировать загрузку. Только будут загружены части, относящиеся к устройствам. Для Например, если есть активы в разных разрешениях, это будет загрузите те, которые подходят для устройства. То же самое для языков, он загружает только файл ресурсов, относящийся к язык устройства. Поэтому, если вы попытаетесь сменить язык, он упадет все еще возвращаются на тот же базовый язык, потому что другие не установлен.
Ответ 3
@ThisWillDoIt и @Herdo
Я добавил задержку, чтобы "Первое" время было в моей ситуации:
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = languageCode;
await Task.Delay(100);
Frame.Navigate(this.GetType());
Надеюсь, что это поможет вам работать.
Ответ 4
Существует страница MSDN, в которой описывается новое перо о языке из Windows 8.1.
После изменения
ApplicationLanguages.PrimaryLanguageOverride = "en-US";
Я просмотрел свойство resourceContext.Languages[0]
, чтобы запустить событие PropertyChanged
моего LanguageManager, который был StaticResources
объявлен в App.xaml
с 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);
}
}
while (true)
был просто для теста, на самом деле лучше избегать "резервной копии", потому что
Эти требования могут различаться в зависимости от используемой приложением интерфейса пользовательского интерфейса, и может потребоваться перезапустить приложение.
Ответ 5
К сожалению, ни один из приведенных выше ответов не помог, если для страницы NavigationCacheMode
установлено значение "Required"
. Вот код, который решил мою проблему.
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;