This package has been deprecated

Author message:

Use vue3-gettext (version 2) instead of @jshmrtn/vue3-gettext

@jshmrtn/vue3-gettext
TypeScript icon, indicating that this package has built-in type declarations

1.5.0 • Public • Published

vue3-gettext 💬

Translate Vue.js applications with gettext.

Table of Contents

  1. Installation
  2. Basic usage
  3. Workflow
  4. Configuration
  5. Annotating strings
  6. Message extraction and compilation
  7. Dependencies
  8. Contribute
  9. Credits
  10. License

Installation

npm i @jshmrtn/vue3-gettext
npm i -D easygettext

main.js

import { createGettext } from "@jshmrtn/vue3-gettext";
import { createApp } from "vue";
import translations from "./path/to/translations.json";

const gettext = createGettext({
  availableLanguages: {
    en_GB: "British English",
  },
  defaultLanguage: "en_GB",
  translations,
});

const app = createApp(App);
app.use(gettext);

Basic usage

Use the component or directive to annotate translatable strings:

<translate>Hello!</translate>

<span v-translate>Hello!</span>

Or inject the plugin using useGettext (Example of a language switcher):

<template>
  <div>
    <select v-model="language.current">
      <option v-for="(language, key) in language.available" :key="key" :value="key">{{ language }}</option>
    </select>
  </div>
</template>

<script>
import { useGettext } from "@jshmrtn/vue3-gettext";

export default {
  setup() {
    const language = useGettext();
    return {
      language,
    };
  },
};
</script>

Workflow

  1. Annotate strings: annotate all the translatable strings in your project using the <translate> component, the v-translate directive or by calling the gettext functions (gettext, pgettext, ngettext, npgettext) directly.

  2. Extract strings: you can now extract all strings to create message files. A message file is just a plain-text file with a .po file extension, representing a single language, that contains all available translation strings as keys and how they should be represented in the given language.

    vue3-gettext provides scripts to make this straightforward. Take a look at the Message extraction and compilation section.

  3. Translate message files: a translator needs to fill out the translations of each generated .po files. I recommend you use software like poedit (some alternatives are listed on wikipedia here).

  4. Compile translations: once all message files have been translated, use gettext-compile to make the translated .po files usable in a Vue app. This will merge all translated .po files into a .json file ready to be used by vue3-gettext.

Configuration

The options you can pass to createGettext are:

availableLanguages

Type: { [key: string]: string }

Default: { en_US: "English" }

An object that represents the list of the available languages for the app whose keys are local names (e.g. en or en_US) and whose values are language names used for the display in UI, e.g. English (United States). It's exposed in all Vue instances via vm.$language.available

Example

availableLanguages: {
  en_GB: "British English",
  fr_FR: "Français",
  it_IT: "Italiano",
},

defaultLanguage

Type: string

Default: 'en_US'

The local name of the default language, e.g. en_US. This will be the current active language. It's exposed in all Vue instances via vm.$language.current

Example

defaultLanguage: 'en_GB',

translations

Type: { [key: string]: { [key: string]: any } }

Default: {}

The JSON file of the application's translations (produced by gettext-compile).

Example

translations: {
  "en_Use": {
    "Color": "Color",
    ...
  },
  "de_DE": {
    "Color": "Farbe",
    ...
  }
},

mutedLanguages

Type: string[]

Default: []

Discard warnings for missing translations for all languages of the list. This is useful to avoid messages from the language used in source code.

Example

mutedLanguages: ['fr_FR', 'de'],

silent

Type: boolean

Default: false

Enable or disable logs/warnings for missing translations and untranslated keys.

Example

silent: true,

setGlobalProperties

Type: boolean

Default: true

Sets the options $gettext $pgettext $ngettext $npgettext $gettextInterpolate $language on app.config.globalProperties, making the globally available in your templates. It is not recommended to disable this as easygettext will not extract strings if your functions are not named exactly like this.

provideDirective

Type: boolean

Default: true

Registers the v-translate directive on you application. If you disable this option and want to provide the directive yourself, you must make sure to name it translate otherwise extraction will fail.

provideComponent

Type: boolean

Default: true

Registers the <translate> component on you application. If you disable this option and want to provide the component yourself, you must make sure to name it translate otherwise extraction will fail.

Full configuration example:

import { createGettext } from "@jshmrtn/vue3-gettext";
import { createApp } from "vue";
import translations from "./path/to/translations.json";

const gettext = createGettext({
  availableLanguages: {
    en_GB: "British English",
    fr_FR: "Français",
    it_IT: "Italiano",
  },
  defaultLanguage: "en_GB",
  mutedLanguages: ["fr_FR"]
  translations,
  silent: true,
});

const app = createApp(App);
app.use(gettext);

Dependencies

  • easygettext

    • gettext-extract to extract annotated strings from template files and produce a .pot (Portable Object Template) file.

    • gettext-compile to produce the sanitized JSON version of a .po file.

  • Some GNU gettext utilities to extract annotated strings from JavaScript files and generate .po files

Message extraction and compilation

vue3-gettext exposes two scripts to simplify this process:

vue-gettext-extract

The extract script will create an output directory containing a .pot file, directories and a .po file for each locale. You can now edit the .po files to translate your app before compiling them.

