システム開発<基本編>SwiftUIで、マルチ言語(多言語)を切り替えるアプリケーション

Swift

前回は、SwiftUI で、上部Tab制御 & 3種類の画像ファイル選択方法を利用した

アプリケーションを開発する記事を紹介しました。

 

MenuPickerView

WheelPickerView

DropDownView

 

今回は、SwiftUI で、マルチ言語(多言語)を切り替えるアプリケーションを

開発する記事を紹介しようと思います。

SwiftUIでマルチ言語(多言語)を切り替えるアプリケーション

 

 

習得内容

今回、SwiftUIで、マルチ言語(多言語)を切り替えるアプリケーションを作成する事で、

下記の内容を習得する事が出来ます。

  • Localizations:プロジェクトで、言語の設定を管理します。
  • Strings File:Xcode14までは、Strings File で各言語の Key と値(文章)の管理を担当しています。Xcode15以降では、非推奨になります。
  • String Catalog:Xcode15以降は、Strings File ではなく、String Catalog が推奨されています。Strings File と同様に、各言語の Key と値(文章)の管理を担当しています。
  • .environment:environmentモディファイアを利用する事で、View のマルチ言語(多言語)を切り替えます。

 

 

マルチ言語(多言語):切り替え方法

2023年に顧客から、保養地予約システム(WEB)&客室コンシェルジェアプリ(iPad)

の開発を依頼された事が有りました。

外国籍のお客様も利用されるとの事で、客室コンシェルジェアプリ(iPad)には、

マルチ言語(多言語)を切り替える機能を組み込む必要が有りました。

 

iOSの設定で、言語と地域を切り替えたり、SwiftUI の Preview でマルチ言語(多言語)

を切り替える方法は、サイトや書籍で見掛けるものの、ボタンやピッカーを利用して、

マルチ言語(多言語)を切り替える方法が見付からず、実装に苦労した経緯が有りました。

また、当時は Strings File で、各言語の key と値(文章)を実装して納品しましたが、現在、

Strings File は Legacy の記載となり、遺産扱いには驚きましたが動作はするようです。

 

2026年初頭の現在も、SwiftUI でボタンやピッカーを利用して、マルチ言語(多言語)を

切り替える方法について、サイトや書籍で見付ける事が出来なかったので、今回紹介します。

 

 

翻訳サービス(API)

マルチ言語(多言語)を切り替えるアプリケーションは、入力した文章をGoogle翻訳、

DeepL翻訳、Microsoft Translator 等の翻訳サービス(API)を利用したアプリケーション

とは別のアプリケーションになります。

翻訳サービス(API)を利用したアプリケーションは、別の機会に紹介が出来ればと思います。

 

 

動作環境

今回も、アプリが動作する環境は下記になります。

  • mac OS:Sequoia 15.6.1
  • iOS:26.0
  • Xcode:26.0.1
  • Swift:6.2.1

 

 

MultiLangView

では、マルチ言語(多言語)を切り替えるアプリケーションを作成して行きましょう。

 

Xcode の上部タブメニューより、File → New → File from Template を選択します。

 

SwiftUI View を選択します。

 

名称は、MultiLangView を入力してみます。

 

Create ボタンを押して、MultiLangView.swift  を作成します。

 

Localizations:言語の追加

マルチ言語(多言語)を実現する為に、プロジェクトに言語を追加して行きましょう。

今回、利用する言語は、下記の4つです。

  1. 日本語
  2. 英語
  3. 韓国語
  4. 中国語(簡体字)

 

SwiftUI の Project を確認してみます。

 

Xcode の左側に配置されている Navigator Area(ナビゲーター・エリア)で、最上段の

Project 名(赤枠)をクリック(タップ)します。

次に、Navigator Area(ナビゲーター・エリア)の右側に PROJECT 文字が見えるので、

こちらも Project 名(オレンジ枠)をクリック(タップ)します。

次に、PROJECT 文字の右側にある info タブ(緑枠)をクリック(タップ)します。

すると、info タブ(青枠)の下位に、Localizations 情報(青枠)が見えると思います。

デフォルトで、English が設定されている状態が確認出来ます。

 

では、他の言語を追加して行きます。

English が設定されている下に [+]  ボタンが有りますので、クリック(タップ)します。

[+]  ボタンをクリック(タップ)すると、言語の選択ドロワー(緑枠)が開きますので、

残りの日本語、韓国語、中国語(簡体字)を選択してみます。

 

