Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/atilafassina/next-g11n
translate and localize your Next.js app smoothly
https://github.com/atilafassina/next-g11n
i18n jamstack nextjs typescript
Last synced: 2 months ago
JSON representation
translate and localize your Next.js app smoothly
- Host: GitHub
- URL: https://github.com/atilafassina/next-g11n
- Owner: atilafassina
- License: mit
- Created: 2021-09-12T18:14:11.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2021-10-10T13:19:19.000Z (about 3 years ago)
- Last Synced: 2024-10-12T23:44:47.750Z (3 months ago)
- Topics: i18n, jamstack, nextjs, typescript
- Language: TypeScript
- Homepage:
- Size: 739 KB
- Stars: 27
- Watchers: 3
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## next-g11n ๐
Your toolbelt for translating Next.js apps
![npm badge](https://img.shields.io/npm/v/next-g11n?color=%23df0000&style=flat-square)
![typescript badge](https://img.shields.io/npm/types/next-g11n?style=flat-square)๐ชก tailor-made for [Next.js i18n Routing](https://nextjs.org/docs/advanced-features/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:
```ts
{
'locale-key': {
'translation-key': 'value - number or string'
}
}
```Copy/paste example
```ts
// 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',
},
}
```3. 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`.
```tsx
const router = useRouter()
const g11nLocale = getLocale(router) as Locales
```## Client-side only ๐ช
When you call your hook, establish the types for the dictionary
```tsx
import type { NextPage } from 'next'
import { useG11n } from 'next-g11n'
import { DICTIONARY } from '../dictionary'const Home: NextPage = () => {
const { translate: t } = useG11n(DICTIONARY)return (
{t('hello')}
)
}```
> โ ๏ธ 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`.
```tsx
const Home = ({ hello }: InferGetStaticPropsType) => {
const router = useRouter()
const g11nLocale = getLocale(router) as Localesreturn
{hello[g11nLocale]}
}export const getStaticProps = async () => {
const hello = createStaticTerm('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.
Why 2 methods?
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.
```tsx
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.
```tsx
export type Locales = keyof typeof DICTIONARYconst Page = ({ rawTerm }: InferGetStaticPropsType) => {
const router = useRouter()
const g11nLocale = getLocale(router) as Locales
const term = clientSideTranslate(rawTerm)return
{term[g11nLocale]({ var1: 'foo', var2: 'bar' })}
}
```## Examples ๐ฑ
| directory | description |
| ---------------------------------------------------------- | ------------------------------------------- |
| [client-side](tree/main/example/client-side) | minimal setup for Client-side translations |
| [server-side-render](tree/main/example/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 |