You may set a source directory to extract messages from, an output directory and a comma separated list of all the locales in your application.

Example call:

vue-gettext-extract --src ./src --out ./src/language --locales "de_CH,en_US"

vue-gettext-compile

The compile script will merge the contents of all the .po files and combine them into a single translations.json file that you can use with vue3-gettext (in the createGettext function).

You may set the directory where all your locales are located (the --out directory of the extract script) and the locales

Example call:

vue-gettext-compile --dir ./src/language --locales "de_CH,en_US"

Recommended setup

We recommend setting up the scripts in your package.json like this:

"scripts": {
    "gettext": "npm run gettext:extract && npm run gettext:compile",
    "gettext:extract": "vue-gettext-extract --src ./src --out ./src/language --locales \"de_CH,en_US\"",
    "gettext:compile": "vue-gettext-compile --dir ./src/language --locales \"de_CH,en_US\""
  },

Annotating strings in templates (.html or .vue files)

Use the component or the directive

Strings are marked as translatable in your templates using either the translate component or the v-translate directive:

<translate>Hello!</translate> <span v-translate>Hello!</span>

This will automatically be translated. For instance, in French, it might read Bonjour!.

Singular

<translate>Hello!</translate>

Plural

<translate :translate-n="count" translate-plural="%{ count } cars">%{ count } car</translate>

Context

<translate translate-context="Verb">Foo</translate>

Comment

<translate translate-comment="My comment for translators">Foo</translate>

Custom parameters

You can set up translation strings that are agnostic to how your app state is structured. This way you can change variable names within your app, it won't break your translation strings.

<translate :translate-params="{name: userFullName}">Foo %{name}</translate>

HTML support: difference between the component and the directive

It proves to be tricky to support interpolation with HTML content in Vue.js components because it's hard to access the raw content of the component itself.

So if you need to include HTML content in your translations you may use the directive.

The directive has the same set of capabilities as the component, except for translate-params which should be passed in as an expression.

<p
  v-translate="{count: carNumbers}"
  :translate-n="carNumbers"
  translate-plural="<strong>%{ count }</strong> cars"
  translate-comment="My comment for translators"
>
  <strong>%{ count }</strong> car
</p>

Custom HTML tag for the translate component

When rendered, the content of the translate component will be wrapped in a span element by default. You can also use another tag:

<translate tag="h1">Hello!</translate>

Interpolation

You can use the tokens %{ and } to for string interpolation within messages:

<translate>Hello %{ name }</translate>

Directive, interpolation and raw HTML in data

Raw HTML in data is interpreted as plain text, not HTML. In order to output real HTML, you will need to use the render-html attribute and set it to true.

<p v-translate render-html="true">Hello %{ openingTag }%{ name }%{ closingTag }</p>

Dynamically rendering arbitrary HTML on your website can be very dangerous because it can easily lead to XSS vulnerabilities. Only use HTML render-html="true" on trusted content and never on user-provided content.

Caveats

Caveat when using either the component <translate> or directive v-translate with interpolation inside v-for

It's not possible to access the scope within v-for, example:

<p>
  <translate v-for="name in names">Hello %{name}</translate>
  <span v-for="name in names" v-translate>Hello %{name}</span>
</p>

Will result in all Hello %{name} being rendered as Hello name.

You need to pass in custom parameters for it to work:

<p>
  <translate v-for="name in names" :translate-params="{name: name}">Hello %{name}</translate>
  <span v-for="name in names" v-translate="{name: name}">Hello %{name}</span>
</p>

Caveat when using v-translate with Vue components or Vue specific attributes

It's not possible to support components or attributes like v-bind and v-on. So make sure that your HTML translations stay basic for now.

For example, this is not supported:

<p v-translate>Please <button @click="doSomething">click</button> here to view <my-account></my-account></p>

1b) Annotating strings in JavaScript code (.js or .vue files)

Strings are marked as translatable in your Vue instances JavaScript code using methods from the plugin.

Singular

const { $gettext } = useGettext();

$gettext(msgid);

Plural

const { $ngettext } = useGettext();

$ngettext(msgid, plural, n);

Context

const { $pgettext } = useGettext();

$pgettext(context, msgid);

Context + Plural

const { $npgettext } = useGettext();

$npgettext(context, msgid, plural, n);

Interpolation support

You can use interpolation in your JavaScript using the method interpolate in combination with one of the annotation functions.

const { $ngettext, interpolate } = useGettext();

const translated = $ngettext("%{ n } foo", "%{ n } foos", n);
const interpolated = interpolate(translated, { n: n });

interpolate dynamically populates a translation string with a given context object.

Contribute

Please make sure your code is properly formatted (the project contains a prettier config) and all the tests run successfully (npm run test) when opening a pull request.

Please specify clearly what you changed and why.

Credits

This plugin heavily relies on the work of the original vue-gettext.

License

MIT

Readme

Keywords

none

Package Sidebar

Install

npm i @jshmrtn/vue3-gettext

Weekly Downloads

52

Version

1.5.0

License

MIT

Unpacked Size

79.6 kB

Total Files

8

Last publish

Collaborators

  • jeremyzahner
  • lzurbriggen
  • reeko