選択ドロワー(緑枠)で、残りの日本語、韓国語、中国語(簡体字)を選択すると、

Project に、日本語、韓国語、中国語(簡体字)が設定された(紫枠)事が分かります。

 

Localizable File:String Catalog

Project に、日本語、韓国語、中国語(簡体字)が設定されましたので、次は、各言語の

key と値(文章)の管理を担当するファイルの作成と編集を行います。

 

Xcode の上部タブメニューより、File → New → File from Template を選択します。

 

String Catalog(下記の青枠) を選択します。

 

名称は、デフォルトの Localizable.xcstrings を変更しないように気を付けて下さい。

名称を変更してしまうと、マルチ言語(多言語)が出来なくなります。

 

Create ボタンを押して、Localizable.xcstrings を作成します。

 

Localizable.xcstrings が作成されると、Navigator Area(ナビゲーター・エリア)に、

Localizable File(緑枠) が生成されている事が分かります。

また、Localizable File の中には、先程、Project で設定した Localizations の

4つの言語設定ファイル(赤枠)も実装されているのが分かります。

 

次に、言語設定ファイル(赤枠)の右側に[+]  ボタン(青枠)が有りますので、

クリック(タップ)します。

 

Key / English (en)  / Comment / State のカラム行と、カラム行の下に、入力行が

追加された事が分かると思います。

ここから、入力行に対して、Key と English (en) :値(文章)をペアで記述します。

 

Localizable File:Key と 文章例

今回、Key と 各言語の値(文章)のサンプルを準備しましたので、参考にしてみて下さい。

Key の記述ルールは、特に有りませんので、管理し易い Key を設定してみて下さい。

 

<Key>
lang_spots_info
lang_weather_info
lang_news_info
lang_fashion_info
lang_music_info
lang_en_info
lang_jp_info
lang_zh_info
lang_ko_info

<英語>
Recommended tourist spots
Tomorrow's weather forecast
Headline news
Trending fashion
Country music
English
Japanese
Chinese
Korean

<日本語>
お勧めの観光地
明日の天気予報
ヘッドラインニュース
流行のファッション
田舎の音楽
英語
日本語
中国語
韓国語

<中国語(簡体字)>
推荐旅游景点
明日天气预报
头条新闻
流行时尚
乡村音乐
英语
日语
中文
韩语

<韓国語>
추천 관광지
내일 날씨 예보
헤드라인 뉴스
유행 패션
시골 음악
영어
일본어
중국어
한국어

 

では、入力行に対して、Key と English (en) :値(文章)をペアで記述してみます。

 

次に、Key と Chinese (zh-Hans) :値(文章)をペアで記述してみます。

 

同様に、Key と Japanese(ja) :値(文章)をペアで記述してみます。

 

最後に、Key と Korean (ko) :値(文章)をペアで記述してみます。

 

これで、マルチ言語(多言語)の準備と設定が完了しました。

 

 

ContentView:メインメニュー(ランチャー)

メインメニュー(ランチャー):ContentView を確認します。

 


import SwiftUI

struct ContentView: View {

    @State var isPopupView_1 = false
    @State var isPopupView_2 = false
    @State var isPopupView_3 = false
    @State var isPopupView_4 = false
    @State var isPopupView_5 = false

    var body: some View {
        
        VStack{
            Button {
                self.isPopupView_1.toggle()
            } label: {
                Text("QRCodeView")
                    .font(.title2)
            }
            .fullScreenCover(isPresented: $isPopupView_1, content: {
                QRCodeView(isPopupView_1: $isPopupView_1)
            })
            .padding()

            Button {
                self.isPopupView_2.toggle()
            } label: {
                Text("ColorPickerView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_2, content: {
                ColorPickerView(isPopupView_2: $isPopupView_2)
            })
            .padding()

            Button {
                self.isPopupView_3.toggle()
            } label: {
                Text("ColorSliderRGBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_3, content: {
                ColorSliderRGBView(isPopupView_3: $isPopupView_3)
            })
            .padding()

            Button {
                self.isPopupView_4.toggle()
                
            } label: {
                Text("ColorSliderHSBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_4, content: {
                ColorSliderHSBView(isPopupView_4: $isPopupView_4)
            })
            .padding()

            Button {
                self.isPopupView_5.toggle()
                
            } label: {
                Text("NavigationListView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_5, content: {
                NavigationListView(isPopupView_5: $isPopupView_5)
            })
            .padding()
        }
    }
}

#Preview {
    ContentView()
}

 

