はじめに
microCMSで入力している日本語をChatGPTで日本語から英語に自動翻訳してみます。他の言語への翻訳にも対応できると思いますが、まずは英語ですね。
そのために、microCMSでコンテンツの公開時に、Webhookのカスタム通知を利用して、AWS API Gateway経由でChatGPT APIを呼び出すという構成にします。
システム構成図
以前の私の記事で、
を改造して、Lamda関数の中で、OPENAI APIを呼び出して翻訳して、その結果をmicroCMS APIでコンテンツに反映します。
(ステップ1) microCMS側の準備
分かりやすくするために、なるべく単純なものを準備します。スキームはタイトルと本文、それぞれの英文とします。

WebHookの通知タイミングはコンテンツの公開時とします。

公開前に一度、翻訳結果を確認したいので、本当は下書き保存時にしたかったのですが、テストすると、コンテンツ更新のAPI呼び出しがうまく動かなったので、公開時にしています。
(下書き保存と更新APIの処理がバッティングする?)
(ステップ2) ChatGPT側
自分で作成した、OpenAPIの使用方法を解説した記事
を参考にして、API KEYを用意しておきます。
(ステップ3) AWS側
AWS Lambdaのコードを以下のように修正します。
import os
import hmac
import hashlib
import json
import urllib.request
from urllib.parse import urlparse
import base64
import re
import requests
import mimetypes
def _get_header(event, name: str):
headers = event.get("headers") or {}
lname = name.lower()
for k, v in headers.items():
if k.lower() == lname:
return v
return None
def _response(status: int, body: str):
return {
"statusCode": status,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(body),
}
def _translate(openai_apikey: str, jptext: str):
engtext = jptext
url = "https://api.openai.com/v1/responses"
payload = {
"model": "gpt-5.2",
"input": [
{ "role": "system", "content": "日本語を英語に翻訳してください。" },
{ "role": "user", "content": jptext }
]
}
headers = {
"accept": "application/json",
"Authorization": "Bearer " + openai_apikey
}
response = requests.post(url, json=payload, headers=headers)
param = json.loads(response.text)
print(param)
engtext = param['output'][0]['content'][0]['text']
return engtext
def _patch_microcms(apikey: str, content_id: str, title: str, content: str, title_eng: str, content_eng: str):
url = "https://8qqq1acxw4.microcms.io/api/v1/notice/" + content_id
payload = { "title": title, "content": content, "title_eng": title_eng, "content_eng": content_eng }
headers = {
"accept": "application/json",
"content-type": "application/x-www-form-urlencoded",
"X-MICROCMS-API-KEY": apikey
}
print("title_eng=", title_eng)
print("content_eng=", content_eng)
response = requests.patch(url, data=payload, headers=headers)
print(response.text)
def lambda_handler(event, context):
# microCMS APIキー
apikey = os.environ.get("MICROCMS_API_KEY")
if not apikey:
return _response(500, "Server misconfigured: missing microCMS API Key")
print('apikey=', apikey)
# microCMS Webhook シークレット
secret = os.environ.get("MICROCMS_WEBHOOK_SECRET")
if not secret:
return _response(500, "Server misconfigured: missing microCMS Webhook secret")
print('secret=', secret)
# OPENAI APIキー
openai_apikey = os.environ.get("OPENAI_API_KEY")
if not openai_apikey:
return _response(500, "Server misconfigured: missing OPENAI API Key")
print('openai_apikey=', openai_apikey)
# イベントとコンテキストの内容を出力
print( "event:" , event )
print( "context:", context )
# microCMSから送られる署名
signature = _get_header(event, "x-microcms-signature")
print('signature=', signature)
# データから計算した署名(HMAC-SHA256)
body = event.get('body')
if event.get("isBase64Encoded"):
try:
body_bytes = base64.b64decode(body)
except Exception:
return _response(400, "Invalid base64 body")
else:
# UTF-8でbytes化
body_bytes = body.encode("utf-8")
expected_signature = hmac.new(
key=secret.encode("utf-8"),
msg=body_bytes,
digestmod=hashlib.sha256,
).hexdigest()
print('expected_signature=', expected_signature)
# 署名の検証
if not hmac.compare_digest(signature, expected_signature):
print("Invalid signature")
return _response(401, "Unauthorized")
# 検証成功
print("Valid signature")
# パースする
param = json.loads(body)
print(param)
content_id = param['id']
# print('id=', content_id)
title = param['contents']['new']['publishValue']['title']
content = param['contents']['new']['publishValue']['content']
title_eng = _translate(openai_apikey, title)
content_eng = _translate(openai_apikey, content)
_patch_microcms(apikey, content_id, title, content, title_eng, content_eng)
return _response(200, "OK")
テスト
画面を再表示すると、

