JavaScript (JSON) Translator based on Laravel™ Translator. The Translator supports variables (optional with first charakter uppercase or complete uppercase) and pluralization.
Using PNPM
pnpm add -D @norman-huth/translator-js
Using NPM
npm i -D @norman-huth/translator-js
Example JSON-File with translations:
{
"Hello": "Hallo",
"Welcome, :name": "Willkommen :name",
"Good morning :name": "Guten Morgen :Name",
"Good evening :name": "Guten Abend :NAME",
"There is one apple|There are many apples": "Hay una manzana|Hay muchas manzanas",
"apples": "{0} There are none|[1,19] There are some|[20,*] There are many",
"minutes_ago": "{1} :value minute ago|[2,*] :value minutes ago"
}
Usage | Result | Note |
---|---|---|
trans('Hello') |
Hallo | |
trans('Welcome, :name', {name: 'Norman'}) |
Willkommen Norman | |
trans('Good morning :name', {name: 'norman'}) |
Guten Morgen Norman | :Name |
trans('Good evening :name', {name: 'norman'}) |
Guten Abend NORMAN | :NAME |
trans_choice('There is one apple|There are many apples', 1) |
Hay una manzana | |
trans_choice('There is one apple|There are many apples', 5) |
Hay muchas manzanas | |
trans_choice('apples', 0) |
There are none | |
trans_choice('apples', 12) |
There are some | |
trans_choice('apples', 22) |
There are many | |
trans_choice('minutes_ago', 1, {value: 1}) |
1 minute ago | |
trans_choice('minutes_ago', 5, {value: 5}) |
5 minutes ago |
import Translator from '@norman-huth/translator-js'
const Trans = new Translator()
return Trans.trans('Hello')
Or create alternativ an "empty" instance:
Translator.factory()
Translator.factory(translations)
Share the App JSON-Translations via HandleInertiaRequests
middleware.
class HandleInertiaRequests extends Middleware
{
// --
/**
* Define the props that are shared by default.
*
* @return array<string, mixed>
*/
public function share(Request $request): array
{
return [
...parent::share($request),
'translations' => $this->jsonTranslations(),
];
}
/**
* Load the messages for the given locale.
*
* @return array<string, string>
*/
protected function jsonTranslations(): array
{
return app('translator')
->getLoader()
->load(app()->getLocale(), '*', '*');
}
}
Add the Translator to the /resources/js/bootstrap.{js|ts}
.
This example add the alias __()
for trans()
. This makes it possible to use trans()
or __()
for translation well
as in Laravel™.
import Translator from '@norman-huth/translator-js'
const JsonTranslator = new Translator()
window.__ = function(key, replace = {}) {
return JsonTranslator.trans(key, replace)
}
window.trans = function(key, replace = {}) {
return JsonTranslator.trans(key, replace)
}
window.trans_choice = function(key, number, replace = {}) {
return JsonTranslator.trans_choice(key, number, replace)
}
TypeScript:
//...
window.__ = function(key: string, replace = {}) {
return JsonTranslator.trans(key, replace)
}
window.trans = function(key: string, replace = {}) {
return JsonTranslator.trans(key, replace)
}
window.trans_choice = function(key: string, number: number, replace = {}) {
return JsonTranslator.trans_choice(key, number, replace)
}
To have the functions also available in the <template>
, edit the /resources/js/app.{js|ts}
and add the functions as
mixin:
createInertiaApp({
//...
setup({ el, App, props, plugin }) {
return createApp({ render: () => h(App, props) })
.use(plugin)
.mixin({
methods: {
__: function(key, replace = {}) {
return __(key, replace)
},
trans: function(key, replace = {}) {
return trans(key, replace)
},
trans_choice: function(key, number, replace = {}) {
return trans_choice(key, number, replace)
}
}
})
.mount(el);
},
//...
})
TypeScript:
//..
__: function(key: string, replace = {}) {
return __(key, replace)
},
trans: function(key: string, replace = {}) {
return trans(key, replace)
},
trans_choice: function(key: string, number: number, replace = {}) {
return trans_choice(key, number, replace)
}
Extend the /resources/js/types/global.d.ts
file.
//...
const JsonTranslator = new Translator()
const __ = (key: string, replace = {}) => {
return JsonTranslator.translator(key, replace)
}
const trans = (key: string, replace = {}) => {
return JsonTranslator.translator(key, replace)
}
const trans_choice = (key, number, replace = {}) => {
return JsonTranslator.trans_choice(key, number, replace)
}
declare global {
interface Window {
axios: AxiosInstance;
__: typeof __
trans: typeof trans
trans_choice: typeof trans_choice
}
let __ = function(key: string, replace = {}) {
return JsonTranslator.trans(key, replace)
}
let trans = function(key: string, replace = {}) {
return JsonTranslator.trans(key, replace)
}
let trans_choice = function(key, number, replace = {}) {
return JsonTranslator.trans_choice(key, number, replace)
}
//..
}
// And for Vue.js <template>
declare module 'vue' {
interface ComponentCustomProperties {
// ...
__: typeof __
trans: typeof trans
trans_choice: typeof trans_choice
}
}
.eslintrc.cjs
module.exports = {
globals: {
__: true,
trans: true,
trans_choice: true,
},
}
The locale is only used from the pluralizer.
This script is oriented towards Inertia.js and determines the translation from the JSON ({"translations": {}}
) of
the data-page
attribute in the div id="app".
and the locale by <html lang="en">
tag.
By default the class bootstrap the translations data.
The Constructor with defaults:
constructor(
prop: string = 'translations',
elementId: string = 'app',
dataAttribute: string = 'page',
locale: string | null = null,
translations: Translations | null = null,
bootstrap: boolean = true
)
Argument | Default | Description |
---|---|---|
prop | translations | The page props key with the translations |
elementId | app | The ID of the described div |
dataAttribute | page | The div data-* attribute |
locale | null |
Initialize the class with locale (override on bootrap) |
translations | null |
Initialize the class with translations (override on bootrap) |
bootstrap | true |
Bootrap the translations' data. |
Manually set the translations.
Translator.setTranslations(
{ "Foo": "Bar" }
)
Manually set the locale.
Translator.setLocale('en')
Bootrap the translations' data (again).
Translator.bootstrap()
Change the array for the translations.
class HandleInertiaRequests extends Middleware
{
public function share(Request $request): array
{
return [
...parent::share($request),
'app' => [
'translations' => $this->jsonTranslations(),
],
];
}
}
Set nested array by using "dot" notation in the Translator script:
import Translator from '@norman-huth/translator-js'
const JsonTranslator = new Translator('app.translations')