Все за back-end та back-end, ще подумаєте що ми фронта не знаємо 😅
Останнім часом нас трохи занесло в оцей весь micro Front-End. Ми розробляємо окремі модулі powered by ReactJS, котрі вбудовуються в батьківську App (CRM, яка також на ReactJS).
CRM-ка росте і постало питання локалізації наших модулів. Як отримати в нашому модулі (котрий є скажімо так, “чужим” для даної CRM) мову, котру обрав користувач в налаштуваннях порталу?
В хід пішов всім відомий i18next
+ Реактівський Context
.
*Так, якщо потрібен коректний переклад, то поки що в широких масах немає нормального автоматизованого інструменту 🤷🤷♀
i18n
.use(initReactI18next)
.use(
resourcesToBackend((language: string, namespace: string, callback) => {
import(`./locales/${language}/${namespace}.json`)
.then((resources) => {
callback(null, resources);
})
.catch((error) => {
callback(error, null);
});
})
)
.init({
fallbackLng: "uk",
});
По коду вище видно, що весь текстовий контент (переклади) знаходяться в директорії locales
. Вона вміщує в себе окремі піддиректорії із мовними версіями. Разом із тим, в директорії із конкретною мовою може знаходитися декілька файлів. Для чого? Тому що, різні компоненти модуля можуть вбудовуватися у різних місцях батьківської апки. Таким чином, конкретний компонент модуля використовує переклади необхідні саме для нього, а не тягне всі текстовки.
Основна ж магія відбувається тут 👇
const Providers: React.FC<{
children: React.ReactNode,
userSettings?: UserSettings,
}> = ({ children, userSettings }) => {
return (
<UserSettingsProvider userSettings={userSettings}>
<LocalizationProvider>{children}</LocalizationProvider>
</UserSettingsProvider>
);
};
Два провайдери: UserSettings
та Localization
. У UserSettings
ми якраз і отримуємо всі налаштування юзера на порталі.
export const UserSettingsContext = React.createContext<UserSettingsContextType>({});
// рядок нижче дає нам змогу із будь-якого компоненту, обгорнутого в провайдер діставати всі налаштування користувача
export const useUserSettingsContext = () =>
useContext<UserSettingsContextType>(UserSettingsContext);
const Provider: React.FC<Props> = ({ children, userSettings }) => {
return (
<UserSettingsContext.Provider value={{ userSettings }}>
{children}
</UserSettingsContext.Provider>
);
};
Localization бере в роботу i18n
:
export const LocalizationContext = React.createContext<LocalizationContextType>({});
const Provider: React.FC<Props> = ({ children }) => {
const { userSettings } = useUserSettingsContext();
useEffect(() => {
i18n.changeLanguage(userSettings?.lang);
}, [userSettings?.lang]);
return (
<LocalizationContext.Provider value={{ userSettings }}>
<I18nextProvider i18n={i18n}>{children}</I18nextProvider>
</LocalizationContext.Provider>
);
};
Ну і how to use? 👩💻
Жив собі компонент модуля, який мав такий експорт:
export default Component;
А тепер з локалізацією став таким:
const ComponentWrap: React.FC<Props> = ({ userSettings }) => (
<Providers userSettings={userSettings}>
<Component />
</Providers>
);
export default ComponentWrap;
to be continued 😉