feat. i18n 설정
This commit is contained in:
107
temp/dynamic-i18n-runtime.client.ts
Normal file
107
temp/dynamic-i18n-runtime.client.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
export default defineNuxtPlugin(() => {
|
||||
// 클라이언트 사이드에서 gameData를 가져와서 i18n 설정 업데이트
|
||||
const { $i18n } = useNuxtApp();
|
||||
|
||||
// gameData에서 언어 코드 추출
|
||||
const getGameDataLangCodes = (gameData: any) => {
|
||||
try {
|
||||
console.log("🚀 ~ getGameDataLangCodes ~ gameData:", gameData);
|
||||
|
||||
if (gameData?.lang_codes) {
|
||||
console.log("🚀 ~ getGameDataLangCodes ~ gameData.lang_codes:", gameData.lang_codes);
|
||||
console.log("🚀 ~ getGameDataLangCodes ~ lang_codes type:", typeof gameData.lang_codes);
|
||||
console.log("🚀 ~ getGameDataLangCodes ~ lang_codes isArray:", Array.isArray(gameData.lang_codes));
|
||||
return Array.isArray(gameData.lang_codes) ? gameData.lang_codes : [gameData.lang_codes];
|
||||
} else {
|
||||
console.log("🚀 ~ getGameDataLangCodes ~ gameData.lang_codes is undefined or null");
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to get gameData lang codes:', error);
|
||||
}
|
||||
|
||||
console.log("🚀 ~ getGameDataLangCodes ~ returning default ['ko']");
|
||||
return ['ko']; // 기본값
|
||||
};
|
||||
|
||||
// i18n 설정 업데이트
|
||||
const updateI18nLocales = async (gameData?: any) => {
|
||||
const langCodes = getGameDataLangCodes(gameData);
|
||||
|
||||
if (langCodes && langCodes.length > 0) {
|
||||
// 새로운 로케일 설정 생성
|
||||
const newLocales = langCodes.map(code => ({
|
||||
code,
|
||||
file: `${code}.ts`,
|
||||
name: getLocaleName(code),
|
||||
iso: getLocaleIso(code),
|
||||
dir: 'ltr'
|
||||
}));
|
||||
|
||||
// i18n 설정 업데이트
|
||||
if ($i18n) {
|
||||
// 로케일 메시지 동적 로드
|
||||
for (const code of langCodes) {
|
||||
try {
|
||||
const messages = await import(`../../i18n/locales/${code}.ts`);
|
||||
// defineI18nLocale 함수를 실행하여 실제 메시지 데이터 가져오기
|
||||
const localeMessages = await messages.default(code);
|
||||
console.log(`🚀 ~ loaded messages for ${code}:`, localeMessages);
|
||||
($i18n as any).setLocaleMessage(code, localeMessages);
|
||||
} catch (error) {
|
||||
console.warn(`Failed to load locale messages for ${code}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 로케일 이름 가져오기
|
||||
const getLocaleName = (code: string): string => {
|
||||
const localeNames: Record<string, string> = {
|
||||
en: 'English',
|
||||
'zh-tw': '繁體中文',
|
||||
ja: '日本語',
|
||||
ko: '한국어',
|
||||
fr: 'Français',
|
||||
de: 'Deutsch',
|
||||
es: 'Español',
|
||||
pt: 'Português',
|
||||
th: 'ภาษาไทย',
|
||||
'zh-cn': '简体中文'
|
||||
};
|
||||
return localeNames[code] || code;
|
||||
};
|
||||
|
||||
// 로케일 ISO 코드 가져오기
|
||||
const getLocaleIso = (code: string): string => {
|
||||
const localeIsos: Record<string, string> = {
|
||||
en: 'en',
|
||||
'zh-tw': 'zh-tw',
|
||||
ja: 'ja',
|
||||
ko: 'ko-KR',
|
||||
fr: 'fr',
|
||||
de: 'de',
|
||||
es: 'es',
|
||||
pt: 'pt',
|
||||
th: 'th',
|
||||
'zh-cn': 'zh-cn'
|
||||
};
|
||||
return localeIsos[code] || code;
|
||||
};
|
||||
|
||||
// gameData가 설정될 때까지 기다리거나 즉시 실행
|
||||
const gameDataStore = useGameDataStore();
|
||||
|
||||
// gameData가 이미 설정되어 있으면 즉시 실행
|
||||
if (gameDataStore.gameData) {
|
||||
updateI18nLocales(gameDataStore.gameData);
|
||||
}
|
||||
|
||||
// gameData가 변경될 때마다 실행
|
||||
watch(() => gameDataStore.gameData, async (newGameData) => {
|
||||
if (newGameData) {
|
||||
console.log("🚀 ~ gameData changed, updating i18n locales");
|
||||
await updateI18nLocales(newGameData);
|
||||
}
|
||||
}, { immediate: true });
|
||||
});
|
||||
94
temp/dynamic-i18n-runtime.server.ts
Normal file
94
temp/dynamic-i18n-runtime.server.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
export default defineNuxtPlugin(async () => {
|
||||
// 서버 사이드에서 gameData를 가져와서 i18n 설정 업데이트
|
||||
const { $i18n } = useNuxtApp();
|
||||
|
||||
// gameData에서 언어 코드 추출
|
||||
const getGameDataLangCodes = () => {
|
||||
try {
|
||||
// 서버 사이드에서 gameData 접근
|
||||
const nuxtApp = useNuxtApp();
|
||||
const gameData = nuxtApp.ssrContext?.event.context.gameData;
|
||||
|
||||
if (gameData?.lang_codes) {
|
||||
console.log("🚀 ~ dynamic-i18n-runtime.server ~ gameData.lang_codes:", gameData.lang_codes);
|
||||
return Array.isArray(gameData.lang_codes) ? gameData.lang_codes : [gameData.lang_codes];
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to get gameData lang codes on server:', error);
|
||||
}
|
||||
|
||||
return ['ko']; // 기본값
|
||||
};
|
||||
|
||||
// i18n 설정 업데이트
|
||||
const updateI18nLocales = async () => {
|
||||
const langCodes = getGameDataLangCodes();
|
||||
console.log("🚀 ~77777 updateI18nLocales ~ langCodes:", langCodes)
|
||||
|
||||
if (langCodes && langCodes.length > 0) {
|
||||
console.log("🚀 ~ dynamic-i18n-runtime.server ~ updating locales with:", langCodes);
|
||||
|
||||
// 새로운 로케일 설정 생성
|
||||
const newLocales = langCodes.map(code => ({
|
||||
code,
|
||||
file: `${code}.ts`,
|
||||
name: getLocaleName(code),
|
||||
iso: getLocaleIso(code),
|
||||
dir: 'ltr'
|
||||
}));
|
||||
|
||||
// i18n 설정 업데이트
|
||||
if ($i18n) {
|
||||
// 로케일 메시지 동적 로드
|
||||
for (const code of langCodes) {
|
||||
try {
|
||||
const messages = await import(`../../i18n/locales/${code}.ts`);
|
||||
// defineI18nLocale 함수를 실행하여 실제 메시지 데이터 가져오기
|
||||
const localeMessages = await messages.default(code);
|
||||
console.log(`🚀 ~ loaded messages for ${code}:`, localeMessages);
|
||||
($i18n as any).setLocaleMessage(code, localeMessages);
|
||||
} catch (error) {
|
||||
console.warn(`Failed to load locale messages for ${code}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 로케일 이름 가져오기
|
||||
const getLocaleName = (code: string): string => {
|
||||
const localeNames: Record<string, string> = {
|
||||
en: 'English',
|
||||
'zh-tw': '繁體中文',
|
||||
ja: '日本語',
|
||||
ko: '한국어',
|
||||
fr: 'Français',
|
||||
de: 'Deutsch',
|
||||
es: 'Español',
|
||||
pt: 'Português',
|
||||
th: 'ภาษาไทย',
|
||||
'zh-cn': '简体中文'
|
||||
};
|
||||
return localeNames[code] || code;
|
||||
};
|
||||
|
||||
// 로케일 ISO 코드 가져오기
|
||||
const getLocaleIso = (code: string): string => {
|
||||
const localeIsos: Record<string, string> = {
|
||||
en: 'en',
|
||||
'zh-tw': 'zh-tw',
|
||||
ja: 'ja',
|
||||
ko: 'ko-KR',
|
||||
fr: 'fr',
|
||||
de: 'de',
|
||||
es: 'es',
|
||||
pt: 'pt',
|
||||
th: 'th',
|
||||
'zh-cn': 'zh-cn'
|
||||
};
|
||||
return localeIsos[code] || code;
|
||||
};
|
||||
|
||||
// 서버 사이드에서 즉시 실행
|
||||
await updateI18nLocales();
|
||||
});
|
||||
58
temp/gameData.get.ts
Normal file
58
temp/gameData.get.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { getHeader } from "h3";
|
||||
import type {
|
||||
GameDataResponse,
|
||||
GameDataValue,
|
||||
} from "#layers/types/api/gameData";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const config = useRuntimeConfig();
|
||||
const baseDomain = (config.public.baseDomain || ".onstove.com") as string;
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl;
|
||||
const apiUrl = `${stoveApiBaseUrl}/pub-comm/v1.0/template/game`;
|
||||
let gameAlias = "";
|
||||
|
||||
try {
|
||||
// 미들웨어에서 설정한 gameAlias가 있다면 우선 사용
|
||||
if (event.context.gameAlias) {
|
||||
gameAlias = event.context.gameAlias;
|
||||
} else {
|
||||
const host = getHeader(event, "host") || "";
|
||||
const isGameAliasExtractable = host.includes(baseDomain);
|
||||
|
||||
if (isGameAliasExtractable) {
|
||||
const subdomain = host.split(".")[0];
|
||||
if (subdomain && subdomain !== "www") {
|
||||
gameAlias = subdomain;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("gameAlias extraction error: ", error);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
const queryParams: Record<string, string> = {
|
||||
game_alias: gameAlias,
|
||||
};
|
||||
|
||||
const response = await $fetch<GameDataResponse>(apiUrl, {
|
||||
query: queryParams,
|
||||
});
|
||||
|
||||
if (response?.code === 0 && "value" in response) {
|
||||
event.context.gameData = response.value;
|
||||
|
||||
// lang_codes를 사용해서 동적으로 i18n 설정 업데이트
|
||||
if (response.value.lang_codes && Array.isArray(response.value.lang_codes)) {
|
||||
event.context.availableLocales = response.value.lang_codes;
|
||||
event.context.defaultLocale = response.value.default_lang_code || response.value.lang_codes[0] || 'ko';
|
||||
}
|
||||
|
||||
return response.value as GameDataValue;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return {};
|
||||
}
|
||||
});
|
||||
40
temp/language-redirect.global.ts
Normal file
40
temp/language-redirect.global.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||
// 서버 사이드에서만 실행
|
||||
if (import.meta.client) {
|
||||
return;
|
||||
}
|
||||
|
||||
const gameDataStore = useGameDataStore();
|
||||
|
||||
// gameData가 로드되지 않았다면 gameData API 호출
|
||||
if (!gameDataStore.gameData) {
|
||||
try {
|
||||
await $fetch('/api/gameData');
|
||||
} catch (error) {
|
||||
console.error('gameData 로드 실패:', error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const availableLangCodes = gameDataStore.gameData?.lang_codes || ['ko'];
|
||||
const defaultLangCode = gameDataStore.gameData?.default_lang_code || availableLangCodes[0];
|
||||
|
||||
// 현재 경로에서 언어 코드 추출
|
||||
const pathSegments = to.path.split('/').filter(Boolean);
|
||||
const currentLangCode = pathSegments[0];
|
||||
|
||||
// 언어 코드가 유효한지 확인
|
||||
const isValidLangCode = availableLangCodes.includes(currentLangCode);
|
||||
|
||||
// 유효하지 않은 언어 코드인 경우 기본 언어로 리다이렉트
|
||||
if (currentLangCode && !isValidLangCode) {
|
||||
const newPath = `/${defaultLangCode}${to.path.replace(`/${currentLangCode}`, '')}`;
|
||||
return navigateTo(newPath, { replace: true });
|
||||
}
|
||||
|
||||
// 언어 코드가 없는 경우 기본 언어 코드 추가
|
||||
if (!currentLangCode || !availableLangCodes.includes(currentLangCode)) {
|
||||
const newPath = `/${defaultLangCode}${to.path}`;
|
||||
return navigateTo(newPath, { replace: true });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user