Skip to content

dai/VinaNihon

Repository files navigation

VinaNihon(ゔぃなにほん)🇯🇵🇻🇳

Tiếng Việt

ベトナム語🇻🇳↔日本語🇯🇵に特化した、シンプルな翻訳MVPです。
トップページでそのまま翻訳でき、言い換え・ニュアンス・返信例まで確認できます。

入力欄では textarea 右下に音声入力・読み上げボタンを埋め込み、アイコンとツールチップで操作できます。 翻訳結果の各セクションも、読み上げ・コピーをアイコンボタン + ツールチップで利用できます。 翻訳履歴はブラウザの localStorage に最新 100 件まで保存されます。 履歴ペインは desktop ではメインペインと高さを揃えたままページ上部に追従し、ペイン内を独立スクロールできる accordion で、sticky ヘッダーの虫眼鏡からフローティング検索を開けます。各項目のピン留め・再入力・コピー・削除・読み上げを行えます。 UI言語はメインペイン右上のトグルボタン(日本語|ベトナム語)で切り替えられ、Cookie単位で SESSION KV に保存されます。

VinaNihon translation interface in light mode with Japanese UI locale active, showing the UI language toggle button in the top-right corner, translation controls, voice input and playback buttons, and translation history VinaNihon translation interface in dark mode with Vietnamese UI locale active, showing the same controls with the language toggle switched to Vietnamese and history items localized accordingly

Stack

  • Astro + TypeScript
  • Cloudflare Pages (@astrojs/cloudflare)
  • Astro API routes (/api/translate, /api/translate-details, /api/reply)
  • Provider abstraction (mock / openai)

Local Setup (Astro dev)

  1. Install dependencies:
nvm use 22
npm install
  1. Create local env file:
cp .env.example .env
  1. (Optional) enable a real provider in .env:
TRANSLATION_PROVIDER=openai
OPENAI_API_KEY=your_api_key
# Optional
OPENAI_MODEL=gpt-4.1-mini
OPENAI_BASE_URL=https://api.openai.com/v1

OpenAI-compatible API を openai provider のまま使う場合:

TRANSLATION_PROVIDER=openai
OPENAI_API_KEY=your_compatible_api_key
OPENAI_MODEL=MiniMax-M3
OPENAI_BASE_URL=https://api.minimax.io/v1
  1. Run:
npm run dev
  1. Open: http://localhost:4321

Local Preview (built output)

npm run dev は開発用サーバーです。ビルド後の出力を確認したいときは、先に build してから preview を使います。

  1. Build:
npm run build
  1. Preview the built app:
npm run preview
  1. Open: http://localhost:4321

PowerShell 環境で npm ラッパーがうまく動かない場合は、次のように npm.cmd を使ってください。

npm.cmd run build
npm.cmd run preview

ローカル開発も Cloudflare Pages と同じく Node.js 22 を前提にしてください。

Quick Start

.env を以下のように設定すると、実際の OpenAI 翻訳を使えます。

TRANSLATION_PROVIDER=openai
OPENAI_API_KEY=your_api_key
OPENAI_MODEL=gpt-4.1-mini
OPENAI_BASE_URL=https://api.openai.com/v1

その後 npm run dev を起動し、トップページから翻訳を実行してください。

TRANSLATION_PROVIDERmock に戻すと、即座にモック動作へ切り替わります。

MiniMax を openai provider のまま使う場合は次の設定です。

TRANSLATION_PROVIDER=openai
OPENAI_API_KEY=your_minimax_api_key
OPENAI_MODEL=MiniMax-M3
OPENAI_BASE_URL=https://api.minimax.io/v1

History

  • 履歴は各ブラウザの localStorage に保存されます
  • 保存対象は原文、主翻訳、言語方向、モード、トーン、作成日時です
  • 最新 100 件まで保持し、ピン留めした履歴は先頭のセクションに分けて表示されます
  • desktop では履歴ペインがページ上部に追従し、メインペインと同じ高さを保ちながら履歴ペイン内を独立スクロールできます
  • 履歴ヘッダーと全件削除ボタンはスクロール中も表示されたままです
  • 日付グループは折りたたみでき、各履歴項目の日時サマリーもスクロール中に sticky 表示されます
  • 履歴ヘッダーの虫眼鏡ボタンでフローティング検索を開けます
  • 検索は原文 + 主翻訳を対象にした部分一致(大文字小文字を区別しない)で、入力中に即時反映されます
  • 検索ヒット 0 件時は通常の「履歴なし」とは別メッセージを表示します
  • トグル再押下 / Escape / 外側クリックで検索を閉じると、検索語は破棄され全件表示に戻ります
  • 各履歴からピン留め / ピン留め解除、再入力、主翻訳のコピー、主翻訳の読み上げ、個別削除ができます
  • 履歴行は視認性向上のために交互に色分けされています
  • 補足情報(言い換え候補、ニュアンスメモ、返信例)は履歴には保存されず、再表示時に必要なら再取得します

