SalesforceのExperience Cloudの組み込みサービスチャットをURLのlanguageパラメータで言語切替

# やりたいこと
Experience Cloud上で組み込みサービスチャットを日本語英語で動作させたい
エクスペリエンスビルダーで日英各ページ作成済み、かつ必要なページに組み込みサービスチャット配置済み
日本語英語を使うEinsteinボットを作成して、各ダイアログのメッセージに日英メッセージを登録するところまではやってある
この後、URLのlanguageパラメータ(ページの言語切替に使われる標準パラメータ)に応じてチャット/ボットの日英切替を行いたい

# この後やることの概要
1. チャットボタンの日英文言はエクスペリエンスビルダーの組み込みサービスチャット設定で行う
1. URLから取得した言語のチャットウィンドウへの言語設定はスニペットで行う
1. URLから取得した言語はスニペットでチャットのトランスクリプトにセットし、Apexで取り出してチャットの会話言語にセットする

# チャットのトランスクリプトオブジェクトにカスタム属性「言語」作成
1. オブジェクトマネージャーでチャットのトランスクリプトオブジェクトに新規カスタム項目追加
    1. データ型：選択リスト
    1. 表示ラベル：言語
    1. 値：
        1. 各値を改行で区切って入力します：チェック
            1. ja
            1. en_US
    1. 最初の値をデフォルト値とする：チェック
    1. 値セットで定義された値に選択リストを制限します：チェック
    1. 項目名：Language
    1. 値の入力を必須にする：チェック

# スニペットファイル作成＆アップロード
1. 以下のファイルをローカルで作成、文字コードはUTF-8
    ```SnapInCodeSnippetSettings.js
    window._snapinsSnippetSettingsFile = (function () {
        // URLからlanguageパラメータの値を取得
        const paramLanguage = (new URL(document.location)).searchParams.get('language');
    
        // 言語を決定
        const language = paramLanguage === 'en_US' ? 'en_US' : 'ja';
    
        // 言語をチャットウィンドウに設定
        embedded_svc.snippetSettingsFile.language = language;
    
        // 言語をチャットのトランスクリプトに設定
        embedded_svc.snippetSettingsFile.extraPrechatFormDetails = [{
            'transcriptFields': ["Language__c"],
            'value': language
        }];
    })();
    ```
1. Salesforceの設定の静的リソースで新規ボタンを押下して作成ファイルをアップロード
    1. 名前：SnapInCodeSnippetSettings
    1. ファイル：作成ファイル
    1. キャッシュコントロール：公開

# Apexクラスを作成
1. 設定のApexクラスで新規ボタンを押下してApexクラスを作成
    ```EinsteinBotPrechatInfo.cls
    public with sharing class EinsteinBotPrechatInfo {
      public class Input {
        @InvocableVariable(required=true)
        public ID routableID;
      }
    
      public class Output {
        @InvocableVariable(required=true)
        public String language;
      }
    
      @InvocableMethod(label='Get Einstein Bot Prechat Info')
      public static List<Output> getPrechatInfo(List<Input> inputs) {
        List<Output> outputs = new List<Output>();
        for (Input input : inputs) {
          // 指定されたIDのチャットのトランスクリプトのレコードを取得
          LiveChatTranscript liveChatTranscript = [
            SELECT Language__c
            FROM LiveChatTranscript
            WHERE Id = :input.routableID
            LIMIT 1
          ];

          // 当該レコードの言語を出力
          Output output = new Output();
          output.language = liveChatTranscript.Language__c;
          outputs.add(output);
        }
        return outputs;
      }
    }
    ```
