Skip to content

Commit

Permalink
feat(localizationprovider): initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulFasola committed Mar 20, 2021
1 parent eb93012 commit beecaa5
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/providers/localization/ILocalizationContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defaultLocale } from './defaultLocalization';
import { ILocalizedStrings } from './ILocalizedStrings';

export type LocaleType = typeof defaultLocale | string;

export interface IViableLocale {
locale: LocaleType;
strings: ILocalizedStrings;
}

export interface ILocalizationContext {
currentlocalization: IViableLocale;
switchTo: (lang: LocaleType) => void;
}
3 changes: 3 additions & 0 deletions src/providers/localization/ILocalizedStrings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ILocales as IPRLocales } from '../../components/PaymentRequest/strings';

export interface ILocalizedStrings extends IPRLocales {}
11 changes: 11 additions & 0 deletions src/providers/localization/defaultLocalization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IViableLocale } from './ILocalizationContext';
import { defaultStrings as defaultPRStrings } from '../../components/PaymentRequest/strings';

export const defaultLocale = 'en-US';

export const defaultLocalization: IViableLocale = {
locale: defaultLocale,
strings: {
...defaultPRStrings,
},
};
84 changes: 84 additions & 0 deletions src/providers/localization/localizationProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React, { useCallback, useEffect, useState } from 'react';
import { ILocalizationContext, IViableLocale, LocaleType } from './ILocalizationContext';
import { mergeDeep } from '../../utils/mergeDeep';
import { ILocalizedStrings } from './ILocalizedStrings';
import { defaultLocale, defaultLocalization } from './defaultLocalization';

const LOCAL_STORAGE_KEY = 'adoption-locale';

interface IProps {
customLocales?: Record<string, Partial<ILocalizedStrings>>;
}

/* istanbul ignore next */
export const LocalizationContext = React.createContext<ILocalizationContext>({
currentlocalization: defaultLocalization,
switchTo: () => {},
});

export const LocalizationProvider: React.FC<IProps> = ({ customLocales, children }) => {
const [availableLocales, setAvailableLocales] = useState<Record<string, ILocalizedStrings>>({
[defaultLocale]: defaultLocalization.strings,
});

const [currentlocalization, setCurrentLocalization] = useState<IViableLocale>(
defaultLocalization
);

const setViableLocaleOrDefault = useCallback(
(locale: LocaleType): [string, ILocalizedStrings] => {
const requestedStrings = availableLocales[locale] as ILocalizedStrings;
let viableLocalization = defaultLocalization;

if (requestedStrings) {
viableLocalization = {
locale,
strings: requestedStrings,
};
} else {
console.warn(`[WARN] Adoption Localization - requested locale "${locale}" was not found. Defaulting to "${locale}" preset.\n
Add your locale to 'customLocales' property on <LocalizationProvider>.
Available locales: ${Object.keys(availableLocales).join(', ')}`);
}

setCurrentLocalization(viableLocalization);

return [locale, requestedStrings];
},
[availableLocales]
);

useEffect(() => {
const locale = localStorage.getItem(LOCAL_STORAGE_KEY) ?? defaultLocalization.locale;
setViableLocaleOrDefault(locale);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
if (!customLocales || Object.keys(customLocales).length === 0) return;
const filledCustomLocales: Record<string, ILocalizedStrings> = {};

Object.keys(customLocales).forEach((key) => {
const viableLocale = (mergeDeep(
defaultLocalization.strings,
customLocales[key]
) as unknown) as ILocalizedStrings;
filledCustomLocales[key] = viableLocale;
});

setAvailableLocales((prevState) => {
return { ...prevState, ...filledCustomLocales };
});
}, [customLocales]);

const switchTo = (nextLocale: LocaleType) => {
const [name] = setViableLocaleOrDefault(nextLocale);
localStorage.setItem(LOCAL_STORAGE_KEY, name);
};

return (
<LocalizationContext.Provider value={{ currentlocalization, switchTo }}>
{children}
</LocalizationContext.Provider>
);
};

0 comments on commit beecaa5

Please sign in to comment.