컨텐츠로 건너뛰기

국제화 (i18n)

Starlight는 라우팅, 대체 콘텐츠 및 전체 RTL(오른쪽에서 왼쪽으로) 언어 지원을 포함한 다국어 사이트에 대한 기본 지원을 제공합니다.

i18n 구성

  1. Starlight 통합에 localesdefaultLocale을 전달하여 사이트가 지원해야 할 언어에 대해 알려주세요.

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import starlight from '@astrojs/starlight';
    export default defineConfig({
    integrations: [
    starlight({
    title: '나의 문서',
    // 사이트의 기본 언어를 영어로 설정합니다.
    defaultLocale: 'en',
    locales: {
    // 영어 문서는 `src/content/docs/en/`에 있습니다.
    en: {
    label: 'English',
    },
    // 중국어 간체 문서는 `src/content/docs/zh-cn/`에 있습니다.
    'zh-cn': {
    label: '简体中文',
    lang: 'zh-CN',
    },
    // 아랍어 문서는 `src/content/docs/ar/`에 있습니다.
    ar: {
    label: 'العربية',
    dir: 'rtl',
    },
    },
    }),
    ],
    });

    defaultLocale은 대체 콘텐츠 및 UI 라벨에 사용되므로 콘텐츠 작성을 시작할 가능성이 가장 높거나 이미 콘텐츠가 있는 언어로 선택하세요.

  2. src/content/docs/에 각 언어에 대한 디렉터리를 만듭니다. 예를 들어 위에서 사용한 구성의 경우 다음과 같이 디렉터리를 생성할 수 있습니다.

    • 디렉터리src/
      • 디렉터리content/
        • 디렉터리docs/
          • 디렉터리ar/
          • 디렉터리en/
          • 디렉터리zh-cn/
  3. 이제 언어 디렉터리에 콘텐츠 파일을 추가할 수 있습니다. 여러 언어로 작성된 페이지를 연결하기 위해 같은 이름의 파일을 사용하면 Starlight의 모든 i18n 기능(대체 콘텐츠, 번역 알림 등)을 활용할 수 있습니다.

    예를 들어, 아랍어와 영어 홈페이지를 각각 나타내려면 ar/index.mden/index.md를 만듭니다.

고급 국제화 시나리오를 위해 Starlight는 Astro의 i18n 구성 옵션을 사용하는 국제화 구성도 지원합니다.

루트 로케일 사용

경로에 i18n 접두사가 없는 언어를 제공하려면 “루트” 로케일을 사용할 수 있습니다. 예를 들어 영어가 루트 로케일인 경우 영어 페이지 경로는 /en/about 대신 /about이 됩니다.

루트 로케일을 설정하려면 locales 구성에서 root 키를 사용하세요. 루트 로케일이 콘텐츠의 기본 로케일이기도 한 경우 defaultLocale을 제거하거나 값을 root로 설정하세요.

astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: '나의 문서',
defaultLocale: 'root', // 선택적
locales: {
root: {
label: 'English',
lang: 'en', // 루트 로케일은 lang이 반드시 필요합니다.
},
'zh-cn': {
label: '简体中文',
lang: 'zh-CN',
},
},
}),
],
});

루트 로케일을 사용하는 경우 해당 언어로 작성된 페이지를 전용 언어 폴더 대신 src/content/docs/에 직접 보관하세요. 예를 들어 위 구성을 사용할 때 영어와 중국어에 대한 홈 페이지 파일은 다음과 같습니다.

  • 디렉터리src/
    • 디렉터리content/
      • 디렉터리docs/
        • index.md
        • 디렉터리zh-cn/
          • index.md

단일 언어를 사용하는 사이트

기본적으로 Starlight는 단일 언어(영어) 사이트입니다. 다른 언어로 단일 언어 사이트를 만들려면 locales 구성에서 root를 해당 언어로 설정하세요.

astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: '나의 문서',
locales: {
root: {
label: '한국어',
lang: 'ko',
},
},
}),
],
});

이를 통해 언어 선택기와 같은 다국어 사이트에 대한 다른 국제화 기능을 활성화하지 않고도 Starlight의 기본 언어를 변경할 수 있습니다.

대체 콘텐츠

Starlight는 귀하가 모든 언어로 같은 페이지를 생성할 것을 기대합니다. 예를 들어 en/about.md 파일이 있는 경우 지원하는 각 언어에 대해 about.md를 만듭니다. 이를 통해 Starlight는 아직 번역되지 않은 페이지에 대체 콘텐츠를 제공합니다.

특정 언어에 대한 번역이 아직 제공되지 않는 경우 Starlight는 독자에게 해당 페이지의 콘텐츠를 기본 언어(defaultLocale을 통해 설정된 언어)로 표시합니다. 예를 들어, About 페이지의 프랑스어 버전을 아직 만들지 않았고 기본 언어가 영어인 경우 /fr/about에 방문한 독자는 이 페이지가 아직 번역되지 않았다는 알림과 함께 /en/about에 있는 영어 콘텐츠를 보게 됩니다. 이를 통해 기본 언어로 콘텐츠를 추가한 다음 점진적으로 번역할 수 있습니다.

사이트 제목 번역

기본적으로 Starlight는 모든 언어에 대해 동일한 사이트 제목을 사용합니다. 각 로케일의 제목을 사용자 정의해야 하는 경우 Starlight 옵션의 title에 객체를 전달할 수 있습니다.

astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: '나의 문서',
title: {
ko: '나의 문서',
'zh-CN': '我的文档',
},
defaultLocale: 'ko',
locales: {
ko: { label: '한국어' },
'zh-cn': { label: '简体中文', lang: 'zh-CN' },
},
}),
],
});

Starlight UI 번역

Starlight를 사용하면 번역된 콘텐츠 파일을 호스팅하는 것 외에도 독자가 선택한 언어로 사이트 전체를 경험할 수 있도록 기본 UI 문자열(예를 들어, 목차의 제목인 “목차”)을 번역할 수 있습니다.

갈리시아어, 네덜란드어, 노르웨이어(보크말), 덴마크어, 독일어, 러시아어, 루마니아어, 베트남어, 스웨덴어, 스페인어, 슬로바키아어, 아랍어, 영어, 우크라이나어, 이탈리아어, 인도네시아어, 일본어, 중국어, 중국어(대만), 체코어, 카탈로니아어, 터키어, 페르시아어, 포르투갈어, 폴란드어, 프랑스어, 한국어, 히브리어 및 힌디어로 번역된 UI 문자열이 기본적으로 제공됩니다. 그리고 우리는 더 많은 기본 언어를 추가하는 데 기여하는걸 환영합니다.

i18n 데이터 컬렉션을 통해 지원하는 추가 언어에 대한 번역을 제공하거나 기본 라벨을 변경할 수 있습니다.

  1. 아직 구성되지 않은 경우 src/content.config.ts에서 i18n 데이터 컬렉션을 구성합니다.

    src/content.config.ts
    import { defineCollection } from 'astro:content';
    import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders';
    import { docsSchema, i18nSchema } from '@astrojs/starlight/schema';
    export const collections = {
    docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
    i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }),
    };
  2. src/content/i18n/에 UI 번역 문자열을 제공하려는 각 추가 언어에 대한 JSON 파일을 만듭니다. 예를 들어 다음은 아랍어 및 중국어 간체에 대한 번역 파일을 추가합니다.

    • 디렉터리src/
      • 디렉터리content/
        • 디렉터리i18n/
          • ar.json
          • zh-CN.json
  3. JSON 파일에서 키에 대한 번역을 추가합니다. 키는 영어로 남겨두고 값을 번역해야합니다. (예: "search.label": "Buscar")

    Starlight와 함께 제공되는 기존 문자열의 영어 기본값은 다음과 같습니다.

    {
    "skipLink.label": "Skip to content",
    "search.label": "Search",
    "search.ctrlKey": "Ctrl",
    "search.cancelLabel": "Cancel",
    "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.",
    "themeSelect.accessibleLabel": "Select theme",
    "themeSelect.dark": "Dark",
    "themeSelect.light": "Light",
    "themeSelect.auto": "Auto",
    "languageSelect.accessibleLabel": "Select language",
    "menuButton.accessibleLabel": "Menu",
    "sidebarNav.accessibleLabel": "Main",
    "tableOfContents.onThisPage": "On this page",
    "tableOfContents.overview": "Overview",
    "i18n.untranslatedContent": "This content is not available in your language yet.",
    "page.editLink": "Edit page",
    "page.lastUpdated": "Last updated:",
    "page.previousLink": "Previous",
    "page.nextLink": "Next",
    "page.draft": "This content is a draft and will not be included in production builds.",
    "404.text": "Page not found. Check the URL or try using the search bar.",
    "aside.note": "Note",
    "aside.tip": "Tip",
    "aside.caution": "Caution",
    "aside.danger": "Danger",
    "fileTree.directory": "Directory",
    "builtWithStarlight.label": "Built with Starlight"
    }

    Starlight의 코드 블록은 Expressive Code 라이브러리에 의해 구동됩니다. expressiveCode 키를 사용하여 동일한 JSON 파일에서 UI 문자열에 대한 번역을 설정할 수 있습니다.

    {
    "expressiveCode.copyButtonCopied": "Copied!",
    "expressiveCode.copyButtonTooltip": "Copy to clipboard",
    "expressiveCode.terminalWindowFallbackTitle": "Terminal window"
    }

    Starlight의 검색 모달은 Pagefind 라이브러리에 의해 구동됩니다. 동일한 JSON 파일에서 pagefind 키를 사용하여 Pagefind의 UI에 대한 번역을 설정할 수 있습니다.

    {
    "pagefind.clear_search": "Clear",
    "pagefind.load_more": "Load more results",
    "pagefind.search_label": "Search this site",
    "pagefind.filters_label": "Filters",
    "pagefind.zero_results": "No results for [SEARCH_TERM]",
    "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]",
    "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]",
    "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead",
    "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:",
    "pagefind.searching": "Searching for [SEARCH_TERM]..."
    }

번역 스키마 확장

i18nSchema() 옵션에서 extend를 설정하여 사이트 번역 사전에 맞춤 키를 추가하세요. 다음 예시에서는 기본 키에 새로운 선택적 custom.label 키가 추가됩니다.

src/content.config.ts
import { defineCollection, z } from 'astro:content';
import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders';
import { docsSchema, i18nSchema } from '@astrojs/starlight/schema';
export const collections = {
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
i18n: defineCollection({
loader: i18nLoader(),
schema: i18nSchema({
extend: z.object({
'custom.label': z.string().optional(),
}),
}),
}),
};

Astro 공식문서의 “컬렉션 스키마 정의”에서 콘텐츠 컬렉션 스키마에 대해 자세히 알아보세요.

UI 번역 사용

Starlight의 기본 제공 UI 문자열사용자 정의플러그인 제공 UI 문자열에 액세스할 수 있는 통합 API는 i18next로 구동됩니다. 여기에는 보간복수화와 같은 기능에 대한 지원이 포함됩니다.

Astro 컴포넌트에서 이 API는 전역 Astro 객체의 일부인 Astro.locals.t로 사용할 수 있습니다:

example.astro
<p dir={Astro.locals.t.dir()}>
{Astro.locals.t('404.text')}
</p>

엔드포인트에서도 API를 사용할 수 있으며, 여기서 locals 객체는 엔드포인트 컨텍스트의 일부로 사용할 수 있습니다:

src/pages/404.ts
export const GET = (context) => {
return new Response(context.locals.t('404.text'));
};

UI 문자열 렌더링

locals.t() 함수를 사용하여 UI 문자열을 렌더링합니다. 이것은 UI 문자열 키를 첫 번째 인수로 받아 현재 언어에 해당하는 번역을 반환하는 i18next의 t() 함수의 인스턴스입니다.

예를 들어 다음과 같은 콘텐츠가 포함된 사용자 정의 번역 파일이 있다고 가정해 보겠습니다:

src/content/i18n/en.json
{
"link.astro": "Astro documentation",
"link.astro.custom": "Astro documentation for {{feature}}"
}

첫 번째 UI 문자열은 t() 함수에 'link.astro'를 전달하여 렌더링할 수 있습니다:

src/components/Example.astro
<a href="https://docs.astro.build/">
{Astro.locals.t('link.astro')}
</a>
<!-- 렌더링: <a href="...">Astro documentation</a> -->

두 번째 UI 문자열은 {{feature}} 자리 표시자에 i18next의 보간 구문을 사용합니다. feature의 값은 t()의 두 번째 인수로 전달된 옵션 객체에서 설정되어야 합니다:

src/components/Example.astro
<a href="https://docs.astro.build/en/guides/astro-db/">
{Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })}
</a>
<!-- 렌더링: <a href="...">Astro documentation for Astro DB</a> -->

보간, 서식 지정 등과 함께 t() 함수를 사용하는 방법에 대한 자세한 내용은 i18next 문서를 참조하세요.

고급 API

t.all()

locals.t.all() 함수는 현재 로케일에서 사용 가능한 모든 UI 문자열이 포함된 객체를 반환합니다.

src/components/Example.astro
---
const allStrings = Astro.locals.t.all();
// ^
// {
// "skipLink.label": "Skip to content",
// "search.label": "Search",
// …
// }
---

t.exists()

로케일에 대한 번역 키가 존재하는지 확인하려면 번역 키를 첫 번째 인수로 전달하여 locals.t.exists() 함수를 사용합니다. 현재 로케일을 재정의해야 하는 경우 선택적 두 번째 인수를 전달합니다.

src/components/Example.astro
---
const keyExistsInCurrentLocale = Astro.locals.t.exists('a.key');
// ^ true
const keyExistsInFrench = Astro.locals.t.exists('another.key', { lng: 'fr' });
// ^ false
---

자세한 내용은 i18next 문서의 exists() 참조를 확인하세요.

t.dir()

locals.t.dir() 함수는 현재 또는 특정 로케일의 텍스트 방향을 반환합니다.

src/components/Example.astro
---
const currentDirection = Astro.locals.t.dir();
// ^
// 'ltr'
const arabicDirection = Astro.locals.t.dir('ar');
// ^
// 'rtl'
---

자세한 내용은 i18next 문서의 dir() 참조를 확인하세요.

현재 로케일에 액세스

Astro.currentLocale을 사용하여 .astro 컴포넌트의 현재 로케일을 읽을 수 있습니다.

다음 예시는 현재 로케일을 읽고 이를 getRelativeLocaleUrl() 헬퍼와 함께 사용하여 현재 언어로 된 소개 페이지 링크를 생성합니다:

src/components/AboutLink.astro
---
import { getRelativeLocaleUrl } from 'astro:i18n';
---
<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>소개</a>