Skip to content

日本語と英語の切り替えに対応する - #2

Merged
ipusiron merged 1 commit into
mainfrom
codex/i18n-20260927
Sep 27, 2026
Merged

ipusiron merged 1 commit into
mainfrom
codex/i18n-20260927

Conversation

@ipusiron

Copy link
Copy Markdown
Owner

概要

WhereShot を日本語と英語の両対応にしました。画面だけでなく、通知・警告・地図のポップアップ・解析レポートの全文が切り替わります。

  • js/i18n.js に日英 217キー の辞書とDOM適用層を置いた(ja/en はキーの並びまで一致)
  • 言語は ?lang= → localStorage(whereshot-language)→ navigator.language の順で決める
  • ヘッダーの #langToggle で即座に切り替わり、再読み込み後も維持される
  • README.en.md を追加(日本語READMEと構成をそろえた)

解析・計算のロジックは無変更

js/whereshot-logic.js の変更は文言をキーに置き換えただけです。機械的に照合しました。

  • isValidWall / parseExifDateTime / parseOffset / wallToUtcMs / utcMsToWall / gpsDateTimeToUtcMs / inferOffsetFromGps / decideOffset / distanceM / bearing / destinationPoint / decimalToDms / nearestStation / sunPhaseKey / sunReport / normalizeTags / extractDatesFromFilename ほか 34関数が旧版と同一
  • OFFSET_CHOICES・EARTH_RADIUS・DAY_MS・JMA_TOP・FILENAME_PATTERNS も同一
  • estimateDateTime は重み(0.95 / 0.9 / 0.85 / 0.4〜0.6 / 0.5 / 0.3)・許容差(1時間 / 24時間)・整合度の式(round(weight × (0.5 + 0.5 × agreement) × 100) ÷ 100)に手を入れていない。差分は label を {key, params} にした部分だけ
  • js/exif-parser.js・js/sun-calculator.js・data/・vendor/・css/ は無変更

日本語の出力が変わっていないことは、既存の「レポートの15行」テストで固定しました(15行の文言を1文字も変えずに残し、I18n.messages(buildReport(...), 'ja') が一致することを assert)。英語15行も同時に固定しています。

i18n化の過程で見つけて直した不具合(7件)

不具合 何が起きるか
トーストが言語切り替えに追従しない 表示中の通知が、消えるまで元の言語のまま残る
地図のポップアップ・精度円のツールチップ・座標表示が追従しない マーカーを開いたまま切り替えると「📍 撮影位置」が英語に変わらない
プレビュー切り替えボタンの文言を直書きで書き戻していた 英語で開いて切り替えると「🙈 プレビュー非表示」が英語に戻らない
SHA-256欄が「未算出」と「この環境では不可」を文言だけで区別していた 言語を切り替えると、計算できなかった旨が消えるか元の言語で残る
起動直後は #upload-title・#direction-info・#map-coordinates・#weather-link がHTMLの日本語のまま 英語で開いた直後、ドロップゾーンの見出しと撮影方位が日本語で出る
検証エラーを '、' で連結してから表示していた 訳した文字列を連結するので、切り替え後に訳し直せない。1件ずつ出すようにした
ファイル形式が空のときの '不明' が純ロジック側にあった 英語のレポートに和文が混ざる

いずれも「訳した文字列で状態を持っていた」ことが原因です。状態は dataset かプロパティで持ち、languagechange で render*() が描き直す形にそろえました。

