@mcmuffindk/laravel-localeinator v1.0.7
laravel-localeinator
A React package that enables localization using Laravel lang files. This package allows you to dynamically load translations, switch locales, persist the user’s preferred locale, and gracefully fall back to keys when translations are missing.
Features
- Dynamic Locale Switching: Switch locales dynamically at runtime.
- Persistent User Preference: Remember the chosen locale using
localStorage
. - Fallback Locale Support: Automatically load a fallback locale if a key is missing.
- Translation Keys as Fallback: Display the translation key if the translation does not exist.
- Pluralization Support: Handle plural translations seamlessly.
- Loading State: Display a loading state while fetching translations.
- Available Locales: Fetch all available locales from the server.
Installation
To install the package, run:
npm install @mcmuffindk/laravel-localeinator
By default, this package fetches translations from a Laravel route that serves them as JSON responses. You need to set up your Laravel backend to expose the translations as JSON.
Laravel Backend Setup
Expose all available languages
Route::get('/lang/available-locales', function () {
$langPath = base_path('lang');
$locales = collect(File::directories($langPath))
->map(fn($dir) => basename($dir))
->reject(fn($locale) => $locale === 'vendor');
return response()->json($locales->values());
});
Expose Lang Files as JSON:
Add the following routes to routes/web.php
to serve translations:
Option 1: Serve translations from JSON files
Route::get('/lang/{locale}', function ($locale) {
$path = resource_path("lang/$locale.json");
if (!File::exists($path)) {
abort(404);
}
return response()->file($path);
}
Option 2: Serve translations directly from php files
Route::get('/lang/{locale}', function ($locale) {
$langPath = base_path("lang/$locale");
if (!File::exists($langPath)) {
abort(404, "Locale not found");
}
$translations = collect(File::allFiles($langPath))->reduce(function ($carry, $file) {
$relativePath = trim($file->getRelativePath(), '/');
$filename = pathinfo($file->getFilename(), PATHINFO_FILENAME);
$nestedKeys = array_filter(explode('/', $relativePath));
$nestedKeys[] = $filename;
$data = include $file->getPathname();
$pointer = &$carry;
foreach ($nestedKeys as $key) {
if (!isset($pointer[$key])) {
$pointer[$key] = [];
}
$pointer = &$pointer[$key];
}
$pointer = $data;
return $carry;
}, []);
return response()->json($translations);
});
Usage
1. Wrap Your Application with LocalizationProvider
Wrap your root component with the LocalizationProvider
and set the defaultLocale
and fallbackLocale
:
import React from 'react';
import ReactDOM from 'react-dom';
import { LocalizationProvider } from '@mcmuffindk/laravel-localeinator';
import App from './App';
ReactDOM.render(
<LocalizationProvider defaultLocale="en" fallbackLocale="en">
<App />
</LocalizationProvider>,
document.getElementById('root')
);
2. Use the useLocalization
Hook
Access localization features using the useLocalization
hook in your components:
import React from 'react';
import { useLocalization } from '@mcmuffindk/laravel-localeinator';
const MyComponent = () => {
const { t, switchLocale, locale, loading, availableLocales } = useLocalization();
if (loading) return <p>Loading translations...</p>;
return (
<div>
<h1>{t('welcome_message', null, { name: 'John' })}</h1>
<p>Current Locale: {locale}</p>
<h3>Switch Locale:</h3>
<button onClick={() => switchLocale('fr')}>French</button>
<button onClick={() => switchLocale('es')}>Spanish</button>
<h3>Available Locales:</h3>
<ul>
{availableLocales.map((loc) => (
<li key={loc}>{loc}</li>
))}
</ul>
</div>
);
};
export default MyComponent;
API Reference
LocalizationProvider
Wrap your application in the LocalizationProvider
.
Prop | Type | Description |
---|---|---|
defaultLocale | string | The default locale (e.g., 'en' ). |
fallbackLocale | string | The fallback locale when keys are missing. |
useLocalization Hook
Use the useLocalization
hook to access localization features.
Property | Type | Description |
---|---|---|
t(key, <replacements>, <count>) | function | Translate a key. Supports pluralization and placeholders. |
switchLocale(newLocale) | function | Switch to a new locale. |
locale | string | The currently active locale. |
loading | boolean | Indicates whether translations are being loaded. |
availableLocales | array | List of all available locales fetched from the server. |
t Function
The t
function supports:
Simple Translations:
t('welcome_message', 'John'); // Output: "Welcome, John!"
t('welcome_message', { name: 'John' }); // Output: "Welcome, John!"
Simple Pluralization:
t('item_count', 1); // Output: "There is one item."
t('item_count', 5); // Output: "There are 5 items."
Complex Pluralization:
people_count = "{0} There are no people.|{1} There is one person.|[2,*] There are :count people."
t('people_count', 0); // Output: "There are no people."
t('people_count', 1); // Output: "There is one person."
t('people_count', 5); // Output: "There are 5 people."
Fallback for Missing Keys:
If a key is not found in the current locale, the key itself is returned:
t('nonexistent_key'); // Output: "nonexistent_key"
Loading State
You can display a loading indicator while translations are being fetched:
if (loading) {
return <p>Loading translations...</p>;
}
Available Locales
The available locales can be fetched and displayed using the availableLocales
property:
<ul>
{availableLocales.map((loc) => (
<li key={loc}>{loc}</li>
))}
</ul>
License
This package is licensed under the GNU GPLv3 License.
Contributing
Contributions are welcome! If you find a bug or have a suggestion for improvement, please submit an issue or pull request.