と、無事に翻訳できています。
メデタシ、メデタシ!
自動的にフィールドの値を更新する方法はまた、今度考えてみます。
補足
Lamda関数の解説
このLambda関数は、microCMSのWebhookを安全に受信し、OpenAI APIで日本語コンテンツを英語に自動翻訳して、翻訳結果をmicroCMSに保存するシステムです。
全体の流れ
- microCMSからWebhookでコンテンツデータを受信
- 署名検証でリクエストの正当性を確認(セキュリティ対策)
- タイトルと本文を抽出
- OpenAI APIで日本語→英語に翻訳
- 翻訳結果をmicroCMSのAPIで更新
コードの詳細解説
1. ヘルパー関数群
_get_header: 大文字小文字を区別しないヘッダー取得
def _get_header(event, name: str):
headers = event.get("headers") or {}
lname = name.lower()
for k, v in headers.items():
if k.lower() == lname:
return v
return None
HTTPヘッダーは大文字小文字を区別しないため、安全に取得するためのユーティリティ関数です。X-MicroCMS-Signatureやx-microcms-signatureのどちらでも取得できます。
_response: Lambda関数のレスポンス生成
def _response(status: int, body: str):
return {
"statusCode": status,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(body),
}
Lambda関数がAPI Gateway経由で呼ばれる場合の標準的なレスポンス形式を返します。
2. 翻訳関数 _translate
def _translate(openai_apikey: str, jptext: str):
engtext = jptext
url = "https://api.openai.com/v1/responses"
OpenAI APIを使って日本語テキストを英語に翻訳します。
リクエストペイロードの構成
payload = {
"model": "gpt-5.2",
"input": [
{"role": "system", "content": "日本語を英語に翻訳してください。"},
{"role": "user", "content": jptext}
]
}
- model: 使用するAIモデルを指定
-
input:
-
system: AIに翻訳者としての役割を指示 -
user: 翻訳対象の日本語テキスト
-
APIリクエストの送信と結果取得
headers = {
"accept": "application/json",
"Authorization": "Bearer " + openai_apikey
}
response = requests.post(url, json=payload, headers=headers)
param = json.loads(response.text)
print(param)
engtext = param['output'][0]['content'][0]['text']
return engtext
- Bearer認証でAPIキーを送信
-
json=payloadでJSON形式に自動変換 - レスポンスから翻訳テキストを抽出
3. microCMS更新関数 _patch_microcms
def _patch_microcms(apikey: str, content_id: str, title: str, content: str,
title_eng: str, content_eng: str):
翻訳結果をmicroCMSに保存します。
エンドポイントURLの構築
url = "https://8qqq1acxw4.microcms.io/api/v1/notice/" + content_id
microCMSの特定コンテンツを更新するAPIエンドポイント。noticeはAPIのID(エンドポイント名)です。
更新データの準備
payload = {
"title": title,
"content": content,
"title_eng": title_eng,
"content_eng": content_eng
}
元の日本語と翻訳された英語の両方を含むペイロード。4つのフィールドを一度に更新します。
PATCHリクエストの送信
headers = {
"accept": "application/json",
"content-type": "application/x-www-form-urlencoded",
"X-MICROCMS-API-KEY": apikey
}
response = requests.patch(url, data=payload, headers=headers)
- PATCH: 既存コンテンツの部分更新
- X-MICROCMS-API-KEY: microCMS認証用のカスタムヘッダー
- デバッグ用に
printで翻訳結果とレスポンスを出力
4. メイン処理 lambda_handler
環境変数の取得と検証
apikey = os.environ.get("MICROCMS_API_KEY")
if not apikey:
return _response(500, "Server misconfigured: missing microCMS API Key")
Lambda環境変数から各種APIキーを取得。設定漏れがあればエラーを返します。
必要な環境変数:
-
MICROCMS_API_KEY: microCMSのAPIキー -
MICROCMS_WEBHOOK_SECRET: Webhook署名検証用のシークレット -
OPENAI_API_KEY: OpenAI APIキー
Webhook署名の検証(セキュリティ対策)
signature = _get_header(event, "x-microcms-signature")
microCMSから送られてくる署名を取得します。
リクエストボディの取得とデコード
body = event.get('body')
if event.get("isBase64Encoded"):
try:
body_bytes = base64.b64decode(body)
except Exception:
return _response(400, "Invalid base64 body")
else:
body_bytes = body.encode("utf-8")
API Gatewayでは、バイナリデータがBase64エンコードされている場合があるため、その処理を行います。
署名の計算と検証
expected_signature = hmac.new(
key=secret.encode("utf-8"),
msg=body_bytes,
digestmod=hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(signature, expected_signature):
print("Invalid signature")
return _response(401, "Unauthorized")
重要なセキュリティ機能:
- HMAC-SHA256でリクエストボディから署名を計算
- microCMSから送られた署名と比較
- 一致しない場合は不正なリクエストとして拒否
-
hmac.compare_digestでタイミング攻撃を防止
コンテンツデータの取得
param = json.loads(body)
content_id = param['id']
title = param['contents']['new']['publishValue']['title']
content = param['contents']['new']['publishValue']['content']
microCMSのWebhookペイロード構造:
-
id: コンテンツID -
contents['new']['publishValue']: 新しく公開された値-
title: タイトル(日本語) -
content: 本文(日本語)
-
翻訳の実行
title_eng = _translate(openai_apikey, title)
content_eng = _translate(openai_apikey, content)
タイトルと本文をそれぞれ翻訳します。2回のAPI呼び出しが発生します。
microCMSへの保存
_patch_microcms(apikey, content_id, title, content, title_eng, content_eng)
return _response(200, "OK")
翻訳結果を保存し、成功レスポンスを返します。


