ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
多言語対応アプリの構築
使用する言語に関わらず、ユーザーがアプリを適切かつ効果的に利用できるようにしましょう。このセッションでは、テキストの入力、表示、検索、フォーマットに関するベストプラクティスをご紹介します。別のキーボードに切り替えることなく、複数の言語でテキストを入力できるようにする方法を詳しく説明します。また、String Catalogの最新機能を使用して、ローカリゼーションをさらに簡単に行う方法も取り上げます。
関連する章
- 0:00 - Introduction
- 2:24 - Input
- 8:08 - Display
- 11:01 - Localization
- 16:07 - Wrap-up
リソース
関連ビデオ
WWDC24
WWDC23
WWDC21
WWDC20
-
ダウンロード
こんにちは آداب(ādāb) नमस्ते(namaste) 大家好(dàjiāhǎo) Karanです 今回皆さんにお話しするのは 多言語に対応するアプリの構築についてです 今日の世界ではほとんどの人が 複数の言語を話して育つか 複数の言語に触れながら生活しています バンクーバーで 読みたい本を探している時でも 台北でかき氷を食べている時でも デリーで地下鉄に乗っている時でも 誰もが多言語社会にいて 周りの人は色々な言語で話したり 読んだり聞いたり メッセージをやり取りしています 私たちは毎日アプリを使って人と話したり 日記をつけたり 映画を観たり本を読んだりしていて 私たちが使うすべての言語で アプリがうまく動作することを求めています
そこで今日は 多言語のユーザーにとって 魅力的なアプリを実現するための ヒントを紹介したいと思います その話に進む前に Appleで力を入れている 取り組みの一部をご紹介します 今年は 多言語の体験を向上させる 新機能を数多く導入すると同時に 既存の機能を拡張して さらに多くの言語をサポートします これらの新機能をいくつか見てみましょう
まず新しい多言語キーボードでは 言語を手動で切り替えることなく 複数の言語を入力できます
例えば 韓国語と英語を話す人のために iOS 18では 独自の マルチスクリプト文字入力体験を導入しています
既存の様々な機能が より多くの言語で利用できるようになります 例えば テキスト認識表示が アラビア語に対応します また 壁紙や文字盤の 数字をカスタマイズできるように インド文字が10種類追加されました 最後に 新しいM4 iPad Proの Magic Keyboardでは アラビア語用の ファンクションキーが再設計されて 音量や明るさのキーが ハードウェアとソフトウェアの間で 正確に対応するようになりました
これを始めとして Appleでは様々な形で ソフトウェアとハードウェアを 1つのシームレスな体験に融合させています こうした素晴らしい新機能を ぜひお試しください では 多言語に対応する 優れたアプリの構築についてお話しします 今日の内容は3部構成になっています 入力 表示 ローカリゼーションです 多言語への取り組みとして まず入力を取り上げます 今回の取り組みを手伝ってくれるのは 様々な言語を話す世界各国の3人の友人です この3人の力を借りて 東から西へ移動しながら 一般的な多言語のシナリオを確認していきます 入力についてお話しするために Aprilの一日を見てみましょう Aprilはシンガポールに住んでいて 英語と中国語を話します 親友のFarahとは英語で会話し
そしてパートナーとは中国語で会話します
Aprilがこうした会話をする時 それぞれの会話でAprilが使う言語を キーボードが記憶しています アプリでこれを行う方法を お見せしましょう とても簡単です UIResponderのメソッドである textInputContextIdentifierを オーバーライドし 一意の文字列識別子を返すだけです Aprilは手書きキーボードを使って 中国語で文字を書く時 書きやすいように キーボードをよく縦に広げます この時にメッセージアプリは UIを上に移動してスペースを確保します
これには2つの方法があります 1つ目に キーボードの真上に ビューを配置する必要がある場合は inputAccessoryViewを使えば キーボードの上にビューを固定できます 画面の下部にビューを固定することで ハードウェアキーボードを 入力に使う場合にも対応できます 2つ目の方法は keyboardLayoutGuideを使うことです これにより キーボードを基準にして ビューの配置をカスタマイズできます また 中国語や日本語などの言語で 入力する場合は マークされたテキストを キーボードで使用します マークされたテキストとは何か お見せしましょう マークされたテキストは 候補を選択する前の一時的なテキストで 下線が引かれています 候補が確定されると マークされたテキストは消えます
悪い例を見てみましょう キーを押すたびにテキストが変更されて 入力の邪魔になっています アプリがこのように動作するのは 入力中に自動補完を提供するためです では 便利なインラインの補完を 表示しながら 中国語で入力する 方法を見てみましょう ここで重要となるのは マークされたテキストがないのを テキストの変更前に確認することです markedTextRangeから 空の結果が返された時は テキストを変更して自動補完を インラインで表示しても問題ありません ただし マークされたテキストがある時でも そのテキストに基づいて検索を行い テーブルビューなどの他の場所に 候補を表示することはできます Spotlightでは実際にこれを実現しています ご覧のように 入力に応じて上の候補が更新され 候補が確定された時にだけ インラインのテキストが変更されます ありがとう April 次はRajの例を通して 優れた検索体験を 実現する方法を見ていきましょう
Rajはインドに住んでいて ヒンディー語と英語を話します ヒンディー語で検索していると 目的のものが見つからない場合があります こうしたことが起こる原因と 解決方法を見てみましょう
各言語には まったく異なる綴りと関連する綴りを 判別するためのルールがあります
英語では 小文字のaでappleを検索した時に 大文字のAのAppleに 一致すると期待されます ドイツ語などの言語にも 同様のルールがあります Rajの場合 検索で入力した綴りの形式は 連絡先に登録された名前の形式と まったく違うものでした この問題はコードを 1行変更するだけで修正できます localizedStandardRange を使うのです localizedStandardRange はご想像の通り ロケール固有の規則を優先して 検索を行う標準的な方法です 今年はこのAPIの機能も 大幅にアップグレードされて 多種多様な文字の 様々な綴りの規則にわたるマッチングや 様々な文字にわたる数字のマッチングが サポートされるようになりました localizedStandardRangeと iOS 18の新しい機能強化により Rajは好きな方法で入力して 探している連絡先を簡単に見つけられます
最後に Rajが 検索フィールドに入力する時に 時々遭遇する問題がひとつあります 見てみましょう
一部のアプリでは Rajがヒンディー語で 入力するとテキストが崩れて見えます
この問題は 入力されたテキストの部分を アプリでハイライトする方法に起因します
ヒンディー語や他の多くの言語では文字に 母音やその他の記号が付随します 例として 地平線を意味する単語の क्षितिज(kshitij)を キーごとに分けて入力してみましょう その際にどう変化するかに注目してください
ご覧のようにヒンディー語ではキーを押すと 文字が右側に挿入されるとは限らず 既存の文字が変化することもあります
通常の文字と太字は 技術的に異なるフォントであり あるフォントの文字を別のフォントの記号と つなぐことはできません これが テキストが崩れて見える原因です しかし いい方法として 代わりに色を使用して テキストの一部をハイライトできます こちらが色の属性を 属性付き文字列に追加する方法です これに関連して 斜体化にも触れておきたいと思います こちらは「こんにちは」を 10の言語で表しています では すべて斜体にしてみましょう 10個のうち3つしか変化していません 残り7つの言語には斜体の概念がなく 斜体化を適用しても 見た目が変わらないからです したがって斜体を使う時には 翻訳で区別が失われる 可能性があるため注意が必要です
さて 太字の代わりに 色を使うようにしたので Rajは検索結果を読める上に 表示されているテキストのどの部分が 入力した文字と一致するか 区別することもできます 入力については以上です ありがとう Raj April 次にテキストの表示方法について説明します 表示に関しては Ismatの目線で世界を見てみましょう
Ismatは米国に住んでいて 英語とウルドゥー語を話します
Ismatはウルドゥー語のテキストが ほとんどのアプリでは完璧に表示されるものの 一部のアプリではテキストが崩れて 判読できなくなる場合があることに 気づきました こちらはنستعلیق(Nastālīq)という ウルドゥー文字の名前で 左側は正しく表示されていますが 右側は誤って表示されています この場合の解決策は簡単で TextKit 2を使うだけです この次世代テキストエンジンにより すべての文字が正しくレンダリングされます ちなみに SwiftUI AppKit UIKitで ラベルやテキストビューを使う時は このエンジンが自動的に使用されます
今Ismatは日記を読み返して 過去の出来事を思い出しています
素晴らしいことに ジャーナルアプリを英語で実行していても TextKit 2のおかげで ウルドゥー語の文章が美しく表示されます しかし ジャーナルやほとんどのアプリでは ウルドゥー語の文章がうまく処理される一方 一部のアプリでは ウルドゥー語の文章の行が極端に詰まって 読みにくい場合があります ジャーナルでは ウルドゥー語固有のコードなしに ウルドゥー語の文章を適切に処理できます これは多くのアプリと同様に アプリの言語だけでなく Ismatの場合のように あらゆるユーザーの言語も考慮した テキストスタイルを使用しているからです この方法により あらゆる言語のテキストを どのアプリでも正しくレンダリングできます テキストスタイルの使い方はとても簡単です こちらはSwiftUI UIKit AppKitで テキストスタイルを初期化する 方法を示しています また デフォルトでオフになっている clipsToBoundsを ラベルやテキストビューではfalseのままに しておく必要があることに注意してください 多くの言語のテキストはビューの境界外で レンダリングする必要があるからです オフにしないと判読できなくなります
さて 特定の言語で コンテンツを表示していて その言語に最適な 印字動作が必要になる場合も あるでしょう このような場合は typesettingLanguageを指定できます
左側の例は 優先する言語を すべて考慮したデフォルトの印字で Ismatが使うウルドゥー語も含まれます 右側の例では typesettingLanguageを英語に設定して 同じテキストでも行の間隔を狭くしています 最後に April Raj Ismatは 名前が正しく表示されることが とても重要だと考えています formatted APIを使用すると アプリの言語に関係なく あらゆる言語と文字で 名前を正しく表示できるようになります 例えば 中国語や日本語などの言語では 下の名だけを表示するのは 適切ではありません 代わりにフォーマッタの短い形式を使って 適切な場合にのみ 下の名を使用するようにします モノグラムでは省略形式を使用します
April Raj Ismatには ここでお別れをして アプリのローカライズに毎日使うツールの 注目すべき機能強化について 見ていきましょう
まずはString Catalogsです String Catalogsは Xcodeでのローカライズの基盤であり 文字列とコードの同期を維持し 強力な編集ツールを提供することで プロジェクトの 翻訳管理プロセスを簡素化します String Catalogsの新機能を見てみましょう
String Catalogsでは 書式指定子の不一致など 検証でよくある問題が検出され ワンクリックで修正できるようになりました
次に 特定の文字列を 「Don’t Translate」としてマークできるので コンテンツの最終調整が まだ進行中であるのを 翻訳者に簡単に知らせることができます
そして最後に 特定の文字列について コードとカタログ間を 簡単に行き来できるようになりました String Catalogsの こうした機能強化すべてによって 開発とローカリゼーションの ワークフローが加速すれば幸いです 次に アプリ内の1つ1つの文字列を 魅力的にするために よりインクルーシブでパーソナライズされた ものにする方法について説明します
文法的な一致を 自動で確保する強力なエンジンにより アプリで「言語と地域」設定の 呼称を使ってユーザーに話しかけ 親近感を高めることができます
アプリで代名詞を使って 人を表すこともできます 最後に 文法エンジンにより アプリ内のテキストが すべて文法的に正しいことを 確保できるだけでなく 1つのテキストに対して 何十もの文字列のバリエーションを 作成する必要もなくなります そして今年は文法エンジンが 新たに2つの言語に対応します 1つ目はヒンディー語です ヒンディー語でデバイスを使う場合 「言語と地域」設定で呼びかけ語を指定して どう呼びかけてもらうかを ユーザーが選べるようになりました
また 文法エンジンは 韓国語にも対応するので 後続の単語に応じて 助詞を変化させることが可能になります ドイツ語 英語 スペイン語 フランス語 イタリア語 ポルトガル語 ヒンディー語 韓国語をアプリでサポートする場合は 自動文法一致機能を利用できます
次に数字についてお話ししましょう 英語ではアラビア数字が使われていて これらの数字は 他の多くの言語でも使われています ただし アラビア数字は 世界中で使われている 様々な数体系の1つです 複数の数体系をサポートする言語では ユーザーは「言語と地域」設定で 好きな数字を選択できます 便利なことに フォーマッタを使うと 数字が自動的に ロケール固有のすべてのルールに従います フォーマッタを使用していない数字を フォーマットする簡単な方法を紹介します 天気アプリのこのテキストは 「10日間の予報」を意味していて 通常はこれを表す ローカライズ可能な文字列があります
これをローカライズする方法は2つあります 1つ目は補間を使用して コードで数字をフォーマットすることです Text内にあるため NumberOfDaysは現在のロケールに合わせ 自動的にフォーマットされます この機能が役立つのは 実行時に数字が決まる場合や どの言語でも この文字列で数字を使う場合です
今年は2つ目の方法として 文字列内で直接 数字をフォーマットする機能も導入します この方法は コードでフォーマットする場合と まったく同じ状況で使用できます ただし 最大の利点として この機能を使うと ローカライズされた文字列内の数字を コードなしで簡単にフォーマットできます
この最初の例では 10日間の予報という文字列を この方法でローカライズできます この例では ソース文字列は英語で ヒンディー語に翻訳された文字列では formatNumberを使います これにより 「言語と地域」の数字設定に従って 実行時に正しい数体系が使用されます
数体系に加えて 小数点の区切り文字など 数字フォーマットの別の面にも対応できます 例えば スペイン語の場合 1つの文字列を スペインと米国の両方で使用できます
複数のローカリゼーションを サポートするアプリでは 「言語と地域」設定で 複数の言語が指定されている場合 ユーザーがアプリを使う時に 言語設定が自動的に表示されるので デバイス全体の言語とは関係なく アプリ固有の言語を選択できます この機能は 様々な言語で様々なアプリを使う 多言語のユーザーから高い支持を得ています 複数の優先する言語を ユーザーが指定している場合だけでなく 常にアプリの設定に 言語オプションを表示したい場合は InfoPlistで UIPrefersShowingLanguageSettingsを YESに指定します
必要に応じて アプリの設定に直接移動する ボタンなどの機能も追加できます 最後にご紹介するSF Symbolsは ローカリゼーションで 大いに役立つ重要なツールであり これらのシンボルは 多種多様な言語や文字に対応しています Appleのアプリでよく使われるシンボルでは SF Symbolsを使用しています フォーマットコントロールを表示する ボタンで使われるtextformatなどです 署名のような 決まった形のない要素を含むシンボルも 各言語で自然に見えるよう調整されていて SF Symbolsは様々な数体系だけでなく 右から左に書く言語もサポートしています したがって アプリで使う シンボルを探している時は 最初にSF Symbolsの 豊富なライブラリをチェックしてみてください
まとめると 現在の多言語の世界では ユーザーはアプリで色々な言語を使うので キーボード入力や表示を どの言語でも適切に機能させて 優れた体験をユーザーに 提供する必要があります また String Catalogsなどの ツールを活用することで 開発とローカリゼーションの ワークフローを大幅に加速できます 皆さんの多言語対応の アプリを楽しみにしています ありがとうございました شکریہ(shukriyā) धन्यवाद(dhanyavād) 謝謝(xièxiè)
-
-
3:18 - Specify textInputContextIdentifier
override var textInputContextIdentifier: String? { uniqueID }
-
3:41 - Place a view directly above the keyboard
textView.inputAccessoryView = viewAboveKeyboard
-
4:00 - Use keyboardLayoutGuide to adapt to keyboard
view.keyboardLayoutGuide.topAnchor.constraint(equalToSystemSpacingBelow: textView.bottomAnchor, multiplier: 1.0).isActive = true
-
4:42 - Check for marked text before modifying
if textView.markedTextRange.empty { // Perform actions involving editing text }
-
5:58 - Use localizedStandardRange when searching
let range = text.localizedStandardRange(of: search)
-
7:24 - Use color differences to highlight text
attributedString[range].foregroundColor = highlightColor
-
9:39 - Text Styles
// Text Styles // SwiftUI Text("Hello, world!") // uses .body Text Style by default Text("Hello, world!").font(.title) // UIKit let label = UILabel() label.text = "Hello, world!" label.font = UIFont.preferredFont(forTextStyle: .body) // AppKit let textField = NSTextField(labelWithString: "Hello, world!") textField.font = NSFont.preferredFont(forTextStyle: .body) // Keep clipsToBounds off clipsToBounds = false
-
10:03 - Typesetting language
// Typesetting language // SwiftUI Text(verbatim: "Hello, world!").typesettingLanguage(.init(languageCode: .english)) // UIKit let label = UILabel() label.text = "Hello, world!" label.traitOverrides.typesettingLanguage = Locale.Language(languageCode: .english)
-
10:29 - Formatting names
// Formatting names let nameComponents = PersonNameComponents (givenName: "瑗珺", familyName: "汪", nickname: "珺珺") // Short Name (respects settings like “Prefer Nicknames”) let shortName = nameComponents.formatted(.name(style: .short)) // 珺珺 // Abbreviated Name (can be used for monograms) let monogram = nameComponents.formatted(.name(style: .abbreviated)) // 汪
-
12:20 - Examples of personalizing text
"^[Nuestro %@](inflect: true) está ^[hecho](agreeWithArgument: 1) de %@." "अगर आप पहुँच नहीं ^[पाते हैं](inflect: true)" "예: ‘^[%@을](inflect: true) 켤 때’"
-
13:43 - Format numbers using Text
Text("\(numberOfDays)-day forecast")
-
14:21 - Format numbers using AttributedString
AttributedString(localized: "10-day forecast") AttributedString(localized: "0.5× zoom")
-
15:23 - Launch to your app’s settings
// Launch to your app’s settings if let url = URL(string: UIApplication.openSettingsURLString) { await UIApplication.shared.open(url) }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。