WinUI 3 prend pleinement en charge l’internationalisation. Cela dit, la méthode la plus fiable à l’heure actuelle consiste à redémarrer l’application après avoir changé de langue pour garantir un rendu impeccable. Même s’il est techniquement possible d’actualiser dynamiquement la langue de l’interface sans redémarrage, sa mise en œuvre devient extrêmement complexe. J’ai passé beaucoup de temps à résoudre des problèmes sur ce point : j’ai rencontré à maintes reprises des textes d’interface déformés ou des plantages après un changement de langue. Après de nombreux essais et ajustements, j’ai élaboré une méthode de travail solide pour l’internationalisation sous WinUI 3, que je vous détaille ci-dessous.
Commencez par ajouter la logique d’initialisation de la langue dans le code-behind du fichier App.xaml.cs. Si l’utilisateur n’a pas défini de langue personnalisée, l’application utilise la langue par défaut du système d’exploitation. Si la langue système ne figure pas dans la liste des langues prises en charge, l’application bascule automatiquement vers l’anglais.
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
const string LangSettingKey = "AppLanguageCode";
// All supported language tags of project
List<string> supportLangs = new() { "zh-CN", "en-US", "th-TH" };
string finalLang = "en-US"; // Default language
try
{
var localSetting = ApplicationData.Current.LocalSettings;
// ① Use saved language if local configuration exists
if (localSetting.Values.TryGetValue(LangSettingKey, out var savedVal))
{
finalLang = NormalizeLang(savedVal?.ToString() ?? "");
}
else
{
// ② No saved config: read system primary preferred language
string sysLang = ApplicationLanguages.Languages.FirstOrDefault() ?? "";
sysLang = NormalizeLang(sysLang);
// ③ Use system language if supported, otherwise fall back to English
finalLang = supportLangs.Contains(sysLang) ? sysLang : "en-US";
}
}
catch
{
// Ignore exception when running unpackaged, ApplicationData unavailable
}
ApplicationLanguages.PrimaryLanguageOverride = finalLang;
_window = new MainWindow();
_window.Activate();
}
/// <summary>
/// Standardize culture code: map system returned zh-Hans-CN to zh-CN
/// </summary>
private static string NormalizeLang(string lang)
{
if (string.IsNullOrEmpty(lang)) return lang;
return lang switch
{
"zh-Hans-CN" => "zh-CN",
"zh-Hant-TW" => "zh-TW", // For future Traditional Chinese support
_ => lang
};
}Langage du code : PHP (php)
Cette configuration peut encore être améliorée. Pour obtenir un code plus propre, évitez de coder en dur la liste des langues prises en charge ici. Placez-la plutôt dans une classe statique d’assistance, afin de pouvoir réutiliser cette liste partout où vous devez gérer les paramètres de langue.
public class Languages
{
public static List<string> supportLangs = new() { "zh-CN", "en-US", "th-TH" };
}Langage du code : PHP (php)
Le rôle principal du bloc de code ci-dessus est de configurer la langue de l’application au démarrage : charger d’abord la préférence linguistique enregistrée par l’utilisateur, utiliser la langue système par défaut en l’absence de paramètre personnalisé, et enfin recourir à l’anglais comme dernière solution de secours.
Créer une page dédiée au changement de langue
Nous avons besoin d’une interface dédiée pour permettre aux utilisateurs de modifier la langue d’affichage. C’est pourquoi j’ai créé une page indépendante exclusivement dédiée à la configuration linguistique.
<?xml version="1.0" encoding="utf-8"?>
<Page
x:Class="ThaiTong.Pages.LanguageSettingPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ThaiTong.Pages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<StackPanel Padding="20" Spacing="24">
<TextBlock x:Uid="Txt_LangTip" FontSize="22"/>
<ComboBox x:Name="cbLangSelect" Width="320" Height="40" CornerRadius="6">
<ComboBoxItem Tag="zh-CN" Content="简体中文"/>
<ComboBoxItem Tag="en-US" Content="English"/>
<ComboBoxItem Tag="th-TH" Content="ภาษาไทย"/>
</ComboBox>
<StackPanel Orientation="Horizontal" Spacing="12">
<Button x:Name="btnSave" x:Uid="Btn_Save" Content="Save" Click="BtnSave_Click" Width="120" Height="38" CornerRadius="5"/>
</StackPanel>
<TextBlock Foreground="Gray" Text="Note: After saving, page will refresh to apply language."/>
</StackPanel>
</Page>
Langage du code : HTML, XML (xml)
Voici le code C# associé en arrière-plan :
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Microsoft.Windows.ApplicationModel.Resources;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using ThaiTong.Common;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Globalization;
using Windows.Storage;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace ThaiTong.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class LanguageSettingPage : Page
{
private const string LangSettingKey = "AppLanguageCode";
private string _currentLang;
private readonly ResourceLoader _resLoader;
public LanguageSettingPage()
{
InitializeComponent();
_resLoader = new ResourceLoader();
var setting = ApplicationData.Current.LocalSettings;
if (setting.Values.TryGetValue(LangSettingKey, out var saveLang))
{
_currentLang = saveLang.ToString();
}
else
{
string sysLang = ApplicationLanguages.Languages.FirstOrDefault() ?? "";
_currentLang = Languages.supportLangs.Contains(sysLang) ? sysLang : "en-US";
}
// Pre-select matched language in dropdown list
foreach (var item in cbLangSelect.Items)
{
if (item is ComboBoxItem cbi && cbi.Tag.ToString() == _currentLang)
{
cbLangSelect.SelectedItem = item;
break;
}
}
}
// Save selected language setting
private async void BtnSave_Click(object sender, RoutedEventArgs e)
{
if (cbLangSelect.SelectedItem is not ComboBoxItem selectItem) return;
string newLang = selectItem.Tag.ToString();
if (_currentLang == newLang) return;
ApplicationData.Current.LocalSettings.Values[LangSettingKey] = newLang;
_currentLang = newLang;
ApplicationLanguages.PrimaryLanguageOverride = newLang;
// Load localized text from resw resource file
ContentDialog tipDialog = new ContentDialog()
{
XamlRoot = this.XamlRoot,
Title = _resLoader.GetString("Dlg_LangChange_Title"),
Content = _resLoader.GetString("Dlg_LangChange_Content"),
CloseButtonText = _resLoader.GetString("Dlg_LangChange_BtnOk")
};
await tipDialog.ShowAsync();
}
}
}
Langage du code : HTML, XML (xml)
À chaque enregistrement d’une nouvelle préférence linguistique par l’utilisateur, nous lui demandons de redémarrer l’application afin que l’ensemble des textes de l’interface se mette à jour complètement.
La mise en œuvre de la localisation sous WinUI 3 se divise en deux parties distinctes : le balisage dans les fichiers XAML et la lecture des textes dans le code C# en arrière-plan.
Pour les éléments XAML, utilisez l’attribut x:Uid comme dans cet exemple :
<TextBlock x:Uid="Txt_LangTip" FontSize="22"/>Langage du code : HTML, XML (xml)
Ensuite, organisez la structure des dossiers de ressources de localisation : créez un dossier racine nommé Strings dans votre projet, puis ajoutez des sous-dossiers correspondant à chaque code de culture (par exemple en-US pour l’anglais américain). Dans chaque dossier linguistique, ajoutez un fichier Resources.resw contenant des paires clé-valeur pour les traductions.
<data name="Btn_Save.Content" xml:space="preserve">
<value>Enregistrer</value>
</data>Langage du code : HTML, XML (xml)
Le champ name sert de clé de recherche. Le suffixe .Content désigne la propriété cible du contrôle. L’élément Txt_LangTip évoqué plus haut se définit comme suit :
<data name="Txt_LangTip.Text" xml:space="preserve"><value>Sélectionner la langue de l'application</value></data>Langage du code : HTML, XML (xml)
Nous ajoutons ici .Text car nous ciblons spécifiquement la propriété Text du contrôle TextBlock.
Pour les textes dynamiques présents dans le code C#, commencez par instancier un objet ResourceLoader :
private readonly ResourceLoader _resLoader;
public LanguageSettingPage()
{
InitializeComponent();
_resLoader = new ResourceLoader();Langage du code : PHP (php)
Après l’initialisation, récupérez les chaînes localisées partout dans le code grâce à la méthode GetString :
Title = _resLoader.GetString("Dlg_LangChange_Title"),Langage du code : JavaScript (javascript)
