ChatGPT4oがホームページの英語化に便利な件

# ChatGPT4oがホームページの英語化に便利な件

ホームページの英語化（locale対応）でChatGPT4oがとても便利だったので

やり方を含め実践的なChatGPTの活用事例を紹介します。

## やりたいこと

ホームページに表示させる文章を日本語ファイルと英語ファイルの２つ用意しておき

英語圏の人がアクセスしたらen.jsonデータを表示し

日本語圏の人がアクセスしたらja.jsonデータを表示させる

といったイメージです。

ja.json
```
{
  "title": "採用ページ",
  "description": "採用ページの詳細"
}
```

en.json
```
{
  "title": "Recruitment",
  "description": "detail of recruitment page"
}
```


技術的には[next-intl](https://next-intl-docs.vercel.app/)というnext.js用の複数言語対応ライブラリを利用しているのですが、
本記事の趣旨ではないため省略します。

## ChatGPT4oを使うと？

### 1.既存サイトのスクショからja.jsonを作成してもらう

英語化対応したい画面の全体のスクリーンショットを撮影し、CHatGPT4oに添付します。

そして以下のようなPromptを書いてJSONを作成してもらいます。

※これくらい適当に書いても期待する品質に近いものが出てきます。

```
この画像を読み込んで次の作業をおこなってください。

日本語の文章のまとまりごとに、そのまとまりを表すラベルとその文章をJSONのkeyとvalueのようにあらわしたいです。

たとえば、「テックレイスでは 共に働く仲間を募集しています。」というまとまりがあれば、

{ "title": "テックレイスでは 共に働く仲間を募集しています。"}のようにします。

これを画像のすべての日本語のまとまりに対して行い、１つのJSONファイルを出力してください
```

ポイントは

- ブラウザのズーム率を下げる
  - 画面全体を１度にスクリーンショットに収めたいため
- 出力形式を明確に指定
  - JSONというファイル形式やkeyとvalueという表現でやってほしいことを具体化しています
  - （全然具体的でないような気もします）
- 例題の提示
  - どういうことを「まとまり」と表現しているかを入力画像の具体的な箇所を示して伝えています。

![スクリーンショット 2024-05-29 12.01.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714510/f6a8f07e-870c-525f-7ae8-56d483b86cb8.png)

すると以下のアウトプットができました
ja.json
```json
{
  "title": "テックレイスでは 以下に特化した仲間を募集しています。",
  "question": "どの職種を希望されていますか？",
  "buttons": {
    "button1": "システムエンジニア",
    "button2": "キャリアアドバイザー"
  },
  "recruitment_period": {
    "title": "採用人数・期間",
    "description": "現在、2024年05月31日までに1名の正社員エンジニアを募集しています。",
    "time_left": {
      "days": "02",
      "hours": "12",
      "minutes": "03",
      "seconds": "19"
    }
  },
  "employment_conditions": {
    "title": "雇用条件",
    "description": "あなたのこれまでの経験とこれからの希望での雇用条件を元に、年収をシミュレーションできます。",
    "annual_salary": "468万円",
    "monthly_salary": "39万円",
    "reward": "60万円",
    "years": "0年"
  },
  "check_salary": "自分の年収を試算してみる",
  "recruitment_steps": {
    "title": "採用手順",
    "steps": [
      {
        "step": "STEP1",
        "title": "求人サイトまたはエントリーフォームよりご応募いただきます",
        "description": "上記の資料をご用意ください",
        "details": {
          "skill_sheet": "職務経歴書(スキルシート)\nこれまでのプロジェクトや業務などを時系列で記載した詳細な履歴書",
          "resume": "履歴書\n基本的な個人情報、学歴、資格、勤務歴などを記載した文書"
        },
        "apply": "応募方法",
        "options": {
          "line": "LINEで応募",
          "email": "メールで応募"
        }
      },
      {
        "step": "STEP2",
        "title": "Web応募書類による書類選考を行います",
        "description": "3営業日以内にメールまたは電話にて書類選考の結果をご連絡いたします。"
      },
      {
        "step": "STEP3",
        "title": "採用面談（オンラインまたはオフライン）を行います",
        "details": {
          "remote_interview": "リモート面談\n仕事に支障がないかリモート環境を確認します",
          "in_person_interview": "対面での面談\n詳細をつかみたい方は対面での面談もあります"
        }
      },
      {
        "step": "STEP4",
        "title": "内定後にオファー面談を実施します",
        "description": "各種条件の確認を行い、契約書を取り交わします。人事労務などの手続きを開始いたします。"
      }
    ]
  },
  "advisors_feedback": {
    "title": "エンジニアから見てTech ReisのCA（キャリアアドバイザー）の雰囲気を教えてください",
    "description": "接しやすく親身になって話しを聞いてくれる印象です。"
  },
  "hobbies": {
    "title": "あなたが今ハマっていることを熱く語ってください！",
    "description": "相撲です。たまたまテレビをつけたらやっていたというのがきっかけでしたが、最初から最後まで息つく暇もなく全力で戦う姿、短期決戦という明確さ、大きな体同士がぶつかる迫力に圧倒されすぐにハマりました。まだ一場所の途中からしか見ていませんが、新しい趣味になりそうです。"
  },
  "future_goals": {
    "title": "3年後、5年後、10年後に実現したい目標ってなにかありますか？",
    "description": "具体的にはありませんが、暖かい家庭を築いていたいです。また一週間の中で休みを3日つくるというのは憧れます。"
  },
  "final_message": {
    "title": "最後になにか一言お願いします！",
    "description": "一緒に働けることを楽しみにしています！"
  }
}
```

雰囲気、なかなかにいい感じのアウトプットが出てきました。

文章のまとまりごとに、JSONのkeyをつける必要があるのですが、
命名をいちいち考えなくて良いだけでほんと助かります😭

気を利かせて、セクションごとに命名を意識しながら階層化してくれてるのもありがたいですね！

### 2.細かいミスや構造の修正

肌感８０点くらいの解答が出てきたのですが、細かいミスや意図しない構造になっているところがあるので
そこは手動で直していきます。

#### 文言ミスの修正

もともと記載されていた文章と異なる出力をしているところを直していきます。
具体的には以下のようなミスがありました。

|誤り|正解|
|---|---|
|あなたのこれまでの経験とこれからの希望での雇用条件を元に、年収をシミュレーションできます。|あなたのこれまでの単価とこれからの弊社での勤続年数から、年収をシミュレーションできます。|
|テックレイスでは 以下に特化した仲間を募集しています。|テックレイスでは 共に働く仲間を募集しています。|
|上記の資料をご用意ください|次の書類をご用意ください|
|基本的な個人情報、学歴、資格、勤務歴などを記載した文書|基本的な個人情報、学歴、職歴などを簡潔にまとめた文書|
|仕事に支障がないかリモート環境を確認します|仕事でお忙しい方にはリモート面談を承ります|
|詳細をつかみたい方は対面での面談もあります|雰囲気をつかみたい方には対面での面談も承ります|

#### 構造やkey名の修正

もともとChatGPTが出力したJSONは以下のとおりです。

```json
"recruitment_steps": { // ①recruitmentSteps(キャメルケース)にしたい
  "title": "採用手順",
  // ②stepsの配列ではなく、step1, step2ごとにオブジェクト型にしたい
  "steps": [
    {
      "step": "STEP1", // ③keyを"label"に変更したい
      "title": "求人サイトまたはエントリーフォームよりご応募いただきます",
      "description": "次の資料をご用意ください",
      "details": {
        // ①と同様にキャメルケースにしたい
        // ④"職務経歴書(スキルシート)\nこれまでのプロジェクトや業務などを時系列で記載した詳細な履歴書
        // ではなく以下のように構造化したい
        // {
        //   "title": "職務経歴書(スキルシート)"
        //   "description": "これまでのプロジェクトや業務などを時系列で記載した詳細な履歴書"
        // }
        "skill_sheet": "職務経歴書(スキルシート)\nこれまでのプロジェクトや業務などを時系列で記載した詳細な履歴書",
        //　④と同様
        "resume": "履歴書\n基本的な個人情報、学歴、資格、勤務歴などを記載した文書"
      },
      // ⑤既存に存在しない文言なので削除したい
      "apply": "応募方法",
      "options": {
        "line": "LINEで応募",
        "email": "メールで応募"
      }
    },
    { // STEP1同様
      "step": "STEP2",
      "title": "Web応募書類による書類選考を行います",
      "description": "3営業日以内にメールまたは電話にて書類選考の結果をご連絡いたします。"
    },
    { // STEP1同様
      "step": "STEP3",
      "title": "採用面談（オンラインまたはオフライン）を行います",
      "details": {
        "remote_interview": "リモート面談\n仕事に支障がないかリモート環境を確認します",
        "in_person_interview": "対面での面談\n詳細をつかみたい方は対面での面談もあります"
      }
    },
    { // STEP1同様
      // ⑥descriptionの文章が誤っているので修正したい
      "step": "STEP4",
      "title": "内定後にオファー面談を実施します",
      "description": "各種条件の確認を行い、契約書を取り交わします。人事労務などの手続きを開始いたします。"
    }
  ]
}
```

上記の①〜⑥の点が気になったので修正します。

修正の種類は次のとおりでうす。


- snake cale -> camel caseにする
- 配列ではなくオブジェクトにする
- 不要なオブジェクトは削除する
- titleとdescriptionが改行で１文字列になっていたので、titleとdescriptionに分けて構造化する
- 文言の修正

修正した結果は次のとおりです。

ja.json
```
"recruitmentSteps": {
  "title": "採用手順",
  "steps1": {
    "stepLabel": "STEP1",
    "title": "求人サイトまたはエントリーフォームよりご応募いただきます",
    "description1": "次の資料をご用意ください",
    "description2": "次のいづれかの方法で書類をお送りください",
    "details": {
      "skillSheet": {
        "title": "職務経歴書(スキルシート)",
        "description": "これまでのプロジェクトや業務などを時系列で記載した経歴書"
      },
      "resume": {
        "title": "履歴書",
        "description": "基本的な個人情報、学歴、職歴などを簡潔にまとめた文書"
      }
    }
  },
  "step2": {
    "stepLabel": "STEP2",
    "title": "Web応募書類による書類選考を行います",
    "description": "3営業日以内にメールまたは電話にて書類選考の結果をご連絡いたします。"
  },
  "step3": {
    "stepLabel": "STEP3",
    "title": "採用面談（オンラインまたはオフライン）を行います",
    "details": {
      "remoteInterview": {
        "title": "リモート面談",
        "description": "仕事でお忙しい方にはリモート面談を承ります"
      },
      "inPersonInterview": {
        "title": "対面での面談",
        "description": "雰囲気をつかみたい方には対面での面談も承ります"
      }
    }
  },
  "step4": {
    "stepLabel": "STEP4",
    "title": "内定後にオファー面談を実施します",
    "description": "年収をはじめとする各種雇用条件のご説明を人事担当から皆さまに直接させていただきます。\n各種ご提示／ご説明の内容を踏まえた上で、内定受諾可否や入社希望時期などについてご検討ください。\n（もちろんオファー面談後のご回答でも構いませんので、ご安心ください）"
  }
}
```

### 3.en.jsonの作成

日本語ファイルja.jsonが作成できたらen.jsonを作成します。

もちろん私は努力しません。

```
以下の日本語をすべて英語に変換してください。

{
  "RecruitPage": {
    "helloTitle": "テックレイスでは 共に働く仲間を募集しています。",
    "jobTypeQuestion": "どの職種を希望されていますか？",
    "jobTypeLabel": {
      "engineer": "システムエンジニア",
      "careerAdvisor": "キャリアアドバイザー"
    },
    ....
    ....
    ....
}
````

![スクリーンショット 2024-05-29 13.55.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714510/08060fef-9d6a-5354-eec1-7a3272167943.png)

だいたい**15秒**くらいで

en.jsonができました。
```json
{
  "RecruitPage": {
    "helloTitle": "We are looking for teammates to work with us at Tech Reis.",
    "jobTypeQuestion": "Which job type are you interested in?",
    "jobTypeLabel": {
      "engineer": "System Engineer",
      "careerAdvisor": "Career Advisor"
    },
    "recruitmentPeriod": {
      "title": "Recruitment Numbers and Period",
      "description": "We are currently looking for one full-time engineer by May 31, 2024."
    },
    "employmentConditions": {
      "title": "Employment Conditions",
      "description": "You can simulate your annual salary based on your past rates and your expected years of service with us."
    },
    "checkSalary": "Estimate your annual salary",
    "recruitmentSteps": {
      "title": "Recruitment Process",
      "steps1": {
        "stepLabel": "STEP1",
        "title": "Apply through job sites or the entry form",
        "description1": "Please prepare the following documents",
        "description2": "Send the documents using one of the following methods",
        "details": {
          "skillSheet": {
            "title": "Work History (Skill Sheet)",
            "description": "A detailed resume listing your past projects and work in chronological order"
          },
          "resume": {
            "title": "Resume",
            "description": "A concise document summarizing your personal information, education, and work history"
          }
        },
        "apply": "How to Apply",
        "options": {
          "line": "Apply via LINE",
          "email": "Apply via Email"
        }
      },
      "step2": {
        "stepLabel": "STEP2",
        "title": "Document screening based on web application documents",
        "description": "We will inform you of the results of the document screening by email or phone within three business days."
      },
      "step3": {
        "stepLabel": "STEP3",
        "title": "Conduct interviews (online or offline)",
        "details": {
          "remoteInterview": {
            "title": "Remote Interview",
            "description": "We offer remote interviews for those who are busy with work"
          },
          "inPersonInterview": {
            "title": "In-Person Interview",
            "description": "We also offer in-person interviews for those who want to get a feel for the atmosphere"
          }
        }
      },
      "step4": {
        "stepLabel": "STEP4",
        "title": "Offer interview after a job offer",
        "description": "Our HR will directly explain various employment conditions, including annual salary, to you.\nBased on the provided information, please consider whether to accept the offer and your desired start date.\n(Feel free to respond after the offer interview, so please be assured.)"
      }
    },
    "meta": {
      "title": "Careers｜Tech Reis Inc.",
      "description": "Tech Reis Inc. is looking for teammates to work with us."
    }
  }
}
```

### 4.ベタ書きされていた文章を変数に置換

`ja.json`と`en.json`とnext-intlライブラリのセットアップができていれば
たとえば

```json
{
  "RecruitPage": {
    "helloTitle": "テックレイスでは 共に働く仲間を募集しています。",
  }
}
```

という文言データを以下のように

`t("helloTitle")`

で呼び出せ、ブラウザの設定やアクセスパスに応じていい感じに言語を切り替えてくれます。

```tsx
export const OverviewSection: FC = () => {
  const t = useTranslations("RecruitPage")
  return (
    <div className="hero">
      <div className="hero-content flex-col lg:flex-row-reverse">
        <JobOfferIcon className="" />
        <div>
          <PageTitle>Recruit</PageTitle>
          <p className="py-6">
            {/*英語圏からアクセスさせると"We are looking for teammates to work with us at Tech Reis."*/}
            {/*日本語圏からアクセスさせると"テックレイスでは 共に働く仲間を募集しています。"*/}
            t("helloTitle")
          </p>
        </div>
      </div>
    </div>
  )
}
```

## 普通にやると？

ChatGPT4oの手順はいかがでしたか？

私はトータル１時間くらいの作業で終わりましたし
そのほとんどが
３の構造化、スペルミスチェック
４の変数埋め込み作業や文言チェックなどの
確認作業に時間を費やせました。

これがどれくらいコスパが良いことなのかを示すために

普通の手順を記載します。

### １．日本語文章をJSONで構造化

ホームページにベタ書きで書かれている日本語の単語や文章をしらみつぶしに探し

適当なkey(変数名)をつけてja.jsonを作成していきます。

```tsx
// 便宜上簡略化しています
export const RecruitPage: FC = () => {
  return (
    <Page>
      {/* ① */}
      <OverviewSection />
      {/* ② */}
      <JobsChoiceSection />
      {/* ③ */}
      <EngineersRecruitSections />
    </Page>
  )
}
```

ページのindexを見ると①、②、③の子コンポーネントがあるので一つずつ見ていきます。

(心の声：もうこの時点でだるい、子コンポーネントにも孫コンポーネントがあるかもと思うと絶句します)

たとえば①の中身は

```tsx
export const OverviewSection: FC = () => {
  return (
    <div className="hero sp:hidden">
      <div className="hero-content flex-col lg:flex-row-reverse">
        <JobOfferIcon className="" />
        <div>
          <PageTitle>Recruit</PageTitle>
          <p className="py-6">
            {/* ④ */}
            テックレイスでは 共に働く仲間を募集しています。
          </p>
        </div>
      </div>
    </div>
  )
}
```

④の日本語にkeyをつけてja.jsonに追加します。

(心の声：jsonのkeyの命名考えるのしんどい、命名って結構エネルギー使うのに、いったい何グループのkey名を考えないといけないのか、、、)

ja.json
```json
{
  "RecruitPage": {
    ...
    "helloTitle": "テックレイスでは 共に働く仲間を募集しています。",
    ...
  }
}
```


### ２．ja.jsonを翻訳してen.jsonを作成

ja.jsonが完成したら、日本語で書かれたvalueをすべて英語に翻訳してen.jsonを作成します。

すべて英語に翻訳します。

ja.json
```json
{
  "RecruitPage": {
    ...
    "helloTitle": "テックレイスでは 共に働く仲間を募集しています。",
    ...
  }
}
```

であればgoogle翻訳を使い

![スクリーンショット 2024-05-29 13.10.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714510/957e2661-54f9-4406-e8f6-04979980f553.png)

こんな感じになります。

en.json
```json
{
  "RecruitPage": {
    ...
    "helloTitle": "At Techrais, we are looking for people to work with us.",
    ...
  }
}
```


(心の声：これ31件も頑張るのか、、、)

### ３．ベタ書きされていた文章を変数に置換

`ja.json`と`en.json`とnext-intlライブラリのセットアップができていれば

以下のように t("helloTitle")を埋め込むと、いい感じに言語を切り替えてくれます。

これはChatGPT4oの手順と全く同じです。

```tsx
export const OverviewSection: FC = () => {
  const t = useTranslations("RecruitPage")
  return (
    <div className="hero">
      <div className="hero-content flex-col lg:flex-row-reverse">
        <JobOfferIcon className="" />
        <div>
          <PageTitle>Recruit</PageTitle>
          <p className="py-6">
            t("helloTitle")
          </p>
        </div>
      </div>
    </div>
  )
}
```

## さいごに

いかがでしたか？

ChatGPTは単純作業に限定して使えばかなり高いパフォーマンスを発揮します。

正解不正解の判断はAIにはできないので、ミスを無くすことはできず

人間の確認工程は当分なくならない気もしますが、

手はAIに動かしてもらい、自分は確認や判断だけしていれば良いので

個人的には月2000円前後の給料で単価60万はくだらない優秀なエンジニアアシスタントを雇っている気分です。

今後の発展に期待です！

## 採用案内
株式会社TechReisでは、一緒に成長できるエンジニアを募集しています！

エンジニアが案件を選択できる制度
契約時の単価を完全公開
単価に連動した給与設定
などの仕組みがあり、自身のキャリアプランやライフスタイルに合わせた案件選びが可能です。

興味のある方は、[Green](https://www.green-japan.com/company/9886)または[HP](https://techreis.co.jp/)をチェックしてみてください！お問い合わせお待ちしています！