» [WPF] ResourceDictionary 다국어 지원

[WPF] ResourceDictionary 다국어 지원

by DUBUKIMCH

아래 코드들로 다국어 지원 기능을 구현하기 위해 각 요소가 하는 역할을 단계별로 설명드리겠습니다.

1. 프로젝트 구조

프로젝트에는 각 언어별 ResourceDictionary 파일을 준비해 두었습니다. 예를 들어 ResourceDictionary.ko-KR.xaml, ResourceDictionary.ja-JP.xaml, ResourceDictionary.es-EU.xaml 파일을 만들어 각 언어에 맞는 문자열을 저장합니다.

  • 예: ResourceDictionary.ko-KR.xaml
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:system="clr-namespace:System;assembly=mscorlib">

    <system:String x:Key="EXPLAIN_01">모든 요소들은 제거됩니다.</system:String>
    <system:String x:Key="EXPLAIN_02">폴더에 같은 이름의 파일이 존재합니다.</system:String>

</ResourceDictionary>
  • 예: ResourceDictionary.ja-JP.xaml
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:system="clr-namespace:System;assembly=mscorlib">

    <system:String x:Key="EXPLAIN_01">すべての要素が削除されます。</system:String>
    <system:String x:Key="EXPLAIN_02">同じ名前のファイルがフォルダに存在します。</system:String>

</ResourceDictionary>
  • 예: ResourceDictionary.es-EU.xaml
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:system="clr-namespace:System;assembly=mscorlib">

    <system:String x:Key="EXPLAIN_01">Todos los elementos serán eliminados.</system:String>
    <system:String x:Key="EXPLAIN_02">Un archivo con el mismo nombre existe en la carpeta.</system:String>

</ResourceDictionary>
  • 예: ResourceDictionary.en-US.xaml
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:system="clr-namespace:System;assembly=mscorlib">

    <system:String x:Key="EXPLAIN_01">All elements will be removed.</system:String>
    <system:String x:Key="EXPLAIN_02">A file with the same name already exists in the folder.</system:String>

</ResourceDictionary>

이처럼 각 파일에 특정 언어에 해당하는 리소스를 정의합니다. 이 리소스들은 프로그램에서 DynamicResource로 불러올 수 있습니다.

2. App.xaml 설정

App.xaml 파일에서 초기 리소스 딕셔너리를 설정합니다. 기본적으로 사용될 리소스들을 지정하며, 프로그램 실행 중 MergedDictionaries에 추가된 리소스를 변경하면 UI가 자동으로 갱신됩니다.

  • App.xaml
<Application x:Class="test241106_ResouceDictionary.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:test241106_ResouceDictionary"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <!-- 초기 상태에서 ko-KR을 기본으로 설정 -->
                <ResourceDictionary Source="ResourceDictionary.ko-KR.xaml" />
                <ResourceDictionary Source="ResourceDictionary.ja-JP.xaml" />
                <ResourceDictionary Source="ResourceDictionary.es-EU.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

여기서는 ResourceDictionary.ko-KR.xaml, ResourceDictionary.ja-JP.xaml, ResourceDictionary.es-EU.xaml을 포함하지만, 실행 중에 코드로 각 리소스를 교체할 수 있습니다.

3. MainWindow.xaml UI 설정

MainWindow.xaml 파일에서는 언어를 선택할 수 있는 ComboBoxButton을 추가하고, 각 UI 요소가 DynamicResource를 통해 텍스트를 표시하도록 설정합니다.

  • MainWindow.xaml
