npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jamstack-translate

v2.0.5

Published

Generate static translations for any front end project.

Readme

jamstack-translate

Generate static translations for any front end project.

Google Translate your source folder and compile to static dist language directories without writing convoluted references to json files... I hate i18n libraries so much, here is my personal fix.

What does this package do?

  • Translates all strings inside <t>Some String</t>
  • Supports all file types.
  • Copies your source files into a generated/translated folder of your choice.
  • Generate a named JSON file with all your translations.
  • Load specified JSON file to generate files.

Example

Before...
.
├── src
|   └── components
|   |   └── Header.svelte
|   |   └── NoTranslations.svelte
|   └── helpers.js
|   └── App.svelte
|   └── main.js
<!-- ./src/components/Header.svelte -->
<header>
  <t>Welcome</t>
</header>
// ./src/helpers.js
const string = `<t>Welcome to ${name}</t>`
After...
.
├── src
|   ├── __generated__
|   |   └── es
|   |   |   └── components
|   |   |   |   └── Header.svelte
|   |   |   |   └── NoTranslations.svelte
|   |   |   └── helpers.js
|   |   |   └── App.svelte
|   |   └── fr
|   |   |   └── components
|   |   |   |   └── Header.svelte
|   |   |   |   └── NoTranslations.svelte
|   |   |   └── helpers.js
|   |   |   └── App.svelte
|   └── components
|   |   └── Header.svelte
|   |   └── NoTranslations.js
|   └── helpers.js
|   └── App.svelte
|   └── main.js
<!-- ./src/__generated__/fr/components/Header.svelte -->
<header>
  <t>Bienvenue</t>
</header>
// ./src/__generated__/fr/helpers.js
const string = `<t>Bienvenue sur ${name}</t>`

The package also produces a (specified) JSON file with your translations, so you may load from file, adjusting translations after initial run.

[
  {
    "_src": "./src/components/Header.svelte",
    "en": "Welcome",
    "es": "Bienvenidos",
    "fr": "Bienvenue"
  },
  {
    "_src": "./src/helpers.js",
    "en": "Welcome to ${name}",
    "es": "Bienvenido a ${name}",
    "fr": "Bienvenue sur ${name}"
  },
]

This file allows version control of your translations, also allows easy A/B testing for your translations quite easily.

See the Example Svelte.js or Example Vue.js for how your project can look.

Requirements

  • Node.js > 10
  • Google Cloud Translate account + API Key

Getting started

Install

npm install --save-dev jamstack-translate

Usage

Create a file in your root directory (ex: translate.js)

require('dotenv').config()
const translate = require('../index.js');

const GOOGLEKEY = process.env.GOOGLE_API_KEY
const OPTIONS = {
  targetLanguages: [
    'fr',
    'es',
  ],
  targetFiles: [
    './src/App.svelte',
    './src/components/**/*.svelte',
    './src/views/**/*.svelte',
    './src/helpers.js',
    // etc
  ],
  targetDirectory: './src/__generated__/',
  sourceDirectory: './src/',
  translationFile: './translations.json',
  loadTranslationsFromFile: true,
}

const init = async () => {
  const result = await translate(GOOGLEKEY, OPTIONS);
  console.log(result);
}

init();

Run

then simply run node translate.js


Current Issues and best practices and how to avoid them

The pacakge does some rudimentary regex/replace in order to address most issues (mostly caused by Google translate), here are those issues currenlty active and observed.

For most issues, you can manually fix these issues in your created JSON file, and compile with fixes.

CSS BEM (Modifier) classes

Currently, this...

<t><span class="text--green">hello</span> there</t>

Becomes...

<t><span class="text - green"> bonjour </span> là</t>

Single quotes when inside a JS file

Currently, if you translate a string inside a JS file, like so...

const string = '<t>Please</t>'

Becomes

const string = '<t>S'il vous plaît</t>'

Which is unnescaped, and will cause and compile/runtime error.

Best to use backticks instead of single quotes.

const string = `<t>Please</t>`

If you can't use backticks, you must manually escape the single quotes created in your created JSON file, and compile with fixes.

[
 {
  _file: "file.html",
  en: "Please",
  fr: "S\\'il vous plaît"
 }
]

Usage with JS frameworks

TLDR

For every new language folder you create, create a new entry file (multi input) for your application and point the respective imports to their lanuage folder. Then, in your index.html file, dynamically load your bundle.js depending on your method of choosing languages (I prefer URL parameters ?lng={language}).

Full Example

Note: Below is with Rollup/Svelte v3, other docs for webpack etc. will coming soon.

Entry files

Create new main.js files for each new langauge,

.
├── src
|   └── App.svelte
|   └── main-es.js <<<< New
|   └── main-fr.js <<<< New
|   └── main.js

Edit each new main file, and point to your new entry file

main-fr.js

import App from './__generated__/fr/App.svelte';

const app = new App({
	target: document.body,
	props: {
	  name: 'world'
	}
});

export default app;

Bundler (Rollup.js)

Generate a new bundle for each main file

Rollup.config.js

//...
import multiInput from 'rollup-plugin-multi-input';

export default {
	input: [{
		bundle_en: 'src/main.js',
		bundle_fr: 'src/main-fr.js',
		bundle_es: 'src/main-es.js',
	}],
	output: {
		sourcemap: true,
		name: 'app',
		format: 'es',
		dir: 'public/build'
	},
	plugins: [
		multiInput(),
		// ...

Index.html (using new bundle)

In your HTML, instead of a script tag for bundle.js, dynamically load your new bundle depending on query param ?lng={language}

<!-- <script defer src='/build/bundle.js'></script> -->
<script>
	var urlParams = new URLSearchParams(window.location.search);
	var language = urlParams.get('lng') || 'en';
	language = language.toLowerCase()

	var head = document.getElementsByTagName('head')[0];
	var script = document.createElement('script');
	script.type = 'module';
	script.src = '/build/bundle_' + language + '.js';
	head.appendChild(script);
</script>

Testing each language

And then use like so:

http://localhost:5000/?lng=es

TODO

  • [x] Test static HTML files (index.html => fr/index.html)
  • [x] Parse target folder (src) for all tags.
  • [x] Build JSON file of output.
  • [x] Load JSON file for input.
  • [x] Copy src/ to src/__generated__/${lang}/
  • [x] Replace each src/__generated__/${lang}/ with their translations.
  • [x] Clean up translation.json file, duplicates in there.
  • [x] Generate __generated__ folder, and language folders inside.
  • [x] Refactor, ready for tests
  • [ ] Copy of other folders (non translated) into dist.
  • [ ] Allow <title> translations, as this is parsed as a string inside the html. Do replace?
  • [ ] Test React.js cli starter
  • [x] Framework agnostic
  • [x] Test Svelte.js cli starter
  • [x] Test Vue.js cli starter
  • [ ] Typescript Support
  • [ ] Tests

Stretch goals

  • [ ] Look into an "escape keywork" for variables. Without handlebar variable ${var}, google translate can transform our variables: {name} becomes {nombre} etc.
    • [ ] Triple underscore idea: <t>Hello ___{name}___</t> => <t>Hola {name}</t>