メインメニュー(ランチャー)は、以下の内容です。

  • QRCodeView
  • ColorPickerView
  • ColorSliderRGBView
  • ColorSliderHSBView
  • NavigationListView

 

先程、作成しました MultiLangView を、ContentView のメニューに追加します。

 


import SwiftUI

struct ContentView: View {

    @State var isPopupView_1 = false
    @State var isPopupView_2 = false
    @State var isPopupView_3 = false
    @State var isPopupView_4 = false
    @State var isPopupView_5 = false
    @State var isPopupView_6 = false

    var body: some View {

        VStack{
            Button {
                self.isPopupView_1.toggle()

            } label: {
                Text("QRCodeView")
                    .font(.title2)
            }
            .fullScreenCover(isPresented: $isPopupView_1, content: {
                QRCodeView(isPopupView_1: $isPopupView_1)
            })
            .padding()

            Button {
                self.isPopupView_2.toggle()

            } label: {
                Text("ColorPickerView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_2, content: {
                ColorPickerView(isPopupView_2: $isPopupView_2)
            })
            .padding()

            Button {
                self.isPopupView_3.toggle()

            } label: {
                Text("ColorSliderRGBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_3, content: {
                ColorSliderRGBView(isPopupView_3: $isPopupView_3)
            })
            .padding()

            Button {
                self.isPopupView_4.toggle()

            } label: {
                Text("ColorSliderHSBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_4, content: {
                ColorSliderHSBView(isPopupView_4: $isPopupView_4)
            })
            .padding()

            Button {
                self.isPopupView_5.toggle()

            } label: {
                Text("NavigationListView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_5, content: {
                NavigationListView(isPopupView_5: $isPopupView_5)
            })
            .padding()

            Button {
                self.isPopupView_6.toggle()

            } label: {
                Text("MultiLangView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_6, content: {
                MultiLangView(isPopupView_6: $isPopupView_6)
            })
            .padding()

        }
    }
}

#Preview {
    ContentView()
}

 

ColorPickerView、ColorSliderRGBView、ColorSliderHSBView と同様に

MultiLangView を呼び出す際、モーダル表示をさせる Sheet() を指定しました。

 

 

MultiLangView:マルチ言語(多言語)切り替えアプリ

では、マルチ言語(多言語)を切り替えるアプリケーションを作ってみます。

 

ソース例:MultiLangView(マルチ言語切り替え)

ContentView(親画面) から呼び出される MultiLangView(子画面) のソースを

紹介します。

 


import SwiftUI

struct MultiLangView: View {

    @Binding var isPopupView_6: Bool

    @State private var selectedLang = "ja"

    var body: some View {
        ZStack {
            Color(red: 1.0, green: 0.75, blue: 0.5, opacity: 0.2)
                .edgesIgnoringSafeArea(.all)

            VStack {

                Text(LocalizedStringKey("lang_spots_info"))
                    .font(.system(size: 24))
                    .foregroundColor(.green)
                    .padding()

                Text(LocalizedStringKey("lang_weather_info"))
                    .font(.system(size: 24))
                    .foregroundColor(.teal)
                    .padding()

                Text(LocalizedStringKey("lang_fashion_info"))
                    .font(.system(size: 24))
                    .foregroundColor(.pink)
                    .padding()

                Text(LocalizedStringKey("lang_news_info"))
                    .font(.system(size: 24))
                    .foregroundColor(.blue)
                    .padding()

                Text(LocalizedStringKey("lang_music_info"))
                    .font(.system(size: 24))
                    .foregroundColor(.orange)
                    .padding()


                HStack {
                    Button(LocalizedStringKey("lang_jp_info")) {
                        withAnimation {
                            selectedLang = "ja"
                        }
                    }
                    .font(.system(size: 24))
                    .foregroundColor(selectedLang == "ja" ? Color.red : Color.white)
                    .padding()
                    .background(
                        RoundedRectangle(cornerRadius: 8)
                            .fill(selectedLang == "ja" ? Color.white : Color.gray)
                            .shadow(radius: 5)
                    )
                    .padding()

                    Button(LocalizedStringKey("lang_en_info")) {
                        withAnimation {
                            selectedLang = "en"
                        }
                    }
                    .font(.system(size: 24))
                    .foregroundColor(Color.white)
                    .padding()
                    .background(
                        RoundedRectangle(cornerRadius: 8)
                            .fill(selectedLang == "en" ? Color.blue : Color.gray)
                            .shadow(radius: 5)
                    )
                }
                .padding()

                HStack {
                    Button(LocalizedStringKey("lang_ko_info")) {
                        withAnimation {
                            selectedLang = "ko"
                        }
                    }
                    .font(.system(size: 24))
                    .foregroundColor(Color.white)
                    .padding()
                    .background(
                        RoundedRectangle(cornerRadius: 8)
                            .fill(selectedLang == "ko" ? Color.orange : Color.gray)
                            .shadow(radius: 5)
                    )
                    .padding()
                    
                    Button(LocalizedStringKey("lang_zh_info")) {
                        withAnimation {
                            selectedLang = "zh-Hans"
                        }
                    }
                    .font(.system(size: 24))
                    .foregroundColor(Color.white)
                    .padding()
                    .background(
                        RoundedRectangle(cornerRadius: 8)
                            .fill(selectedLang == "zh-Hans" ? Color.red : Color.gray)
                            .shadow(radius: 5)
                    )

                }
                .padding()


                Button(action: {
                    withAnimation {
                        self.isPopupView_6.toggle()
                    }
                }, label: {
                    Text("Close")
                        .font(.system(size: 24))
                        .foregroundColor(.black)
                })
                .padding()
            }
        }
        .environment(\.locale, .init(identifier: selectedLang))

    }
}

