350 Views
September 29, 25
スライド概要
https://2025.pycon.jp/ja
Day2 LT
what's up, dogs?
Flask-Babel webサイトのお手軽国際化対応 i18n - internationalization shimizu haruki 1
自己紹介 shimizu haruki • 2026卒 大学生 - uni student • pythonを使うIT企業に就職予定 - will join IT company • PyCon JP 初参加 - first time 2
自己紹介 shimizu haruki • Flaskweb運用5年目 - web launched, 5 years ◦ 某国際イベントの非公式情報サイト unofficial info web for an international event ◦ 最近 韓国からのアクセスが増加 increasing access from Korea recently → 海外対応したい - i18n wanted 3
Today's topic • 調子に乗って16言語対応w - 16 languages available lmao 日本語, 한국어, English, Deutsch, Español, Français, हिन्दी, Magyar, Italiano, Bahasa MY, Norsk, Português, தமிழ், ไทย, 简体/繁體中文 4
So, How? どうやって16言語対応を実現したか Flask-Babel 5
Flask-Babelとは? Flaskに多言語対応(i18n)を追加 1. 日付や数値のローカライズ - date/number localization 2. テキスト翻訳 - text translation 3. 言語設定を自動判別 - auto language detection 6
1. ローカライズとは localization • 日付 ◦ ASIA: 2025年9月27日 / 2025-09-27 ◦ U.S.: Sep. 27, 2025 / 09-27-2025 ◦ EUROPE: 27 September 2025 / 27/09/2025 順番が違う! the order is different 7
1. ローカライズとは localization • 数字 ◦ ASIA: 1,234,567.89 ◦ EUROPE: 1.234.567,89 ◦ INDIA: 12,34,567.89 カンマの扱いが違う! the comma position is different 8
自動フォーマット from flask_babel import format_datetime, format_date, format_time import datetime now = datetime.datetime.now() format_datetime(now, "full") # ja: 2025年9月28日日曜日 0時10分10秒 日本標準時 # en: Sunday, September 28, 2025, 12:10:41 AM Japan Standard Time # ko: 2025년 9월 28일 일요일 AM 12시 7분 12초 대한민국 표준시 9
カスタム日付フォーマット format_datetime(now, 'short') # ja: 2025/09/27 14:30 # en: 9/27/25, 2:30 PM # ko: 25. 9. 27. 오후 2:30 format_datetime(now, 'medium') # ja: 2025年9月27日 午後2:30:45 # en: Sep 27, 2025, 2:30:45 PM # ko: 2025. 9. 27. 오후 2:30:45 format_datetime(now, 'long') # ja: 2025年9月27日 午後2時30分45秒 JST # en: September 27, 2025 at 2:30:45 PM JST # ko: 2025년 9월 27일 오후 2시 30분 45초 JST 10
数値のローカライズ from flask_babel import format_decimal, format_currency, format_percent number = 1234567.89 format_decimal(number) # ja: 1,234,567.89 en: 1,234,567.89 ko: 1,234,567.89 # de: 1.234.567,89 fr: 1 234 567,89 hi: 12,34,567.89 price = 123456789 format_currency(price, 'JPY') # ¥123,456,789 format_currency(price, 'KRW') # ₩123,456,789 format_currency(price, 'USD') # $123,456,789.00 format_currency(price, 'EUR') # €123,456,789.00 11
2. 翻訳ファイル生成 1. テキスト抽出 ◦ htmlにある文章を自動で抽出し、.poファイルを作成 extract text from html, create .po file 2. 翻訳ファイルに自分で翻訳を記入 ◦ 自動化できます - add translations (automation later) 3. コンパイル - compile 12
下準備 HTMLの文字列を gettext の引数として設定 Set the text in HTML as an argument to gettext <h1>{{ gettext("こんにちは") }}</h1> <p>{{ gettext("PyCon JP {year} へようこそ") }}</p> 13
翻訳ファイル生成コマンド # メッセージ抽出 pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot . # 翻訳ファイル作成 (messages.po) pybabel init -i messages.pot -d translations -l en # コンパイル pybabel compile -d translations # pythonでもOK import os os.system("YOUR_COMMAND") 14
messages.po msgid "こんにちは" msgstr "" #, python-brace-format msgid "PyCon JP {year} へようこそ" msgstr "" 15
messages.po msgid "こんにちは" msgstr "Hello" #, python-brace-format msgid "PyCon JP {year} へようこそ" msgstr "Welcome to PyCon JP {year}" 自分で書く or 自動化 Write it yourself or automate 16
ライブラリ polib poファイル用のライブラリで簡単に文章を抽出 import polib from my_function import translate path = "PATH_TO_PO_FILE" po = polib.pofile(path) # ファイルを読み込む untranslated_entries = po.untranslated_entries() for entry in untranslated_entries: # 翻訳実行 translated_text = translate(entry.msgid) entry.msgstr = translated_text po.save(path) # 保存 17
無料のAI翻訳API - free translation AI api • Gemini API ◦ 2.0-flash-lite: 30 RPM ◦ 対応言語数 100以上 - available locales 100+ • Deepl API ◦ 500,000 文字/月 - characters/month 18
3. 言語自動選択 from flask import Flask, request from flask_babel import Babel app = Flask(__name__) babel = Babel(app) LOCALES = ['ja', 'en', 'ko', ...] @babel.localeselector def get_locale(): # ユーザーに最適な言語を選定 return request.accept_languages.best_match(LOCALES) 19
まとめ summary • Flask-BabelでWebアプリの国際化 (i18n) が簡単に • 自動ローカライズで日付・数値変換 - auto localization • AI翻訳 + polib でお手軽テキスト翻訳 20
ありがとうございました Thank you! 21