<Window x:Class="test241106_ResouceDictionary.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ResourceDictionary Example" Height="200" Width="600">
    <Grid>
        <!-- ComboBox로 언어 선택 -->
        <ComboBox Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top" 
                  ItemsSource="{Binding LanguageList, Mode=TwoWay}" 
                  SelectedItem="{Binding SelectLanguage, Mode=TwoWay}"
                  SelectionChanged="ComboBox_SelectionChanged"/>
        <!-- Button 클릭 시 언어 변경 -->
        <Button Name="MyButton" Content="{DynamicResource EXPLAIN_01}" 
                Command="{Binding SwitchLanguage_ClickCommand}" 
                HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,20,0,0"/>
        <!-- DynamicResource를 사용하여 TextBlock에 텍스트 표시 -->
        <TextBlock Text="{DynamicResource EXPLAIN_01}" HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
        <TextBlock Text="{DynamicResource EXPLAIN_02}" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
    </Grid>
</Window>

4. ViewModel 설정

ViewModel에서는 ComboBox로 선택된 언어에 따라 ResourceDictionary를 갱신합니다. ResetLanguage 메서드는 선택된 언어에 맞는 리소스를 불러와 UI를 업데이트합니다. (code pro플러그인에서 json 양식이 맞지 않는 오류가 생겨 임시적으로 viewmodel만 설정 다르게 함.)

  • ViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Input;

namespace test241106_ResouceDictionary
{
    public class ViewModel : INotifyPropertyChanged
    {
        public string SelectLanguage { get; set; }
        public ObservableCollection LanguageList { get; set; }
        public ICommand SwitchLanguage_ClickCommand => new RelayCommand(SwitchLanguage_Click);

        public ViewModel()
        {
            LanguageList = new ObservableCollection { "en-us", "ko-kr", "es-eu", "ja-jp" };
            SelectLanguage = CultureInfo.CurrentCulture.Name;
            ResetLanguage();
        }

        public void SwitchLanguage_Click()
        {
            ResetLanguage();
        }

        public void ComboBoxEdit_EditValueChanged()
        {
            ResetLanguage();
        }

        private void ResetLanguage()
        {
            // 프로젝트 루트 디렉터리에서 리소스 파일을 가져옴
            string projectDirectory = Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory)?.Parent?.Parent?.FullName;
            string dictionaryPath = Path.Combine(projectDirectory, $"ResourceDictionary.{SelectLanguage}.xaml");

            Application.Current.Resources.MergedDictionaries.Clear();

            if (File.Exists(dictionaryPath))
            {
                var newDictionary = new ResourceDictionary { Source = new Uri(dictionaryPath, UriKind.RelativeOrAbsolute) };
                Application.Current.Resources.MergedDictionaries.Add(newDictionary);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

    public class RelayCommand : ICommand
    {
        private readonly Action _execute;
        public RelayCommand(Action execute) => _execute = execute;
        public bool CanExecute(object parameter) => true;
        public void Execute(object parameter) => _execute();
        public event EventHandler CanExecuteChanged;
    }
}

5. MainWindow.xaml.cs에서 언어 변경 이벤트 설정

ComboBox에서 언어를 선택하면 SelectionChanged 이벤트가 발생하여 ResetLanguage 메서드를 호출합니다.

  • MainWindow.xaml.cs
using System.Windows;

namespace test241106_ResouceDictionary
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ViewModel();
        }

        private void ComboBox_SelectionChanged(object sender, RoutedEventArgs e)
        {
            ((ViewModel)DataContext).ComboBoxEdit_EditValueChanged();
        }
    }
}

동작 설명

  1. 앱 실행 시 초기 언어 설정: App.xaml에서 ResourceDictionary.ko-KR.xaml이 기본으로 로드됩니다. 따라서 앱이 처음 실행될 때는 한국어가 기본 언어로 설정됩니다.
  2. 언어 선택: ComboBox에서 언어를 선택하면 ComboBox_SelectionChanged 이벤트가 발생하여 ComboBoxEdit_EditValueChanged 메서드를 호출하고, 이 메서드는 ResetLanguage를 실행합니다.
  3. 리소스 갱신: ResetLanguage는 선택된 언어에 해당하는 ResourceDictionary 파일을 찾아 로드하고, UI는 DynamicResource를 통해 자동으로 해당 언어로 업데이트됩니다.

You may also like

Leave a Comment

error: Content is protected !!