Skip to main content
Glama
LanguageSwitcher.svelte6.47 kB
<script> import { locale, _ } from 'svelte-i18n'; import { saveLocale } from '../i18n/index.js'; import { invalidateAll } from '$app/navigation'; import { languageConfig, statusStyles, statusLabels, readyLanguages, developmentLanguages } from '../i18n/language-config.js'; let isOpen = false; let showAdvanced = false; // 현재 locale을 reactive하게 추적 $: currentLocale = $locale || 'ko'; // 기본값을 한국어로 설정 // 언어 변경 함수 async function changeLanguage(newLocale) { // 불완전한 번역 언어 선택 시 경고 (개발 환경에서만) const config = languageConfig[newLocale]; if (config && !config.ready && typeof window !== 'undefined') { const fallbackLang = ['zh-CN', 'ja', 'ko'].includes(newLocale) ? '한국어' : '영어'; const confirmChange = confirm( `이 언어는 번역이 ${config.completeness.toFixed(1)}%만 완성되었습니다. 누락된 텍스트는 ${fallbackLang}로 표시됩니다. 계속하시겠습니까?` ); if (!confirmChange) { isOpen = false; return; } } locale.set(newLocale); saveLocale(newLocale); isOpen = false; showAdvanced = false; // 현재 페이지를 다시 로드하여 언어 변경사항을 즉시 반영 await invalidateAll(); } // 드롭다운 외부 클릭 시 닫기 function handleClickOutside(event) { if (!event.target.closest('.language-switcher')) { isOpen = false; } } $: if (typeof window !== 'undefined') { if (isOpen) { window.addEventListener('click', handleClickOutside); } else { window.removeEventListener('click', handleClickOutside); } } </script> <div class="relative language-switcher"> <button on:click={() => isOpen = !isOpen} class="flex items-center space-x-2 px-3 py-2 text-sm font-medium text-gray-700 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 rounded-md" type="button" > <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129" /> </svg> <span>{languageConfig[currentLocale]?.native || currentLocale}</span> <svg class="w-4 h-4 transition-transform" class:rotate-180={isOpen} fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" /> </svg> </button> {#if isOpen} <div class="absolute right-0 z-50 mt-2 w-64 rounded-md bg-white py-2 shadow-lg ring-1 ring-black ring-opacity-5"> <!-- 준비된 언어들 --> <div class="px-3 py-1 text-xs font-medium text-gray-500 uppercase tracking-wider border-b border-gray-100"> 권장 언어 </div> {#each readyLanguages as localeCode} {@const config = languageConfig[localeCode]} {@const styles = statusStyles[config.status]} <button on:click={() => changeLanguage(localeCode)} class="flex items-center w-full px-4 py-2 text-sm hover:bg-gray-100 focus:bg-gray-100 focus:outline-none" class:bg-blue-50={localeCode === currentLocale} class:text-blue-900={localeCode === currentLocale} type="button" > <span class="flex-1 text-left text-gray-700">{config.native}</span> <div class="flex items-center space-x-2"> <span class="text-xs px-2 py-1 rounded-full {styles.badgeClass}"> {Math.round(config.completeness)}% </span> {#if localeCode === currentLocale} <svg class="w-4 h-4 text-blue-600" fill="currentColor" viewBox="0 0 20 20"> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" /> </svg> {/if} </div> </button> {/each} <!-- 개발 중인 언어들 --> {#if developmentLanguages.length > 0} <div class="border-t border-gray-100 mt-2 pt-2"> <button on:click={() => showAdvanced = !showAdvanced} class="flex items-center w-full px-4 py-2 text-xs text-gray-500 hover:text-gray-700 focus:outline-none" type="button" > <span class="flex-1 text-left">개발 중인 언어 ({developmentLanguages.length}개)</span> <svg class="w-3 h-3 transition-transform" class:rotate-180={showAdvanced} fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" /> </svg> </button> {#if showAdvanced} {#each developmentLanguages as localeCode} {@const config = languageConfig[localeCode]} {@const styles = statusStyles[config.status]} <button on:click={() => changeLanguage(localeCode)} class="flex items-center w-full px-4 py-2 text-sm hover:bg-gray-100 focus:bg-gray-100 focus:outline-none {styles.bgClass} {styles.borderClass} border-l-2 ml-2 mr-1 rounded" class:bg-blue-50={localeCode === currentLocale} class:text-blue-900={localeCode === currentLocale} type="button" > <span class="flex-1 text-left {styles.textClass}">{config.native}</span> <div class="flex items-center space-x-2"> <span class="text-xs px-2 py-1 rounded-full {styles.badgeClass}"> {Math.round(config.completeness)}% </span> {#if localeCode === currentLocale} <svg class="w-4 h-4 text-blue-600" fill="currentColor" viewBox="0 0 20 20"> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" /> </svg> {/if} </div> </button> {/each} {/if} </div> {/if} </div> {/if} </div> <style> .rotate-180 { transform: rotate(180deg); } </style>

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/foswmine/workflow-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server