acf
domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init
action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/evomark/public_html/wp-includes/functions.php on line 6121There are over 7,000 languages in active use today. Even if you only deal in English, is that British English, American English, Caribbean English, Sinaporean English, Hong Kong English or any of the many other variations?<\/p>\n\n\n\n
Supporting multiple languages and dialects in your applications is often essential in our global world, and is something that generally presents a challenge to developers.<\/p>\n\n\n\n
Language is everywhere in software. It tells you what to do, when to do it, what just happened, what’s going to happen and explains the context around what you’re looking at. It’s inextricable from the software.<\/p>\n\n\n\n
So naturally we have to extricate it.<\/p>\n\n\n\n
Take, for example, a simple text input. The text input will have a label, it may have a placeholder, it may have help text and it will have descriptive error messages. Something like this would not be unusual:<\/p>\n\n\n\n
<<\/span>div<\/span>><\/span><\/span><\/div>\t<\/span><<\/span>label<\/span> <\/span>for<\/span>=<\/span>\"<\/span>first_name<\/span>\"<\/span>><\/span>First name<\/span><\/<\/span>label<\/span>><\/span><\/span><\/div>\t<\/span><<\/span>input<\/span> <\/span>type<\/span>=<\/span>\"<\/span>text<\/span>\"<\/span> <\/span>id<\/span>=<\/span>\"<\/span>first_name<\/span>\"<\/span> <\/span>placeholder<\/span>=<\/span>\"<\/span>e.g. John<\/span>\"<\/span> <\/span>required<\/span> <\/span>\/><\/span><\/span><\/div>\t<\/span><<\/span>p<\/span> <\/span>class<\/span>=<\/span>\"<\/span>error-message<\/span>\"<\/span>><\/span><\/<\/span>p<\/span>><\/span><\/span><\/div><\/span><\/<\/span>div<\/span>><\/span><\/div><\/code><\/pre><\/div>\n\n\n\nThis HTML template could be located anywhere in your codebase. The error message is probably generated on the server via a validation service that is buried away something else.<\/p>\n\n\n\n
Now imagine having dozens of different translations of all that text in those far reaches of your application. Completely unmanageable for all but the smallest of applications.<\/p>\n\n\n\n
The Laravel answer and the Inertia problem<\/h2>\n\n\n\n
Laravel has internationalisation (i18n) support built in via a collection of PHP files that are accessed through a __('some_file.some_field')<\/code> function. This works fine for the server and would work fine for Laravel Blade components too. Only problem is that if you’re using Inertia, you don’t have access to either Blade components or PHP functions in your application’s frontend.<\/p>\n\n\n\nSure, you could create a separate i18n setup for your frontend, but now you have the same problem of fragmenting from the intro. Every translation would likely become the subject of a hunt as you wonder if flash messages generated on the server but shown on the frontend should be part of which package. Then also, the duplications would be many.<\/p>\n\n\n\n
Ideally then, we need a way for our translations to be stored in one single place and then made available to both the server and the frontend, which is where our open-source package Inertia-I18n<\/em> comes in!<\/p>\n\n\n\nGetting started<\/h2>\n\n\n\n
Because this package deals with both server setup and frontend features, it comes as a hybrid package (one containing both PHP and JavaScript in this case) and as such, we distribute it via Composer rather than NPM since the latter doesn’t allow any integration with PHP autoloading. So step one is to install it into your Laravel application:<\/p>\n\n\n\n
composer<\/span> require evo-mark\/inertia-i18n<\/span><\/div><\/code><\/pre><\/div>\n\n\n\nWe also need our bundlers to be able to use the JavaScript parts of the package, so we can install it as a “local” package like so:<\/p>\n\n\n\n
npm<\/span> <\/span>install<\/span> .\/vendor\/evo-mark\/inertia-i18n<\/span><\/div><\/span># OR<\/span><\/span><\/div><\/span>pnpm<\/span> <\/span>add<\/span> .\/vendor\/evo-mark\/inertia-i18n<\/span><\/div><\/code><\/pre><\/div>\n\n\n\nThe next step is setting up Vite to convert our PHP language files into a format that JavaScript can read. The handly Vite plugin included in our package automatically handles this.<\/p>\n\n\n\n
1<\/span>\/\/ vite.config.js<\/span><\/span><\/span><\/div>2<\/span><\/span>import<\/span> <\/span>InertiaI18n<\/span> <\/span>from<\/span> <\/span>\"inertia-i18n\/vite\"<\/span>;<\/span><\/span><\/span><\/div>3<\/span>\n<\/span><\/span><\/div>4<\/span><\/span>export<\/span> <\/span>default<\/span> <\/span>{<\/span><\/span><\/span><\/div>5<\/span> <\/span>plugins<\/span>:<\/span> <\/span>[<\/span>InertiaI18n<\/span>(<\/span>)<\/span>]<\/span>,<\/span><\/span><\/span><\/div>6<\/span><\/span>}<\/span>;<\/span><\/span><\/div><\/code><\/pre><\/div>\n\n\n\nThen finally we need to make our language files available to our Inertia application with a Vue plugin (also included)<\/p>\n\n\n\n
1<\/span>\/\/ resources\/js\/app.js<\/span><\/span><\/span><\/div>2<\/span><\/span>import<\/span> <\/span>useInertiaI18nVue<\/span> <\/span>from<\/span> <\/span>\"inertia-i18n\/vue\"<\/span>;<\/span><\/span><\/span><\/div>3<\/span>\n<\/span><\/span><\/div>4<\/span><\/span>createInertiaApp<\/span>(<\/span>{<\/span><\/span><\/span><\/div>5<\/span> <\/span>async<\/span> <\/span>setup<\/span>(<\/span>{<\/span> el<\/span>,<\/span> <\/span>App<\/span>,<\/span> props<\/span>,<\/span> plugin <\/span>}<\/span>)<\/span> <\/span>{<\/span><\/span><\/span><\/div>6<\/span> <\/span>const<\/span> inertiaI18nPlugin <\/span>=<\/span> <\/span>useInertiaI18nVue<\/span>(<\/span>props<\/span>)<\/span>;<\/span><\/span><\/span><\/div>7<\/span> <\/span>\/\/ Optional, but you may get warnings without this<\/span><\/span><\/span><\/div>8<\/span> <\/span>await<\/span> inertiaI18nPlugin<\/span>.<\/span>load<\/span>(<\/span>)<\/span>;<\/span><\/span><\/span><\/div>9<\/span>\n<\/span><\/span><\/div>10<\/span> <\/span>createSSRApp<\/span>(<\/span>{<\/span> <\/span>render<\/span>:<\/span>