1. 同様にテストクラス作成
    ```EinsteinBotPrechatInfoTest.cls
    @IsTest
    public with sharing class EinsteinBotPrechatInfoTest {
      @IsTest(SeeAllData=true)
      public static void testGetPrechatInfoJa() {
        testGetPrechatInfo('ja');
      }
    
      @IsTest(SeeAllData=true)
      public static void testGetPrechatInfoEnUS() {
        testGetPrechatInfo('en_US');
      }
    
      private static void testGetPrechatInfo(String language) {
        // チャット訪問者のレコードを作成
        LiveChatVisitor liveChatVisitor = new LiveChatVisitor();
        insert liveChatVisitor;
    
        // 言語と作成したチャット訪問者のIDを指定してチャットのトランスクリプトのレコードを作成
        LiveChatTranscript liveChatTranscript = new LiveChatTranscript(
          Language__c = language,
          LiveChatVisitorId = liveChatVisitor.Id
        );
        insert liveChatTranscript;
    
        // 作成したチャットのトランスクリプトのIDを指定してGetPrechatInfo()実行
        EinsteinBotPrechatInfo.Input input = new EinsteinBotPrechatInfo.Input();
        input.routableID = liveChatTranscript.Id;
        List<EinsteinBotPrechatInfo.Input> inputs = new List<EinsteinBotPrechatInfo.Input>();
        inputs.add(input);
        List<EinsteinBotPrechatInfo.Output> outputs = EinsteinBotPrechatInfo.getPrechatInfo(
          inputs
        );
    
        // 結果確認
        System.assertEquals(outputs.size(), 1);
        System.assertEquals(outputs[0].language, language);
      }
    }
    ```

# 組み込みサービスチャットの設定
1. エクスペリエンスビルダーで組み込みサービスチャット配置ページを開く
    1. この時点で画面右上の言語は日本語が選ばれている前提
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112363/88c0687b-ea28-46cf-46ba-9c3f7431637b.png)
1. ページに配置された組み込みサービスチャットをクリック
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112363/887d689e-5ed8-7f55-62bd-21f1973fe0de.png)
1. 右側に組み込みサービスチャットの設定が開くので以下を設定
    1. ボタン文言(日本語)
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112363/698494fe-8691-5fc9-681a-346fad7e83d9.png)
    1. スニペット設定ファイル ※静的リソースの名前
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112363/6bd8a375-d19f-f47a-86ab-9fd7494e02d4.png)
1. 画面右上の言語をEnglishに切り替え、同様に組み込みサービスチャットの設定にボタン文言(英語)を設定
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112363/9b02b38b-81d1-3709-4545-2b673cd53e46.png)
1. サイトを公開する

# Einsteinボットの設定
1. 設定のEinsteinボットの対象のボットの編集を開始
1. 変数作成、詳細は以下
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112363/30373819-cfba-649a-79f3-4d488de13343.png)
1. 先頭のダイアログの先頭に以下のステップを追加
    1. ステップ1
        1. コンポーネント：Apex
        1. その他：以下の通り
            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112363/d71177ab-7b38-5341-dab3-bc8860ce8309.png)
    1. ステップ2
        1. コンポーネント：言語を設定
        1. その他：以下の通り
            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112363/a64ab0d4-edac-93bf-8874-108ec89db2b9.png)

# その他

### ボット名

ボット対応時のチャットウィンドウタイトルに表示される

日英切り替えの方法分からず、日本人にもわかる平易な英語とすることとした

### 有人チャット時のカスタムエージェント名・自動挨拶

Einsteinボット内でエージェントに転送した(そして有人オペレータがチャット対応を開始した)場合の、カスタムエージェント名(ウィンドウタイトルや会話の発言者に使用される)・自動挨拶について

これらは、設定の機能設定＞サービス＞チャット＞[チャット]ボタンと招待で、対象チャットボタンの編集にて変更できるが、日英切り替えの方法が見当たらない

いずれもデフォルトは空欄
空欄にするとカスタムエージェント名は対応オペレータの名前になる、自動挨拶は無しになる

そのため、カスタムエージェント名は平易な英語、自動挨拶は無し、とすることにした

### 表示ラベル

設定の機能設定＞サービス＞組み込みサービス＞組み込みサービスリリースで、対象リリースに入り、チャットの設定の編集をクリックし、追加のブランド設定の編集をクリックし、表示ラベルタブを選ぶとより細かく表示ラベルを変更できる

参考：
https://help.salesforce.com/s/articleView?id=sf.snapins_chat_localization.htm&type=5
https://help.salesforce.com/s/articleView?id=sf.embedded_chat_custom_labels.htm&type=5

# 参考
https://qiita.com/shunkosa/items/a0f0470ccea9645c513f#%E3%82%B9%E3%83%8B%E3%83%9A%E3%83%83%E3%83%88%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA
https://help.salesforce.com/s/articleView?id=sf.snapins_chat_parameters.htm&type=5