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

Swift

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

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

 

MenuPickerView

WheelPickerView

DropDownView

 

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

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

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

 

 

習得内容

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

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

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

 

 

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

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

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

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

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

 

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

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

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

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

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

 

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) :値(文章)ペアで記述してみます。

 

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

 

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

 

最後に、KeyKorean (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()
}

 

ColorPickerViewColorSliderRGBViewColorSliderHSBView と同様に

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をコピーしました