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 🙏

© 2024 – Pkg Stats / Ryan Hefner

next-g11n

v1.1.0

Published

Your toolbelt for translating Next.js apps

Downloads

355

Readme

next-g11n 🌐

Your toolbelt for translating Next.js apps

npm badge typescript badge

🪡 tailor-made for Next.js i18n Routing

👮 Type-safe dictionaries

☁️ optimized for Server-Side Rendering

Getting started 🏗

  1. Install the dependency yarn add next-g11n or npm i next-g11n

  2. Create your dictionary.ts (or any other name, actually)

| type | default | | -------- | ------- | | object | - |

The translation object/map. It can either carry one locale, or all. The object format is as follows:

{
  'locale-key': {
    'translation-key': 'value - number or string'
  }
}
// example dictionary.ts
const dictionary = {
  // top level are locales (de) or (de-at), for example
  en: {
    // these are the translation keys
    hello: 'Hi',
  },
  'de-de': {
    hello: 'Hallo',
  },
  'de-at': {
    hello: 'Grüß Gott',
  },
}
  1. Choose between Client-Side-only or Server-Side translations

Helper methods 🧠

getLocale

Receives a router instance from Next.js useRouter and returns the current locale if supported by your app, or the defaultLocale.

const router = useRouter()
const g11nLocale = getLocale(router) as Locales

Client-side only 🪝

When you call your hook, establish the types for the dictionary

import type { NextPage } from 'next'
import { useG11n } from 'next-g11n'
import { DICTIONARY } from '../dictionary'

const Home: NextPage = () => {
  const { translate: t } = useG11n<typeof DICTIONARY>(DICTIONARY)

  return (
    <h1>{t('hello')}</h1>
  )
}

⚠️ this strategy will bring in the entire Dictionary to your bundle

useFallback

When true, if the translation does not exist in dictionary, the key will show. When set to false, it will throw an error.

| type | default | | --------- | ------- | | boolean | false |

† recomended for apps without TypeScript

Server-Side Rendering 🌤

Static Translations

Translations which do not require interpolation, can be completely rendered on the Server-Side within getStaticProps. An object with all translated terms will be injected in your page props.

const Home = ({ hello }: InferGetStaticPropsType<typeof getStaticProps>) => {
  const router = useRouter()
  const g11nLocale = getLocale(router) as Locales

  return <h1 className={styles.title}>{hello[g11nLocale]}</h1>
}

export const getStaticProps = async () => {
  const hello = createStaticTerm<Keys, Locales>('hello', DICTIONARY)

  return {
    props: {
      hello,
    },
  }
}

Interpolated Terms

To interpolate terms there are 2 methods required. On the server-side it’s required to map all possible translation terms (still with template variables) by locale with createFunctionTerm. That object can then be passed down to each page props. Once arriving on the client-side, it’s required to use clientSideTranslate to map each translation term to its method to interpolate the term with each variable and assign the proper types.

Functions are not serializable out-of-the-box in JavaScript, and getStaticProps only passes down serialized object as its returned props. It is possible to call both methods on the server if you handle serializing the output functions. But then again, it will be required to deserializing them on the client-side.

createFunctionTerm (server-side)

This method will receive a translation key, and the whole dictionary. It will output a raw translation term (with uninterpolated variables). This is an object literal ready to be serialized by getStaticProps on its way to the client-side.

const rawTerm = createFunctionTerm('term', DICTIONARY)

clientSideTranslate (client-side)

Once on the client-side, this method will receive the raw term from createFunctionTerm and ouput one method for each supported locale. This method is a TypeScript generic, first parameter is your Locales exported from your whole dictionary, and the second is a string union with each available parameter for that translation term.

export type Locales = keyof typeof DICTIONARY

const Page = ({ rawTerm }: InferGetStaticPropsType<typeof getStaticProps>) => {
  const router = useRouter()
  const g11nLocale = getLocale(router) as Locales
  const term = clientSideTranslate<Locales, 'var1' | 'var2'>(rawTerm)

  return <h1>{term[g11nLocale]({ var1: 'foo', var2: 'bar' })}</h1>
}

Examples 🍱

| directory | description | | ---------------------------------------------------------- | ------------------------------------------- | | client-side | minimal setup for Client-side translations | | server-side-render | minimal setup for SSR-friendly translations |

Additional info ❓

  • Support starts with Next.js i18n Routing, so v10+
  • Next.js is a peerDependency
  • React is a peerDependency

Glossary 📖

| abbreviation | full word | meaning | | ------------ | -------------------- | ---------------------------------------------------- | | i18n | internationalization | enable adaptation of a product to multiple languages | | L10n | localization | translating and customizing to a specific place | | g11n | globalization | addressing requirements to launch globally |