LoginSignup
3
3

[FastAPI] ニッチなところを突く!Pydantic-i18nでPydanticのバリデーションメッセージを英語から日本語へ変換!!

Last updated at Posted at 2023-01-06

この記事を読んでできること

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に沿ってコピペ実装可能

main.py
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"にするように!

translation.py
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における注意点

  1. en_USのJSONのkeyとja_JPのkeyは必ず同じ値でなければならない(Pydantic-18nはそれぞれのkeyを照らしあわせて、valueを返しているため)
  2. en_USのvalueは任意
  3. 変数を必要とする場合(4文字以上、5文字以下など)、{}で対応することが可能(この記法はREADMEにも記載がなく、調査に苦労した)
pydantic_messages.py
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文字以上だった場合

スクリーンショット 2023-01-06 17.03.50.png (86.5 kB)

ちゃんと動いてますね!!

所感

READMEをみれば実装できると思いますが、このライブラリは情報量が限りなく少なく、初心者さんには大変だと思い、書かせていただきました。
どんなシステムもユーザフレンドリーでいきましょう!!

参考

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3