Closed gzhihao closed 5 years ago
This is definitely something that I would agree should be a part of PingCRM as a showcase. Making use of the lang
files in the resources
directory.
I am not sure if this is already relatively simple to implement, but I'll have a look when I have some free time.
Hi folks, sorry, but I don't see adding this to Ping CRM. I want to keep this project as simple as possible to help folks get up and running with Inertia.js. The idea isn't to show how to solve every possible problem with the library.
Thanks for your interest either way! 😍
@gzhihao If you're still looking for a solution I suggest having a look at this npm package: https://github.com/martinlindhe/laravel-vue-i18n-generator
Thanks for both.
Yeah, I got my setup working, for those who are interested, I'm using following two packages
I ended up localizing a Laravel, Vue.js app that was using Inertia.js without adding any required extra dependencies to the front or backend. I wrote about it in a pretty straight forward step by step format in case it might help anyone (myself) in the future 🤙🏻 https://devonmather.xyz/localizing-a-laravel-app-using-vue-js-and-inertia-js-without-any-dependencies/
I was also seeking for a way to use localization with Inertia, simply because it seemed logic to me.
But remember that you use a fully fledged javascript framework for your frontend! That means that most of the time you can use the localization system of your frontend framework (for vuejs it's Vue-i18n) instead of Laravel's one (you can still use Laravel's localization system for your controller logic, emails and blade views if your app is not 100% inertia based).
I think this is the cleanest and easiest way to go.
I ended up localizing a Laravel, Vue.js app that was using Inertia.js without adding any required extra dependencies to the front or backend. I wrote about it in a pretty straight forward step by step format in case it might help anyone (myself) in the future 🤙🏻 https://devonmather.xyz/localizing-a-laravel-app-using-vue-js-and-inertia-js-without-any-dependencies/
could you provide us with the Github repo please
I ended up localizing a Laravel, Vue.js app that was using Inertia.js without adding any required extra dependencies to the front or backend. I wrote about it in a pretty straight forward step by step format in case it might help anyone (myself) in the future 🤙🏻 https://devonmather.xyz/localizing-a-laravel-app-using-vue-js-and-inertia-js-without-any-dependencies/
Can you do a review for vue3. Its not loading base.js mixin
I ended up localizing a Laravel, Vue.js app that was using Inertia.js without adding any required extra dependencies to the front or backend. I wrote about it in a pretty straight forward step by step format in case it might help anyone (myself) in the future 🤙🏻 https://devonmather.xyz/localizing-a-laravel-app-using-vue-js-and-inertia-js-without-any-dependencies/
Can you do a review for vue3. Its not loading base.js mixin
You need to modify the base.js a bit:
module.exports = {
methods: {
__(key, replace = {}) {
var translation = this.$page.props.language[key]
? this.$page.props.language[key]
: key
Object.keys(replace).forEach(function (key) {
translation = translation.replace(':' + key, replace[key])
});
return translation
},
},
}
And app.js lookslike:
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => require(`./Pages/${name}.vue`),
setup({ el, app, props, plugin }) {
return createApp({ render: () => h(app, props) })
.use(plugin)
.mixin({ methods: { route } })
.mixin(require('./base'))
.mount(el);
},
});
This worked for me with Vue3
Due to the Laravel 9 update, the AppServiceProvider.php has to be edited because the change of the "lang" folder.
Inertia::share([
'locale' => function () {
return app()->getLocale();
},
'language' => function () {
return translations(
app_path('../lang/'. app()->getLocale() .'.json')
);
}
]);
This works as from 03-03-2022.
Thanks for helpful topic @devonmather and everyone else!
I might be wrong and missed the info in original article that explained this process, so just wanted to share. If you're ever in need to pass parameters, same way you use it regularly in Larval app, you can always do something like:
Then in template:
And finally in the end ( en.json ):
Vuejs has its own localization system (Vue-i18n) that's easy to use, so you don't need to reinvent the wheel. I came across this excellent package that bridges Laravel language files and Vue for that purpose: https://github.com/xiCO2k/laravel-vue-i18n
@djpmedia's modified solution from @devonmather works in the template part. However, I couldn't find an easy way to use it in the script block.
I tried to use the provide/inject method but it didn't work since the "$this.page" part in the module doesn't work with the composition API.
Anyone has a practical solution to deal with this?
Edit: I ended up by creating a Composable and copying the function there, then replacing the $this.page part with usePage(). But still looking for an ideal solution without duplicating the translation function.
'language' => function () {
return translations(
resource_path('lang/'. app()->getLocale() .'.json')
);
},
function translations($json)
{
if(!file_exists($json)) {
return [];
}
return json_decode(file_get_contents($json), true);
}
i vijay kanaujia update this things to get data from multiple files
'language' => translations(),
function translations()
{
$path = resource_path('lang/'. app()->getLocale());
$files = array_diff(scandir($path), array('.', '..'));
$languages = [];
if(count($files)){
foreach($files as $file){
$ext = pathinfo($file);
$languages[$ext['filename']] = Lang::get($ext['filename']);
}
}
return $languages;
}
I ended up localizing a Laravel, Vue.js app that was using Inertia.js without adding any required extra dependencies to the front or backend. I wrote about it in a pretty straight forward step by step format in case it might help anyone (myself) in the future 🤙🏻 https://devonmather.xyz/localizing-a-laravel-app-using-vue-js-and-inertia-js-without-any-dependencies/
Can you do a review for vue3. Its not loading base.js mixin
You need to modify the base.js a bit:
module.exports = { methods: { __(key, replace = {}) { var translation = this.$page.props.language[key] ? this.$page.props.language[key] : key Object.keys(replace).forEach(function (key) { translation = translation.replace(':' + key, replace[key]) }); return translation }, }, }
And app.js lookslike:
createInertiaApp({ title: (title) => `${title} - ${appName}`, resolve: (name) => require(`./Pages/${name}.vue`), setup({ el, app, props, plugin }) { return createApp({ render: () => h(app, props) }) .use(plugin) .mixin({ methods: { route } }) .mixin(require('./base')) .mount(el); }, });
This worked for me with Vue3
When I used this, I got Uncaught ReferenceError: require is not defined. Why did it happen?
I have the same. The problem is, that Laravel is switched to Vite. Vite hasn't a require method. I tried
.mixin(import('./base'))
But I get following error:
app.cc8c8888.js:31 TypeError: m.__ is not a function
I have the same. The problem is, that Laravel is switched to Vite. Vite hasn't a require method. I tried
.mixin(import('./base'))
But I get following error:
app.cc8c8888.js:31 TypeError: m.__ is not a function
Did you fix this issue when switching to Vite? And if so how'd you fix this issue?
I have the same. The problem is, that Laravel is switched to Vite. Vite hasn't a require method. I tried
.mixin(import('./base'))
But I get following error:app.cc8c8888.js:31 TypeError: m.__ is not a function
Did you fix this issue when switching to Vite? And if so how'd you fix this issue?
@KickSchutte67
I fixed it with
base.js:
export default {
methods: {
__(key, replace = {}) {
var translation = this.$page.props.language[key]
? this.$page.props.language[key]
: key
Object.keys(replace).forEach(function (key) {
translation = translation.replace(':' + key, replace[key])
});
return translation
},
},
}
and app.js:
import translation from './Helper/Translation';
return createApp({render: () => h(app, props)})
....
.mixin(translation)
.....
Hello,
I just put a new laravel 9 version with inertiajs and I had some small problems here is the solution.
in app.js
...
import base from './base';
...
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, app, props, plugin }) {
return createApp({ render: () => h(app, props) })
.use(plugin)
.use(ZiggyVue, Ziggy)
.mixin(base) //add this line.
.mount(el);
},
});
in base.js change module.exports =
to export default
show code:
export default {
methods: {
/**
* Translate the given key.
*/
__(key, replace = {}) {
var translation = this.$page.props.language[key]
? this.$page.props.language[key]
: key
Object.keys(replace).forEach(function (key) {
translation = translation.replace(':' + key, replace[key])
});
return translation
},
/**
* Translate the given key with basic pluralization.
*/
__n(key, number, replace = {}) {
var options = key.split('|');
key = options[1];
if(number == 1) {
key = options[0];
}
return tt(key, replace);
},
},
}
I have created an example for a multi-language website using Laravel, Vue, and InertiaJS. Take a look https://github.com/GankCC/multilang
In Laravel 10:
class HandleInertiaRequests extends Middleware
{
// ...
public function share(Request $request): array
{
return array_merge(parent::share($request), [
// ...
'language' => function () {
$langFile = lang_path(app()->getLocale() . ".json");
if (!File::exists($langFile)) return [];
return File::json($langFile);
},
// ...
]);
}
}
Don't forget to import use Illuminate\Support\Facades\File;
facade at the top.
Dears, After reviewing various suggestions and solutions for localizing Laravel with Inertia React, I have distilled my goals My aim is to adopt a solution that:
I attempted to share the language as JSON using 'inertia::share.' However, in my opinion, this is not a recommended practice because:
use Illuminate\Support\Facades\Inertia;
public function boot(): void
{
// Check your condition here
if (/* your condition */) {
Inertia::share([
'lang' => function () {
// Your logic to fetch and return the data
return $this->mergeLangFiles();
},
]);
}
}
I have come across several solutions, and most of them involve custom server-side implementations.
My solution is :
Create a new Larvel project
Use starter-kits quick setup front-end react
publish Defulat framework Lang files via the lang:publish Artisan command. The result should be a new folder named "Lang" and nested folder "EN" contains four .php files:
Create a simple Artisan command to merge these files into a single JSON file based on the language namespace [EN, FR, AR, ...] and save them in the Public folder under the same structure.
private function mergeLanguageFiles($languagesPath, $outputPath)
{
$mergedTranslations = [];
// Get all language files
$files = File::allFiles($languagesPath);
foreach ($files as $file) {
$langArray = include $file;
$locale = pathinfo($file, PATHINFO_FILENAME);
$mergedTranslations[$locale] = $langArray;
}
}
// Save the merged translations to separate JSON files
File::put($outputPath . '/shared.json', json_encode($sharedTranslations, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}
To ensure these files remain up-to-date, run the following command each time you boot the project. Apply this step only in development mode
/**
* Bootstrap any application services.
*/
public function boot(): void
{
if ($this->app->environment('local')) {
// Run the command only in the local environment
Artisan::call('make:lang-merge');
}
}
Result :
"dependencies": { "i18next": "^23.7.6", "i18next-http-backend": "^2.4.1", "react-i18next": "^13.5.0" }
You can get this code from official documentation
import i18n from 'i18next';
import HttpApi from 'i18next-http-backend';
import { initReactI18next } from 'react-i18next';
i18n
.use(initReactI18next)
.use(HttpApi)
.init({
lng: 'ar', // en
fallbackLng: 'ar', // en
debug: true,
interpolation: {
escapeValue: false,
},
backend:{
loadPath: '/lang/{{lng}}/{{ns}}.json',
},
load: 'languageOnly', // Load only the language part of the locale
ns: ['messages'],
defaultNS: 'shared', // Set the default namespace
});
export default i18n;
In app.tsx import the previous file : import './i18n'; // Import the i18n configuration.
Now, it's ready for transitioning content, as shown in the screenshot below
This solution is very simple, robust, and easy to scale. Additionally, it allows you to leverage the features of the 'i18next' library. In the backend, you can continue translating content as follows:
__('auth.password')
Maybe out of this demo app's scope, but would like to see how multi-language is supported in an inertia app. It might be similar to the typical SPA way, but I see some differences, e.g. we can leverage the lang switching feature on server side, which could make frontend dumb simple. (That's the beauty of inertia).
Feel free to close this issue if it's not align with the goal of this repo.