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

i18n-google-sheets

v0.3.0

Published

Translations fetcher from Google Sheets with automatic TypeScript type generation for react-intl

Readme

Install

 npm install i18n-google-sheets --save-dev

Google spreadsheet example

Sheet named "controls" | key | en | es | | ----- | ----- | ----- | | ready | ready | listo |

Sheet named "root" (or "all") | key | en | es | | --- | --- | --- | | yes | yes | si |

Both sheets will be fetched and processed into the following files:

en.json

{
    "controls": {
        "ready": "ready"
    },
    "yes": "yes"
}

es.json

{
    "controls": {
        "ready": "listo"
    },
    "yes": "si"
}

Google API Credentials

Create an API key or service account with API key on google cloud

Enable the google sheets API for your project

Create a .env file with the GOOGLE API CREDENTIALS

### If you're using a service account to access translations set the path to the credentials:
### Don't forget to give your service account at least view permission

GOOGLE_APPLICATION_CREDENTIALS='./credentionals.json'

### If you're using an API KEY set the following:
### Don't forget to share your google sheet 

GOOGLE_API_KEY=<api_key>

SPREADSHEET_ID=<spreadsheet id from url>

### Optional: Set the base language for TypeScript type generation (defaults to 'en')
BASE_LANGUAGE=en

Run with npx

npx i18n-google-sheets

Run with npm

Add the following command to package.json

"scripts": {
    "i18n": "i18n-google-sheets"
}

and

npm run i18n

TypeScript Support

Auto-Generated Types

This package automatically generates TypeScript types for your translations using FormatJS official TypeScript support, providing full type safety when using react-intl.

After running the command, you'll find a generated type definition file in your translations folder:

translations/
  ├── en.json           # Your translation files
  ├── es.json
  ├── index.d.ts        # 🆕 Generated TypeScript types (FormatJS global augmentation)
  └── flatten.ts        # 🆕 Utility to flatten nested messages

The generated index.d.ts uses FormatJS official approach to augment global types, which means you use standard react-intl directly - no wrappers needed!

Using Typed Translations with React-Intl

Basic Setup

Important: Since FormatJS expects flat keys when using typed IDs, you need to flatten nested JSON:

import { IntlProvider } from 'react-intl';
import enMessages from './translations/en.json';
import { flattenMessages } from './translations/flatten';

function App() {
  return (
    <IntlProvider 
      messages={flattenMessages(enMessages)} 
      locale="en" 
      defaultLocale="en"
    >
      <YourApp />
    </IntlProvider>
  );
}

The flattenMessages utility converts nested structure like { title: { main: "Hello" } } into flat structure like { "title.main": "Hello" } which FormatJS expects.

Using Standard React-Intl with Type Safety

Simply import the generated types and use standard react-intl components and hooks:

// Import once in your app to enable types
import './translations/index.d.ts';

// Then use standard react-intl everywhere
import { FormattedMessage, useIntl } from 'react-intl';

function MyComponent() {
  const intl = useIntl();
  
  return (
    <div>
      {/* ✅ Full autocomplete and type checking */}
      <FormattedMessage id="controls.ready" />
      
      {/* ✅ Typed formatMessage with autocomplete */}
      {intl.formatMessage({ id: "yes" })}
      
      {/* ❌ TypeScript error: invalid key */}
      <FormattedMessage id="invalid.key" />
    </div>
  );
}

No wrappers, no custom hooks - just standard react-intl with full type safety!

Features

  • 🎯 Full Type Safety: Catch translation key errors at compile time, not runtime
  • ✨ IntelliSense: Get autocomplete for all available translation keys
  • 🔄 Auto-Generated: Types update automatically when you sync translations
  • 📦 Official FormatJS Approach: Uses FormatJS TypeScript support
  • 🚫 No Wrappers: Works directly with standard <FormattedMessage> and useIntl()
  • 🌍 Locale Types: Automatically types available locales too
  • 🌳 Nested Keys Support: Full support for nested translations (e.g., "controls.ready")
  • ⚠️ Key Validation: Warnings for keys with spaces or special characters

Configuration

Set the base language for type generation in your .env file:

BASE_LANGUAGE=en  # defaults to 'en' if not specified

The base language is used as the source of truth for generating TypeScript types.

Notes on Translation Keys

  • Nested keys use dot notation: "controls.ready" for { "controls": { "ready": "..." } }
  • Keys with spaces are supported but will show warnings: "controls.not ready"
    • Consider using camelCase (notReady) or underscores (not_ready) instead
  • Special characters in keys are allowed but may trigger validation warnings