johannhsdev / octolang
A elegant Laravel package for managing application locales — OctoLang
Requires
- php: ^8.2|^8.4
- illuminate/contracts: ^11.0|^12.0|^13.0
- illuminate/http: ^11.0|^12.0|^13.0
- illuminate/routing: ^11.0|^12.0|^13.0
- illuminate/session: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^2.0|^3.0
Suggests
- livewire/livewire: Required for the OctoLangSwitch Livewire component (^3.0)
README
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
OctoLang includes:
- A
LocaleManagerservice to store and resolve the active locale from the session - A
SetLocalemiddleware that applies the active language on every request - A
POSTroute for safely switching languages - A Blade component:
<x-octolang::locale-switcher /> - 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:
| Resource | Blade | Livewire | Vue | React | Svelte |
|---|---|---|---|---|---|
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
- PHP
^8.2|^8.4 - Laravel
^11.0|^12.0|^13.0
Installation
1. Install via Composer
composer require johannhsdev/octolang
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
The install command runs the package setup explicitly. It does not run automatically on every request.
This command:
- Copies
lang/en/messages.phpandlang/es/messages.phponly if those files do not exist - Copies
resources/views/vendor/octolang/components/locale-switcher.blade.phpif needed - Copies
resources/css/octolang.cssif needed - Adds
@import "./octolang.css";toresources/css/app.cssif the file exists and does not already contain that line - Processes
resources/views/welcome.blade.php - Records created files and tracked changes in
storage/app/octolang/install.json
Available commands
php artisan octolang:install
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
welcomeview
php artisan octolang:status
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:uninstallwill be able to remove
php artisan octolang:uninstall
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
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
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_LOCALEis the source of truth for OctoLang's initial language.LOCALE_SESSION_KEYonly changes the key used insession().APP_FALLBACK_LOCALEremains Laravel's responsibility for missing translations.APP_FAKER_LOCALEonly affects Faker and does not participate in the app's visible language.LOCALE_SUPPORTEDvalidates changes made from the switcher, but does not replace or reorder the baseAPP_LOCALE.
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
OctoLang saves the selected language in the session and applies it via middleware.
Flow:
- The user sends a locale to the OctoLang route
LocaleControllervalidates the locale againstlocale.supportedLocaleManagersaves it in the sessionSetLocalecallsApp::setLocale(...)on the next request, usingAPP_LOCALEas the base- 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
Adding the switcher
You can place the component in any Blade view:
<x-octolang::locale-switcher />
Example in a navbar:
<header class="flex items-center justify-between px-6 py-4"> <div> <a href="/">{{ config('app.name') }}</a> </div> <nav class="flex items-center gap-4"> <a href="{{ route('dashboard') }}">{{ __('messages.dashboard') }}</a> <a href="{{ route('profile') }}">{{ __('messages.profile') }}</a> <x-octolang::locale-switcher /> </nav> </header>
Example in a sidebar:
<aside class="w-64 p-4 space-y-4"> <x-octolang::locale-switcher /> <nav class="space-y-2"> <a href="{{ route('dashboard') }}">{{ __('messages.dashboard') }}</a> <a href="{{ route('settings') }}">{{ __('messages.settings') }}</a> <a href="{{ route('users.index') }}">{{ __('messages.users') }}</a> </nav> </aside>
Using translations in Blade views
Use Laravel's standard translation helpers:
<h1>{{ __('messages.welcome') }}</h1> <p>{{ __('messages.dashboard_description') }}</p>
With replacements:
<p>{{ __('messages.greeting', ['name' => $user->name]) }}</p>
Pluralization:
<p>{{ trans_choice('messages.notifications', $count, ['count' => $count]) }}</p>
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
OctoLang includes a native Livewire v3 component: <livewire:octolang-switch />.
It registers automatically when Livewire is installed. No extra backend setup required.
What octolang:install 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 viewresources/css/octolang.cssand the import inapp.css- Injects
<livewire:octolang-switch />intowelcome.blade.phpwithout replacing its content
In Livewire projects,
components/locale-switcher.blade.phpis not copied — that file belongs to the pure Blade stack only.
Adding the switcher
Place the component in any Blade view within your Livewire app:
<livewire:octolang-switch />
Example in a layout:
<header class="flex items-center justify-between px-6 py-4"> <a href="/">{{ config('app.name') }}</a> <nav class="flex items-center gap-4"> <a href="{{ route('dashboard') }}">{{ __('messages.dashboard') }}</a> <livewire:octolang-switch /> </nav> </header>
How language switching works
- The user clicks a button in the switcher
- Livewire calls the
switchLocale($locale)action via AJAX LocaleManager::set()saves the new locale in the session- The component dispatches the
octolang:locale-changedevent - The component's script listens for that event and calls
window.location.reload() - The browser reloads the page — the
SetLocalemiddleware 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
Translations work the same as in pure Blade:
<h1>{{ __('messages.welcome') }}</h1> <p>{{ __('messages.dashboard_description') }}</p>
With package keys:
{{ __('octolang::messages.switcher.label') }} {{ __('octolang::messages.switcher.tooltip') }}
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)
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
When a Vue/Inertia project is detected, the command creates:
resources/js/components/octolang/OctoLangSwitch.vue— ready-to-use componentresources/js/composables/useOctoLang.ts— composable for accessing translations and switching localeresources/css/octolang.cssand the import inapp.css
Generated files include the // octolang:processed marker so reinstalls do not overwrite them.
Automatically shared props
The middleware injects the following into every Inertia response:
| Prop | Type | Description |
|---|---|---|
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 composable generated at resources/js/composables/useOctoLang.ts exposes:
const { locale, supported_locales, __, switchLocale } = useOctoLang()
locale— reactive computed with the active localesupported_locales— reactive computed with available locales__('messages.welcome.title')— translation function equivalent to__('octolang::messages.welcome.title')in BladeswitchLocale('en')— sendsPOST /localeand reloads the page via Inertia
Using translations in a component
<script setup lang="ts"> import { useOctoLang } from '@/composables/useOctoLang' const { __ } = useOctoLang() </script> <template> <section> <h1>{{ __('messages.welcome.title') }}</h1> <p>{{ __('messages.welcome.octolang_status') }}</p> </section> </template>
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 component generated at resources/js/components/octolang/OctoLangSwitch.vue renders a <nav> with one button per supported locale. It takes no props — data comes automatically from the composable.
<script setup lang="ts"> import OctoLangSwitch from '@/components/octolang/OctoLangSwitch.vue' </script> <template> <nav class="flex items-center gap-4"> <OctoLangSwitch /> <!-- rest of your nav --> </nav> </template>
Clicking a button sends POST /locale and Inertia reloads the page with the updated translations reactively.
Integration in welcome.vue
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:
<script setup lang="ts"> 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: boolean }>(), { canRegister: true }) </script> <template> <Head title="Welcome" /> <div class="flex min-h-screen flex-col items-center ..."> <header class="..."> <nav class="flex items-center justify-end gap-4"> <!-- octolang:start --> <OctoLangSwitch /> <!-- octolang:end --> <Link v-if="$page.props.auth.user" :href="dashboard()">Dashboard</Link> <template v-else> <Link :href="login()">Log in</Link> <Link v-if="canRegister" :href="register()">Register</Link> </template> </nav> </header> <!-- octolang:block:start --> <div class="w-full max-w-4xl text-center mb-6"> <p class="text-base font-medium"> {{ __('messages.welcome.octolang_thanks') }} </p> <p class="text-sm text-[#706f6c] dark:text-[#A1A09A]"> {{ __('messages.welcome.octolang_status') }} </p> </div> <!-- octolang:block:end --> <!-- rest of your welcome --> </div> </template>
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:
<script setup lang="ts"> import { useOctoLang } from '@/composables/useOctoLang' const { __ } = useOctoLang() </script> <template> <h1>{{ __('messages.hero.title') }}</h1> <a href="/dashboard">{{ __('messages.nav.dashboard') }}</a> </template>
Usage in React (Inertia.js)
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
When a React/Inertia project is detected, the command creates:
resources/js/components/octolang/LocaleSwitcher.tsx— ready-to-use componentresources/js/hooks/useOctoLang.ts— hook for accessing translations and switching localeresources/css/octolang.cssand the import inapp.css
Generated files include the // octolang:processed marker so reinstalls do not overwrite them.
Automatically shared props
The middleware injects the following into every Inertia response:
| Prop | Type | Description |
|---|---|---|
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 hook generated at resources/js/hooks/useOctoLang.ts exposes:
const { locale, supported_locales, __, switchLocale } = useOctoLang()
locale— string with the active localesupported_locales— array of available locales__('messages.welcome.title')— translation function equivalent to__('octolang::messages.welcome.title')in BladeswitchLocale('en')— sendsPOST /localeand reloads the page via Inertia
Using translations in a component
import { useOctoLang } from '@/hooks/useOctoLang' export default function HeroBanner() { const { __ } = useOctoLang() return ( <section> <h1>{__('messages.welcome.title')}</h1> <p>{__('messages.welcome.description')}</p> </section> ) }
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 component generated at resources/js/components/octolang/LocaleSwitcher.tsx renders a <nav> with one button per supported locale. It takes no props — data comes automatically from the hook.
import LocaleSwitcher from '@/components/octolang/LocaleSwitcher' <nav className="flex items-center gap-4"> <LocaleSwitcher /> {/* rest of your nav */} </nav>
Clicking a button sends POST /locale and Inertia reloads the page with the updated translations.
Integration in welcome.tsx
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<SharedData>().props const { __ } = useOctoLang() return ( <> <Head title="Welcome" /> <div className="flex min-h-screen flex-col items-center ..."> <header className="..."> <nav className="flex items-center justify-end gap-4"> <LocaleSwitcher /> {auth.user ? ( <Link href={dashboard()}>Dashboard</Link> ) : ( <> <Link href={login()}>Log in</Link> {canRegister && <Link href={register()}>Register</Link>} </> )} </nav> </header> <div className="w-full max-w-4xl text-center mb-6"> <p className="text-base font-medium"> {__('messages.welcome.octolang_thanks')} </p> <p className="text-sm text-[#706f6c]"> {__('messages.welcome.octolang_status')} </p> </div> {/* rest of your welcome */} </div> </> ) }
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 React:
const { __ } = useOctoLang() <h1>{__('messages.hero.title')}</h1> <a href="/dashboard">{__('messages.nav.dashboard')}</a>
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)
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
When a Svelte/Inertia project is detected, the command creates:
resources/js/components/octolang/OctoLangSwitch.svelte— ready-to-use componentresources/js/stores/useOctoLang.ts— store with access to translations and locale switchingresources/css/octolang.cssand the import inapp.css
Generated files include the // octolang:processed marker so reinstalls do not overwrite them.
Automatically shared props
The middleware injects the following into every Inertia response:
| Prop | Type | Description |
|---|---|---|
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 store generated at resources/js/stores/useOctoLang.ts exposes:
import { getLocale, getSupportedLocales, __, switchLocale } from '@/stores/useOctoLang'
getLocale()— returns the active locale, reactive via$derivedin componentsgetSupportedLocales()— returns the array of available locales__('messages.welcome.title')— translation function equivalent to__('octolang::messages.welcome.title')in BladeswitchLocale('en')— sendsPOST /localeand reloads the page with the new language
Svelte 5 note:
pagefrom@inertiajs/svelteis a$staterune object, not asvelte/store. That is why the OctoLang store exposes getters instead ofderived()values. Always wrap them in$derived()inside your components to maintain reactivity.
Using translations in a component
<script lang="ts"> import { __ } from '@/stores/useOctoLang' </script> <section> <h1>{__('messages.welcome.title')}</h1> <p>{__('messages.welcome.octolang_status')}</p> </section>
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 component generated at resources/js/components/octolang/OctoLangSwitch.svelte renders a <nav> with one button per supported locale. It handles its own reactivity internally — no props needed.
<script lang="ts"> import OctoLangSwitch from '@/components/octolang/OctoLangSwitch.svelte' </script> <nav class="flex items-center gap-4"> <OctoLangSwitch /> <!-- rest of your nav --> </nav>
Clicking a button sends POST /locale and the page reloads with the updated translations.
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:
<script lang="ts"> import { getLocale, getSupportedLocales, switchLocale, __ } from '@/stores/useOctoLang' const locale = $derived(getLocale()) const supported_locales = $derived(getSupportedLocales()) </script> <p>Active language: {locale}</p> {#each supported_locales as loc (loc)} <button class={loc === locale ? 'font-bold' : ''} onclick={() => switchLocale(loc)} > {loc.toUpperCase()} </button> {/each}
Integration in Welcome.svelte
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:
<script lang="ts"> // 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) </script> <AppHead title="Welcome" /> <div class="flex min-h-screen flex-col items-center ..."> <header class="..."> <nav class="flex items-center justify-end gap-4"> <!-- octolang:start --> <OctoLangSwitch /> <!-- octolang:end --> {#if auth.user} <Link href="/dashboard">Dashboard</Link> {:else} <Link href="/login">Log in</Link> {#if canRegister} <Link href="/register">Register</Link> {/if} {/if} </nav> </header> <!-- octolang:block:start --> <div class="w-full max-w-[335px] text-center mb-6 lg:max-w-4xl"> <p class="text-base font-medium text-[#1b1b18] dark:text-[#EDEDEC]"> {__('messages.welcome.octolang_thanks')} </p> <p class="text-sm text-[#706f6c] dark:text-[#A1A09A]"> {__('messages.welcome.octolang_status')} </p> </div> <!-- octolang:block:end --> <!-- rest of your welcome --> </div>
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 Svelte:
<script lang="ts"> import { __ } from '@/stores/useOctoLang' </script> <h1>{__('messages.hero.title')}</h1> <a href="/dashboard">{__('messages.nav.dashboard')}</a>
Navbar and sidebar examples
Example translation file:
return [ 'home' => 'Home', 'dashboard' => 'Dashboard', 'reports' => 'Reports', 'settings' => 'Settings', 'logout' => 'Log out', ];
Navbar:
<nav class="flex items-center gap-4"> <a href="/">{{ __('messages.home') }}</a> <a href="{{ route('dashboard') }}">{{ __('messages.dashboard') }}</a> <a href="{{ route('reports.index') }}">{{ __('messages.reports') }}</a> <x-octolang::locale-switcher /> </nav>
Sidebar:
<aside class="space-y-3"> <h2>{{ __('messages.dashboard') }}</h2> <ul class="space-y-2"> <li><a href="{{ route('dashboard') }}">{{ __('messages.dashboard') }}</a></li> <li><a href="{{ route('reports.index') }}">{{ __('messages.reports') }}</a></li> <li><a href="{{ route('settings') }}">{{ __('messages.settings') }}</a></li> </ul> </aside>
Available route
OctoLang registers one route for switching the language:
POST /locale
The URI and route name come from the configuration:
locale.route_urilocale.route_namelocale.route_middleware
Example form:
<form method="POST" action="{{ route('locale.store') }}"> @csrf <input type="hidden" name="locale" value="en"> <button type="submit">English</button> </form>
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
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.cssif OctoLang created it - removes the import from
resources/css/app.cssif OctoLang inserted it - removes files inside
resources/views/vendor/octolang/...if they were created by OctoLang - removes the OctoLang block from the
welcomeview 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
Install
composer require johannhsdev/octolang php artisan octolang:install php artisan optimize:clear npm run dev
Review tracked resources
php artisan octolang:status
Uninstall
php artisan octolang:uninstall composer remove johannhsdev/octolang
Testing
vendor/bin/pest
Contributing
If you would like to contribute to OctoLang, feel free to open an issue, suggest improvements, or submit a pull request.
Lead development:
Visual direction and graphic support:
License
MIT