A powerful, intelligent translation system for SvelteKit with automatic type generation, runtime injection, tree-shaking, and build-time optimizations. Designed for maximum performance and developer experience with a highly optimized, modular codebase.
page.data
access for maximum performancenpm install sveltekit-translations-loader
// src/types/default-translations.ts
const defaultTranslations = {
hello: 'Hello (default)',
goodbye: 'Goodbye (default)',
welcome: 'Welcome, {{name}}!',
'user-count': 'There {{count}} users online',
'nested-params': 'Hello {{name}}, you have {{count}} messages',
layoutTitle: 'My App Layout',
pageContent: 'This is the page content'
} as const;
export default defaultTranslations;
// vite.config.ts
import { sveltekit } from '@sveltejs/kit/vite';
import { sveltekitTranslationsImporterPlugin } from 'sveltekit-translations-loader/plugin';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
sveltekitTranslationsImporterPlugin({
defaultPath: 'src/types/default-translations.ts',
runtimePath: 'src/types/translations/messages/index.ts',
verbose: false, // Set to true for detailed logging
removeFunctionsOnBuild: true // Enable production optimization
}), //---------------> IMPORTANT to be before sveltekit()
sveltekit()
]
});
// src/hooks.server.ts
import { TranslationsManager } from 'sveltekit-translations-loader/server';
import type { Handle } from '@sveltejs/kit';
const translationsManager = new TranslationsManager({
defaultTranslations: defaultTranslations,
getAvailableLocales: ['en-US', 'de-DE', 'es-ES', 'fr-FR'],
getTranslationsForLocale: async (locale) => {
// Custom translation loading logic
return await loadTranslationsForLocale(locale);
}
});
export const handle: Handle = async ({ event, resolve }) => {
// Initialize translations manager
await translationsManager.initialize();
// Detect locale from cookies, headers, or URL
const locale = event.cookies.get('locale') || 'en-US';
// Set up translations context
event.locals.translationsManager = translationsManager;
event.locals.locale = locale;
return resolve(event);
};
<!-- src/routes/+page.svelte -->
<script lang="ts">
import * as t from '@i18n';
import type { PageData } from './$types.js';
let { data }: { data: PageData } = $props();
</script>
<div>
<h1>{t.hello()}</h1>
<p>{t.welcome('Alice')}</p>
<p>{t.userCount(42)}</p>
<p>{t.nestedParams({ name: 'Bob', count: 5 })}</p>
</div>
interface PluginConfig {
/** Path to your default translations file */
defaultPath: string;
/** Path where generated runtime files will be stored */
runtimePath: string;
/** Enable detailed logging during build */
verbose?: boolean;
/**
* Enable production build optimization
* Removes @i18n imports and uses direct page.data access
* Only active during 'npm run build'
*/
removeFunctionsOnBuild?: boolean;
}
interface TranslationsManagerConfig {
/** Default translations or function to load them */
defaultTranslations:
| TranslationData
| (() => Promise<TranslationData>)
| Promise<{ default: TranslationData }>;
/** Available locales or function to get them */
getAvailableLocales: (() => Promise<string[]>) | string[];
/** Function to get translations for a specific locale */
getTranslationsForLocale: ((locale: string) => Promise<TranslationData>) | TranslationData;
}
npm run dev
)<script lang="ts">
import * as t from '@i18n';
</script>
<p>{t.hello()}</p><p>{t.welcome('User')}</p><p>{t.userCount(42)}</p>
Benefits:
npm run build
)When removeFunctionsOnBuild: true
is enabled, the build process automatically transforms your components:
<script lang="ts">
import { page } from '$app/state';
import { r } from '$lib/helpers';
</script>
<p>{page.data._loadedTranslations['hello']}</p>
<p>{r(page.data._loadedTranslations['welcome'], { name: 'User' })}</p>
<p>{r(page.data._loadedTranslations['user-count'], { count: 42 })}</p>
Benefits:
The plugin automatically scans your components and generates load functions with only the translations you actually use:
// src/routes/+page.server.ts (auto-generated)
import { injectTranslations } from 'sveltekit-translations-loader/server';
export const load = async ({ locals }) => {
const { translationsManager, locale } = locals;
// Only keys actually used in components
const translationKeys = ['hello', 'welcome', 'user-count'];
return {
...(await injectTranslations(translationsManager, locale, translationKeys))
};
};
// src/types/translations/
// βββ en-US.ts
// βββ de-DE.ts
// βββ es-ES.ts
// βββ fr-FR.ts
// de-DE.ts
export default {
hello: 'Hallo',
welcome: 'Willkommen, {{name}}!',
'user-count': 'Es gibt {{count}} Benutzer online'
};
<script lang="ts">
async function switchLanguage(locale: string) {
await fetch('/api/language', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ locale })
});
window.location.reload();
}
</script>
<select onchange={(e) => switchLanguage(e.target.value)}>
<option value="en-US">πΊπΈ English</option>
<option value="de-DE">π©πͺ Deutsch</option>
<option value="es-ES">πͺπΈ EspaΓ±ol</option>
<option value="fr-FR">π«π· FranΓ§ais</option>
</select>
Feature | Development | Production |
---|---|---|
Function Imports | β Included | β Removed |
Direct Data Access | β No | β Yes |
Parameter Wrapping | β Function calls | β Inline |
Type Safety | β Full | β Full |
The codebase has been optimized with a highly modular architecture:
src/lib/
βββ plugin/ # Vite plugin components
β βββ index.ts # Main plugin orchestrator
β βββ helpers.ts # Shared utility functions
β βββ scanner.ts # File scanning and analysis
β βββ function-generator.ts # Translation function generation
β βββ load-function-updater.ts # Load function injection
β βββ svelte-transformer.ts # Svelte file transformation
β βββ type-generator.ts # TypeScript declaration generation
βββ server/ # Server-side components
β βββ translationsManager.ts # Translation management
β βββ translations-injector.ts # Server-side injection
βββ helpers/ # Client-side utilities
βββ utils.ts # Runtime helper functions
// Single parameter (auto-wrapped)
t.welcome('Alice');
// Transforms to: r(translations['welcome'], { name: 'Alice' })
// Multiple parameters (object)
t.nestedParams({ name: 'Bob', count: 5 });
// Transforms to: r(translations['nested-params'], { name: 'Bob', count: 5 })
// Parent layout translations are inherited by child routes
// src/routes/+layout.server.ts β ['layoutTitle', 'navigation']
// src/routes/dashboard/+page.server.ts β ['pageTitle', 'content']
// Result: Child has access to all parent + own translations
const manager = new TranslationsManager({
defaultTranslations: defaultTranslations,
getAvailableLocales: ['en-US', 'custom'],
getTranslationsForLocale: async (locale) => {
// Custom loading logic
const translations = await fetchFromAPI(locale);
return translations;
}
});
// From '@i18n'
import * as t from '@i18n';
// Individual translation functions (auto-generated)
t.hello(): string
t.welcome(name: string): string
t.userCount(count: number): string
t.nestedParams(params: { name: string; count: number }): string
// From '$lib/helpers'
import { getTData, r } from '$lib/helpers';
// Get current translation data
const translations = getTData();
// Parameter replacement function
const result = r('Hello {{name}}', { name: 'World' });
// From 'sveltekit-translations-loader/server'
import { TranslationsManager, injectTranslations } from 'sveltekit-translations-loader/server';
// Translation manager for server-side operations
const manager = new TranslationsManager(config);
// Inject translations into load functions
await injectTranslations(manager, locale, keys);
# Clone the repository
git clone https://github.com/yourusername/sveltekit-translations-loader.git
# Install dependencies
npm install
# Build the library
npm run build
# Run tests
npm run test:unit
# Type checking
npm run check
git checkout -b feature/amazing-feature
)git commit -m 'Add amazing feature'
)git push origin feature/amazing-feature
)removeFunctionsOnBuild
option for production performanceMIT License - see LICENSE file for details.
Made with β€οΈ for the SvelteKit community