@norman-huth/translator-js
TypeScript icon, indicating that this package has built-in type declarations

1.2.0 • Public • Published

TranslatorJs

JavaScript (JSON) Translator based on Laravel™ Translator. The Translator supports variables (optional with first charakter uppercase or complete uppercase) and pluralization.

Installation

Using PNPM

pnpm add -D @norman-huth/translator-js

Using NPM

npm i -D @norman-huth/translator-js

Contents

Example:

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

Usage

Simple VanillaJs

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)

Laravel™ with Inertia.js

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(), '*', '*');
    }
}

Vue.js / React / VanillaJs etc

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)
}
Vue.js

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)
}
Optional: TypeScript

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
  }
}
Optional: ESLint

.eslintrc.cjs

module.exports = {
  globals: {
    __: true,
    trans: true,
    trans_choice: true,
  },
}

Digging Deeper

The locale is only used from the pluralizer.

The Translator Constructor

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.

Translator.setTranslations

Manually set the translations.

Translator.setTranslations(
  { "Foo": "Bar" }
)

Translator.setLocale

Manually set the locale.

Translator.setLocale('en')

Translator.bootstrap

Bootrap the translations' data (again).

Translator.bootstrap()

Example: Other Inertia.js Share Key

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')

Package Sidebar

Install

npm i @norman-huth/translator-js

Weekly Downloads

193

Version

1.2.0

License

MIT

Unpacked Size

34.5 kB

Total Files

9

Last publish

Collaborators

  • muetze