訳さなかったものと理由

  • Exifのタグ名・セグメント名(DateTimeOriginal・OffsetTimeOriginal・GPSHPositioningError・GPSDOP・ExposureTime)— 実物のタグ名そのもので、訳すと原典と照合できない
  • 地図・外部サービスの名前(OpenStreetMap・NASA Worldview・Street View・SunCalc.org・GSI Maps)— 固有名詞
  • 座標の表記(34°17'10.01"N と小数6桁)— 数値と記号だけで言語に依存しない
  • 気象庁観測所の名前(高松・那覇 ほか54件)— data/stations.json の識別子で、READMEの表と既存テストが名前で照合している。英語表示でも Past weather (高松, about 23 km) と出る
  • ファイル名の日本語日付パターン(ja-full・ja-date の (\d{4})年(\d{1,2})月…)— ツールの入力そのもの
  • 開発者向けの console.error と内部例外(WhereShot: failed to initialize the map ほか)— 画面に出ないので辞書に入れず、固定の英文にした

meta

data-i18n-content を6つに付けました(grep -c data-i18n-content index.html → 6)。

description / keywords / og:title / og:description / twitter:title / twitter:description

keywords とOGP・Twitterカードはこのツールに無かったので追加しました。英語でリンクを共有しても説明文が日本語になりません。和文の content を持つmetaに data-i18n-content が付いているかはテストで縛っています。

テスト

58件 → 73件(npm test、すべてパス)。

test/i18n.test.js で次を固定しました。

  1. 日英でキーの集合と並びが一致する
  2. 差し込みの名前({name})が日英で一致する
  3. HTMLが指すキー(87か所)がすべて辞書にある
  4. スクリプトが呼ぶキー(127種)がすべて辞書にある。組み立てる phase.*・cardinal.*・SOURCE_KEYS は別に数え上げる
  5. 英語の辞書に和文が残っていない(app.langButton だけ例外)
  6. t() が差し込みを埋め、知らないキーで throw する。入れ子の {key, params} を表示の直前に訳す
  7. data-i18n を付けた78要素が子要素を抱えていない
  8. 状態で変わる28スロットに data-i18n を付けていない(付けると切り替えで結果が消える)
  9. HTMLに残る和文が <title> と <noscript> の2行だけ(行の配列で deepEqual)
  10. 純ロジックに残る和文が日本語ファイル名パターンの2行だけ(同じく行の配列)
  11. 和文リテラルとの比較・和文の書き戻しが残っていない
  12. 言語を切り替えてもレポートの行数と構造が変わらない

既存テストの修正は、スクリプトの読み込み順(js/i18n.js を追加)、外形の数、formatWall の引数、toCardinalJa → cardinalKey、formatCamera(null, null) が null、構成図の件数(26 → 28)です。

ブラウザー実測(Chromium、ポート8131)

  • ?lang=ja / ?lang=en で documentElement.lang・<title>・本文が切り替わる。CSP違反0、JSエラー0
  • 英語表示に残った和文は noscript と切り替えボタンの 「日本語」、および観測所名の 「高松」 のみ
  • 切り替えボタンで即座に変わり、localStorage に保存され、再読み込み後も維持される
  • サンプル画像を解析した状態で切り替えても消えない — 解析日時(2016-07-24T10:33:57)、UTCオフセット(540)、Exif 4カード、日時ソース6行、太陽5項目、レポート15行がすべて訳し直される
  • 食い違いのある名前(IMG_20240101_123456.jpg)で出る警告3件と注記1件も訳し直される
  • 開いているマーカーのポップアップが、閉じずに訳し直される
  • 状態で変わる属性が巻き戻らない — 手動位置指定モード ON(aria-pressed="true")、プレビュー表示中を保つ
  • 出ている最中のトーストが訳し直される(Click the map to set the capture location → 地図をクリックして撮影位置を指定してください)
  • 失敗系(4KBのゼロ埋め .tiff)— Exif読み取り失敗のトースト、This format cannot be previewed、空欄表示のすべてが切り替わる
  • 何も読み込んでいない状態で切り替えても空の状態を壊さない(結果パネルと警告は hidden のまま、- のプレースホルダーが残る)
  • 320px・390pxの英語表示で溢れなし — documentElement.scrollWidth がビューポート幅と一致、ビューポートより広い要素0件(CSSの変更は不要だった)
  • localStorage のゲッターに throw を仕込んだ環境でも init が落ちず、切り替えも動く
  • file:// で直接開いても ?lang=en が効く

🤖 Generated with Claude Code

js/i18n.js に日英217キーの辞書とDOM適用層を置き、画面・通知・解析レポートの
全文を切り替えられるようにした。?lang= → localStorage → navigator.language の順で
言語を決め、選択は whereshot-language に保存する。

純ロジック(js/whereshot-logic.js)からは文言を外し、{key, params} を返す形にした。
座標変換・距離計算・太陽位置・Exifの読み出し・整合度の式は無変更(34関数と
OFFSET_CHOICES・FILENAME_PATTERNS が旧版と同一であることを機械的に照合済み)。

i18n化の過程で見つけて直した不具合:

- 表示中のトーストが言語切り替えに追従しない。訳した文字列ではなくキーを
  data-toast-key に覚え、languagechange で訳し直すようにした
- 地図マーカーのポップアップ・精度円のツールチップ・座標表示が、
  作った言語のまま残る。{key, params} を保持して作り直すようにした
- プレビュー切り替えボタンの文言を直書きで書き戻していた。開いているか
  どうかの状態から組み立てるようにした
- SHA-256欄が「未算出」と「この環境では不可」を文言だけで区別していた。
  hashState を持たせた
- 起動直後は #upload-title・#direction-info・#map-coordinates・#weather-link が
  HTMLの日本語のままだった(JSが上書きするのは操作後)。初期化で描くようにした
- 検証エラーを '、' で連結してから表示していたため、言語を切り替えると
  直せなかった。1件ずつトーストを出すようにした
- ファイル形式が空のときの '不明' が pure logic 側にあり、英語でも和文が出た

訳さなかったもの: Exifのタグ名(DateTimeOriginal・GPSHPositioningError ほか)、
地図サービス名(OpenStreetMap・NASA Worldview・Street View)、座標の度分秒表記、
気象庁観測所の名前(データの識別子。READMEの表と既存テストが照合している)、
ファイル名の日本語日付パターン(ツールの入力そのもの)。

metaは description・keywords・og:title・og:description・twitter:title・
twitter:description の6つを data-i18n-content で訳す(OGPとカードを追加)。

テストは58件から73件へ。test/i18n.test.js でキー集合・差し込み名・HTMLと
スクリプトが使うキーの実在・英語辞書の和文・data-i18nの子要素・状態スロットに
data-i18nを付けないこと・純ロジックとHTMLに残る和文の行を固定した。

実測(Chromium、ポート8131): ?lang=ja/en で切り替わり、CSP違反0・JSエラー0。
英語表示に残る和文は noscript と切り替えボタンの「日本語」、および観測所名の
「高松」だけ。解析結果・入力値・開いたプレビュー・aria-pressed・出ている
トーストは切り替えても保たれる。320pxと390pxの英語表示で溢れなし
(documentElement.scrollWidth = ビューポート幅)。localStorageを塞いだ環境と
file:// でも動作する。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ipusiron
ipusiron merged commit 0a2c2e6 into main Sep 27, 2026
2 checks passed
@ipusiron
ipusiron deleted the codex/i18n-20260927 branch September 27, 2026 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant