Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI
История версий
- "Обновление использования API useIntlayer в Solid для прямого доступа к свойствам"v8.9.004.05.2026
- "Добавить команду init"v7.5.930.12.2025
- "Инициализация истории"v5.5.1029.06.2025
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомЕсли у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHubКопировать Markdown документа в буфер обмена
Переведите ваш сайт на Vite и Preact с помощью Intlayer | Интернационализация (i18n)
Содержание
Что такое Intlayer?
Intlayer, это инновационная библиотека интернационализации (i18n) с открытым исходным кодом, разработанная для упрощения поддержки многоязычности в современных веб-приложениях.
С Intlayer вы можете:
- Легко управлять переводами с помощью декларативных словарей на уровне компонентов.
- Динамически локализовать метаданные, маршруты и контент.
- Обеспечить поддержку TypeScript с помощью автоматически генерируемых типов, улучшающих автодополнение и обнаружение ошибок.
- Пользоваться расширенными функциями, такими как динамическое определение локали и переключение языков.
Пошаговое руководство по настройке Intlayer в приложении на Vite и Preact
См. Шаблон приложения на GitHub.
Шаг 1: Установка зависимостей
Установите необходимые пакеты с помощью npm:
Копировать код в буфер обмена
npm install intlayer preact-intlayernpm install vite-intlayer --save-devnpx intlayer initintlayer
Основной пакет, предоставляющий инструменты интернационализации для управления конфигурацией, перевода, объявления контента, компиляции и CLI-команд.
preact-intlayer
Пакет, который интегрирует Intlayer с приложением на Preact. Он предоставляет провайдеры контекста и хуки для интернационализации Preact.
vite-intlayer
Включает плагин Vite для интеграции Intlayer с сборщиком Vite, а также промежуточное ПО для определения предпочтительной локали пользователя, управления куки и обработки перенаправления URL.
Шаг 2: Конфигурация вашего проекта
Создайте файл конфигурации для настройки языков вашего приложения:
Копировать код в буфер обмена
import { Locales, type IntlayerConfig } from "intlayer";
const config: IntlayerConfig = {
internationalization: {
locales: [
Locales.ENGLISH,
Locales.FRENCH,
Locales.SPANISH,
// Ваши другие локали
],
defaultLocale: Locales.ENGLISH,
},
routing: {
mode: "prefix-no-default", // По умолчанию: префикс для всех локалей, кроме основной
storage: ["cookie", "header"], // По умолчанию: хранение локали в куки и определение из заголовка
},
};
export default config;Через этот конфигурационный файл вы можете настроить локализованные URL, режимы маршрутизации, параметры хранения, имена куки, расположение и расширение ваших объявлений контента, отключить логи Intlayer в консоли и многое другое. Полный список доступных параметров см. в документации по конфигурации.
Шаг 3: Интеграция Intlayer в конфигурацию Vite
Добавьте плагин intlayer в вашу конфигурацию.
Копировать код в буфер обмена
import { defineConfig } from "vite";
import preact from "@preact/preset-vite";
import { intlayer } from "vite-intlayer";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [preact(), intlayer()],
});Плагин Vite intlayer() используется для интеграции Intlayer с Vite. Он обеспечивает сборку файлов объявлений контента и отслеживает их в режиме разработки. Он определяет переменные окружения Intlayer внутри приложения Vite. Кроме того, он предоставляет алиасы для оптимизации производительности.
Шаг 4: Объявление контента
Создайте и управляйте своими объявлениями контента для хранения переводов:
Копировать код в буфер обмена
import { t, type Dictionary } from "intlayer";
import type { ComponentChildren } from "preact";
const appContent = {
key: "app",
content: {
viteLogo: t({
en: "Vite logo",
fr: "Logo Vite",
es: "Logo Vite",
}),
preactLogo: t({
en: "Preact logo",
fr: "Logo Preact",
es: "Logo Preact",
}),
title: "Vite + Preact",
count: t({
en: "count is ",
fr: "le compte est ",
es: "el recuento es ",
}),
edit: t<ComponentChildren>({
en: (
<>
Edit <code>src/app.tsx</code> and save to test HMR
</>
),
fr: (
<>
Éditez <code>src/app.tsx</code> et enregistrez pour tester HMR
</>
),
es: (
<>
Edita <code>src/app.tsx</code> y guarda para probar HMR
</>
),
}),
readTheDocs: t({
en: "Click on the Vite and Preact logos to learn more",
fr: "Cliquez sur les logos Vite et Preact pour en savoir plus",
es: "Haga clic en los logotipos de Vite y Preact para obtener más información",
}),
},
} satisfies Dictionary;
export default appContent;Ваши объявления контента могут быть определены в любом месте вашего приложения, при условии, что они включены в каталогcontentDir(по умолчанию./src). И соответствуют расширению файла объявлений контента (по умолчанию.content.{json,ts,tsx,js,jsx,mjs,cjs}).
Подробнее см. в документации по объявлению контента.
Если ваш файл контента содержит код TSX, вам может потребоваться импортировать import { h } from "preact"; или убедиться, что ваша JSX прагма правильно настроена для Preact.
Шаг 5: Использование Intlayer в коде
Получайте доступ к вашим словарям контента по всему приложению:
Копировать код в буфер обмена
import { useState } from "preact/hooks";
import type { FunctionalComponent } from "preact";
import preactLogo from "./assets/preact.svg"; // Предполагается, что у вас есть preact.svg
import viteLogo from "/vite.svg";
import "./app.css"; // Предполагается, что ваш CSS-файл называется app.css
import { IntlayerProvider, useIntlayer } from "preact-intlayer";
const AppContent: FunctionalComponent = () => {
const [count, setCount] = useState(0);
const content = useIntlayer("app");
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} class="logo" alt={content.viteLogo.value} />
</a>
<a href="https://preactjs.com" target="_blank">
<img
src={preactLogo}
class="logo preact"
alt={content.preactLogo.value}
/>
</a>
</div>
<h1>{content.title}</h1>
<div class="card">
<button onClick={() => setCount((count) => count + 1)}>
{content.count}
{count}
</button>
<p>{content.edit}</p>
</div>
{/* Markdown контент */}
<div>{content.myMarkdownContent}</div>
{/* HTML контент */}
<div>{content.myHtmlContent}</div>
<p class="read-the-docs">{content.readTheDocs}</p>
</>
);
};
const App: FunctionalComponent = () => (
<IntlayerProvider>
<AppContent />
</IntlayerProvider>
);
export default App;Если вы хотите использовать свой контент в строковом атрибуте, таком как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)}" />
Примечание: В PreactclassNameобычно пишется какclass.
Чтобы узнать больше о хукеuseIntlayer, обратитесь к документации (API дляpreact-intlayerаналогично).
Если ваше приложение уже существует, вы можете использовать Intlayer Compiler в сочетании с командой extract, чтобы преобразовать тысячи компонентов за одну секунду.
(Необязательно) Шаг 6: Изменение языка контента
Для изменения языка контента вы можете использовать функцию setLocale, предоставляемую хуком useLocale. Эта функция позволяет установить локаль приложения и обновить контент соответствующим образом.
Копировать код в буфер обмена
import type { FunctionalComponent } from "preact";
import { Locales } from "intlayer";
import { useLocale } from "preact-intlayer";
const LocaleSwitcher: FunctionalComponent = () => {
const { setLocale } = useLocale();
return (
<button onClick={() => setLocale(Locales.ENGLISH)}>
Change Language to English
</button>
);
};
export default LocaleSwitcher;Чтобы узнать больше о хукеuseLocale, обратитесь к документации (API дляpreact-intlayerаналогично).
(Необязательно) Шаг 7: Добавьте локализованную маршрутизацию в ваше приложение
Цель этого шага, создать уникальные маршруты для каждого языка. Это полезно для SEO и создания дружественных к поисковым системам URL. Пример:
Копировать код в буфер обмена
- https://example.com/about- https://example.com/es/about- https://example.com/fr/aboutПо умолчанию маршруты не имеют префикса для основной локали. Если вы хотите добавить префикс для основной локали, вы можете установить опциюrouting.modeв значение"prefix-all"в вашей конфигурации. См. документацию по конфигурации для получения дополнительной информации.
Чтобы добавить локализованную маршрутизацию в ваше приложение, вы можете создать компонент LocaleRouter, который оборачивает маршруты вашего приложения и обрабатывает маршрутизацию на основе локали. Вот пример использования preact-iso:
Копировать код в буфер обмена
import { localeMap } from "intlayer";
import { IntlayerProvider } from "preact-intlayer";
import { LocationProvider, Router, Route } from "preact-iso";
import type { ComponentChildren, FunctionalComponent } from "preact";
/**
* Компонент маршрутизатора, который настраивает маршруты с учетом локали.
* Использует preact-iso для управления навигацией и рендеринга локализованных компонентов.
*/
export const LocaleRouter: FunctionalComponent<{
children: ComponentChildren;
}> = ({ children }) => (
<LocationProvider>
<Router>
{localeMap(({ locale, urlPrefix }) => ({ locale, urlPrefix }))
.sort((a, b) => b.urlPrefix.length - a.urlPrefix.length)
.map(({ locale, urlPrefix }) => (
<Route
key={locale}
path={`${urlPrefix}/:rest*`}
component={() => (
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
)}
/>
))}
</Router>
</LocationProvider>
);Затем вы можете использовать компонент LocaleRouter в своем приложении:
Копировать код в буфер обмена
import { LocaleRouter } from "./components/LocaleRouter";
import type { FunctionalComponent } from "preact";
// ... Ваш компонент AppContent
const App: FunctionalComponent = () => (
<LocaleRouter>
<AppContent />
</LocaleRouter>
);
export default App;(Необязательно) Шаг 8: Изменяйте URL при смене локали
Чтобы изменить URL при смене локали, вы можете использовать проп onLocaleChange, предоставляемый хуком useLocale. Параллельно вы можете использовать метод route из useLocation библиотеки preact-iso для обновления пути URL.
Копировать код в буфер обмена
import { useLocation } from "preact-iso";
import {
Locales,
getHTMLTextDir,
getLocaleName,
getLocalizedUrl,
} from "intlayer";
import { useLocale } from "preact-intlayer";
import type { FunctionalComponent } from "preact";
const LocaleSwitcher: FunctionalComponent = () => {
const { url, route } = useLocation();
const { locale, availableLocales, setLocale } = useLocale({
onLocaleChange: (newLocale) => {
// Создаем URL с обновленной локалью
// Пример: /es/about?foo=bar
const pathWithLocale = getLocalizedUrl(url, newLocale);
// Обновляем путь URL
route(pathWithLocale, true); // true для замены (replace)
},
});
return (
<div>
<button popovertarget="localePopover">{getLocaleName(locale)}</button>
<div id="localePopover" popover="auto">
{availableLocales.map((localeItem) => (
<a
href={getLocalizedUrl(url, localeItem)}
hreflang={localeItem}
aria-current={locale === localeItem ? "page" : undefined}
onClick={(e) => {
e.preventDefault();
setLocale(localeItem);
// Программная навигация после смены локали будет обработана в onLocaleChange
}}
key={localeItem}
>
<span>
{/* Локаль, например, FR */}
{localeItem}
</span>
<span>
{/* Язык на самой локали, например, Français */}
{getLocaleName(localeItem, localeItem)}
</span>
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
{/* Язык на текущей локали, например, Francés, если текущая локаль Locales.SPANISH */}
{getLocaleName(localeItem, locale)}
</span>
<span dir="ltr" lang={Locales.ENGLISH}>
{/* Язык на английском, например, French */}
{getLocaleName(localeItem, Locales.ENGLISH)}
</span>
</a>
))}
</div>
</div>
);
};
export default LocaleSwitcher;Ссылки на документацию:
- ХукuseLocale(API дляpreact-intlayerаналогично)> - ХукgetLocaleName> - ХукgetLocalizedUrl> - ХукgetHTMLTextDir> - Атрибутhreflang> - Атрибутlang> - Атрибутdir> - Атрибутaria-current> - Popover API
(Необязательно) Шаг 9: Переключайте атрибуты языка и направления HTML
Когда ваше приложение поддерживает несколько языков, крайне важно обновлять атрибуты lang и dir тега <html>, чтобы они соответствовали текущей локали. Это обеспечивает:
- Доступность: Экранные дикторы и вспомогательные технологии полагаются на правильный атрибут
langдля точного произношения и интерпретации контента. - Отображение текста: Атрибут
dir(direction) гарантирует, что текст отображается в правильном порядке (например, слева направо для английского, справа налево для арабского или иврита), что важно для удобочитаемости. - SEO: Поисковые системы используют атрибут
langдля определения языка вашей страницы, помогая показывать правильный локализованный контент в результатах поиска.
Обновляя эти атрибуты динамически при изменении локали, вы гарантируете согласованный и доступный опыт для пользователей на всех поддерживаемых языках.
Реализация хука
Создайте пользовательский хук для управления атрибутами HTML. Хук прослушивает изменения локали и соответствующим образом обновляет атрибуты:
Копировать код в буфер обмена
import { useEffect } from "preact/hooks";
import { useLocale } from "preact-intlayer";
import { getHTMLTextDir } from "intlayer";
/**
* Обновляет атрибуты `lang` и `dir` HTML-элемента <html> на основе текущей локали.
* - `lang`: Информирует браузеры и поисковые системы о языке страницы.
* - `dir`: Обеспечивает правильный порядок чтения (например, 'ltr' для английского, 'rtl' для арабского).
*
* Это динамическое обновление необходимо для правильного отображения текста, доступности и SEO.
*/
export const useI18nHTMLAttributes = () => {
const { locale } = useLocale();
useEffect(() => {
// Обновляет атрибут языка на текущую локаль.
document.documentElement.lang = locale;
// Устанавливает направление текста на основе текущей локали.
document.documentElement.dir = getHTMLTextDir(locale);
}, [locale]);
};Использование хука в вашем приложении
Интегрируйте хук в свой основной компонент, чтобы атрибуты HTML обновлялись при каждом изменении локали:
Копировать код в буфер обмена
import type { FunctionalComponent } from "preact";
import { IntlayerProvider } from "preact-intlayer"; // useIntlayer уже импортирован, если AppContent его требует
import { useI18nHTMLAttributes } from "./hooks/useI18nHTMLAttributes";
import "./app.css";
// Определение AppContent из Шага 5
const AppWithHooks: FunctionalComponent = () => {
// Применяем хук для обновления атрибутов lang и dir тега <html> в зависимости от локали.
useI18nHTMLAttributes();
// Предполагается, что AppContent, это ваш основной компонент отображения контента из Шага 5
return <AppContent />;
};
const App: FunctionalComponent = () => (
<IntlayerProvider>
<AppWithHooks />
</IntlayerProvider>
);
export default App;(Необязательно) Шаг 10: Создание компонента локализованной ссылки
Чтобы навигация в вашем приложении учитывала текущую локаль, вы можете создать пользовательский компонент Link. Этот компонент автоматически добавляет префикс текущего языка к внутренним URL.
Это поведение полезно по нескольким причинам:
- SEO и пользовательский опыт: Локализованные URL помогают поисковым системам правильно индексировать страницы на разных языках и предоставляют пользователям контент на их предпочтительном языке.
- Последовательность: Используя локализованную ссылку во всем приложении, вы гарантируете, что навигация остается в пределах текущей локали, предотвращая неожиданные переключения языка.
- Поддерживаемость: Централизация логики локализации в одном компоненте упрощает управление URL.
Ниже приведена реализация компонента локализованной ссылки Link в Preact:
Копировать код в буфер обмена
import { getLocalizedUrl } from "intlayer";
import { useLocale } from "preact-intlayer";
import { forwardRef } from "preact/compat";
import type { JSX } from "preact";
export interface LinkProps extends JSX.HTMLAttributes<HTMLAnchorElement> {
href: string;
}
/**
* Вспомогательная функция для проверки, является ли данный URL внешним.
* Если URL начинается с http:// или https://, он считается внешним.
*/
export const checkIsExternalLink = (href?: string): boolean =>
/^https?:\/\//.test(href ?? "");
/**
* Пользовательский компонент Link, который адаптирует атрибут href в зависимости от текущей локали.
* Для внутренних ссылок он использует `getLocalizedUrl`, чтобы добавить префикс локали к URL (например, /fr/about).
* Это гарантирует, что навигация остается в контексте той же локали.
*/
export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
({ href, children, ...props }, ref) => {
const { locale } = useLocale();
const isExternalLink = checkIsExternalLink(href);
// Если ссылка внутренняя и предоставлен валидный href, получаем локализованный URL.
const hrefI18n =
href && !isExternalLink ? getLocalizedUrl(href, locale) : href;
return (
<a href={hrefI18n} ref={ref} {...props}>
{children}
</a>
);
}
);
Link.displayName = "Link";Как это работает
- Определение внешних ссылок:
Вспомогательная функцияcheckIsExternalLinkопределяет, является ли URL внешним. Внешние ссылки остаются без изменений, так как они не нуждаются в локализации. - Получение текущей локали:
ХукuseLocaleпредоставляет текущую локаль (например,frдля французского). - Локализация URL:
Для внутренних ссылок (т. е. не внешних) используетсяgetLocalizedUrlдля автоматического добавления префикса текущей локали к URL. Это означает, что если ваш пользователь использует французский язык, передача/aboutв качествеhrefпреобразует его в/fr/about. - Возврат ссылки:
Компонент возвращает элемент<a>с локализованным URL, гарантируя, что навигация соответствует локали.
(Необязательно) Шаг 11: Рендеринг Markdown и HTML
Intlayer поддерживает рендеринг контента в форматах Markdown и HTML в Preact.
Вы можете настроить рендеринг контента Markdown и HTML с помощью метода .use(). Этот метод позволяет переопределить стандартный рендеринг определенных тегов.
Копировать код в буфер обмена
import { useIntlayer } from "preact-intlayer";const { myMarkdownContent, myHtmlContent } = useIntlayer("my-component");// ...return ( <div> {/* Базовый рендеринг */} {myMarkdownContent} {/* Пользовательский рендеринг для Markdown */} {myMarkdownContent.use({ h1: (props) => <h1 style={{ color: "red" }} {...props} />, })} {/* Базовый рендеринг для HTML */} {myHtmlContent} {/* Пользовательский рендеринг для HTML */} {myHtmlContent.use({ b: (props) => <strong style={{ color: "blue" }} {...props} />, })} </div>);Настройка TypeScript
Intlayer использует расширение модулей (module augmentation) для получения преимуществ TypeScript и усиления вашей кодовой базы.


Убедитесь, что ваша конфигурация TypeScript включает автоматически генерируемые типы.
Копировать код в буфер обмена
{ // ... Ваши существующие конфигурации TypeScript "compilerOptions": { // ... "jsx": "react-jsx", "jsxImportSource": "preact", // Рекомендуется для Preact 10+ // ... }, "include": [ // ... Ваши существующие конфигурации TypeScript ".intlayer/**/*.ts", // Включить автоматически генерируемые типы ],}Убедитесь, что вашtsconfig.jsonнастроен для Preact, особенноjsxиjsxImportSourceилиjsxFactory/jsxFragmentFactoryдля старых версий Preact, если вы не используете настройки по умолчаниюpreset-vite.
Конфигурация Git
Рекомендуется игнорировать файлы, генерируемые Intlayer. Это позволит избежать их фиксации в вашем Git-репозитории.
Для этого вы можете добавить следующие инструкции в ваш файл .gitignore:
Копировать код в буфер обмена
# Игнорировать файлы, генерируемые Intlayer.intlayerРасширение VS Code
Для улучшения опыта разработки с Intlayer вы можете установить официальное расширение Intlayer для VS Code.
Установить из VS Code Marketplace
Это расширение предоставляет:
- Автодополнение ключей перевода.
- Обнаружение ошибок в реальном времени для отсутствующих переводов.
- Встроенный предпросмотр переведенного контента.
- Быстрые действия для удобного создания и обновления переводов.
Для получения более подробной информации о том, как использовать расширение, обратитесь к документации по расширению Intlayer для VS Code.
(Опционально) Шаг 1 : Извлечение содержимого ваших компонентов
Если у вас есть существующая кодовая база, преобразование тысяч файлов может занять много времени.
Чтобы упростить этот процесс, Intlayer предлагает компилятор / экстрактор для преобразования ваших компонентов и извлечения содержимого.
Чтобы настроить его, вы можете добавить раздел 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;Запустите экстрактор для преобразования компонентов и извлечения содержимого
Копировать код в буфер обмена
npx intlayer extract(Опционально) Sitemap и robots.txt (генерация на сборке)
Intlayer предоставляет generateSitemap и getMultilingualUrls - утилиты, которые формируют многоязычные sitemap.xml и robots.txt для краулеров и позволяют автоматически записать их в public/. Обычно запускают небольшой Node-скрипт до Vite (например, npm-хуки predev / prebuild).
Sitemap
Генератор sitemap учитывает локали и добавляет нужные метаданные.
Поддерживается пространство имёнxhtml:link(hreflang). Вместо плоского списка URL Intlayer связывает все языковые версии страницы в обе стороны (например/about,/fr/aboutили/about?lang=frв зависимости от режима маршрутизации).
Robots.txt
Используйте getMultilingualUrls, чтобы правила Disallow покрывали все локализованные варианты путей.
1. Файл generate-seo.mjs в корне проекта
Копировать код в буфер обмена
import fs from "fs";import path from "path";import { fileURLToPath } from "url";import { generateSitemap, getMultilingualUrls } from "intlayer";const __dirname = path.dirname(fileURLToPath(import.meta.url));const SITE_URL = (process.env.SITE_URL || "http://localhost:5173").replace( /\/$/, "");const pathList = [ { path: "/", changefreq: "daily", priority: 1.0 }, { path: "/about", changefreq: "monthly", priority: 0.7 },];const sitemapXml = generateSitemap(pathList, { siteUrl: SITE_URL });fs.writeFileSync(path.join(__dirname, "public", "sitemap.xml"), sitemapXml);const getAllMultilingualUrls = (urls) => urls.flatMap((url) => Object.values(getMultilingualUrls(url)));const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);const robotsTxt = [ "User-agent: *", "Allow: /", ...disallowedPaths.map((path) => `Disallow: ${path}`), "", `Sitemap: ${SITE_URL}/sitemap.xml`,].join("\n");fs.writeFileSync(path.join(__dirname, "public", "robots.txt"), robotsTxt);console.log("SEO files generated successfully.");Пакет intlayer должен быть установлен. Для продакшена задайте SITE_URL в окружении (например в CI).
Для Node ESM предпочтительноgenerate-seo.mjs. Дляgenerate-seo.jsукажите"type": "module"вpackage.jsonили включите ESM иначе.
2. Запуск скрипта до Vite
Копировать код в буфер обмена
{ "scripts": { "dev": "vite", "prebuild": "node generate-seo.mjs", "build": "vite build", "preview": "vite preview" }}Подстройте команды для pnpm или yarn. Скрипт можно вызывать из CI или другого шага.
Продвигайтесь дальше
Чтобы продвинуться дальше, вы можете реализовать визуальный редактор или вынести ваш контент вовне с помощью CMS.