All files / src/libs i18n.ts

64% Statements 32/50
42.85% Branches 3/7
66.66% Functions 2/3
64% Lines 32/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   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)
}
// ===== 追記ここまで =====