Skip to content

Commit

Permalink
fix: TolgeeProvider initial loading with Suspense, language storage b…
Browse files Browse the repository at this point in the history
…ehavior, remove unnecessary prepare method
  • Loading branch information
stepan662 authored and JanCizmar committed Dec 9, 2022
1 parent f60e03c commit 00b7a94
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 30 deletions.
7 changes: 4 additions & 3 deletions packages/core/src/Controller/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,16 @@ export const Controller = ({ options }: StateServiceProps) => {
}

const checkCorrectConfiguration = () => {
const languageDetector = pluginService.getLanguageDetector();
if (languageDetector) {
const languageComputable =
pluginService.getLanguageDetector() || pluginService.getLanguageStorage();
if (languageComputable) {
const availableLanguages = state.getAvailableLanguages();
if (!availableLanguages) {
throw new Error(missingOptionError('availableLanguages'));
}
}
if (!state.getLanguage() && !state.getInitialOptions().defaultLanguage) {
if (languageDetector) {
if (languageComputable) {
throw new Error(missingOptionError('defaultLanguage'));
} else {
throw new Error(missingOptionError('language'));
Expand Down
25 changes: 5 additions & 20 deletions packages/core/src/Controller/Plugins/Plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ export const Plugins = (
getTranslation: (props: KeyAndNamespacesInternal) => string | undefined,
changeTranslation: ChangeTranslationInterface
) => {
let prepared = false;
let onPrepareQueue: (() => void)[] = [];
const plugins = {
ui: undefined as UiMiddleware | undefined,
observer: undefined as ObserverMiddleware | undefined,
Expand Down Expand Up @@ -116,6 +114,10 @@ export const Plugins = (
instances.languageStorage = storage;
};

const getLanguageStorage = () => {
return instances.languageStorage;
};

const setStoredLanguage = (language: string) => {
instances.languageStorage?.setLanguage(language);
};
Expand Down Expand Up @@ -231,10 +233,6 @@ export const Plugins = (
instances.observer?.retranslate();
};

const onPrepare = (callback: () => void) => {
onPrepareQueue.push(callback);
};

function addPlugin(tolgeeInstance: TolgeeInstance, plugin: TolgeePlugin) {
const pluginTools = Object.freeze({
setFinalFormatter,
Expand All @@ -247,12 +245,8 @@ export const Plugins = (
addBackend,
setLanguageDetector,
setLanguageStorage,
onPrepare,
});
plugin(tolgeeInstance, pluginTools);
if (prepared) {
prepare();
}
}

function formatTranslation({
Expand Down Expand Up @@ -316,23 +310,14 @@ export const Plugins = (
return params.translation;
};

function prepare() {
prepared = true;
while (onPrepareQueue.length) {
const queue = onPrepareQueue;
onPrepareQueue = [];
queue.forEach((callback) => callback());
}
}

return Object.freeze({
prepare,
addPlugin,
formatTranslation,
getDevBackend,
getBackendRecord,
getBackendDevRecord,
getLanguageDetector,
getLanguageStorage,
getInitialLanguage,
setStoredLanguage,
run,
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/__test/languageStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,10 @@ describe('language storage plugin', () => {
expect(tolgee.getLanguage()).toEqual('es');
});

it('will return invalid value if no available languages', () => {
it('will throw an error when no available languages are specified', () => {
tolgee = TolgeeCore().use(StoragePlugin('eq')).init({
defaultLanguage: 'es',
});
tolgee.run();
expect(tolgee.getLanguage()).toEqual('eq');
expect(() => tolgee.run()).toThrowError('availableLanguages');
});
});
1 change: 0 additions & 1 deletion packages/core/src/types/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ export type PluginTools = Readonly<{
setLanguageStorage: (
languageStorage: LanguageStorageMiddleware | undefined
) => void;
onPrepare: (callback: () => void) => void;
}>;

export type TolgeePlugin = (
Expand Down
38 changes: 37 additions & 1 deletion packages/react/src/TolgeeProvider.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
jest.autoMockOff();

import { Tolgee, TolgeeInstance } from '@tolgee/web';
import { Tolgee, TolgeeInstance, TolgeePlugin } from '@tolgee/web';

import '@testing-library/jest-dom';
import React from 'react';
import { TolgeeProvider } from './TolgeeProvider';

import { act, render, screen, waitFor } from '@testing-library/react';
import { createResolvablePromise } from '@tolgee/testing/createResolvablePromise';

describe('Tolgee Provider Component', () => {
let mockedTolgee: TolgeeInstance;
Expand Down Expand Up @@ -67,4 +68,39 @@ describe('Tolgee Provider Component', () => {
expect(loading).toBeNull();
});
});

test('renders fallback when language is being fetched', async () => {
const language = createResolvablePromise('en');

const storagePlugin: TolgeePlugin = (tolgee, { setLanguageStorage }) => {
setLanguageStorage({
getLanguage() {
return language.promise;
},
setLanguage() {},
});
return tolgee;
};
const tolgee = Tolgee()
.use(storagePlugin)
.init({
defaultLanguage: 'en',
staticData: {
en: {},
},
});
render(
<TolgeeProvider tolgee={tolgee} fallback="Loading...">
It's rendered!
</TolgeeProvider>
);
await waitFor(async () => {
expect(screen.getByText('Loading...')).toBeTruthy();
});
await act(async () => {
language.resolve();
await language.promise;
});
expect(screen.getByText("It's rendered!")).toBeTruthy();
});
});
8 changes: 6 additions & 2 deletions packages/react/src/TolgeeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ export const TolgeeProvider: React.FC<Props> = ({
<TolgeeProviderContext.Provider
value={{ tolgee, options: optionsWithDefault }}
>
<Suspense fallback={fallback || null}>{children}</Suspense>
{loading ? (
fallback
) : (
<Suspense fallback={fallback || null}>{children}</Suspense>
)}
</TolgeeProviderContext.Provider>
);
}
Expand All @@ -50,7 +54,7 @@ export const TolgeeProvider: React.FC<Props> = ({
<TolgeeProviderContext.Provider
value={{ tolgee, options: optionsWithDefault }}
>
{fallback && loading ? fallback : children}
{loading ? fallback : children}
</TolgeeProviderContext.Provider>
);
};
1 change: 1 addition & 0 deletions testapps/core/apps/lang_switching/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const tolgee = Tolgee()
.use(BackendFetch({ prefix: 'i18n' }))
.use(LanguageStorage())
.init({
availableLanguages: ['en', 'cs'],
highlightColor: 'yellow',
defaultLanguage: 'en',
fallbackLanguage: 'en',
Expand Down

0 comments on commit 00b7a94

Please sign in to comment.