Skip to content

Latest commit

 

History

History
247 lines (209 loc) · 9.83 KB

README.md

File metadata and controls

247 lines (209 loc) · 9.83 KB

@zakkudo/translate-webpack-plugin

A webpack plugin for scanning javscript files to build translation mappings in json automatically.

Build Status Coverage Status Known Vulnerabilities Node License

Why use this?

  • Automated code splittiing
  • You no longer have to manage hierarchies of translations
  • Designed for architectures leveraging dynamic imports, allowing splitting of the translations based off of file structure
  • Templates are automatically generated for the translators where they only need to fill in the blanks
  • The translations are annoted if they are new or unused as well as the file names and line numbers of usages
  • Easy auditing for missing or non-updated translation strings with never running your application or enlisting QA
  • Any string wrapped in __() or __n() or __p() or __np(), will be picked up as a translatable making usage extremely easy for developers
  • Works similarly to the venerable gettext. Any translation strategies that work for that library work for this library. translatable making usage extremely easy for developers

What does it do?

  • It searches your source code for translatable strings and aggregates them
  • It writes human-centric translation templates in json5 showing usages, new strings and no longer used strings
  • It generates developer-centric optimized json templates, stripping away any unused strings and metadata

Install

# Install using npm
npm install @zakkudo/translate-webpack-plugin
# Install using yarn
yarn add @zakkudo/translate-webpack-plugin

Setup

  1. Wrap strings you want to be translated in __('text') or __n('singlular', 'plural', number) using a library like @zakkudo/translator
  2. Add the plugin to webpack
const TranslateWebpackPlugin = require('@zakkudo/translate-webpack-plugin');

module.exports = {
    plugins: [
        new TranslateWebpackPlugin({
            // Analyzes all javscript files in the src directory, which is a good initial value
            files: 'src/**/*.js',
            // Use verbose output to see what files are parsed, what keys are extracted, and where they are being written to
            debug: true,
            // You do not need to add your default language (which for most people will be English)
            locales: ['fr'],
            // Consolidate all of the optimized localizations into `src/.locale`, good as an initial configuration
            target: 'src'
        })
    ]
};
  1. Add .locales to your .gitignore so it isn't commited. It is a dynamic source file that has no value being added to a repository. Its existance in the src directory is simply to facilitate importing it.
  2. Add find src -name '.locales' | xargs rm -r to your clean scripts for an easy way to remove the auto generated src/.locales from your source code
  3. Import locales into your source code from the src/.locales folder so you can merge it into the lookup of @zakkudo/translator. It is plain old json with the untranslated and unexisting values optimized out.
  4. Have your localization team use the files from locales (without a period.) It's annoted with information about new, unused, and existing usages of the translations to help them audit what needs updating.

You'll end up with a file structure similar to below.

File Structure
├── locales <- For your translators
│   ├── en.json
│   └── fr.json
└── src
    ├── .locales <- For your developers
    │   ├── en.json
    │   └── fr.json
    └── pages
        ├── About
        │   └── index.js
        └── Search
            └── index.js

Where locales/fr.json will look like this for use by your translators:

{
    "About": {
        // NEW
        // src/pages/AboutPage/index.js:14
        "default": ""
    },
    "Search": {
        // UNUSED
        "default": "French translation",
        // UNUSED
        "menuitem": "French translation"
    },
    "There is one user": {
        // src/pages/AboutPage/index.js:40
        "default": {"1":"French translation", "2":"French translation"},
    },
    "Welcome to the about page!": {
        // src/pages/AboutPage/index.js:38
        "default": "French translation"
    }
}

And the optimized src/.locales/fr.json will look like this for use by your developers:

{
    "There is one user": {"one":"French translation", "other":"French translation"},
    "Welcome to the about page!": "French translation"
}

Your developers will use the translation similarly to below:

import Translator from '@zakkudo/translator';
import fr from 'src/.locales/fr.json';
const translator = new Translator();
const {__, __n} = translator;
const language = navigator.language.split('-')[0];

translator.setLocalization('fr', fr);
translator.setLocale(language);

document.title = __('About');
document.body.innerHTML = __n('There is one user', 'There are %d users', 2);

Examples

Configure the plugin to build a single .locales directory

module.exports = {
    plugins: [
        new TranslateWebpackPlugin({
            files: 'src/**/*.js',
            locales: ['es', 'fr'],
            target: 'src'
        });
    ]
};
File Structure
├── locales <- For your translators. Contains translations for everything
│   ├── es.json
│   └── fr.json
└── src
    ├── Application.js
    ├── .locales <- For your developers. Contains translations for everything
    │   ├── es.json
    │   └── fr.json
    └── pages
        ├── About
        │   └── index.js
        └── Search
            └── index.js

Configure the plugin for a split .locales directory

module.exports = {
    plugins: [
        new TranslateWebpackPlugin({
            files: 'src/**/*.js',
            locales: ['es', 'fr'],
            target: 'src/pages/*'
        })
    ]
};
File Structure
├── locales <- For your translators. Contains translations for everything
│   ├── es.json
│   └── fr.json
└── src
    ├── Application.js
    └── pages
        ├── About
        │   ├── .locales <- For your developers. Contains translations for `Application.js` and `About/index.js`
        │   │   ├── es.json
        │   │   └── fr.json
        │   └── index.js
        └── Search
            ├── .locales <- For your developers. Contains translations for `Application.js` and `Search/index.js`
            │   ├── es.json
            │   └── fr.json
            └── index.js

Also see

  • @zakkudo/translation-static-analyzer for the generic library that this package thinly wraps
  • @zakkudo/translator is a library that can read the localization with no fuss and apply the translations.
  • Polymer 3 Starter Project is an example project using this library.

API

@zakkudo/translate-webpack-plugin~TranslateWebpackPlugin ⏏

Plugin for analyzing javascript source files, extracting the translations, and converting them into localization templates.

Kind: Exported class

new TranslateWebpackPlugin(options)

Param Type Default Description
options Object The modifiers for how the analyzer is run
options.files String A glob pattern of the files to pull translations from
[options.debug] Boolean false Show debugging information in the console
[options.locales] Array.<String> [] The locales to generate (eg fr, ja_JP, en)
[options.templates] String The location to store the translator translatable templates for each language. Defaults to making a locales directory in the current working directory
[options.target] String Where to write the final translations, which can be split between multiple directories for modularity. If there are no targets, no .locales directory will be generated anywhere.

translateWebpackPlugin.apply(compiler)

Method called by the webpack plugin system during watch to inform the plugin when some files have been updated.

Kind: instance method of TranslateWebpackPlugin

Param Type Description
compiler Object The webpack compiler object