All files / src/libs i18n.ts

82% Statements 41/50
40% Branches 4/10
100% Functions 3/3
82% Lines 41/50

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 691x 1x   1x 1x 1x 1x   1x 1x 1x 1x 1x 1x 1x 1x     1x   2x 2x         2x     2x 2x         2x 2x     1x 1x 1x 1x 1x 1x 1x 1x 1x 1x     1x   1x 1x             1x 1x 1x 1x 1x 1x    
import { createI18n } from 'vue-i18n'
import api from '@/libs/axios'
 
const initLocale =
  sessionStorage.getItem('lang') ||
  localStorage.getItem('lang') ||
  (navigator.language?.split('-')[0] ?? 'ja')
 
export const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: initLocale,
  fallbackLocale: 'en',
  messages: { [initLocale]: {}},
  warnHtmlMessage: false,
})
 
// ===== ここから追記 =====
let _ready: Promise<void> | null = null
 
async function loadBundle(lang: string) {
  const res = await api.get(`/i18n/bundle`, { params: { lang } , responseType: 'json' }).catch(async (e) => {
    // もしサーバが text/html を返していて axios が自動JSON化に失敗する場合の保険
    // e.response?.data が string(HTML) なら詳細ログだけ出す
    console.error('[i18n] bundle request failed', e?.response?.status, e?.response?.data?.slice?.(0,200))
    throw e
  })
 
  // Content-Typeがjsonか確認(HTMLなら弾く)
  const ct = res.headers['content-type'] ?? ''
  if (!ct.includes('application/json')) {
    // サーバ側設定ミス or 認可で弾かれてHTMLが返っている
    throw new Error(`i18n bundle content-type not JSON: ${ct}`)
  }
 
  return res.data as Record<string, any>
}
 
/** アプリ起動時の一度きりの初期化。resolve するまで mount/遷移を待たせる想定。 */
export function i18nReady(): Promise<void> {
  if (_ready) return _ready
  _ready = (async () => {
    const lang = initLocale
    const msgs = await loadBundle(lang)
    i18n.global.setLocaleMessage(lang, msgs)
    i18n.global.locale.value = lang
  })()
  return _ready
}
 
/** 途中で言語を切り替える用(設定画面などから呼ぶ想定) */
export async function setLocale(lang: string) {
  // 既にロード済みなら即切替
  if (i18n.global.availableLocales.includes(lang) &&
    Object.keys(i18n.global.getLocaleMessage(lang) || {}).length > 0) {
    i18n.global.locale.value = lang
    sessionStorage.setItem('lang', lang)
    localStorage.setItem('lang', lang)
    return
  }
  // 未ロードなら取得してから切替
  const msgs = await loadBundle(lang)
  i18n.global.setLocaleMessage(lang, msgs)
  i18n.global.locale.value = lang
  sessionStorage.setItem('lang', lang)
  localStorage.setItem('lang', lang)
}
// ===== 追記ここまで =====