A lightweight translation library for React/Preact projects with a similar interface to react-i18next
.
Made with ❤️ by loveholidays.com
- Tree-shakeable
- Similar interface to
react-i18next
- Native ESM module with TypeScript type definitions
- Small bundle size (~1kb)
This package exports native ESM and does not provide a CommonJS export.
Package | Bundle size (gzip) | Difference |
---|---|---|
@loveholidays/phrasebook | 1.1kb | baseline |
@lingui/[email protected] | 1.4kb | + 27% |
[email protected] | 5.3kb | + 482% |
Currently available on NPM:
$ npm i -S @loveholidays/phrasebook
- or -
$ yarn add @loveholidays/phrasebook
We can use yalc for this, which creates a local store that we can publish and pull dependencies from.
To publish Phrasebook to the local store:
npx --yes yalc publish
In your target repo (eg. sunrise), update the dependency to local Phrasebook:
npx yalc add @loveholidays/phrasebook
If you make a change in your local Phrasebook repo, update the local store and the target repo:
npx yalc publish --push
To reset the dependency of Phraseboook, in your target repo run:
npx yalc remove @loveholidays/phrasebook
Use the TranslationProvider
to create the localisation context:
import { TranslationProvider } from '@loveholidays/phrasebook';
const App = () => (
<TranslationProvider
locale="en-gb"
translations={translations}
onError={(errorType, data) => {
const { key, argumentName } = data;
}}
>
// ...
</TranslationProvider>
);
The locale
string is used for locale specific number formatting.
The translations
object follows a format similar to the i18next JSON format with some exceptions.
Use the useTranslation
hook to access the translation function:
import { useTranslation } from '@loveholidays/phrasebook';
const MyComponent = () => {
const { t } = useTranslation();
return (
<>
<h1>{t('helloWorld')}</h1>
<h2>{t('welcomeBack', { name: 'David' })}</h2>
<p>{t('youHaveXNewMessages', { count: 14 })}</p>
</>
);
};
Use the Translation
component to embed React components into the translations (similar to the Trans component of react-i18next
):
import { Translation } from '@loveholidays/phrasebook';
const MyComponent = () => (
<p>
<Translation
translationKey="myKey" // "Read all the {count} reviews <1>here</1>, served by: <2>"
params={{
count: 1234,
}}
components={[
(text) => <a href="/#">{text}</a>, // text between <1> and </1> is passed in as a param
<img src="logo.svg" />,
]}
/>
</p>
);
// result: <p>Read all the 1234 reviews <a href="/#">here</a>, served by: <img src="logo.svg" /></p>
The goal is to provide a lightweight alternative for the most common used features of react-i18next
, although phrasebook won't ever be 100% compatible with that.
- There is no support for translation backends, the translation object must be loaded and passed in to the
TranslationProvider
. - The translation object format is not fully compatible with the i18next JSON format, the currently supported features are: nested translations,
_plural
suffix, contexts.
Namespaced translations can be used with <TranslationProvider />
by passing an object into the namespaces
prop - where the keys are the names of the namespaces and the values are the translations for the given namespace:
<TranslationProvider
locale={locale}
namespaces={{
homepage: {
title: 'Homepage',
},
checkout: {
title: 'Checkout',
},
}}
>
The ns
option controls the namespace when using the t
function:
const { t } = useTranslation();
const homepageTitle = t('title', { ns: 'homepage' });
const checkoutTitle = t('title', { ns: 'checkout' });
To avoid repeating the ns
option when using t
, the default namespace can be changed when using the useTranslation
hook:
const { t } = useTranslation('homepage');
const homepageTitle = t('title');
const checkoutTitle = t('title', { namespace: 'checkout' });
The Translation
component takes an optional namespace
prop to achieve the same:
<Translation
translationKey="myKey"
namespace="myNamespace"
params={ ... }
components={ ... }
/>
We highly recommend to use the i18n ally extension for VS Code users. To make it work with phrasebook you need to add this file to your project:
# .vscode/i18n-ally-custom-framework.yml
languageIds:
- javascript
- typescript
- javascriptreact
- typescriptreact
usageMatchRegex:
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
monopoly: false
Please see our contributing guidelines