홈샌드박스쇼케이스앱문서블로그
    • English영어
      EN
    • русский러시아어
      RU
    • 日本語일본어
      JA
    • français프랑스어
      FR
    • 한국어한국어
      KO
    • 中文중국어
      ZH
    • español스페인어
      ES
    • Deutsch독일어
      DE
    • العربية아랍어
      AR
    • italiano이탈리아어
      IT
    • British English영어(영국)
      EN-GB
    • português포르투갈어
      PT
    • हिन्दी힌디어
      HI
    • Türkçe튀르키예어
      TR
    • polski폴란드어
      PL
    • Indonesia인도네시아어
      ID
    • Tiếng Việt베트남어
      VI
    • українська우크라이나어
      UK
    /
    프레임워크로 문서 필터링
    Alt+←
    Intlayer의 이점
    시작하기
    개념
    • Intlayer 작동 방식
    • 구성
    • TestFillBuildWatchExtractLoginPushPullConfigurationListVersionEditorLiveDebugDoc ReviewDoc TranslateSDK
    • 비주얼 편집기
    • CMS
    • CI/CD 통합
    • 번역복수형열거조건성별삽입파일중첩MarkdownHTML함수 가져오기
    • 로케일별 파일
    • 컴파일러
    • 자동 채우기
    • 테스트
    • 번들 최적화
    환경
    • Next.js 14 및 앱 라우터
      Next.js 15
      Next.js 로케일 없는 URL
      Next.js 및 페이지 라우터
      컴파일러
    • Tanstack Start Solid
    • Astro 및 React
      Astro 및 Svelte
      Astro 및 Vue
      Astro 및 Solid
      Astro 및 Preact
      Astro 및 Lit
      Astro 및 Vanilla JS
    • React Router v7
      React Router v7 (fs-routes)
      Compiler
    • Nuxt 및 Vue
    • Vite 및 Solid
    • SvelteKit
    • Vite 및 Preact
    • Vite 및 Vanilla JS
    • Vite 및 Lit
    • Angular 19 (Webpack)
      Analog
    • React CRA
    • React Native 및 Expo
    • Express.js
      NestJS
      Fastify
      Hono
      Adonis
    • Lynx 및 React
    Plugins
    • JSON
    • gettext (.po)
    VS Code 확장 기능
    에이전트
    • MCP 서버
    • 에이전트 기술
    릴리스
    • v8
    • v7
    • v6
    벤치마크
    • Next.js
    • TanStack
    • Vue
    • Solid
    • Svelte
    블로그
    질문 발표
    1. Documentation
    2. 환경
    3. Astro
    4. Svelte
    \n\n
    \n

    {$content.title}

    \n \n
    \n 언어 전환:\n
    \n {#each availableLocales as localeItem}\n setLocale(localeItem)}\n >\n {getLocaleName(localeItem)}\n {getLocaleName(localeItem, $currentLocale)}\n {localeItem.toUpperCase()}\n \n {/each}\n
    \n
    \n
    \n```\n\n> `locale` 프롭은 Astro 페이지(서버 감지)에서 전달되어 `setupIntlayer`를 초기화하는 데 사용되며, 이로 인해 컴포넌트 전반의 모든 스토어에 대한 초기 로케일이 결정됩니다.\n\n### 7단계: 언어 전환기 추가\n\n언어 전환 기능은 Svelte 아일랜드(위 6단계 참조)에 직접 내장되어 있습니다. `svelte-intlayer`의 `useLocale` 스토어를 사용하며, 사용자가 새 언어를 선택할 때 로컬라이즈된 URL로 이동합니다:\n\n```svelte fileName=\"src/components/svelte/SvelteIsland.svelte\"\n\n\n
    \n 언어 전환:\n
    \n {#each availableLocales as localeItem}\n setLocale(localeItem)}\n >\n {getLocaleName(localeItem)}\n {getLocaleName(localeItem, $currentLocale)}\n {localeItem.toUpperCase()}\n \n {/each}\n
    \n
    \n```\n\n> **영속성에 관한 참고 사항:**\n> `window.location.href`를 통한 리디렉션을 위해 `onLocaleChange`를 사용하면 새 언어 URL이 확실히 방문되도록 보장합니다. 이를 통해 Intlayer 미들웨어가 언어 쿠키를 설정하고 향후 방문 시 사용자의 선호도를 기억할 수 있습니다.\n\n### 8단계: Sitemap 및 Robots.txt\n\nIntlayer는 동적으로 로컬라이즈된 사이트맵과 robots.txt 파일을 생성하기 위한 유틸리티를 제공합니다.\n\n#### 사이트맵\n\nIntlayer는 애플리케이션의 사이트맵을 쉽게 만들 수 있는 내장 사이트맵 생성기를 제공합니다. 로컬라이즈된 경로를 처리하고 검색 엔진에 필요한 메타데이터를 추가합니다.\n\n> Intlayer에서 생성한 사이트맵은 `xhtml:link` 네임스페이스(Hreflang XML 확장)를 지원합니다. 원시 URL만 나열하는 기본 사이트맵 생성기와 달리, Intlayer는 페이지의 모든 언어 버전(예: `/about`, `/about?lang=fr`, `/about?lang=es`) 간에 필요한 양항향 링크를 자동으로 생성합니다. 이를 통해 검색 엔진이 올바른 언어 버전을 올바른 사용자에게 색인화하고 제공할 수 있도록 보장합니다.\n\n모든 로컬라이즈된 경로를 포함하는 사이트맵을 생성하기 위해 `src/pages/sitemap.xml.ts`를 생성합니다.\n\n```typescript fileName=\"src/pages/sitemap.xml.ts\"\nimport type { APIRoute } from \"astro\";\nimport { generateSitemap, type SitemapUrlEntry } from \"intlayer\";\n\nconst pathList: SitemapUrlEntry[] = [\n { path: \"/\", changefreq: \"daily\", priority: 1.0 },\n { path: \"/about\", changefreq: \"monthly\", priority: 0.7 },\n];\n\nconst SITE_URL = import.meta.env.SITE ?? \"http://localhost:4321\";\n\nexport const GET: APIRoute = async ({ site }) => {\n const xmlOutput = generateSitemap(pathList, { siteUrl: SITE_URL });\n\n return new Response(xmlOutput, {\n headers: { \"Content-Type\": \"application/xml\" },\n });\n};\n```\n\n#### Robots.txt\n\n검색 엔진 크롤링을 제어하기 위해 `src/pages/robots.txt.ts`를 생성합니다.\n\n```typescript fileName=\"src/pages/robots.txt.ts\"\nimport type { APIRoute } from \"astro\";\nimport { getMultilingualUrls } from \"intlayer\";\n\nconst getAllMultilingualUrls = (urls: string[]) =>\n urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);\n\nconst disallowedPaths = getAllMultilingualUrls([\"/admin\", \"/private\"]);\n\nexport const GET: APIRoute = ({ site }) => {\n const robotsTxt = [\n \"User-agent: *\",\n \"Allow: /\",\n ...disallowedPaths.map((path) => `Disallow: ${path}`),\n \"\",\n `Sitemap: ${new URL(\"/sitemap.xml\", site).href}`,\n ].join(\"\\n\");\n\n return new Response(robotsTxt, {\n headers: { \"Content-Type\": \"text/plain\" },\n });\n};\n```\n\n### TypeScript 설정\n\nIntlayer는 모듈 증강(module augmentation)을 사용하여 TypeScript의 이점을 활용함으로써 코드베이스를 더 견고하게 만듭니다.\n\n![자동 완성](https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true)\n\n![번역 오류](https://github.com/aymericzip/intlayer/blob/main/docs/assets/translation_error.png?raw=true)\n\nTypeScript 설정에 자동 생성된 타입이 포함되어 있는지 확인하세요.\n\n```json5 fileName=\"tsconfig.json\"\n{\n // ... 기존 TypeScript 설정\n \"include\": [\n // ... 기존 TypeScript 설정\n \".intlayer/**/*.ts\", // 자동 생성된 타입 포함\n ],\n}\n```\n\n### Git 설정\n\nIntlayer가 생성한 파일은 무시하는 것이 좋습니다. 이를 통해 Git 리포지토리에 커밋되는 것을 방지할 수 있습니다.\n\n무시하려면 `.gitignore` 파일에 다음 지침을 추가하세요:\n\n```bash\n# Intlayer가 생성한 파일 무시\n.intlayer\n```\n\n### VS Code 확장 프로그램\n\nIntlayer 개발 환경을 개선하기 위해 **공식 Intlayer VS Code 확장 프로그램**을 설치할 수 있습니다.\n\n[VS Code Marketplace에서 설치](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)\n\n이 확장 프로그램은 다음 기능을 제공합니다:\n\n- 번역 키 **자동 완성**.\n- 누락된 번역에 대한 **실시간 오류 감지**.\n- 번역된 콘텐츠의 **인라인 미리보기**.\n- 번역을 쉽게 생성하고 업데이트할 수 있는 **빠른 작업(Quick Actions)**.\n\n확장 프로그램 사용에 대한 자세한 내용은 [Intlayer VS Code 확장 프로그램 문서](https://intlayer.org/doc/vs-code-extension)를 참조하세요.\n\n---\n\n### 15단계: 컴포넌트에서 콘텐츠 추출(선택 사항)\n\n기존 코드베이스가 있는 경우 수천 개의 파일을 변환하는 데 시간이 많이 걸릴 수 있습니다.\n\n이 프로세스를 용이하게 하기 위해 Intlayer는 컴포넌트를 변환하고 콘텐츠를 추출하기 위한 [컴파일러](/ko/doc/compiler) / [추출기](/ko/doc/concept/cli/extract)를 제안합니다.\n\n설정하려면 `intlayer.config.ts` 파일에 `compiler` 섹션을 추가할 수 있습니다.\n\n```typescript fileName=\"intlayer.config.ts\" codeFormat=\"typescript\"\nimport { type IntlayerConfig } from \"intlayer\";\n\nconst config: IntlayerConfig = {\n // ... 나머지 구성\n compiler: {\n /**\n * 컴파일러 활성화 여부를 나타냅니다.\n */\n enabled: true,\n\n /**\n * 출력 파일 경로를 정의합니다.\n */\n output: ({ fileName, extension }) => `./${fileName}${extension}`,\n\n /**\n * 변환 후 컴포넌트를 저장할지 여부를 나타냅니다. 그렇게 하면 컴파일러를 한 번만 실행하여 앱을 변환한 다음 제거할 수 있습니다.\n */\n saveComponents: false,\n\n /**\n * 사전 키 접두사\n */\n dictionaryKeyPrefix: \"\",\n },\n};\n\nexport default config;\n```\n\n\n \n\n컴포넌트를 변환하고 콘텐츠를 추출하기 위해 추출기를 실행합니다\n\n```bash packageManager=\"npm\"\nnpx intlayer extract\n```\n\n```bash packageManager=\"pnpm\"\npnpm intlayer extract\n```\n\n```bash packageManager=\"yarn\"\nyarn intlayer extract\n```\n\n```bash packageManager=\"bun\"\nbun x intlayer extract\n```\n\n \n \n\n`vite.config.ts`를 업데이트하여 `intlayerCompiler` 플러그인을 포함합니다.\n\n```ts fileName=\"vite.config.ts\"\nimport { defineConfig } from \"vite\";\nimport { intlayer, intlayerCompiler } from \"vite-intlayer\";\n\nexport default defineConfig({\n plugins: [\n intlayer(),\n intlayerCompiler(), // 컴파일러 플러그인을 추가합니다\n ],\n});\n```\n\n \n\n\n---\n\n### 더 알아보기\n\n더 자세히 알고 싶다면 [비주얼 에디터](/ko/doc/concept/editor)를 구현하거나 [CMS](/ko/doc/concept/cms)를 사용하여 콘텐츠를 외부화할 수 있습니다.\n","about":"Intlayer를 사용하여 Astro + Svelte 사이트에 국제화(i18n)를 추가하는 방법을 배워보세요. 이 가이드를 따라 사이트를 다국어로 만들어 보세요.","url":"https://intlayer.org/ko/doc/environment/astro/svelte","datePublished":"24-04-2026","dateModified":"06-05-2026","keywords":"국제화, 문서, Intlayer, Astro, Svelte, i18n, JavaScript","license":"https://raw.githubusercontent.com/aymericzip/intlayer/refs/heads/main/LICENSE","audience":{"@type":"Audience","audienceType":"개발자, 콘텐츠 관리자"}}
    생성:2026-04-24마지막 업데이트:2026-05-06
    GitHub에서 애플리케이션 템플릿 보기

    이 페이지에는 애플리케이션 템플릿이 제공됩니다.

    쇼케이스 애플리케이션 보기

    이 페이지는 템플릿의 라이브 데모로 연결됩니다.

    이 문서를 원하는 AI 어시스턴트에 참조하세요
    ChatGPT
    Claude
    DeepSeek
    Google AI mode
    Gemini
    Perplexity
    Mistral
    Grok

    이 페이지와 원하는 AI 어시스턴트를 사용하여 문서를 요약합니다

    버전 기록

    1. "Solid useIntlayer API 사용법을 직접 속성 액세스로 업데이트"
      v8.9.02026. 5. 4.
    2. "Astro + Svelte를 위한 초기 문서"
      v8.7.72026. 4. 24.

    이 페이지의 콘텐츠는 AI를 사용하여 번역되었습니다.

    영어 원본 내용의 최신 버전을 보기
    문서 수정

    이 문서를 개선할 아이디어가 있으시면 GitHub에 풀 리퀘스트를 제출하여 자유롭게 기여해 주세요.

    문서에 대한 GitHub 링크
    복사

    문서의 Markdown을 클립보드에 복사

    Intlayer를 사용하여 Astro + Svelte 사이트 번역하기 | 국제화 (i18n)

    ide.intlayer.org
    intlayer-astro-template.vercel.app

    목차

    Intlayer란 무엇인가요?

    Intlayer는 현대적인 웹 애플리케이션에서 다국어 지원을 단순화하기 위해 설계된 혁신적이고 오픈 소스인 국제화(i18n) 라이브러리입니다.

    Intlayer를 사용하면 다음을 할 수 있습니다:

    • 번역을 쉽게 관리하세요: 컴포넌트 레벨의 선언적 사전(Dictionaries)을 사용합니다.
    • 메타데이터, 라우트 및 콘텐츠를 동적으로 로컬라이즈하세요.
    • TypeScript 지원을 보장받으세요: 자동 생성된 타입을 통해 자동 완성 및 오류 감지 기능을 향상시킵니다.
    • 고급 기능을 활용하세요: 동적 로케일 감지 및 언어 전환과 같은 기능을 제공합니다.

    Astro + Svelte에서 Intlayer 설정을 위한 단계별 가이드

    GitHub에서 애플리케이션 템플릿 보기.

    1단계: 종속성 설치

    선호하는 패키지 관리자를 사용하여 필요한 패키지를 설치합니다:

    bash
    코드 복사

    코드를 클립보드에 복사

    npm install intlayer astro-intlayer svelte svelte-intlayer @astrojs/sveltenpx intlayer init
    alt, title, href, aria-label 등과 같은 문자열 속성에서 콘텐츠를 사용하려면 다음과 같이 함수의 값을 사용할 수 있습니다.
    html
    코드 복사

    코드를 클립보드에 복사

    <img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />
    • intlayer 설정 관리, 번역, 콘텐츠 선언, 트랜스파일 및 CLI 명령어를 위한 국제화 도구를 제공하는 핵심 패키지입니다.

    • astro-intlayer Intlayer를 Vite 번들러와 통합하기 위한 Astro 통합 플러그인과 사용자의 선호 로케일을 감지하고 쿠키를 관리하며 URL 리디렉션을 처리하는 미들웨어가 포함되어 있습니다.

    • svelte 핵심 Svelte 패키지입니다.

    • svelte-intlayer Intlayer를 Svelte 애플리케이션과 통합하는 패키지입니다. Svelte의 국제화를 위한 setupIntlayer, useIntlayer 및 useLocale 스토어를 제공합니다.

    • @astrojs/svelte Svelte 컴포넌트 아일랜드를 사용할 수 있게 해주는 공식 Astro 통합 도구입니다.

    2단계: 프로젝트 설정

    애플리케이션의 언어를 설정하기 위한 설정 파일을 생성합니다:

    intlayer.config.ts
    코드 복사

    코드를 클립보드에 복사

    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ENGLISH,      Locales.FRENCH,      Locales.SPANISH,      // 기타 로케일    ],    defaultLocale: Locales.ENGLISH,  },};export default config;
    이 설정 파일을 통해 로컬라이즈된 URL, 미들웨어 리디렉션, 쿠키 이름, 콘텐츠 선언 위치 및 확장자 설정, 콘솔의 Intlayer 로그 비활성화 등을 구성할 수 있습니다. 사용 가능한 파라미터의 전체 목록은 설정 문서를 참조하세요.

    3단계: Astro 설정에 Intlayer 통합

    Astro 설정에 intlayer 플러그인과 Svelte 통합을 추가합니다.

    astro.config.ts
    코드 복사

    코드를 클립보드에 복사

    // @ts-checkimport { intlayer } from "astro-intlayer";import svelte from "@astrojs/svelte";import { defineConfig } from "astro/config";// https://astro.build/configexport default defineConfig({  integrations: [intlayer(), svelte()],});
    intlayer() 통합 플러그인은 Intlayer를 Astro와 통합하는 데 사용됩니다. 콘텐츠 선언 파일의 빌드를 보장하고 개발 모드에서 이를 감시합니다. Astro 애플리케이션 내에서 Intlayer 환경 변수를 정의하며, 성능 최적화를 위한 에일리어스(alias)를 제공합니다.
    svelte() 통합은 client:only="svelte"를 통해 Svelte 컴포넌트 아일랜드를 사용할 수 있게 합니다.

    4단계: 콘텐츠 선언

    번역을 저장하기 위해 콘텐츠 선언을 생성하고 관리합니다:

    src/app.content.ts
    코드 복사

    코드를 클립보드에 복사

    import { t, type Dictionary } from "intlayer";const appContent = {  key: "app",  content: {    title: t({      en: "Hello World",      fr: "Bonjour le monde",      es: "Hola mundo",      ko: "안녕하세요",    }),  },} satisfies Dictionary;export default appContent;
    콘텐츠 선언은 contentDir(기본값 ./src)에 포함되어 있고 콘텐츠 선언 파일 확장자(기본값 .content.{json,ts,tsx,js,jsx,mjs,cjs})와 일치한다면 애플리케이션 어디에서나 정의할 수 있습니다.
    자세한 내용은 콘텐츠 선언 문서를 참조하세요.

    5단계: Astro에서 콘텐츠 사용

    intlayer에서 내보낸 핵심 헬퍼를 사용하여 .astro 파일에서 직접 사전을 소비할 수 있습니다. 또한 각 페이지에 hreflang 및 canonical 링크와 같은 SEO 메타데이터를 추가하고, 클라이언트 사이드의 인터랙티브 콘텐츠를 위해 Svelte 아일랜드를 포함해야 합니다.

    src/pages/[...locale]/index.astro
    코드 복사

    코드를 클립보드에 복사

    ---import {  getIntlayer,  getLocaleFromPath,  getLocalizedUrl,  getHTMLTextDir,  getPrefix,  localeMap,  defaultLocale,  type LocalesValues,} from "intlayer";import SvelteIsland from "../../components/svelte/SvelteIsland.svelte";export const getStaticPaths = () => {  return localeMap(({ locale }) => ({    params: { locale: getPrefix(locale).localePrefix },  }));};const locale = getLocaleFromPath(Astro.url.pathname) as LocalesValues;const { title } = getIntlayer("app", locale);---<!doctype html><html lang={locale} dir={getHTMLTextDir(locale)}>  <head>    <meta charset="utf-8" />    <meta name="viewport" content="width=device-width" />    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />    <title>{title}</title>    <!-- Canonical 링크: 검색 엔진에 이 페이지의 주 버전임을 알립니다 -->    <link      rel="canonical"      href={new URL(getLocalizedUrl(Astro.url.pathname, locale), Astro.site)}    />    <!-- Hreflang: 모든 로컬라이즈된 버전에 대해 Google에 알립니다 -->    {      localeMap(({ locale: mapLocale }) => (        <link          rel="alternate"          hreflang={mapLocale}          href={new URL(            getLocalizedUrl(Astro.url.pathname, mapLocale),            Astro.site          )}        />      ))    }    <!-- x-default: 일치하는 언어가 없는 사용자를 위한 폴백(fallback) 옵션 -->    <link      rel="alternate"      hreflang="x-default"      href={new URL(        getLocalizedUrl(Astro.url.pathname, defaultLocale),        Astro.site      )}    />  </head>  <body>    <!-- Svelte 아일랜드는 언어 전환기를 포함한 모든 인터랙티브 콘텐츠를 렌더링합니다 -->    <SvelteIsland locale={locale} client:only="svelte" />  </body></html>

    라우팅 설정에 관한 참고 사항: 사용하는 디렉토리 구조는 intlayer.config.ts의 middleware.routing 설정에 따라 달라집니다:

    • prefix-no-default (기본값): 루트(프레픽스 없음)에 기본 언어를 유지하고 나머지에 프레픽스를 붙입니다. 모든 케이스를 처리하려면 [...locale]을 사용하세요.
    • prefix-all: 모든 URL에 언어 프레픽스가 붙습니다. 루트를 분리해서 처리할 필요가 없다면 표준 [locale]을 사용할 수 있습니다.
    • search-param 또는 no-prefix: 로케일 폴더가 필요 없습니다. 로케일은 검색 파라미터나 쿠키를 통해 처리됩니다.

    6단계: Svelte 아일랜드 컴포넌트 생성

    Svelte 애플리케이션을 감싸는 아일랜드 컴포넌트를 생성합니다. 스토어에 접근하기 전에 서버에서 감지된 로케일을 사용하여 setupIntlayer를 호출해야 합니다.

    src/components/svelte/SvelteIsland.svelte
    코드 복사

    코드를 클립보드에 복사

    <script lang="ts">  import { useIntlayer, useLocale, setupIntlayer } from "svelte-intlayer";  import { getLocalizedUrl, getLocaleName, type LocalesValues } from "intlayer";  export let locale: LocalesValues;  setupIntlayer(locale);  const content = useIntlayer("app");  const { locale: currentLocale, availableLocales, setLocale } = useLocale({    onLocaleChange: (newLocale: LocalesValues) => {      window.location.href = getLocalizedUrl(window.location.pathname, newLocale);    },  });</script><div>  <h1>{$content.title}</h1>  <!-- 언어 전환기는 아일랜드 내에 인라인으로 렌더링됩니다 -->  <div class="locale-switcher">    <span class="switcher-label">언어 전환:</span>    <div class="locale-buttons">      {#each availableLocales as localeItem}        <button          class="locale-btn {localeItem === $currentLocale ? 'active' : ''}"          disabled={localeItem === $currentLocale}          on:click={() => setLocale(localeItem)}        >          <span class="ls-own-name">{getLocaleName(localeItem)}</span>          <span class="ls-current-name">{getLocaleName(localeItem, $currentLocale)}</span>          <span class="ls-code">{localeItem.toUpperCase()}</span>        </button>      {/each}    </div>  </div></div>
    locale 프롭은 Astro 페이지(서버 감지)에서 전달되어 setupIntlayer를 초기화하는 데 사용되며, 이로 인해 컴포넌트 전반의 모든 스토어에 대한 초기 로케일이 결정됩니다.

    7단계: 언어 전환기 추가

    언어 전환 기능은 Svelte 아일랜드(위 6단계 참조)에 직접 내장되어 있습니다. svelte-intlayer의 useLocale 스토어를 사용하며, 사용자가 새 언어를 선택할 때 로컬라이즈된 URL로 이동합니다:

    src/components/svelte/SvelteIsland.svelte
    코드 복사

    코드를 클립보드에 복사

    <script lang="ts">  import { useLocale } from "svelte-intlayer";  import { getLocalizedUrl, getLocaleName, type LocalesValues } from "intlayer";  // 6단계와 동일한 로케일/setupIntlayer 설정 재사용...  const {    locale: currentLocale,    availableLocales,    setLocale,  } = useLocale({    onLocaleChange: (newLocale: LocalesValues) => {      // 언어 변경 시 로컬라이즈된 URL로 이동      window.location.href = getLocalizedUrl(window.location.pathname, newLocale);    },  });</script><div class="locale-switcher">  <span class="switcher-label">언어 전환:</span>  <div class="locale-buttons">    {#each availableLocales as localeItem}      <button        class="locale-btn {localeItem === $currentLocale ? 'active' : ''}"        disabled={localeItem === $currentLocale}        on:click={() => setLocale(localeItem)}      >        <span class="ls-own-name">{getLocaleName(localeItem)}</span>        <span class="ls-current-name">{getLocaleName(localeItem, $currentLocale)}</span>        <span class="ls-code">{localeItem.toUpperCase()}</span>      </button>    {/each}  </div></div>

    영속성에 관한 참고 사항: window.location.href를 통한 리디렉션을 위해 onLocaleChange를 사용하면 새 언어 URL이 확실히 방문되도록 보장합니다. 이를 통해 Intlayer 미들웨어가 언어 쿠키를 설정하고 향후 방문 시 사용자의 선호도를 기억할 수 있습니다.

    8단계: Sitemap 및 Robots.txt

    Intlayer는 동적으로 로컬라이즈된 사이트맵과 robots.txt 파일을 생성하기 위한 유틸리티를 제공합니다.

    사이트맵

    Intlayer는 애플리케이션의 사이트맵을 쉽게 만들 수 있는 내장 사이트맵 생성기를 제공합니다. 로컬라이즈된 경로를 처리하고 검색 엔진에 필요한 메타데이터를 추가합니다.

    Intlayer에서 생성한 사이트맵은 xhtml:link 네임스페이스(Hreflang XML 확장)를 지원합니다. 원시 URL만 나열하는 기본 사이트맵 생성기와 달리, Intlayer는 페이지의 모든 언어 버전(예: /about, /about?lang=fr, /about?lang=es) 간에 필요한 양항향 링크를 자동으로 생성합니다. 이를 통해 검색 엔진이 올바른 언어 버전을 올바른 사용자에게 색인화하고 제공할 수 있도록 보장합니다.

    모든 로컬라이즈된 경로를 포함하는 사이트맵을 생성하기 위해 src/pages/sitemap.xml.ts를 생성합니다.

    src/pages/sitemap.xml.ts
    코드 복사

    코드를 클립보드에 복사

    import type { APIRoute } from "astro";import { generateSitemap, type SitemapUrlEntry } from "intlayer";const pathList: SitemapUrlEntry[] = [  { path: "/", changefreq: "daily", priority: 1.0 },  { path: "/about", changefreq: "monthly", priority: 0.7 },];const SITE_URL = import.meta.env.SITE ?? "http://localhost:4321";export const GET: APIRoute = async ({ site }) => {  const xmlOutput = generateSitemap(pathList, { siteUrl: SITE_URL });  return new Response(xmlOutput, {    headers: { "Content-Type": "application/xml" },  });};

    Robots.txt

    검색 엔진 크롤링을 제어하기 위해 src/pages/robots.txt.ts를 생성합니다.

    src/pages/robots.txt.ts
    코드 복사

    코드를 클립보드에 복사

    import type { APIRoute } from "astro";import { getMultilingualUrls } from "intlayer";const getAllMultilingualUrls = (urls: string[]) =>  urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);export const GET: APIRoute = ({ site }) => {  const robotsTxt = [    "User-agent: *",    "Allow: /",    ...disallowedPaths.map((path) => `Disallow: ${path}`),    "",    `Sitemap: ${new URL("/sitemap.xml", site).href}`,  ].join("\n");  return new Response(robotsTxt, {    headers: { "Content-Type": "text/plain" },  });};

    TypeScript 설정

    Intlayer는 모듈 증강(module augmentation)을 사용하여 TypeScript의 이점을 활용함으로써 코드베이스를 더 견고하게 만듭니다.

    자동 완성

    번역 오류

    TypeScript 설정에 자동 생성된 타입이 포함되어 있는지 확인하세요.

    tsconfig.json
    코드 복사

    코드를 클립보드에 복사

    {  // ... 기존 TypeScript 설정  "include": [    // ... 기존 TypeScript 설정    ".intlayer/**/*.ts", // 자동 생성된 타입 포함  ],}

    Git 설정

    Intlayer가 생성한 파일은 무시하는 것이 좋습니다. 이를 통해 Git 리포지토리에 커밋되는 것을 방지할 수 있습니다.

    무시하려면 .gitignore 파일에 다음 지침을 추가하세요:

    bash
    코드 복사

    코드를 클립보드에 복사

    # Intlayer가 생성한 파일 무시.intlayer

    VS Code 확장 프로그램

    Intlayer 개발 환경을 개선하기 위해 공식 Intlayer VS Code 확장 프로그램을 설치할 수 있습니다.

    VS Code Marketplace에서 설치

    이 확장 프로그램은 다음 기능을 제공합니다:

    • 번역 키 자동 완성.
    • 누락된 번역에 대한 실시간 오류 감지.
    • 번역된 콘텐츠의 인라인 미리보기.
    • 번역을 쉽게 생성하고 업데이트할 수 있는 빠른 작업(Quick Actions).

    확장 프로그램 사용에 대한 자세한 내용은 Intlayer VS Code 확장 프로그램 문서를 참조하세요.


    15단계: 컴포넌트에서 콘텐츠 추출(선택 사항)

    기존 코드베이스가 있는 경우 수천 개의 파일을 변환하는 데 시간이 많이 걸릴 수 있습니다.

    이 프로세스를 용이하게 하기 위해 Intlayer는 컴포넌트를 변환하고 콘텐츠를 추출하기 위한 컴파일러 / 추출기를 제안합니다.

    설정하려면 intlayer.config.ts 파일에 compiler 섹션을 추가할 수 있습니다.

    intlayer.config.ts
    코드 복사

    코드를 클립보드에 복사

    import { type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  // ... 나머지 구성  compiler: {    /**     * 컴파일러 활성화 여부를 나타냅니다.     */    enabled: true,    /**     * 출력 파일 경로를 정의합니다.     */    output: ({ fileName, extension }) => `./${fileName}${extension}`,    /**     * 변환 후 컴포넌트를 저장할지 여부를 나타냅니다. 그렇게 하면 컴파일러를 한 번만 실행하여 앱을 변환한 다음 제거할 수 있습니다.     */    saveComponents: false,    /**     * 사전 키 접두사     */    dictionaryKeyPrefix: "",  },};export default config;

    컴포넌트를 변환하고 콘텐츠를 추출하기 위해 추출기를 실행합니다

    bash
    코드 복사

    코드를 클립보드에 복사

    npx intlayer extract

    vite.config.ts를 업데이트하여 intlayerCompiler 플러그인을 포함합니다.

    vite.config.ts
    코드 복사

    코드를 클립보드에 복사

    import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // 컴파일러 플러그인을 추가합니다 ],});

    더 알아보기

    더 자세히 알고 싶다면 비주얼 에디터를 구현하거나 CMS를 사용하여 콘텐츠를 외부화할 수 있습니다.

    Astro 및 React
    Astro 및 Vue
    Alt+→

    이 페이지에서

      토론은 익명이며 일반적인 문제를 해결하기 위해 정기적으로 검토됩니다. 기능 아이디어, 문서에 대한 피드백 또는 Intlayer와 관련된 모든 것을 자유롭게 공유하세요, 이 의견을 로드맵 구성과 제품 개선에 활용합니다.

      npm install intlayer astro-intlayer svelte svelte-intlayer @astrojs/sveltenpx intlayer init
      <img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />
      import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ENGLISH,      Locales.FRENCH,      Locales.SPANISH,      // 기타 로케일    ],    defaultLocale: Locales.ENGLISH,  },};export default config;
      // @ts-checkimport { intlayer } from "astro-intlayer";import svelte from "@astrojs/svelte";import { defineConfig } from "astro/config";// https://astro.build/configexport default defineConfig({  integrations: [intlayer(), svelte()],});
      import { t, type Dictionary } from "intlayer";const appContent = {  key: "app",  content: {    title: t({      en: "Hello World",      fr: "Bonjour le monde",      es: "Hola mundo",      ko: "안녕하세요",    }),  },} satisfies Dictionary;export default appContent;
      ---import {  getIntlayer,  getLocaleFromPath,  getLocalizedUrl,  getHTMLTextDir,  getPrefix,  localeMap,  defaultLocale,  type LocalesValues,} from "intlayer";import SvelteIsland from "../../components/svelte/SvelteIsland.svelte";export const getStaticPaths = () => {  return localeMap(({ locale }) => ({    params: { locale: getPrefix(locale).localePrefix },  }));};const locale = getLocaleFromPath(Astro.url.pathname) as LocalesValues;const { title } = getIntlayer("app", locale);---<!doctype html><html lang={locale} dir={getHTMLTextDir(locale)}>  <head>    <meta charset="utf-8" />    <meta name="viewport" content="width=device-width" />    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />    <title>{title}</title>    <!-- Canonical 링크: 검색 엔진에 이 페이지의 주 버전임을 알립니다 -->    <link      rel="canonical"      href={new URL(getLocalizedUrl(Astro.url.pathname, locale), Astro.site)}    />    <!-- Hreflang: 모든 로컬라이즈된 버전에 대해 Google에 알립니다 -->    {      localeMap(({ locale: mapLocale }) => (        <link          rel="alternate"          hreflang={mapLocale}          href={new URL(            getLocalizedUrl(Astro.url.pathname, mapLocale),            Astro.site          )}        />      ))    }    <!-- x-default: 일치하는 언어가 없는 사용자를 위한 폴백(fallback) 옵션 -->    <link      rel="alternate"      hreflang="x-default"      href={new URL(        getLocalizedUrl(Astro.url.pathname, defaultLocale),        Astro.site      )}    />  </head>  <body>    <!-- Svelte 아일랜드는 언어 전환기를 포함한 모든 인터랙티브 콘텐츠를 렌더링합니다 -->    <SvelteIsland locale={locale} client:only="svelte" />  </body></html>
      <script lang="ts">  import { useIntlayer, useLocale, setupIntlayer } from "svelte-intlayer";  import { getLocalizedUrl, getLocaleName, type LocalesValues } from "intlayer";  export let locale: LocalesValues;  setupIntlayer(locale);  const content = useIntlayer("app");  const { locale: currentLocale, availableLocales, setLocale } = useLocale({    onLocaleChange: (newLocale: LocalesValues) => {      window.location.href = getLocalizedUrl(window.location.pathname, newLocale);    },  });</script><div>  <h1>{$content.title}</h1>  <!-- 언어 전환기는 아일랜드 내에 인라인으로 렌더링됩니다 -->  <div class="locale-switcher">    <span class="switcher-label">언어 전환:</span>    <div class="locale-buttons">      {#each availableLocales as localeItem}        <button          class="locale-btn {localeItem === $currentLocale ? 'active' : ''}"          disabled={localeItem === $currentLocale}          on:click={() => setLocale(localeItem)}        >          <span class="ls-own-name">{getLocaleName(localeItem)}</span>          <span class="ls-current-name">{getLocaleName(localeItem, $currentLocale)}</span>          <span class="ls-code">{localeItem.toUpperCase()}</span>        </button>      {/each}    </div>  </div></div>
      <script lang="ts">  import { useLocale } from "svelte-intlayer";  import { getLocalizedUrl, getLocaleName, type LocalesValues } from "intlayer";  // 6단계와 동일한 로케일/setupIntlayer 설정 재사용...  const {    locale: currentLocale,    availableLocales,    setLocale,  } = useLocale({    onLocaleChange: (newLocale: LocalesValues) => {      // 언어 변경 시 로컬라이즈된 URL로 이동      window.location.href = getLocalizedUrl(window.location.pathname, newLocale);    },  });</script><div class="locale-switcher">  <span class="switcher-label">언어 전환:</span>  <div class="locale-buttons">    {#each availableLocales as localeItem}      <button        class="locale-btn {localeItem === $currentLocale ? 'active' : ''}"        disabled={localeItem === $currentLocale}        on:click={() => setLocale(localeItem)}      >        <span class="ls-own-name">{getLocaleName(localeItem)}</span>        <span class="ls-current-name">{getLocaleName(localeItem, $currentLocale)}</span>        <span class="ls-code">{localeItem.toUpperCase()}</span>      </button>    {/each}  </div></div>
      import type { APIRoute } from "astro";import { generateSitemap, type SitemapUrlEntry } from "intlayer";const pathList: SitemapUrlEntry[] = [  { path: "/", changefreq: "daily", priority: 1.0 },  { path: "/about", changefreq: "monthly", priority: 0.7 },];const SITE_URL = import.meta.env.SITE ?? "http://localhost:4321";export const GET: APIRoute = async ({ site }) => {  const xmlOutput = generateSitemap(pathList, { siteUrl: SITE_URL });  return new Response(xmlOutput, {    headers: { "Content-Type": "application/xml" },  });};
      import type { APIRoute } from "astro";import { getMultilingualUrls } from "intlayer";const getAllMultilingualUrls = (urls: string[]) =>  urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);export const GET: APIRoute = ({ site }) => {  const robotsTxt = [    "User-agent: *",    "Allow: /",    ...disallowedPaths.map((path) => `Disallow: ${path}`),    "",    `Sitemap: ${new URL("/sitemap.xml", site).href}`,  ].join("\n");  return new Response(robotsTxt, {    headers: { "Content-Type": "text/plain" },  });};
      {  // ... 기존 TypeScript 설정  "include": [    // ... 기존 TypeScript 설정    ".intlayer/**/*.ts", // 자동 생성된 타입 포함  ],}
      # Intlayer가 생성한 파일 무시.intlayer
      import { type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  // ... 나머지 구성  compiler: {    /**     * 컴파일러 활성화 여부를 나타냅니다.     */    enabled: true,    /**     * 출력 파일 경로를 정의합니다.     */    output: ({ fileName, extension }) => `./${fileName}${extension}`,    /**     * 변환 후 컴포넌트를 저장할지 여부를 나타냅니다. 그렇게 하면 컴파일러를 한 번만 실행하여 앱을 변환한 다음 제거할 수 있습니다.     */    saveComponents: false,    /**     * 사전 키 접두사     */    dictionaryKeyPrefix: "",  },};export default config;
      npx intlayer extract
      import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // 컴파일러 플러그인을 추가합니다 ],});