#Preview {
    MultiLangView(isPopupView_6: .constant(false))
}
  • @State private var selectedLang = “ja“:ボタンの選択を、selectedLang で宣言しています。初期値は、日本語を表す “ja” を代入しています。
  • Text(LocalizedStringKey(“lang_spots_info“)):Localizable File で設定した Key:”lang_spots_info” を、LocalizedStringKey() でラッピングしてテキストに設定する事で、選択された言語で “お勧めの観光地” を表示します。
  • Text(LocalizedStringKey(“lang_weather_info“)):Localizable File で設定した Key:”lang_weather_info”  を、LocalizedStringKey() でラッピングしてテキストに設定する事で、選択された言語で “明日の天気予報” を表示します。
  • Text(LocalizedStringKey(“lang_fashion_info“)):Localizable File で設定した Key:
  • “lang_fashion_info” を、LocalizedStringKey() でラッピングしてテキストに設定する事で、選択された言語で “流行のファッション” を表示します。
  • Text(LocalizedStringKey(“lang_news_info“)):Localizable File で設定した Key:”lang_news_info” を、LocalizedStringKey() でラッピングしてテキストに設定する事で、選択された言語で “ヘッドラインニュース” を表示します。
  • Text(LocalizedStringKey(“lang_music_info“)):Localizable File で設定した Key:”lang_music_info”  を、LocalizedStringKey() でラッピングしてテキストに設定する事で、選択された言語で “田舎の音楽” を表示します。

 

  • Button(LocalizedStringKey(“lang_jp_info“)) { withAnimation { selectedLang = “ja“:ボタンの文字に、Localizable File で設定した Key:”lang_jp_info” を、LocalizedStringKey() でラッピングしてボタンに設定する事で、選択された言語で “日本語” を表示します。ボタンが押された(タップされた)時、selectedLang に “ja” を代入しています。
  • .foregroundColor(selectedLang == “ja” ? Color.red : Color.white):selectedLang が “ja” の場合は、ボタンの文字色を赤色に設定し、それ以外の場合は、白色に設定しています。
  • .fill(selectedLang == “ja” ? Color.white : Color.gray):selectedLang が “ja” の場合は、ボタンの色を白色に設定し、それ以外の場合は、グレー色に設定しています。
  • Button(LocalizedStringKey(“lang_en_info“)) { withAnimation { selectedLang = “en“:ボタンの文字に、Localizable File で設定した Key:”lang_en_infol” を、LocalizedStringKey() でラッピングしてボタンに設定する事で、選択された言語で “英語” を表示します。ボタンが押された(タップされた)時、selectedLang に “en” を代入しています。
  • .fill(selectedLang == “en” ? Color.blue : Color.gray):selectedLang が “en” の場合は、ボタンの色を青色に設定し、それ以外の場合は、グレー色に設定しています。
  • Button(LocalizedStringKey(“lang_ko_info“)) { withAnimation { selectedLang = “ko“:ボタンの文字に、Localizable File で設定した Key:”lang_ko_info” を、LocalizedStringKey() でラッピングしてボタンに設定する事で、選択された言語で “韓国語” を表示します。ボタンが押された(タップされた)時、selectedLang に “ko” を代入しています。
  • .fill(selectedLang == “ko” ? Color.orange : Color.gray):selectedLang が “ko” の場合は、ボタンの色をオレンジ色に設定し、それ以外の場合は、グレー色に設定しています。
  • Button(LocalizedStringKey(“lang_zh_info“)) { withAnimation { selectedLang = “zh-Hans“:ボタンの文字に、Localizable File で設定した Key:”lang_zh_info” を、LocalizedStringKey() でラッピングしてボタンに設定する事で、選択された言語で “中国語” を表示します。ボタンが押された(タップされた)時、selectedLang に “zh-Hans” を代入しています。
  • .fill(selectedLang == “zh-Hans” ? Color.red : Color.gray):selectedLang が “zh-Hans” の場合は、ボタンの色を赤色に設定し、それ以外の場合は、グレー色に設定しています。
  • .environment(\.locale, .init(identifier: selectedLang)):environmentモディファイアを利用する事で、View のマルチ言語(多言語)を切り替えます。第一引数には locale、第二引数に選択した selectedLang を設定します。

最後に説明している environmentモディファイアを利用する事で、View全体の

マルチ言語(多言語)を切り替えますので、ここが重要なポイントになります。

 

 

アプリ実行:シミュレータ起動

実際にアプリを実行してみます。

Xcode の上部タブメニューより、Product → Run を選択するか、command + R を

押してみて下さい。

 

エラーが無ければ、iPhoneシミュレータが起動します。

 

 

ContntVeiw(メインメニュー)が表示されました。

MultiLangViewボタンが、最下位に表示されているのが確認出来ました。

 

MultiLangView:日本語表示

続けて、MultiLangViewボタンを押してみます(タップします)。

 

 

ContntVeiw(メインメニュー)の上に MultiLangView が重なって、表示されました。

初期値は、日本語が選択されている状態です。

  • 画面上部には、日本語の文章が配置されています。内容は、サンプルの日本語文章です。
  • 日本語の文章の下に、4つの言語ボタンが配置されています。
  • 日本語ボタンがカラー(白色)表示で、他の言語ボタンはグレー表示となっています。

 

 

MultiLangView:英語表示

では、4つの言語ボタンから、右上の英語ボタンを押してみます(タップします)。

 

 

  • 画面上部は、日本語から英語の文章に切り替わりました。
  • 英語の文章の下に配置された、4つの言語ボタンが英語の文字に切り替わりました。
  • 英語ボタンがカラー(青色)表示で、他の言語ボタンはグレー表示です。

 

 

MultiLangView:韓国語表示

次に、4つの言語ボタンから、左下の韓国語ボタンを押してみます(タップします)。

英語表記だと、Koreanボタンです。

 

 

  • 画面上部は、英語から韓国語の文章に切り替わりました。
  • 韓国語の文章の下に配置された、4つの言語ボタンが韓国語の文字に切り替わりました。
  • 韓国語ボタンがカラー(オレンジ色)表示で、他の言語ボタンはグレー表示です。

 

 

MultiLangView:中国語(簡体字)表示

次に、4つの言語ボタンから、右下の中国語ボタンを押してみます(タップします)。

韓国語表記だと、중국어ボタンです。

 

 

  • 画面上部は、韓国語から中国語(簡体字)の文章に切り替わりました。
  • 中国語の文章の下に配置された、4つの言語ボタンが中国語(簡体字)の文字に切り替わりました。
  • 中国語ボタンがカラー(赤色)表示で、他の言語ボタンはグレー表示です。

 

 

MultiLangView:日本語表示

最後に、4つの言語ボタンから、左上の日本語ボタンを押してみます(タップします)。

中国語(簡体字)表記だと、日语ボタンです。

 

 

  • 画面上部には、中国語(簡体字)から日本語の文章に切り替わりました。
  • 日本語の文章の下に、4つの言語ボタンが配置されています。
  • 日本語ボタンがカラー(白色)表示で、他の言語ボタンはグレー表示です。

 

SwiftUI でボタンを利用して、マルチ言語(多言語)を切り替える方法を実装しました。

ボタンと同様に、ピッカーやドロップダウンでも、マルチ言語(多言語)を切り替える

方法も実装が出来ると思いますので、試してみて下さい。

 

 

まとめ

今回は、SwiftUI で、マルチ言語(多言語)を切り替えるアプリケーションを開発する

記事を紹介しました。

 

次回は、SwiftUIで、動画をループ再生するアプリケーションを開発する記事を

紹介しようと思います。

 

コメント

タイトルとURLをコピーしました