【问题标题】:WinUI 3 运行时本地化
【发布时间】:2022-01-23 04:03:36
【问题描述】:

我正在开发 WinUI 3 应用程序,目前卡在本地化上。尽管我为不同的文化编写了单独的 resw 资源文件并使用 x:Uid 进行了本地化,但我找不到在应用运行时更改语言的方法。

设置Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride仅适用于设置启动语言。

WinUI 3 中的运行时本地化是否可能?

【问题讨论】:

    标签: c# .net xaml winui-3


    【解决方案1】:

    原答案:

    我认为你在正确的轨道上。如果您尝试在运行时更改语言,请调用将Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride 设置为新语言“字符串”的方法。但在那之后,你还必须reload your Page so that the new language takes effect

    private void ReloadLanguage(string languageOverride)
    {
        // Change the app language
        Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = languageOverride;
    
        // Be sure to clear the Frame stack so that cached Pages are removed, otherwise they will have the old language.
        Frame.BackStack.Clear();
    
        // Reload the page that you want to have the new language
        Frame.Navigate(typeof(MainPage));
    
    }
    

    -或-

    您必须call your ResourceLoader 获取您需要/想要一次刷新一个的 UI 组件。

    private void RefreshUIText()
    {
        var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
        this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Farewell");
    }
    

    更新答案:

    根据Microsoft online documentation,他们建议您随时更改语言以“从默认的ResourceContext 重新加载您的字符串”。我知道这并不理想,但它似乎有效。

    我得到了以下示例解决方案:

    MainWindow.xaml

    <Grid>
        <Frame x:Name="MainFrame"/>
    </Grid>
    

    MainWindow.xaml.cs

    public MainWindow()
    {
        this.InitializeComponent();
        MainFrame.Navigate(typeof(MainPage));
    }
    

    MainPage.xaml

    <Grid>
        <StackPanel>
            <TextBlock x:Uid="Greeting" x:Name="Greeting" Text="" Margin="15"/>
            <TextBlock x:Uid="Farewell" x:Name="Farewell" Text="" Margin="15"/>
            <Button x:Name="SelectLanguageButton" Click="SelectLanguageButton_Click" Content="Select Language" Margin="15"/>
        </StackPanel>
    </Grid>
    

    MainPage.xaml.cs

    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }
    
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            RefreshUIText();
        }
    
        private void SelectLanguageButton_Click(object sender, RoutedEventArgs e)
        {
            Frame.Navigate(typeof(LanguagePage));
        }
    
        private void RefreshUIText()
        {
            var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForViewIndependentUse();
            this.Greeting.Text = resourceLoader.GetString("Greeting/Text");
            this.Farewell.Text = resourceLoader.GetString("Farewell/Text");
        }
    }
    

    LanguagePage.xaml

    <Grid>
        <StackPanel>
            <Button x:Name="EnglishButton" Click="EnglishButton_Click" Content="English" Margin="15"/>
            <Button x:Name="FrenchButton" Click="FrenchButton_Click" Content="French" Margin="15"/>
        </StackPanel>
    </Grid>
    

    LanguagePage.xaml.cs

    public sealed partial class LanguagePage : Page
    {
        public LanguagePage()
        {
            this.InitializeComponent();
        }
    
        private void EnglishButton_Click(object sender, RoutedEventArgs e)
        {
            ReloadLanguage("en");
        }
    
        private void FrenchButton_Click(object sender, RoutedEventArgs e)
        {
            ReloadLanguage("fr");
        }
    
        private void ReloadLanguage(string languageOverride)
        {
            // Change the app language
            Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = languageOverride;
    
            // Be sure to clear the Frame stack so that cached Pages are removed, otherwise they will have the old language.
            Frame.BackStack.Clear();
    
            // Reload the page that you want to have the new language
            Frame.Navigate(typeof(MainPage));
        }
    }
    

    资源文件和内容,解决方案资源管理器

    还记得在 Package.appxmanifest 文件中添加您的语言声明

    【讨论】:

    • 不幸的是,建议不适用于 Win32(桌面)应用程序模型。
    • 究竟是什么不起作用?你有错误吗?如果是这样,它是什么?此外,如果我们可以看到您迄今为止实现的内容,显示一些代码可以帮助您更接近解决方案。
    • 谢谢,您更新的答案很有意义。注意 Refresh 方法也可以写成如下: private void RefreshUIText(string lang) { var context = new ResourceContext(); // 故意不使用 getForCurrentView() context.Languages = new List() { lang }; ResourceMap resourceMap=ResourceManager.Current.MainResourceMap.GetSubtree("Resources"); String str = resourceMap.GetValue("LanguageSettings_Title/Text", context).ValueAsString; this.BackBtn.Content = str; }
    【解决方案2】:

    我创建了新项目 - Blank App, Packaged with WAP(WinUI 3 in Desktop) 带有最新的项目模板,带有 VS 扩展 Windows APP SDK C# VS2019。正如您所注意到的 - 我正在使用 VS 2019,社区版。我在下面附上一个项目的 csproj 配置。

    主窗口中有一个框架导航到主页。主页上只有一个按钮,点击后会跳转到 LanguagePage。

    目标是更改语言、清除导航堆栈并导航回主页。然而,SetAppLanguage 中的各种场景并没有产生想要的结果。

    请查看https://www.py4u.net/discuss/731870 - 尝试了所有场景,对 GUI 没有影响。 尽管如此,Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView(); 正在抛出 COMException:'资源上下文可能不会在没有 CoreWindow 的线程上创建。 (0x80073B27)'

    【讨论】:

    • 我像你一样尝试了所有场景,可以确认对 GUI 没有影响。它仅在您关闭/重新启动应用程序时才有效。我认为这是因为缓存,但即使是重置 ResourceContext 的步骤似乎也不起作用。但是我能够让它工作(虽然不理想)。请查看我对答案的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    相关资源
    最近更新 更多