PHPackages                             johannhsdev/octolang - 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. johannhsdev/octolang

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

johannhsdev/octolang
====================

A elegant Laravel package for managing application locales — OctoLang

v1.0.0(2w ago)02↓100%MITPHPPHP ^8.2|^8.4CI failing

Since May 25Pushed 2w agoCompare

[ Source](https://github.com/johannhsdev/octolang)[ Packagist](https://packagist.org/packages/johannhsdev/octolang)[ RSS](/packages/johannhsdev-octolang/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (7)Versions (2)Used By (0)

OctoLang 🐙
==========

[](#octolang-)

OctoLang is a Laravel package for managing language switching in a simple, explicit way — with a ready-to-use visual switcher and a safe uninstall process.

It is primarily designed for Blade projects, but also works with Livewire, Vue, React, and Svelte when Laravel remains the source of truth for the active locale.

What the package does
---------------------

[](#what-the-package-does)

OctoLang includes:

- A `LocaleManager` service to store and resolve the active locale from the session
- A `SetLocale` middleware that applies the active language on every request
- A `POST` route for safely switching languages
- A Blade component: ``
- Install, status, and uninstall Artisan commands
- An internal manifest to remove only what OctoLang created or modified

During installation, OctoLang may create or update the following resources depending on the detected stack:

ResourceBladeLivewireVueReactSvelte`resources/views/welcome.blade.php` (injection)✓✓———`resources/css/octolang.css`✓✓✓✓✓`resources/css/app.css` (`@import`)✓✓✓✓✓`resources/views/vendor/octolang/components/locale-switcher.blade.php`✓————`resources/views/vendor/octolang/livewire/octo-lang-switch.blade.php`—✓———`resources/js/components/octolang/OctoLangSwitch.vue` + `useOctoLang.ts`——✓——`resources/js/components/octolang/LocaleSwitcher.tsx` + `useOctoLang.ts`———✓—`resources/js/components/octolang/OctoLangSwitch.svelte`————✓`resources/js/stores/useOctoLang.ts`————✓`lang/en/messages.php` and `lang/es/messages.php`✓✓✓✓✓`storage/app/octolang/install.json`✓✓✓✓✓Requirements
------------

[](#requirements)

- PHP `^8.2|^8.4`
- Laravel `^11.0|^12.0|^13.0`

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

[](#installation)

### 1. Install via Composer

[](#1-install-via-composer)

```
composer require johannhsdev/octolang
```

### 2. Run the OctoLang installer

[](#2-run-the-octolang-installer)

After `composer require`, run:

```
php artisan octolang:install
php artisan optimize:clear
```

If your project uses Vite, rebuild the assets:

```
npm run dev
```

or:

```
npm run build
```

What `php artisan octolang:install` does
----------------------------------------

[](#what-php-artisan-octolanginstall-does)

The install command runs the package setup explicitly. It does not run automatically on every request.

This command:

1. Copies `lang/en/messages.php` and `lang/es/messages.php` only if those files do not exist
2. Copies `resources/views/vendor/octolang/components/locale-switcher.blade.php` if needed
3. Copies `resources/css/octolang.css` if needed
4. Adds `@import "./octolang.css";` to `resources/css/app.css` if the file exists and does not already contain that line
5. Processes `resources/views/welcome.blade.php`
6. Records created files and tracked changes in `storage/app/octolang/install.json`

Available commands
------------------

[](#available-commands)

### `php artisan octolang:install`

[](#php-artisan-octolanginstall)

Use it after installing the package with Composer.

When to use:

- when installing OctoLang for the first time
- when you want to regenerate missing package resources
- when you want OctoLang to process the `welcome` view

### `php artisan octolang:status`

[](#php-artisan-octolangstatus)

Shows the files and mutations that OctoLang has on record.

When to use:

- when you want to audit what OctoLang created
- when you want to know what `octolang:uninstall` will be able to remove

### `php artisan octolang:uninstall`

[](#php-artisan-octolanguninstall)

Removes only the files and changes that OctoLang has on record.

When to use:

- when you want to tear down the package before running `composer remove`
- when you are testing the install/uninstall flow

Recommended uninstall flow:

```
php artisan octolang:uninstall
composer remove johannhsdev/octolang
```

Configuration
-------------

[](#configuration)

To edit the configuration manually, publish it with:

```
php artisan vendor:publish --tag=octolang-config
```

Default configuration:

```
return [
    'supported' => array_filter(
        explode(',', env('LOCALE_SUPPORTED', 'es,en'))
    ),
    'session_key' => env('LOCALE_SESSION_KEY', 'locale'),
    'route_name' => 'locale.store',
    'route_uri' => '/locale',
    'route_middleware' => ['web'],
];
```

### `.env` example

[](#env-example)

```
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US

LOCALE_SUPPORTED=en,es,fr,de
LOCALE_SESSION_KEY=locale
```

Important notes:

- `APP_LOCALE` is the source of truth for OctoLang's initial language.
- `LOCALE_SESSION_KEY` only changes the key used in `session()`.
- `APP_FALLBACK_LOCALE` remains Laravel's responsibility for missing translations.
- `APP_FAKER_LOCALE` only affects Faker and does not participate in the app's visible language.
- `LOCALE_SUPPORTED` validates changes made from the switcher, but does not replace or reorder the base `APP_LOCALE`.

Supported languages
-------------------

[](#supported-languages)

OctoLang validates language changes against `locale.supported`.

To add more languages, update your config or `.env`:

```
LOCALE_SUPPORTED=en,es,fr,pt,de,it
```

Then create your translation files:

```
lang/
  en/
    messages.php
  es/
    messages.php
  fr/
    messages.php

```

Example:

```
// lang/en/messages.php
return [
    'welcome'   => 'Welcome',
    'dashboard' => 'Dashboard',
    'settings'  => 'Settings',
];
```

```
// lang/es/messages.php
return [
    'welcome'   => 'Bienvenido',
    'dashboard' => 'Panel',
    'settings'  => 'Configuración',
];
```

How language switching works
----------------------------

[](#how-language-switching-works)

OctoLang saves the selected language in the session and applies it via middleware.

Flow:

1. The user sends a locale to the OctoLang route
2. `LocaleController` validates the locale against `locale.supported`
3. `LocaleManager` saves it in the session
4. `SetLocale` calls `App::setLocale(...)` on the next request, using `APP_LOCALE` as the base
5. Laravel resolves translations using the active locale

When the user switches to a language other than the default, OctoLang pins it in the session. When they switch back to the default, OctoLang clears that session key so the app follows `APP_LOCALE` again.

In the visual switcher, the active language is always shown as active in both cases. When the active locale comes from the app default rather than a saved preference, OctoLang adds a subtle visual indicator to signal that the language is following the base configuration.

Usage in Blade
--------------

[](#usage-in-blade)

### Adding the switcher

[](#adding-the-switcher)

You can place the component in any Blade view:

```

```

Example in a navbar:

```

        {{ config('app.name') }}

        {{ __('messages.dashboard') }}
        {{ __('messages.profile') }}

```

Example in a sidebar:

```

        {{ __('messages.dashboard') }}
        {{ __('messages.settings') }}
        {{ __('messages.users') }}

```

### Using translations in Blade views

[](#using-translations-in-blade-views)

Use Laravel's standard translation helpers:

```
{{ __('messages.welcome') }}
{{ __('messages.dashboard_description') }}
```

With replacements:

```
{{ __('messages.greeting', ['name' => $user->name]) }}
```

Pluralization:

```
{{ trans_choice('messages.notifications', $count, ['count' => $count]) }}
```

### Package translation keys

[](#package-translation-keys)

OctoLang also exposes namespaced keys:

```
{{ __('octolang::messages.switcher.label') }}
{{ __('octolang::messages.switcher.tooltip') }}
```

In your regular views, prefer your own application keys like `__('messages.welcome')`.

Usage in Livewire
-----------------

[](#usage-in-livewire)

OctoLang includes a native Livewire v3 component: ``.

It registers automatically when Livewire is installed. No extra backend setup required.

### What `octolang:install` sets up in a Livewire project

[](#what-octolanginstall-sets-up-in-a-livewire-project)

When Livewire is detected, the command creates:

- `resources/views/vendor/octolang/livewire/octo-lang-switch.blade.php` — publishable component view
- `resources/css/octolang.css` and the import in `app.css`
- Injects `` into `welcome.blade.php` without replacing its content

> In Livewire projects, `components/locale-switcher.blade.php` is **not** copied — that file belongs to the pure Blade stack only.

### Adding the switcher

[](#adding-the-switcher-1)

Place the component in any Blade view within your Livewire app:

```

```

Example in a layout:

```

    {{ config('app.name') }}

        {{ __('messages.dashboard') }}

```

### How language switching works

[](#how-language-switching-works-1)

1. The user clicks a button in the switcher
2. Livewire calls the `switchLocale($locale)` action via AJAX
3. `LocaleManager::set()` saves the new locale in the session
4. The component dispatches the `octolang:locale-changed` event
5. The component's script listens for that event and calls `window.location.reload()`
6. The browser reloads the page — the `SetLocale` middleware applies the new locale to the entire view

This flow ensures all `__()` calls in the welcome view and any other view are re-rendered with the correct language.

### Using translations

[](#using-translations)

Translations work the same as in pure Blade:

```
{{ __('messages.welcome') }}
{{ __('messages.dashboard_description') }}
```

With package keys:

```
{{ __('octolang::messages.switcher.label') }}
{{ __('octolang::messages.switcher.tooltip') }}
```

### Customizing the component view

[](#customizing-the-component-view)

If you need to adjust the HTML or styles of the switcher, publish the view:

```
php artisan vendor:publish --tag=octolang-views
```

This copies the view to `resources/views/vendor/octolang/livewire/octo-lang-switch.blade.php` where you can edit it freely without touching the package.

Usage in Vue (Inertia.js)
-------------------------

[](#usage-in-vue-inertiajs)

OctoLang includes native support for Vue 3 with Inertia.js. The `SetLocale` middleware automatically shares the active locale and translations as Inertia props — no backend changes needed beyond installing the package.

### What `octolang:install` sets up in a Vue project

[](#what-octolanginstall-sets-up-in-a-vue-project)

When a Vue/Inertia project is detected, the command creates:

- `resources/js/components/octolang/OctoLangSwitch.vue` — ready-to-use component
- `resources/js/composables/useOctoLang.ts` — composable for accessing translations and switching locale
- `resources/css/octolang.css` and the import in `app.css`

Generated files include the `// octolang:processed` marker so reinstalls do not overwrite them.

### Automatically shared props

[](#automatically-shared-props)

The middleware injects the following into every Inertia response:

PropTypeDescription`locale``string`Active locale (`"en"`, `"es"`, etc.)`supported_locales``string[]`Locales enabled in config`translations``object`Translation files from the `octolang::` namespace### The `useOctoLang` composable

[](#the-useoctolang-composable)

The composable generated at `resources/js/composables/useOctoLang.ts` exposes:

```
const { locale, supported_locales, __, switchLocale } = useOctoLang()
```

- `locale` — reactive computed with the active locale
- `supported_locales` — reactive computed with available locales
- `__('messages.welcome.title')` — translation function equivalent to `__('octolang::messages.welcome.title')` in Blade
- `switchLocale('en')` — sends `POST /locale` and reloads the page via Inertia

### Using translations in a component

[](#using-translations-in-a-component)

```

import { useOctoLang } from '@/composables/useOctoLang'

const { __ } = useOctoLang()

        {{ __('messages.welcome.title') }}
        {{ __('messages.welcome.octolang_status') }}

```

The key follows the `file.group.key` format. The first segment is the PHP filename inside `lang/{locale}/`:

```
__('messages.welcome.title')
 ↑         ↑       ↑
 file      group   key

```

If the first segment does not match any known file, `useOctoLang` defaults to `messages`:

```
__('welcome.title')  // equivalent to __('messages.welcome.title')
```

### The `OctoLangSwitch` component

[](#the-octolangswitch-component)

The component generated at `resources/js/components/octolang/OctoLangSwitch.vue` renders a `` with one button per supported locale. It takes no props — data comes automatically from the composable.

```

import OctoLangSwitch from '@/components/octolang/OctoLangSwitch.vue'

```

Clicking a button sends `POST /locale` and Inertia reloads the page with the updated translations reactively.

### Integration in `welcome.vue`

[](#integration-in-welcomevue)

The installer detects your `welcome.vue` and **does not replace it** — it only injects the import, the composable, and the component. A typical result looks like this:

```

import { Head, Link } from '@inertiajs/vue3'
import { dashboard, login, register } from '@/routes'
// octolang:start
import OctoLangSwitch from '@/components/octolang/OctoLangSwitch.vue'
import { useOctoLang } from '@/composables/useOctoLang'
const { __ } = useOctoLang()
// octolang:end

withDefaults(defineProps(), { canRegister: true })

                Dashboard

                    Log in
                    Register

                {{ __('messages.welcome.octolang_thanks') }}

                {{ __('messages.welcome.octolang_status') }}

```

### Adding your own translations

[](#adding-your-own-translations)

Create or edit `lang/en/messages.php` and `lang/es/messages.php` in your project root:

```
// lang/en/messages.php
return [
    'nav' => [
        'home'      => 'Home',
        'dashboard' => 'Dashboard',
        'logout'    => 'Log out',
    ],
    'hero' => [
        'title'    => 'Welcome to my app',
        'subtitle' => 'The best platform on the market',
    ],
];
```

```
// lang/es/messages.php
return [
    'nav' => [
        'home'      => 'Inicio',
        'dashboard' => 'Panel',
        'logout'    => 'Cerrar sesión',
    ],
    'hero' => [
        'title'    => 'Bienvenido a mi app',
        'subtitle' => 'La mejor plataforma del mercado',
    ],
];
```

Use them in Vue:

```

import { useOctoLang } from '@/composables/useOctoLang'

const { __ } = useOctoLang()

    {{ __('messages.hero.title') }}
    {{ __('messages.nav.dashboard') }}

```

Usage in React (Inertia.js)
---------------------------

[](#usage-in-react-inertiajs)

OctoLang includes native support for React with Inertia.js. The `SetLocale` middleware automatically shares the active locale and translations as Inertia props — no backend changes needed beyond installing the package.

### What `octolang:install` sets up in a React project

[](#what-octolanginstall-sets-up-in-a-react-project)

When a React/Inertia project is detected, the command creates:

- `resources/js/components/octolang/LocaleSwitcher.tsx` — ready-to-use component
- `resources/js/hooks/useOctoLang.ts` — hook for accessing translations and switching locale
- `resources/css/octolang.css` and the import in `app.css`

Generated files include the `// octolang:processed` marker so reinstalls do not overwrite them.

### Automatically shared props

[](#automatically-shared-props-1)

The middleware injects the following into every Inertia response:

PropTypeDescription`locale``string`Active locale (`"en"`, `"es"`, etc.)`supported_locales``string[]`Locales enabled in config`translations``object`Translation files from the `octolang::` namespace### The `useOctoLang` hook

[](#the-useoctolang-hook)

The hook generated at `resources/js/hooks/useOctoLang.ts` exposes:

```
const { locale, supported_locales, __, switchLocale } = useOctoLang()
```

- `locale` — string with the active locale
- `supported_locales` — array of available locales
- `__('messages.welcome.title')` — translation function equivalent to `__('octolang::messages.welcome.title')` in Blade
- `switchLocale('en')` — sends `POST /locale` and reloads the page via Inertia

### Using translations in a component

[](#using-translations-in-a-component-1)

```
import { useOctoLang } from '@/hooks/useOctoLang'

export default function HeroBanner() {
    const { __ } = useOctoLang()

    return (

            {__('messages.welcome.title')}
            {__('messages.welcome.description')}

    )
}
```

The key follows the `file.group.key` format. The first segment is the PHP filename inside `lang/{locale}/`:

```
__('messages.welcome.title')
 ↑         ↑       ↑
 file      group   key

```

If the first segment does not match any known file, `useOctoLang` defaults to `messages`:

```
__('welcome.title')  // equivalent to __('messages.welcome.title')
```

### The `LocaleSwitcher` component

[](#the-localeswitcher-component)

The component generated at `resources/js/components/octolang/LocaleSwitcher.tsx` renders a `` with one button per supported locale. It takes no props — data comes automatically from the hook.

```
import LocaleSwitcher from '@/components/octolang/LocaleSwitcher'

    {/* rest of your nav */}

```

Clicking a button sends `POST /locale` and Inertia reloads the page with the updated translations.

### Integration in `welcome.tsx`

[](#integration-in-welcometsx)

The installer detects your `welcome.tsx` and **does not replace it** — it only injects the import and the hook. A typical result looks like this:

```
import { Head, Link, usePage } from '@inertiajs/react'
import { dashboard, login, register } from '@/routes'
import type { SharedData } from '@/types'
import LocaleSwitcher from '@/components/octolang/LocaleSwitcher'
import { useOctoLang } from '@/hooks/useOctoLang'

export default function Welcome({ canRegister = true }: { canRegister?: boolean }) {
    const { auth } = usePage().props
    const { __ } = useOctoLang()

    return (

                        {auth.user ? (
                            Dashboard
                        ) : (

                                Log in
                                {canRegister && Register}

                        )}

                        {__('messages.welcome.octolang_thanks')}

                        {__('messages.welcome.octolang_status')}

                {/* rest of your welcome */}

    )
}
```

### Adding your own translations

[](#adding-your-own-translations-1)

Create or edit `lang/en/messages.php` and `lang/es/messages.php` in your project root:

```
// lang/en/messages.php
return [
    'nav' => [
        'home'      => 'Home',
        'dashboard' => 'Dashboard',
        'logout'    => 'Log out',
    ],
    'hero' => [
        'title'    => 'Welcome to my app',
        'subtitle' => 'The best platform on the market',
    ],
];
```

```
// lang/es/messages.php
return [
    'nav' => [
        'home'      => 'Inicio',
        'dashboard' => 'Panel',
        'logout'    => 'Cerrar sesión',
    ],
    'hero' => [
        'title'    => 'Bienvenido a mi app',
        'subtitle' => 'La mejor plataforma del mercado',
    ],
];
```

Use them in React:

```
const { __ } = useOctoLang()

{__('messages.hero.title')}
{__('messages.nav.dashboard')}
```

### Note on Windows

[](#note-on-windows)

On Windows, OctoLang internally uses `dirname(__DIR__, 3)` and `str_replace('\\', '/', $dir)` to resolve translation file paths with `glob()`. This is transparent to the user — mentioned here only as a compatibility reference.

Usage in Svelte (Inertia.js)
----------------------------

[](#usage-in-svelte-inertiajs)

OctoLang includes native support for Svelte 5 with Inertia.js. The `SetLocale` middleware automatically shares the active locale and translations as Inertia props — no backend changes needed beyond installing the package.

### What `octolang:install` sets up in a Svelte project

[](#what-octolanginstall-sets-up-in-a-svelte-project)

When a Svelte/Inertia project is detected, the command creates:

- `resources/js/components/octolang/OctoLangSwitch.svelte` — ready-to-use component
- `resources/js/stores/useOctoLang.ts` — store with access to translations and locale switching
- `resources/css/octolang.css` and the import in `app.css`

Generated files include the `// octolang:processed` marker so reinstalls do not overwrite them.

### Automatically shared props

[](#automatically-shared-props-2)

The middleware injects the following into every Inertia response:

PropTypeDescription`locale``string`Active locale (`"en"`, `"es"`, etc.)`supported_locales``string[]`Locales enabled in config`translations``object`Translation files from the `octolang::` namespace### The `useOctoLang` store

[](#the-useoctolang-store)

The store generated at `resources/js/stores/useOctoLang.ts` exposes:

```
import { getLocale, getSupportedLocales, __, switchLocale } from '@/stores/useOctoLang'
```

- `getLocale()` — returns the active locale, reactive via `$derived` in components
- `getSupportedLocales()` — returns the array of available locales
- `__('messages.welcome.title')` — translation function equivalent to `__('octolang::messages.welcome.title')` in Blade
- `switchLocale('en')` — sends `POST /locale` and reloads the page with the new language

> **Svelte 5 note:** `page` from `@inertiajs/svelte` is a `$state` rune object, not a `svelte/store`. That is why the OctoLang store exposes getters instead of `derived()` values. Always wrap them in `$derived()` inside your components to maintain reactivity.

### Using translations in a component

[](#using-translations-in-a-component-2)

```

    import { __ } from '@/stores/useOctoLang'

    {__('messages.welcome.title')}
    {__('messages.welcome.octolang_status')}

```

The key follows the `file.group.key` format. The first segment is the PHP filename inside `lang/{locale}/`:

```
__('messages.welcome.title')
 ↑         ↑       ↑
 file      group   key

```

If the first segment does not match any known file, `useOctoLang` defaults to `messages`:

```
__('welcome.title')  // equivalent to __('messages.welcome.title')
```

### The `OctoLangSwitch` component

[](#the-octolangswitch-component-1)

The component generated at `resources/js/components/octolang/OctoLangSwitch.svelte` renders a `` with one button per supported locale. It handles its own reactivity internally — no props needed.

```

    import OctoLangSwitch from '@/components/octolang/OctoLangSwitch.svelte'

```

Clicking a button sends `POST /locale` and the page reloads with the updated translations.

### Reactive access to locale in your components

[](#reactive-access-to-locale-in-your-components)

When you need to react to the active locale (for example for conditional logic), use `$derived` with the getter:

```

    import { getLocale, getSupportedLocales, switchLocale, __ } from '@/stores/useOctoLang'

    const locale            = $derived(getLocale())
    const supported_locales = $derived(getSupportedLocales())

Active language: {locale}

{#each supported_locales as loc (loc)}
     switchLocale(loc)}
    >
        {loc.toUpperCase()}

{/each}
```

### Integration in `Welcome.svelte`

[](#integration-in-welcomesvelte)

The installer detects your `Welcome.svelte` and **does not replace it** — it only injects the imports and the component. A typical result looks like this:

```

    // octolang:start
    import OctoLangSwitch from '@/components/octolang/OctoLangSwitch.svelte'
    import { __ } from '@/stores/useOctoLang'
    // octolang:end
    import { Link, page } from '@inertiajs/svelte'
    import AppHead from '@/components/AppHead.svelte'

    let { canRegister = true }: { canRegister: boolean } = $props()
    const auth = $derived(page.props.auth)

            {#if auth.user}
                Dashboard
            {:else}
                Log in
                {#if canRegister}
                    Register
                {/if}
            {/if}

            {__('messages.welcome.octolang_thanks')}

            {__('messages.welcome.octolang_status')}

```

### Adding your own translations

[](#adding-your-own-translations-2)

Create or edit `lang/en/messages.php` and `lang/es/messages.php` in your project root:

```
// lang/en/messages.php
return [
    'nav' => [
        'home'      => 'Home',
        'dashboard' => 'Dashboard',
        'logout'    => 'Log out',
    ],
    'hero' => [
        'title'    => 'Welcome to my app',
        'subtitle' => 'The best platform on the market',
    ],
];
```

```
// lang/es/messages.php
return [
    'nav' => [
        'home'      => 'Inicio',
        'dashboard' => 'Panel',
        'logout'    => 'Cerrar sesión',
    ],
    'hero' => [
        'title'    => 'Bienvenido a mi app',
        'subtitle' => 'La mejor plataforma del mercado',
    ],
];
```

Use them in Svelte:

```

    import { __ } from '@/stores/useOctoLang'

{__('messages.hero.title')}
{__('messages.nav.dashboard')}
```

Navbar and sidebar examples
---------------------------

[](#navbar-and-sidebar-examples)

Example translation file:

```
return [
    'home'      => 'Home',
    'dashboard' => 'Dashboard',
    'reports'   => 'Reports',
    'settings'  => 'Settings',
    'logout'    => 'Log out',
];
```

Navbar:

```

    {{ __('messages.home') }}
    {{ __('messages.dashboard') }}
    {{ __('messages.reports') }}

```

Sidebar:

```

    {{ __('messages.dashboard') }}

        {{ __('messages.dashboard') }}
        {{ __('messages.reports') }}
        {{ __('messages.settings') }}

```

Available route
---------------

[](#available-route)

OctoLang registers one route for switching the language:

```
POST /locale

```

The URI and route name come from the configuration:

- `locale.route_uri`
- `locale.route_name`
- `locale.route_middleware`

Example form:

```

    @csrf

    English

```

Publishable resources
---------------------

[](#publishable-resources)

To customize resources manually, publish them:

```
php artisan vendor:publish --tag=octolang-config
php artisan vendor:publish --tag=octolang-lang
php artisan vendor:publish --tag=octolang-views
php artisan vendor:publish --tag=octolang-css
```

How safe uninstall works
------------------------

[](#how-safe-uninstall-works)

OctoLang tracks everything it creates in:

```
storage/app/octolang/install.json

```

During uninstall, it removes only the files and changes it has on record.

Examples:

- removes `resources/css/octolang.css` if OctoLang created it
- removes the import from `resources/css/app.css` if OctoLang inserted it
- removes files inside `resources/views/vendor/octolang/...` if they were created by OctoLang
- removes the OctoLang block from the `welcome` view only if it can identify it safely
- preserves files that existed before installing the package
- flags files modified after install for manual review

Recommended full workflow
-------------------------

[](#recommended-full-workflow)

### Install

[](#install)

```
composer require johannhsdev/octolang
php artisan octolang:install
php artisan optimize:clear
npm run dev
```

### Review tracked resources

[](#review-tracked-resources)

```
php artisan octolang:status
```

### Uninstall

[](#uninstall)

```
php artisan octolang:uninstall
composer remove johannhsdev/octolang
```

Testing
-------

[](#testing)

```
vendor/bin/pest
```

Contributing
------------

[](#contributing)

If you would like to contribute to OctoLang, feel free to open an issue, suggest improvements, or submit a pull request.

Lead development:

- [JohannHSDev](https://github.com/johannhsdev)

Visual direction and graphic support:

- [Jose Espinoza](https://www.instagram.com/Joeesp25)

License
-------

[](#license)

MIT

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance97

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

15d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7810b9ef3a7d73ea14c593b4c376b2127926c827a479ed1d9de5b3800f8c1b6a?d=identicon)[johannhsdev](/maintainers/johannhsdev)

---

Top Contributors

[![johannhsdev](https://avatars.githubusercontent.com/u/45208672?v=4)](https://github.com/johannhsdev "johannhsdev (4 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/johannhsdev-octolang/health.svg)

```
[![Health](https://phpackages.com/badges/johannhsdev-octolang/health.svg)](https://phpackages.com/packages/johannhsdev-octolang)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

76318.2M110](/packages/laravel-mcp)[illuminate/routing

The Illuminate Routing package.

1239.0M2.8k](/packages/illuminate-routing)[api-platform/laravel

API Platform support for Laravel

59156.3k10](/packages/api-platform-laravel)[illuminate/auth

The Illuminate Auth package.

9327.9M1.2k](/packages/illuminate-auth)[spatie/laravel-export

Create a static site bundle from a Laravel app

670139.5k6](/packages/spatie-laravel-export)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
