PHPackages                             nvl/laravel-typescript-translations - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Localization &amp; i18n](/categories/localization)
4. /
5. nvl/laravel-typescript-translations

ActiveLibrary[Localization &amp; i18n](/categories/localization)

nvl/laravel-typescript-translations
===================================

Generate TypeScript type definitions from Laravel translation files

v1.0.4(9mo ago)0396↓50%MITPHPPHP ^8.2

Since Aug 11Pushed 9mo agoCompare

[ Source](https://github.com/nicolasvlachos/laravel-typescript-translations)[ Packagist](https://packagist.org/packages/nvl/laravel-typescript-translations)[ RSS](/packages/nvl-laravel-typescript-translations/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (5)Versions (5)Used By (0)

Laravel TypeScript Translations
===============================

[](#laravel-typescript-translations)

[![Latest Version on Packagist](https://camo.githubusercontent.com/173599ee82f8cc65931313f3585f5549013a964044adf657f25ffa7875036d86/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6e766c2f6c61726176656c2d747970657363726970742d7472616e736c6174696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/nvl/laravel-typescript-translations)[![Total Downloads](https://camo.githubusercontent.com/cba638f5737c71c71992a614035368698882f3410a7aec07670797a94c19b160/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6e766c2f6c61726176656c2d747970657363726970742d7472616e736c6174696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/nvl/laravel-typescript-translations)

Generate TypeScript types and translation data from Laravel translation files. **Load only what you need, when you need it.**

Table of Contents
-----------------

[](#table-of-contents)

- [The Problem This Solves](#the-problem-this-solves)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Understanding the Two Approaches](#understanding-the-two-approaches)
- [Mode Comparison](#mode-comparison)
- [Type Generation](#type-generation)
- [Translation Export](#translation-export)
- [Hook Usage](#hook-usage)
    - [use-inertia-translations (Backend)](#use-inertia-translations-backend)
    - [use-local-translations (Frontend)](#use-local-translations-frontend)
- [Laravel Integration](#laravel-integration)
- [Configuration Options](#configuration-options)
- [Performance](#performance)
- [License](#license)

The Problem This Solves
-----------------------

[](#the-problem-this-solves)

In Laravel + TypeScript apps, you typically have:

1. **Massive translation bundles** - Loading all translations for all languages on every page
2. **No type safety** - Typos in translation keys only discovered at runtime
3. **Poor performance** - Sending unused translations over the wire

This package solves all three by:

- Generating TypeScript types from your Laravel translations
- Exporting translation data in a modular, tree-shakeable format
- Providing hooks for both backend-driven and frontend-driven translations
- Enabling fine-grained control over what translations load where

Installation
------------

[](#installation)

```
composer require nvl/laravel-typescript-translations --dev
```

Publish the configuration:

```
php artisan vendor:publish --tag=typescript-translations-config
```

Quick Start
-----------

[](#quick-start)

```
# 1. Generate TypeScript types for backend translations
php artisan translations:generate --mode=module

# 2. Export translation data for frontend usage
php artisan translations:export --mode=module --organize-by=locale-mapped
```

Understanding the Two Approaches
--------------------------------

[](#understanding-the-two-approaches)

This package supports two distinct approaches for handling translations:

### 1. Backend-Driven (use-inertia-translations)

[](#1-backend-driven-use-inertia-translations)

- Server sends specific translations for current page
- Only current locale
- Smaller payload
- No client-side locale switching
- Type-safe with generated interfaces

### 2. Frontend-Driven (use-local-translations)

[](#2-frontend-driven-use-local-translations)

- Client loads translation modules
- All locales available
- Larger initial payload
- Dynamic locale switching
- Tree-shakeable modules

Mode Comparison
---------------

[](#mode-comparison)

### Type Generation Modes

[](#type-generation-modes)

ModeOutput StructureFile CountUse Case**Single**`translations.d.ts`1 fileSmall projects (&lt; 10 translation files)**Module**`vendors.types.d.ts`, `tasks.types.d.ts`1 per source**Recommended** - Balanced approach**Granular**`vendors/actions.types.d.ts`, `vendors/forms.types.d.ts`1 per fileLarge projects needing maximum control#### Single Mode Structure

[](#single-mode-structure)

```
// resources/js/types/translations.d.ts
export interface I18N {
  vendors: {
    actions: VendorsActionsI18N;
    forms: VendorsFormsI18N;
  };
  tasks: {
    actions: TasksActionsI18N;
    filters: TasksFiltersI18N;
  };
}
```

#### Module Mode Structure

[](#module-mode-structure)

```
// resources/js/types/translations/vendors.types.d.ts
export interface VendorsActionsI18N { create: string; edit: string; }
export interface VendorsFormsI18N { title: string; fields: {...} }
export interface VendorsI18N {
  actions: VendorsActionsI18N;
  forms: VendorsFormsI18N;
}
```

#### Granular Mode Structure

[](#granular-mode-structure)

```
resources/js/types/translations/
├── vendors/
│   ├── actions.types.d.ts    // Just VendorsActionsI18N
│   ├── forms.types.d.ts      // Just VendorsFormsI18N
│   └── index.d.ts
└── tasks/
    ├── actions.types.d.ts
    └── filters.types.d.ts

```

### Translation Export Modes

[](#translation-export-modes)

ModeOutput StructureBundle ImpactUse Case**Single**`translations.ts`No tree-shakingSmall projects**Module**`vendors.translations.ts` with multiple exportsGood tree-shaking**Recommended****Granular**`vendors/actions.ts`, `vendors/forms.ts`Best tree-shakingLarge projects#### Module Mode Exports

[](#module-mode-exports)

```
// resources/js/data/translations/vendors.translations.ts
export const VendorsActionsTranslations = {
  en: { create: 'Create', edit: 'Edit' },
  bg: { create: 'Създай', edit: 'Редактирай' }
} as const;

export const VendorsFormsTranslations = {
  en: { title: 'Vendor Form' },
  bg: { title: 'Форма за доставчик' }
} as const;
```

Type Generation
---------------

[](#type-generation)

Generate TypeScript types from your Laravel translations:

```
php artisan translations:generate [options]
```

### Options

[](#options)

OptionValuesDescription`--mode`single, module, granularOutput structure`--locale`en,bg,deSpecific locales to scan`--fresh`-Clear cache before generation`--debug`-Show detailed outputTranslation Export
------------------

[](#translation-export)

Export actual translation data for frontend usage:

```
php artisan translations:export [options]
```

### Options

[](#options-1)

OptionValuesDescription`--mode`single, module, granularFile structure`--organize-by`locale-mapped, locale, moduleHow to organize locales`--locale`en,bg,deSpecific locales only`--format`typescript, jsonOutput format`--output`path/to/dirCustom output directoryHook Usage
----------

[](#hook-usage)

### use-inertia-translations (Backend)

[](#use-inertia-translations-backend)

For server-driven translations passed via Inertia props:

```
import { useInertiaTranslations } from '@/hooks/use-inertia-translations';
import type { VendorsI18N } from '@/types/translations';

interface PageProps {
  vendor: Vendor;
  // Type-safe translation structure from backend
  translations: {
    vendors: Pick;
    common: { save: string; cancel: string; };
  };
}

function VendorEdit({ vendor }: PageProps) {
  // Hook automatically reads from Inertia page props
  const { t, locale } = useInertiaTranslations();

  return (

      {t('vendors.forms.title')}
      {t('common.save')}

      {/* TypeScript error if key doesn't exist */}
      {t('vendors.list.title')} {/* ❌ Error: 'list' not in type */}

  );
}
```

**Pros:**

- Minimal payload (only current locale, only needed keys)
- Type-safe with backend contract
- No unused translations sent

**Cons:**

- No client-side locale switching
- Requires backend changes for new translations

### use-local-translations (Frontend)

[](#use-local-translations-frontend)

For client-side translations with locale switching:

```
import { useLocalTranslations } from '@/hooks/use-local-translations';
import { VendorsFormsTranslations, VendorsActionsTranslations } from '@/data/translations/vendors.translations';

function VendorForm() {
  // Load translation modules with all locales
  const { t, locale, setLocale, availableLocales } = useLocalTranslations({
    forms: VendorsFormsTranslations,
    actions: VendorsActionsTranslations
  });

  return (

      {/* Dynamic locale switching */}
       setLocale(e.target.value)}>
        {availableLocales.map(loc => (
          {loc.toUpperCase()}
        ))}

      {t('forms.title')}
      {t('actions.save')}

  );
}
```

**Pros:**

- Client-side locale switching
- No backend changes needed
- Tree-shakeable (import only needed modules)

**Cons:**

- Larger bundle (all locales)
- All translations exposed to client

### Combining Both Approaches

[](#combining-both-approaches)

Use backend translations for initial render, client translations for dynamic features:

```
import { useInertiaTranslations } from '@/hooks/use-inertia-translations';
import { useLocalTranslations } from '@/hooks/use-local-translations';
import { CommonTranslations } from '@/data/translations/common.translations';

function HybridComponent() {
  // Server translations for page-specific content
  const { t: serverT } = useInertiaTranslations();

  // Client translations for dynamic UI elements
  const { t: clientT, setLocale } = useLocalTranslations({
    common: CommonTranslations
  });

  return (

      {/* Server-driven content */}
      {serverT('vendors.forms.title')}

      {/* Client-driven UI */}

  );
}
```

Laravel Integration
-------------------

[](#laravel-integration)

### Middleware (Global Translations)

[](#middleware-global-translations)

Only share truly global translations:

```
// app/Http/Middleware/HandleInertiaRequests.php
public function share(Request $request): array
{
    return array_merge(parent::share($request), [
        'locale' => app()->getLocale(),
        // ONLY navigation and layout translations
        'translations' => [
            'navigation' => trans('navigation'),
            'common' => [
                'logout' => trans('common.logout'),
                'profile' => trans('common.profile'),
            ]
        ]
    ]);
}
```

### Controllers (Page-Specific)

[](#controllers-page-specific)

Send only what the page needs:

```
// VendorController.php
public function index()
{
    return Inertia::render('Vendors/Index', [
        'vendors' => Vendor::paginate(),
        'translations' => [
            'vendors' => [
                'list' => trans('vendors.list'),
                'filters' => trans('vendors.filters'),
                'actions' => [
                    'create' => trans('vendors.actions.create'),
                    'export' => trans('vendors.actions.export'),
                ]
            ]
        ]
    ]);
}

public function edit(Vendor $vendor)
{
    return Inertia::render('Vendors/Edit', [
        'vendor' => $vendor,
        'translations' => [
            'vendors' => [
                'forms' => trans('vendors.forms'),
                'validation' => trans('vendors.validation'),
            ]
        ]
    ]);
}
```

Configuration Options
---------------------

[](#configuration-options)

### Complete Configuration Reference

[](#complete-configuration-reference)

```
