diff --git a/apps/website/docs/.vitepress/config.js b/apps/website/docs/.vitepress/config.js
index 064fcb63..434d1350 100644
--- a/apps/website/docs/.vitepress/config.js
+++ b/apps/website/docs/.vitepress/config.js
@@ -56,6 +56,17 @@ export default defineConfig({
sidebar: {
...createSidebar('i18next', [
{ text: 'Get Started', link: '/i18next/' },
+ {
+ text: 'API',
+ items: [
+ { text: '$t', link: '/i18next/t' },
+ { text: 'translated', link: '/i18next/translated' },
+ { text: '$isReady', link: '/i18next/is_ready' },
+ { text: 'reporting', link: '/i18next/reporting' },
+ { text: '$language', link: '/i18next/language' },
+ { text: 'changeLanguageFx', link: '/i18next/change_language_fx' },
+ ],
+ },
{ text: 'Release policy', link: '/i18next/releases' },
]),
...createSidebar('redux', [
diff --git a/apps/website/docs/i18next/change_language.md b/apps/website/docs/i18next/change_language.md
new file mode 100644
index 00000000..a5262ac8
--- /dev/null
+++ b/apps/website/docs/i18next/change_language.md
@@ -0,0 +1,15 @@
+# `changeLanguageFx`
+
+An [_Effect_](https://effector.dev/en/api/effector/effect/) that can be called with a language code to change the current language.
+
+```ts
+const { changeLanguageFx } = createI18nextIntegration({
+ /* ... */
+});
+
+sample({
+ clock: someButtonClicked,
+ fn: () => 'en',
+ target: changeLanguageFx,
+});
+```
diff --git a/apps/website/docs/i18next/index.md b/apps/website/docs/i18next/index.md
index d54fb44a..dddc241f 100644
--- a/apps/website/docs/i18next/index.md
+++ b/apps/website/docs/i18next/index.md
@@ -1,7 +1,3 @@
----
-outline: [2, 3]
----
-
# i18next
A powerful internationalization framework for Effector which is based on [i18next](https://www.i18next.com/).
@@ -26,17 +22,19 @@ npm install @withease/i18next i18next
:::
-## API
-
-### Initialization
+## Initialization
All you need to do is to create an integration by calling `createI18nextIntegration` with an integration options:
-- `instance`: an instance of i18next or [_Store_](https://effector.dev/docs/api/effector/store) with i18next instance; it is better to pass a [_Store_](https://effector.dev/docs/api/effector/store) because it will be possible to use isolated i18next instance and [avoid using global state](/magazine/global_variables).
+- `instance`: an instance of i18next in various forms.
- `setup`: after this [_Event_](https://effector.dev/en/api/effector/event/) all listeners will be installed, and the integration will be ready to use; it is required because it is better to use [explicit initialization _Event_ in the application](/magazine/explicit_start).
- `teardown?`: after this [_Event_](https://effector.dev/en/api/effector/event/) all listeners will be removed, and the integration will be ready to be destroyed.
-```ts
+### Use replaceable static `i18next` instance
+
+In the simplest case, you can pass an i18next instance to the integration.
+
+```ts{9-11}
import i18next from 'i18next';
import { createStore, createEvent, fork, allSettled } from 'effector';
import { createI18nextIntegration } from '@withease/i18next';
@@ -45,7 +43,9 @@ import { createI18nextIntegration } from '@withease/i18next';
const appStarted = createEvent();
// Create Store for i18next instance
-const $i18nextInstance = createStore(null);
+const $i18nextInstance = createStore(i18next.createInstance(/* ... */), {
+ serialize: 'ignore',
+});
const integration = createI18nextIntegration({
// Pass Store with i18next instance to the integration
@@ -53,136 +53,80 @@ const integration = createI18nextIntegration({
setup: appStarted,
});
-// You can fill $someInstance later during runtime
+// You can replace $someInstance later during runtime
// e.g., during fork on client or server
-
-const scope = fork({
- values: [[$i18nextInstance, i18next.createInstance(/* ... */)]],
-});
-
-await allSettled(appStarted, { scope });
```
-### Usage
-
-Returned from `createI18nextIntegration` integration contains the following fields:
-
-#### `$t`
-
-A [_Store_](https://effector.dev/docs/api/effector/store) containing a [translation function](https://www.i18next.com/overview/api#t), can be used anywhere in your app.
-
-```ts
-const { $t } = createI18nextIntegration({
- /* ... */
-});
-
-const $someTranslatedString = $t.map((t) => t('cityPois.buttonText'));
-```
+### Use replaceable asynchronous `i18next` instance
-The second argument is an optional object with options for the translation function.
+Sometimes you need to create an instance asynchronously. In this case, you can pass an [_Effect_](https://effector.dev/docs/api/effector/effect) that creates an instance.
-```ts
-const $city = createStore({ name: 'Moscow' });
+```ts{9-11}
+import i18next from 'i18next';
+import { createStore, createEvent, fork, allSettled } from 'effector';
+import { createI18nextIntegration } from '@withease/i18next';
-const { $t } = createI18nextIntegration({
- /* ... */
-});
+// Event that should be called after application initialization
+const appStarted = createEvent();
-const $someTranslatedString = combine({ city: $city, t: $t }, ({ city, t }) =>
- t('cityPois.buttonText', {
- cityName: city.name,
- })
+// Create Effect that creates i18next instance
+const createI18nextFx = createEffect(() =>
+ i18next.use(/* ... */).init(/* ... */)
);
-```
-
-In both cases, result will be a [_Store_](https://effector.dev/docs/api/effector/store) containing a translated string. It will be updated automatically when the language or available translations will be changed.
-
-#### `translated`
-
-A factory that returns [_Store_](https://effector.dev/docs/api/effector/store) containing a translated string.
-
-```ts
-const { translated } = createI18nextIntegration({
- /* ... */
-});
-
-const $someTranslatedString = translated('premiumLabel.BrandOne');
-```
-
-The second argument is an optional object with options for the translation function. Options can be a [_Store_](https://effector.dev/docs/api/effector/store) or a plain value.
-
-```ts
-const $city = createStore({ name: 'Moscow' });
-const { translated } = createI18nextIntegration({
- /* ... */
+const integration = createI18nextIntegration({
+ // Pass Effect that creates i18next instance to the integration
+ instance: createI18nextFx,
+ setup: appStarted,
});
-const $someTranslatedString = translated('cityPois.buttonText', {
- cityName: $city.map((city) => city.name),
-});
+// You can replace createI18nextFx later during runtime
+// e.g., during fork on client or server
```
-Also, you can pass a template string with [_Store_](https://effector.dev/docs/api/effector/store) parts of a key:
-
-```ts
-const $pathOfAKey = createStore('BrandOne');
-
-const { translated } = createI18nextIntegration({
- /* ... */
-});
-
-const $someTranslatedString = translated`premiumLabel.${$pathOfAKey}`;
-```
+### Use static `i18next` instance
-Result of the factory will be a [_Store_](https://effector.dev/docs/api/effector/store) containing a translated string. It will be updated automatically when the language or available translations will be changed.
+Even though it is better to use a replaceable instance to [avoid global state](/magazine/global_variables) and make it possible to replace the instance during runtime, you can pass a static instance as well.
-#### `$isReady`
+```ts{9}
+import i18next from 'i18next';
+import { createStore, createEvent } from 'effector';
+import { createI18nextIntegration } from '@withease/i18next';
-A [_Store_](https://effector.dev/docs/api/effector/store) containing a boolean value that indicates whether the integration is ready to use.
+// Event that should be called after application initialization
+const appStarted = createEvent();
-```ts
-const { $isReady } = createI18nextIntegration({
- /* ... */
+const integration = createI18nextIntegration({
+ instance: i18next.createInstance(/* ... */),
+ setup: appStarted,
});
```
-#### `$language`
+### Use static asynchronous `i18next` instance
-A [_Store_](https://effector.dev/docs/api/effector/store) containing the current language.
+The same approach can be used with an asynchronous instance.
-```ts
-const { $language } = createI18nextIntegration({
- /* ... */
-});
-```
-
-#### `changeLanguageFx`
-
-An [_Effect_](https://effector.dev/en/api/effector/effect/) that can be called with a language code to change the current language.
+```ts{9}
+import i18next from 'i18next';
+import { createStore, createEvent } from 'effector';
+import { createI18nextIntegration } from '@withease/i18next';
-```ts
-const { changeLanguageFx } = createI18nextIntegration({
- /* ... */
-});
+// Event that should be called after application initialization
+const appStarted = createEvent();
-sample({
- clock: someButtonClicked,
- fn: () => 'en',
- target: changeLanguageFx,
+const integration = createI18nextIntegration({
+ instance: () => i18next.use(/* ... */).init(/* ... */),
+ setup: appStarted,
});
```
-#### `reporting`
-
-An object with the following fields:
-
-- `missingKey`, [_Event_](https://effector.dev/en/api/effector/event/) will be triggered when a key is missing in the translation resources, requires [adding `saveMissing` option to the i18next instance](https://www.i18next.com/overview/api#onmissingkey).
+## Usage
-```ts
-const { reporting } = createI18nextIntegration({
- /* ... */
-});
+Returned from `createI18nextIntegration` integration contains the following fields:
-sample({ clock: reporting.missingKey, target: sendWarningToSentry });
-```
+- [`$t`](/i18next/t) is a [_Store_](https://effector.dev/docs/api/effector/store) containing a [translation function](https://www.i18next.com/overview/api#t)
+- [`translated`](/i18next/translated) which can be used as a shorthand for `$t`
+- [`$isReady`](/i18next/is_ready) is a [_Store_](https://effector.dev/docs/api/effector/store) containing a boolean value that indicates whether the integration is ready to use
+- [`reporting`](/i18next/reporting) is an object with the fields that allow you to track different events of the integration
+- [`$language`](/i18next/language) is a [_Store_](https://effector.dev/docs/api/effector/store) containing the current language
+- [`changeLanguageFx`](/i18next/change_language) is an [_Effect_](https://effector.dev/docs/api/effector/effect) that changes the current language
diff --git a/apps/website/docs/i18next/is_ready.md b/apps/website/docs/i18next/is_ready.md
new file mode 100644
index 00000000..598eb89f
--- /dev/null
+++ b/apps/website/docs/i18next/is_ready.md
@@ -0,0 +1,9 @@
+# `$isReady`
+
+A [_Store_](https://effector.dev/docs/api/effector/store) containing a boolean value that indicates whether the integration is ready to use.
+
+```ts
+const { $isReady } = createI18nextIntegration({
+ /* ... */
+});
+```
diff --git a/apps/website/docs/i18next/language.md b/apps/website/docs/i18next/language.md
new file mode 100644
index 00000000..bf660d5a
--- /dev/null
+++ b/apps/website/docs/i18next/language.md
@@ -0,0 +1,9 @@
+# `$language`
+
+A [_Store_](https://effector.dev/docs/api/effector/store) containing the current language.
+
+```ts
+const { $language } = createI18nextIntegration({
+ /* ... */
+});
+```
diff --git a/apps/website/docs/i18next/reporting.md b/apps/website/docs/i18next/reporting.md
new file mode 100644
index 00000000..f356f0ed
--- /dev/null
+++ b/apps/website/docs/i18next/reporting.md
@@ -0,0 +1,13 @@
+# `reporting`
+
+An object with the following fields:
+
+- `missingKey`, [_Event_](https://effector.dev/en/api/effector/event/) will be triggered when a key is missing in the translation resources, requires [adding `saveMissing` option to the i18next instance](https://www.i18next.com/overview/api#onmissingkey).
+
+```ts
+const { reporting } = createI18nextIntegration({
+ /* ... */
+});
+
+sample({ clock: reporting.missingKey, target: sendWarningToSentry });
+```
diff --git a/apps/website/docs/i18next/t.md b/apps/website/docs/i18next/t.md
new file mode 100644
index 00000000..1e8615dc
--- /dev/null
+++ b/apps/website/docs/i18next/t.md
@@ -0,0 +1,29 @@
+# `$t`
+
+A [_Store_](https://effector.dev/docs/api/effector/store) containing a [translation function](https://www.i18next.com/overview/api#t), can be used anywhere in your app.
+
+```ts
+const { $t } = createI18nextIntegration({
+ /* ... */
+});
+
+const $someTranslatedString = $t.map((t) => t('cityPois.buttonText'));
+```
+
+The second argument is an optional object with options for the translation function.
+
+```ts
+const $city = createStore({ name: 'Moscow' });
+
+const { $t } = createI18nextIntegration({
+ /* ... */
+});
+
+const $someTranslatedString = combine({ city: $city, t: $t }, ({ city, t }) =>
+ t('cityPois.buttonText', {
+ cityName: city.name,
+ })
+);
+```
+
+In both cases, result will be a [_Store_](https://effector.dev/docs/api/effector/store) containing a translated string. It will be updated automatically when the language or available translations will be changed.
diff --git a/apps/website/docs/i18next/translated.md b/apps/website/docs/i18next/translated.md
new file mode 100644
index 00000000..ea3173de
--- /dev/null
+++ b/apps/website/docs/i18next/translated.md
@@ -0,0 +1,39 @@
+# `translated`
+
+A factory that returns [_Store_](https://effector.dev/docs/api/effector/store) containing a translated string.
+
+```ts
+const { translated } = createI18nextIntegration({
+ /* ... */
+});
+
+const $someTranslatedString = translated('premiumLabel.BrandOne');
+```
+
+The second argument is an optional object with options for the translation function. Options can be a [_Store_](https://effector.dev/docs/api/effector/store) or a plain value.
+
+```ts
+const $city = createStore({ name: 'Moscow' });
+
+const { translated } = createI18nextIntegration({
+ /* ... */
+});
+
+const $someTranslatedString = translated('cityPois.buttonText', {
+ cityName: $city.map((city) => city.name),
+});
+```
+
+Also, you can pass a template string with [_Store_](https://effector.dev/docs/api/effector/store) parts of a key:
+
+```ts
+const $pathOfAKey = createStore('BrandOne');
+
+const { translated } = createI18nextIntegration({
+ /* ... */
+});
+
+const $someTranslatedString = translated`premiumLabel.${$pathOfAKey}`;
+```
+
+Result of the factory will be a [_Store_](https://effector.dev/docs/api/effector/store) containing a translated string. It will be updated automatically when the language or available translations will be changed.