{"version":3,"sources":["../../src/lib/plugin/index.ts","../../node_modules/tsup/assets/cjs_shims.js","../../src/lib/plugin/middleware.ts","../../src/lib/plugin/po-parser.ts"],"sourcesContent":["import type { Plugin, ViteDevServer } from 'vite';\nimport { resolve, join, dirname } from 'path';\nimport { existsSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport sirv from 'sirv';\nimport type { PluginOptions } from './types.js';\nimport { createApiMiddleware } from './middleware.js';\n\n// Compute __dirname for ESM (CJS already has it)\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore - import.meta.url works in ESM, undefined in CJS\nconst __filename = typeof __dirname !== 'undefined' ? '' : fileURLToPath(import.meta.url);\nconst __dirnameComputed = typeof __dirname !== 'undefined' ? __dirname : dirname(__filename);\n\n// Re-export types\nexport type { PluginOptions, Translation, Language, LanguageStats } from './types.js';\n\n/**\n * vite-plugin-lingo - Visual translation editor for .po files\n *\n * @example\n * ```ts\n * // vite.config.ts (default setup)\n * import { defineConfig } from 'vite';\n * import lingo from 'vite-plugin-lingo';\n *\n * export default defineConfig({\n *   plugins: [\n *     lingo({\n *       route: '/_translations',\n *       localesDir: './locales'\n *     })\n *   ]\n * });\n * ```\n *\n * @example\n * ```ts\n * // vite.config.ts (SvelteKit convention)\n * import { defineConfig } from 'vite';\n * import lingo from 'vite-plugin-lingo';\n *\n * export default defineConfig({\n *   plugins: [\n *     lingo({\n *       route: '/_translations',\n *       localesDir: './src/locales'  // Common in SvelteKit\n *     })\n *   ]\n * });\n * ```\n */\nexport default function lingoPlugin(options: PluginOptions = {}): any {\n\tconst {\n\t\troute = '/_translations',\n\t\tlocalesDir = './locales',\n\t\tproduction = false,\n\t\trestartOnPoChange = false,\n\t\treloadOnPoChange = true\n\t} = options;\n\n\tlet root: string;\n\tlet resolvedLocalesDir: string;\n\n\treturn {\n\t\tname: 'vite-plugin-lingo',\n\n\t\t// Only apply in serve mode (unless production is enabled)\n\t\tapply: production ? undefined : 'serve',\n\n\t\tconfigResolved(config: any) {\n\t\t\troot = config.root;\n\t\t\tresolvedLocalesDir = resolve(root, localesDir);\n\t\t},\n\n\t\thandleHotUpdate({ file, server }: { file: string; server: ViteDevServer }) {\n\t\t\tif (file.endsWith('.po')) {\n\t\t\t\tconsole.log(`[lingo] .po file updated: ${file}`);\n\n\t\t\t\t// Notify connected clients via WebSocket\n\t\t\t\tserver.ws.send({\n\t\t\t\t\ttype: 'custom',\n\t\t\t\t\tevent: 'lingo:po-updated',\n\t\t\t\t\tdata: { path: file }\n\t\t\t\t});\n\n\t\t\t\tif (restartOnPoChange) {\n\t\t\t\t\tconsole.log('[lingo] Restarting dev server...');\n\t\t\t\t\tserver.restart();\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\n\t\t\t\tif (reloadOnPoChange) {\n\t\t\t\t\tconsole.log('[lingo] Triggering full page reload...');\n\t\t\t\t\tserver.ws.send({ type: 'full-reload' });\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tconfigureServer(server: ViteDevServer) {\n\t\t\t// Ensure the route doesn't have trailing slash\n\t\t\tconst cleanRoute = route.replace(/\\/$/, '');\n\n\t\t\t// Find the built UI assets\n\t\t\t// When running from source (dev): __dirnameComputed is src/lib/plugin, UI is at dist/ui-dist\n\t\t\t// When running from dist (published): __dirnameComputed is dist/plugin, UI is at ../ui-dist\n\t\t\tlet uiPath = resolve(__dirnameComputed, '../ui-dist');\n\n\t\t\t// If not found relative to __dirname, try from project root\n\t\t\tif (!existsSync(uiPath)) {\n\t\t\t\tuiPath = resolve(root, 'dist/ui-dist');\n\t\t\t}\n\n\t\t\tconsole.log('[lingo] Looking for UI at:', uiPath);\n\t\t\tconsole.log('[lingo] UI exists:', existsSync(uiPath));\n\n\t\t\t// Serve the editor UI if built assets exist\n\t\t\tif (existsSync(uiPath)) {\n\t\t\t\tconsole.log('[lingo] Serving built UI from:', uiPath);\n\t\t\t\tconst serve = sirv(uiPath, {\n\t\t\t\t\tdev: true,\n\t\t\t\t\tsingle: true // SPA mode\n\t\t\t\t});\n\n\t\t\t\tserver.middlewares.use(cleanRoute, (req, res, next) => {\n\t\t\t\t\t// Redirect to add trailing slash for base route (ensures relative paths work)\n\t\t\t\t\t// When mounted at /path, req.url is already stripped of the prefix\n\t\t\t\t\t// But the browser URL matters for relative path resolution\n\t\t\t\t\tconst reqWithOriginal = req as typeof req & { originalUrl?: string };\n\t\t\t\t\tif (\n\t\t\t\t\t\t(req.url === '/' || req.url === '') &&\n\t\t\t\t\t\treqWithOriginal.originalUrl &&\n\t\t\t\t\t\t!reqWithOriginal.originalUrl.endsWith('/')\n\t\t\t\t\t) {\n\t\t\t\t\t\tres.writeHead(302, { Location: cleanRoute + '/' });\n\t\t\t\t\t\tres.end();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Handle favicon.ico requests with an empty response to prevent 404\n\t\t\t\t\tif (req.url === '/favicon.ico') {\n\t\t\t\t\t\tres.statusCode = 204;\n\t\t\t\t\t\tres.end();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Skip API routes (handled by separate middleware)\n\t\t\t\t\tif (req.url?.startsWith('/api')) {\n\t\t\t\t\t\treturn next();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Serve static files with sirv\n\t\t\t\t\t// req.url is already stripped of the cleanRoute prefix by Connect\n\t\t\t\t\tserve(req, res, () => next());\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Development mode: serve a simple placeholder\n\t\t\t\tserver.middlewares.use(cleanRoute, (req, res, next) => {\n\t\t\t\t\t// Handle favicon.ico requests with an empty response to prevent 404\n\t\t\t\t\tif (req.url === '/favicon.ico') {\n\t\t\t\t\t\tres.statusCode = 204;\n\t\t\t\t\t\tres.end();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (req.url?.startsWith('/api')) {\n\t\t\t\t\t\treturn next();\n\t\t\t\t\t}\n\n\t\t\t\t\tres.setHeader('Content-Type', 'text/html');\n\t\t\t\t\tres.end(`\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>🌍 Lingo Translation Editor</title>\n  <style>\n    * { box-sizing: border-box; margin: 0; padding: 0; }\n    body { font-family: system-ui, -apple-system, sans-serif; background: #f5f5f5; min-height: 100vh; }\n    .container { max-width: 1200px; margin: 0 auto; padding: 2rem; }\n    header { background: white; padding: 1rem 2rem; border-bottom: 1px solid #e0e0e0; margin-bottom: 2rem; }\n    h1 { font-size: 1.5rem; color: #333; }\n    .card { background: white; border-radius: 8px; padding: 1.5rem; margin-bottom: 1rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }\n    .language { display: flex; justify-content: space-between; align-items: center; padding: 0.75rem; border-bottom: 1px solid #eee; }\n    .language:last-child { border-bottom: none; }\n    .progress { background: #e0e0e0; border-radius: 4px; height: 8px; width: 100px; overflow: hidden; }\n    .progress-bar { background: #4caf50; height: 100%; transition: width 0.3s; }\n    .loading { text-align: center; padding: 2rem; color: #666; }\n    .error { color: #f44336; }\n  </style>\n</head>\n<body>\n  <header>\n    <h1>🌍 Lingo Translation Editor</h1>\n  </header>\n  <div class=\"container\">\n    <div class=\"card\">\n      <h2 style=\"margin-bottom: 1rem;\">Languages</h2>\n      <div id=\"languages\" class=\"loading\">Loading...</div>\n    </div>\n  </div>\n  <script>\n    async function loadLanguages() {\n      try {\n        const res = await fetch('${cleanRoute}/api/languages');\n        const { data, error } = await res.json();\n        \n        if (error) throw new Error(error);\n        \n        const container = document.getElementById('languages');\n        if (!data || data.length === 0) {\n          container.innerHTML = '<p>No .po files found in the locales directory.</p>';\n          return;\n        }\n        \n        container.innerHTML = data.map(lang => \\`\n          <div class=\"language\">\n            <div>\n              <strong>\\${lang.name}</strong>\n              <span style=\"color: #666; margin-left: 0.5rem;\">(\\${lang.code})</span>\n            </div>\n            <div style=\"display: flex; align-items: center; gap: 1rem;\">\n              <span>\\${lang.translated}/\\${lang.total} translated</span>\n              <div class=\"progress\">\n                <div class=\"progress-bar\" style=\"width: \\${lang.progress}%\"></div>\n              </div>\n            </div>\n          </div>\n        \\`).join('');\n      } catch (err) {\n        document.getElementById('languages').innerHTML = \n          '<p class=\"error\">Error loading languages: ' + err.message + '</p>';\n      }\n    }\n    \n    loadLanguages();\n  </script>\n</body>\n</html>\n          `);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// API endpoints\n\t\t\tserver.middlewares.use(\n\t\t\t\t`${cleanRoute}/api`,\n\t\t\t\tcreateApiMiddleware({\n\t\t\t\t\tlocalesDir: resolvedLocalesDir,\n\t\t\t\t\troot,\n\t\t\t\t\tserver\n\t\t\t\t})\n\t\t\t);\n\n\t\t\t// Log startup message\n\t\t\tconst port = server.config.server.port || 5173;\n\n\t\t\tconst protocol = server.config.server.https ? 'https' : 'http';\n\t\t\tconst host = server.config.server.host || 'localhost';\n\t\t\tconst hostString = typeof host === 'string' ? host : 'localhost';\n\n\t\t\t// Use server.printUrls hook for better timing\n\t\t\tconst originalPrintUrls = server.printUrls;\n\t\t\tserver.printUrls = () => {\n\t\t\t\toriginalPrintUrls?.();\n\t\t\t\tconsole.log(\n\t\t\t\t\t`  \\x1b[32m➜\\x1b[0m  \\x1b[1mLingo:\\x1b[0m ${protocol}://${hostString}:${port}${cleanRoute}`\n\t\t\t\t);\n\t\t\t};\n\t\t}\n\t};\n}\n\n// Named export for convenience\nexport { lingoPlugin };\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n  typeof document === \"undefined\" \n    ? new URL(`file:${__filename}`).href \n    : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n      ? document.currentScript.src \n      : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import type { IncomingMessage, ServerResponse } from 'http';\nimport { join } from 'path';\nimport type { ViteDevServer } from 'vite';\nimport {\n\tfindPoFiles,\n\tparsePoFile,\n\tsavePoFile,\n\tgetLanguageStats,\n\tupdateTranslation\n} from './po-parser.js';\nimport type { Translation } from './types.js';\n\ninterface MiddlewareOptions {\n\tlocalesDir: string;\n\troot: string;\n\tserver?: ViteDevServer;\n}\n\n/**\n * Parse the request body as JSON\n */\nasync function parseBody<T>(req: IncomingMessage): Promise<T> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet body = '';\n\t\treq.on('data', (chunk) => (body += chunk));\n\t\treq.on('end', () => {\n\t\t\ttry {\n\t\t\t\tresolve(JSON.parse(body));\n\t\t\t} catch {\n\t\t\t\treject(new Error('Invalid JSON'));\n\t\t\t}\n\t\t});\n\t\treq.on('error', reject);\n\t});\n}\n\n/**\n * Send JSON response\n */\nfunction sendJson(res: ServerResponse, data: unknown, statusCode = 200): void {\n\tres.statusCode = statusCode;\n\tres.setHeader('Content-Type', 'application/json');\n\tres.end(JSON.stringify(data));\n}\n\n/**\n * Send error response\n */\nfunction sendError(res: ServerResponse, message: string, statusCode = 500): void {\n\tsendJson(res, { success: false, error: message }, statusCode);\n}\n\n/**\n * Create API middleware for handling translation operations\n */\nexport function createApiMiddleware(options: MiddlewareOptions) {\n\tconst { localesDir, server } = options;\n\n\treturn async (req: IncomingMessage, res: ServerResponse, next: () => void): Promise<void> => {\n\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`);\n\t\tconst path = url.pathname;\n\t\tconst method = req.method?.toUpperCase();\n\n\t\t// Enable CORS for development\n\t\tres.setHeader('Access-Control-Allow-Origin', '*');\n\t\tres.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n\t\tres.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n\t\t// Handle preflight\n\t\tif (method === 'OPTIONS') {\n\t\t\tres.statusCode = 204;\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\t// GET /api/languages - List all languages with stats\n\t\t\tif (path === '/languages' && method === 'GET') {\n\t\t\t\tconst stats = await getLanguageStats(localesDir);\n\t\t\t\tsendJson(res, { success: true, data: stats });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// GET /api/translations/:lang - Get all translations for a language\n\t\t\tconst translationsMatch = path.match(/^\\/translations\\/([^/]+)$/);\n\t\t\tif (translationsMatch && method === 'GET') {\n\t\t\t\tconst langCode = translationsMatch[1];\n\t\t\t\tconst filePath = join(localesDir, `${langCode}.po`);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst translations = await parsePoFile(filePath);\n\t\t\t\t\tsendJson(res, { success: true, data: translations });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsendError(res, `Language not found: ${langCode}`, 404);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// PUT /api/translations/:lang - Update translations for a language\n\t\t\tif (translationsMatch && method === 'PUT') {\n\t\t\t\tconst langCode = translationsMatch[1];\n\t\t\t\tconst filePath = join(localesDir, `${langCode}.po`);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst body = await parseBody<Translation | Translation[]>(req);\n\t\t\t\t\tconst updates = Array.isArray(body) ? body : [body];\n\t\t\t\t\tawait savePoFile(filePath, updates);\n\n\t\t\t\t\tsendJson(res, { success: true, message: 'Translations updated' });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsendError(res, error instanceof Error ? error.message : 'Failed to update', 400);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// PUT /api/translation/:lang/:msgid - Update a single translation\n\t\t\tconst singleMatch = path.match(/^\\/translation\\/([^/]+)\\/(.+)$/);\n\t\t\tif (singleMatch && method === 'PUT') {\n\t\t\t\tconst langCode = singleMatch[1];\n\t\t\t\tconst msgid = decodeURIComponent(singleMatch[2]);\n\t\t\t\tconst filePath = join(localesDir, `${langCode}.po`);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst body = await parseBody<{ msgstr: string; context?: string }>(req);\n\t\t\t\t\tawait updateTranslation(filePath, msgid, body.msgstr, body.context);\n\n\t\t\t\t\tsendJson(res, { success: true, message: 'Translation updated' });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsendError(res, error instanceof Error ? error.message : 'Failed to update', 400);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// GET /api/search - Search translations across languages\n\t\t\tif (path === '/search' && method === 'GET') {\n\t\t\t\tconst query = url.searchParams.get('q')?.toLowerCase() || '';\n\t\t\t\tconst lang = url.searchParams.get('lang');\n\n\t\t\t\tconst languages = await findPoFiles(localesDir);\n\t\t\t\tconst results: Array<{\n\t\t\t\t\tlang: string;\n\t\t\t\t\tmsgid: string;\n\t\t\t\t\tmsgstr: string;\n\t\t\t\t\tcontext?: string;\n\t\t\t\t}> = [];\n\n\t\t\t\tfor (const language of languages) {\n\t\t\t\t\tif (lang && language.code !== lang) continue;\n\n\t\t\t\t\tfor (const t of language.translations) {\n\t\t\t\t\t\tif (t.msgid.toLowerCase().includes(query) || t.msgstr.toLowerCase().includes(query)) {\n\t\t\t\t\t\t\tresults.push({\n\t\t\t\t\t\t\t\tlang: language.code,\n\t\t\t\t\t\t\t\tmsgid: t.msgid,\n\t\t\t\t\t\t\t\tmsgstr: t.msgstr,\n\t\t\t\t\t\t\t\tcontext: t.context\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsendJson(res, { success: true, data: results });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Not found\n\t\t\tsendError(res, 'Not found', 404);\n\t\t} catch (error) {\n\t\t\tconsole.error('[lingo] API error:', error);\n\t\t\tsendError(res, error instanceof Error ? error.message : 'Internal server error');\n\t\t}\n\t};\n}\n","import { po } from 'gettext-parser';\nimport { readFile, writeFile, readdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join, basename } from 'path';\nimport type { Translation, Language, LanguageStats } from './types.js';\n\n/**\n * Parse a .po file and extract translations\n */\nexport async function parsePoFile(filePath: string): Promise<Translation[]> {\n\tif (!existsSync(filePath)) {\n\t\tthrow new Error(`File not found: ${filePath}`);\n\t}\n\n\tconst content = await readFile(filePath);\n\tconst parsed = po.parse(content);\n\n\tconst translations: Translation[] = [];\n\n\tfor (const [context, messages] of Object.entries(parsed.translations)) {\n\t\tfor (const [msgid, data] of Object.entries(messages as Record<string, unknown>)) {\n\t\t\tif (!msgid) continue; // Skip header entry\n\n\t\t\tconst entry = data as {\n\t\t\t\tmsgid: string;\n\t\t\t\tmsgstr?: string[];\n\t\t\t\tcomments?: {\n\t\t\t\t\treference?: string;\n\t\t\t\t\ttranslator?: string;\n\t\t\t\t\textracted?: string;\n\t\t\t\t\tflag?: string;\n\t\t\t\t};\n\t\t\t};\n\n\t\t\ttranslations.push({\n\t\t\t\tmsgid,\n\t\t\t\tmsgstr: entry.msgstr?.[0] || '',\n\t\t\t\tcontext: context || undefined,\n\t\t\t\tcomments: entry.comments,\n\t\t\t\tfuzzy: entry.comments?.flag?.includes('fuzzy') || false\n\t\t\t});\n\t\t}\n\t}\n\n\treturn translations;\n}\n\n/**\n * Save translations back to a .po file\n */\nexport async function savePoFile(filePath: string, updates: Translation[]): Promise<void> {\n\tif (!existsSync(filePath)) {\n\t\tthrow new Error(`File not found: ${filePath}`);\n\t}\n\n\tconst content = await readFile(filePath);\n\tconst parsed = po.parse(content);\n\n\tfor (const update of updates) {\n\t\tconst context = update.context || '';\n\n\t\tif (parsed.translations[context]?.[update.msgid]) {\n\t\t\tparsed.translations[context][update.msgid].msgstr = [update.msgstr];\n\n\t\t\t// Handle fuzzy flag\n\t\t\tif (update.fuzzy !== undefined) {\n\t\t\t\tconst comments = parsed.translations[context][update.msgid].comments || {};\n\t\t\t\tif (update.fuzzy) {\n\t\t\t\t\tcomments.flag = 'fuzzy';\n\t\t\t\t} else {\n\t\t\t\t\tdelete comments.flag;\n\t\t\t\t}\n\t\t\t\tparsed.translations[context][update.msgid].comments = comments;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst compiled = po.compile(parsed);\n\tawait writeFile(filePath, compiled);\n}\n\n/**\n * Update a single translation\n */\nexport async function updateTranslation(\n\tfilePath: string,\n\tmsgid: string,\n\tmsgstr: string,\n\tcontext?: string\n): Promise<void> {\n\tawait savePoFile(filePath, [{ msgid, msgstr, context }]);\n}\n\n/**\n * Find all .po files in a directory\n */\nexport async function findPoFiles(localesDir: string): Promise<Language[]> {\n\tif (!existsSync(localesDir)) {\n\t\treturn [];\n\t}\n\n\tconst files = (await readdir(localesDir)).filter((f) => f.endsWith('.po'));\n\n\treturn Promise.all(\n\t\tfiles.map(async (file) => {\n\t\t\tconst filePath = join(localesDir, file);\n\t\t\tconst code = basename(file, '.po');\n\t\t\tconst translations = await parsePoFile(filePath);\n\n\t\t\tconst translated = translations.filter((t) => t.msgstr && !t.fuzzy).length;\n\t\t\tconst fuzzy = translations.filter((t) => t.fuzzy).length;\n\n\t\t\treturn {\n\t\t\t\tcode,\n\t\t\t\tname: getLanguageName(code),\n\t\t\t\tpath: filePath,\n\t\t\t\ttranslations,\n\t\t\t\tprogress: {\n\t\t\t\t\ttotal: translations.length,\n\t\t\t\t\ttranslated,\n\t\t\t\t\tfuzzy\n\t\t\t\t}\n\t\t\t};\n\t\t})\n\t);\n}\n\n/**\n * Get language statistics for all languages\n */\nexport async function getLanguageStats(localesDir: string): Promise<LanguageStats[]> {\n\tconst languages = await findPoFiles(localesDir);\n\n\treturn languages.map((lang) => ({\n\t\tcode: lang.code,\n\t\tname: lang.name,\n\t\ttotal: lang.progress.total,\n\t\ttranslated: lang.progress.translated,\n\t\tfuzzy: lang.progress.fuzzy,\n\t\tuntranslated: lang.progress.total - lang.progress.translated - lang.progress.fuzzy,\n\t\tprogress:\n\t\t\tlang.progress.total > 0\n\t\t\t\t? Math.round((lang.progress.translated / lang.progress.total) * 100)\n\t\t\t\t: 0\n\t}));\n}\n\n/**\n * Get a human-readable language name from a locale code\n */\nexport function getLanguageName(code: string): string {\n\tconst names: Record<string, string> = {\n\t\ten: 'English',\n\t\tes: 'Spanish',\n\t\tfr: 'French',\n\t\tde: 'German',\n\t\tit: 'Italian',\n\t\tpt: 'Portuguese',\n\t\t'pt-BR': 'Portuguese (Brazil)',\n\t\tja: 'Japanese',\n\t\tko: 'Korean',\n\t\tzh: 'Chinese',\n\t\t'zh-CN': 'Chinese (Simplified)',\n\t\t'zh-TW': 'Chinese (Traditional)',\n\t\tru: 'Russian',\n\t\tar: 'Arabic',\n\t\tnl: 'Dutch',\n\t\tpl: 'Polish',\n\t\tsv: 'Swedish',\n\t\tda: 'Danish',\n\t\tfi: 'Finnish',\n\t\tno: 'Norwegian',\n\t\ttr: 'Turkish',\n\t\tcs: 'Czech',\n\t\thu: 'Hungarian',\n\t\tro: 'Romanian',\n\t\tuk: 'Ukrainian',\n\t\tvi: 'Vietnamese',\n\t\tth: 'Thai',\n\t\tid: 'Indonesian',\n\t\tms: 'Malay',\n\t\the: 'Hebrew',\n\t\thi: 'Hindi'\n\t};\n\treturn names[code] || code.toUpperCase();\n}\n"],"mappings":"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","names":["import_path","import_fs","import_path","resolve","__filename","sirv"]}