UI言語

  • メインペイン右上のトグルボタン(日本語|ベトナム語)でUI言語を切り替えられます
  • UI言語の設定は Cloudflare SESSION KV に保存され、ユーザーのセッション単位で保持されます
  • 翻訳元言語(sourceLang)は従来通り localStorage に保存されます

環境変数

Astro のローカル開発では .env を使用します。

  • TRANSLATION_PROVIDER=mock (デフォルト)
  • OPENAI_API_KEY= (TRANSLATION_PROVIDER=openai の場合必須)
  • OPENAI_MODEL=gpt-4.1-mini (任意)
  • OPENAI_BASE_URL=https://api.openai.com/v1 (任意)

MiniMax を使う場合の例:

  • TRANSLATION_PROVIDER=openai
  • OPENAI_API_KEY=your_minimax_api_key
  • OPENAI_MODEL=MiniMax-M3
  • OPENAI_BASE_URL=https://api.minimax.io/v1

Cloudflare Pages ランタイムでは、Pages プロジェクト設定で同じ環境変数を設定してください。

Wrangler ローカルランタイムを使用する場合は、.dev.vars もサポートされています。

Cloudflare Pages 設定

このプロジェクトは Cloudflare Pages Functions 用に設定されています。

wrangler.jsonc

wrangler.jsonc の内容:

  • pages_build_output_dir: "./dist"
  • compatibility_flags: ["nodejs_compat"]
  • Astro sessions 用 SESSION KV binding
  • env.preview はデフォルトで production と同じ SESSION KV namespace を使用
  • main フィールドなし(このリポジトリは Standalone Worker ではなく Cloudflare Pages にデプロイするため)

Preview と Production を分離する必要がある場合は、後で別の Preview KV namespace を追加してください。

1. SESSION KV namespace を作成

npx wrangler kv namespace create SESSION

返された ID を wrangler.jsonc にコピーします:

"kv_namespaces": [
  {
    "binding": "SESSION",
    "id": "your-session-kv-id"
  }
]

後で Preview KV を分離する場合は、別の namespace を追加して env.preview で上書きしてください。

2. Pages プロジェクトを設定

Cloudflare Pages で:

  • この GitHub リポジトリを接続
  • Build command: npm run build
  • Build output directory: dist
  • Node.js version: 22

3. 環境変数を追加

Pages プロジェクト設定で、ローカル環境の .env で使用するのと同じ環境変数を追加します。

例:

  • TRANSLATION_PROVIDER=mock
  • TRANSLATION_PROVIDER=openai + OPENAI_API_KEY
  • TRANSLATION_PROVIDER=openai + OPENAI_BASE_URL=https://api.minimax.io/v1
  • TRANSLATION_PROVIDER=openai + OPENAI_MODEL=MiniMax-M3

4. Pages で KV namespace をバインド

Pages プロジェクト設定で KV binding を追加します:

  • Variable name: SESSION
  • KV namespace: wrangler.jsonc で使用している same namespace

Routes

POST /api/translate

Request:

{
  "sourceLang": "ja",
  "targetLang": "vi",
  "text": "こんにちは",
  "mode": "daily",
  "tone": "normal"
}

Response:

{
  "mainTranslation": "...",
  "context": {
    "sourceLang": "ja",
    "targetLang": "vi",
    "mode": "daily",
    "tone": "normal"
  }
}

POST /api/translate-details

Request:

{
  "sourceLang": "ja",
  "targetLang": "vi",
  "originalText": "こんにちは",
  "mainTranslation": "Xin chào",
  "mode": "daily",
  "tone": "normal"
}

Response:

{
  "alternatives": ["..."],
  "nuanceNotes": ["..."],
  "suggestedReplies": ["..."]
}

POST /api/reply

Request:

{
  "sourceLang": "ja",
  "targetLang": "vi",
  "originalText": "こんにちは",
  "mainTranslation": "Xin chào",
  "mode": "daily",
  "tone": "normal"
}

Response:

{
  "suggestedReplies": ["..."]
}

Provider Architecture

src/lib/translate/ はサービス抽象化を提供します:

  • mock provider: 常時利用可能なフォールバック
  • openai provider: POST https://api.openai.com/v1/responses を呼び出します OPENAI_BASE_URL を OpenAI-compatible endpoint に切り替えた場合は、その backend に応じて responses または chat/completions を自動選択

API routes はいずれも薄く、service layer に委任します。主翻訳は /api/translate、補足情報は /api/translate-details、返信例専用取得は /api/reply です。

トップページは最初に /api/translate で主翻訳を取得し、ユーザー操作で /api/translate-details を追加呼び出しして言い換え候補・ニュアンスメモ・返信例を表示します。/api/reply は独立 endpoint として残っています。

Cloudflare Pages CI 用に、build script は astro build の後に生成された _worker.js/wrangler.json_worker.js/.dev.vars.wrangler/deploy/config.json を削除します。また、現在の Pages uploader はデプロイ時にそのファイル名を期待するため、_worker.js/entry.mjs_worker.js/index.js にコピーします。

API Smoke Test (local)

開発サーバー起動後に、以下で API の疎通確認ができます。

curl -s -X POST http://localhost:4321/api/translate \
  -H "content-type: application/json" \
  -d '{
    "sourceLang":"ja",
    "targetLang":"vi",
    "text":"こんにちは",
    "mode":"daily",
    "tone":"normal"
  }'
curl -s -X POST http://localhost:4321/api/reply \
  -H "content-type: application/json" \
  -d '{
    "sourceLang":"ja",
    "targetLang":"vi",
    "originalText":"こんにちは",
    "mainTranslation":"Xin chào",
    "mode":"daily",
    "tone":"normal"
  }'
curl -s -X POST http://localhost:4321/api/translate-details \
  -H "content-type: application/json" \
  -d '{
    "sourceLang":"ja",
    "targetLang":"vi",
    "originalText":"こんにちは",
    "mainTranslation":"Xin chào",
    "mode":"daily",
    "tone":"normal"
  }'

Troubleshooting

  • 音声入力ボタンが無効になっている
    • SpeechRecognition / webkitSpeechRecognition が必要です。主に Chrome 系ブラウザで利用できます。非対応時も textarea 内には薄いプレースホルダー風のアイコンが残ります。
  • 読み上げが期待した声で再生されない
    • 利用できる音声はブラウザと OS に依存します。日本語は ja-JP、ベトナム語は vi-VN を優先して選択します。
  • OPENAI_API_KEY is required when TRANSLATION_PROVIDER=openai.
    • .envOPENAI_API_KEY が設定されているか確認してください。
  • MiniMax を openai provider で使いたい
    • OPENAI_BASE_URL=https://api.minimax.io/v1OPENAI_MODEL=MiniMax-M3 を設定してください。
  • 履歴がブラウザごとに違う
    • 履歴はサーバー保存ではなく localStorage 保存です。別ブラウザやシークレットウィンドウとは共有されません。
  • OpenAI 側エラーで json_object 関連メッセージが出る
    • 実装側で json 指示を入力に含める対応済みです。古い dev サーバープロセスを停止して再起動してください。
  • npm run check@rollup/rollup-linux-x64-gnu 欠落エラー
    • npm の optional dependency 問題です。npm i を再実行してください。

Scripts

  • npm run dev : Astro の開発サーバーを起動
  • npm run build : Cloudflare Pages 向けの成果物を dist/ に生成
  • npm run preview : build 後の成果物をローカルで確認
  • npm run check : Astro / TypeScript のチェックを実行

License

このプロジェクトは MIT License の下でライセンスされています。詳細については LICENSE ファイルを参照してください。

About

ベトナム語↔日本語に特化した、(あなただけの)翻訳アプリ | VinaNihon | Cầu Nối | やさしい越日 / 日越翻訳 | 🇻🇳🇯🇵 橋渡し

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors