この記事を読んでできること
Pydanticのバリデーションメッセージを英語から日本語に変換して返すことができる
概要
- i18nとは
- Pydantic-i18nとは
- 実装
記述しないこと
- FastAPIについて
- Pydanticとは
- Pydanticの実装
使用技術
fastapi==0.78.0
pydantic==1.9.1
pydantic-i18n==0.2.3
i18nとは
i18n(Internationalization(国際化対応)の略称)とは、文化や地域、言語によって異なるターゲットオーディエンスに合わせて容易にローカライズできる製品、アプリケーション、または文書内容の設計と開発のこと
今回の実装ではPydanticのデフォルト設定の言語が英語であるため、それを日本語に変換するという国際化対応を行う
Pydantic-i18nとは
Pydantic-i18nとはPydantic専用のi18nライブラリである
これを使用すればPydanticだけでは変更できないバリデーションメッセージもあらゆる言語に変換することができる
実装
基本的にはGitHubのREADMEに沿って実装を行えば良いが、記載されていないところもあるので実例を出して説明する
こんな感じでサクッと!
appオブジェクトが存在するmain.py
READMEに沿ってコピペ実装可能
import os
import translation
from fastapi import FastAPI, Depends
from fastapi.exceptions import RequestValidationError
from routers import router
app = FastAPI(dependencies=[Depends(translation.get_locale)])
app.add_exception_handler(
RequestValidationError, translation.validation_exception_handler
)
app.include_router(router.router)
こちらも基本的にはREADME通りで問題ないが、必ずDEFAULT_LOCALE="ja_JP"
にするように!
from fastapi import Request
from fastapi.exceptions import RequestValidationError
from pydantic_i18n import PydanticI18n
from starlette.responses import JSONResponse
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
from pydantic_messages import translations
__all__ = ["get_locale", "validation_exception_handler"]
DEFAULT_LOCALE = "ja_JP"
tr = PydanticI18n(translations)
def get_locale(locale: str = DEFAULT_LOCALE) -> str:
return locale
async def validation_exception_handler(
request: Request, exc: RequestValidationError
) -> JSONResponse:
current_locale = request.query_params.get("locale", DEFAULT_LOCALE)
return JSONResponse(
status_code=HTTP_422_UNPROCESSABLE_ENTITY,
content={"detail": tr.translate(exc.errors(), current_locale)},
)
ここでは、Pydanticのデフォルトの英文のリデーションメッセージと新たに変換させたい文章をJSON形式で記述する
PydanticI18n.get_pydantic_messages()
を実行することによってPydanticの全てのバリデーションメッセージを取得することができる
pydantic_messages.pyにおける注意点
- en_USのJSONのkeyとja_JPのkeyは必ず同じ値でなければならない(Pydantic-18nはそれぞれのkeyを照らしあわせて、valueを返しているため)
- en_USのvalueは任意
- 変数を必要とする場合(4文字以上、5文字以下など)、
{}
で対応することが可能(この記法はREADMEにも記載がなく、調査に苦労した)
translations = {
"en_US": {
"field required": "",
"value is not a valid integer": "",
"ensure this value has at least {} characters": "",
"ensure this value has at most {} characters": "",
"ensure this value is less than or equal to {}": "",
"ensure this value is less than {}": "",
"ensure this value is greater than or equal to {}": "",
},
"ja_JP": {
"field required": "必須入力です。",
"value is not a valid integer": "半角数字で入力してください。",
"ensure this value has at least {} characters": "{}文字以上で入力してください。",
"ensure this value has at most {} characters": "{}文字以下で入力してください。",
"ensure this value is less than {}": "{}未満で入力してください。",
"ensure this value is less than or equal to {}": "{}以下で入力してください。",
"ensure this value is greater than or equal to {}": "{}以上で入力してください。",
},
}
挙動確認
では、OpenAPI(Swagger)で挙動を確認してみよう!
パスワード(pin_number)が4文字以下を期待しているのに、5文字以上だった場合
ちゃんと動いてますね!!
所感
READMEをみれば実装できると思いますが、このライブラリは情報量が限りなく少なく、初心者さんには大変だと思い、書かせていただきました。
どんなシステムもユーザフレンドリーでいきましょう!!