2.0.0 • Published 11 days ago

@ts-intl/integration v2.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
11 days ago

All in one

Start

pnpm i @ts-intl/eslint-plugin-ts-intl --save-dev
pnpm i eslint-plugin-jsonc --save-dev
pnpm i @ts-intl/integration
npx ts-intl-integrate

config entries, locale folder and supported languages in ts-intl.config.json

Build your project

npx ts-intl-cache # generate i18n deps first
pnpm build # your build command

remember add cache file to .gitignore

Choose a translate func

install translation packages your prefer, like next-intl

required interfaces:

type IntlProvider = ({ defaultLanguage, currentLanguage, dictionary, children }) => ReactNode

interface TSignature {
  (key, vars?: any) => string,
  rich: (key, vars?: any) => ReactNode,
}

type UseTranslations => () => TSignature

example:

const t = useTranslations();
t('namespace A.module A.hello world!');
t.rich('namespace A.module A.hello <b>world</b>!', {
  b: (child) => <b>{child}</b>,
});

SSG runtime (nextjs)

when nextConfig.output === 'export', next do not support built-in nextConfig.i18n, to enable i18n:

pages structure:

pages
  - pageA.ts
  - [lang]
    - pageA.ts

@ts-intl/integration provider runtime utils to hide complexity

import { IntlUtilsBrowser } from '@ts-intl/integration';
const intlUtilsBrowser = new IntlUtilsBrowser(languageConfig);

default useRouter or router:

const {
  pathname, // /[lang]/pageA/[paramA]
  asPath, // /ko/pageA/paramA?a=b
  locale, // undefined
} = useRouter();

after enhanced:

const router = useRouter();
const enhancedRouter = intlUtilsBrowser.enhanceRouter(router);
const {
  pathname, // /pageA/[paramA]
  asPath, // /pageA/paramA?a=b
  locale, // ko
} = enhancedRouter;

enhancedRouter.push, enhancedRouter.replace, only support page path as pathname, do not support external and as

// wrong!
enhancedRouter.push('/pageA/paramA');
enhancedRouter.push('/[lang]/pageA/paramA');

// accept
enhancedRouter.push('/pageA/staticA');
enhancedRouter.push({
  pathname: '/pageA/[paramA]'
  query: {
    paramA: 'paramA',
    queryA: 'queryA'
  },
}, {
  locale: 'ko'
});

SSG/SSR build

Build time utils

import { IntlUtilsServer } from '@ts-intl/integration';
import { resolve } from 'path';
import { languageConfig } from './config';

const intlUtilsServer = new IntlUtilsServer(languageConfig);

export const getStaticPathsWithI18n = intlUtilsServer.getStaticPaths;

type GetDepsProps = Parameters<typeof intlUtilsServer.withI18nDeps>;
export const withI18nDeps = (props: Omit<GetDepsProps[0], 'rootDir' | 'isEntryDepsEnabled'>, mode: GetDepsProps[1] = 'ssg') =>
  intlUtilsServer.withI18nDeps(
    {
      ...props,
      rootDir: resolve(__dirname, '../../../'), // config your rootDir
      isEntryDepsEnabled: process.env.NODE_ENV === 'production',
    },
    mode,
  );

SSG

pages/[lang]/pageA.ts:

export const getStaticPaths = getStaticPathsWithI18n;

export const getStaticProps: GetStaticProps = async (ctx) => {
  const getDeps = withI18nDeps(
    {
      // production mode
      // automatically collect depended keys
      // for dictionary extraction and optimization
      entry: 'src/pages/[lang]/pageA.ts',

      // development mode
      // for dictionary extraction
      ns: {
        include: ['common'],
      },
    },
    'ssg', // get locale from ctx.params?.[languageConfig.languageParamName]
  );
  return {
    props: {
      ...(await getDeps(ctx)),
    },
  };
};

SSR

pages/pageA.ts:

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const getDeps = withI18nDeps(
    {
      entry: 'src/pages/pageA.ts',
      ns: {
        include: ['common'],
      },
    },
    'ssr', // get locale from ctx.locale
  );
  return {
    props: {
      ...(await getDeps(ctx)),
    },
  };
};

Eslint

.eslintrc.js

{
  "extends": ["./ts-intl.eslintrc.js"]
}

Unused keys

npx ts-intl-unused
2.0.0

11 days ago

1.2.0

13 days ago

1.1.1

17 days ago

1.1.0

17 days ago