andrei-bread-i18n
Version:
Small and type-safe package to create multi-language interfaces.
76 lines (75 loc) • 2.46 kB
JavaScript
import { useCallback, useContext, useEffect, useReducer, useRef, useState, } from "react";
import { I18NContext } from "./context";
function useI18NContext() {
const i18n = useContext(I18NContext);
if (!i18n) {
throw new Error("can not `useI18NContext` outside of the `I18NProvider`");
}
return i18n;
}
export function useI18N() {
const i18n = useI18NContext();
const [{ langState, updateCount }, setLangState] = useState(() => ({
langState: i18n.getLang(),
updateCount: 0,
}));
const usesLang = useRef(false);
useEffect(() => {
i18n.subscribe((lang) => {
// only update the state if
// the lang is used
if (!usesLang.current) {
return;
}
setLangState((state) => ({
langState: lang,
updateCount: state.updateCount + 1,
}));
});
}, [i18n]);
const get = useCallback((key, ...rest) => {
usesLang.current = true;
return i18n.get(key, ...rest);
},
// include the `updateCount` into the deps array
// so that `get` function changes it's reference whenever
// the languages changes or the translations are loaded
[i18n, updateCount]);
const getLang = useCallback(() => {
usesLang.current = true;
return i18n.getLang();
},
// include the `langState` into the deps array
// so that `get` function changes it's reference whenever
// the languages changes
[i18n, langState]);
const setLang = useCallback((newLang) => i18n.setLang(newLang), [i18n]);
const subscribe = useCallback((cb, options) => i18n.subscribe(cb, options), [i18n]);
const reactI18N = {
get lang() {
usesLang.current = true;
return langState;
},
get,
getLang,
setLang,
subscribe,
};
return reactI18N;
}
export function useTranslate() {
const i18n = useI18NContext();
const [updateCount, triggerUpdate] = useReducer((v) => v + 1, 0);
useEffect(() => {
return i18n.subscribe(() => {
triggerUpdate();
});
}, []);
const translate = useCallback((key, ...rest) => {
return i18n.get(key, ...rest);
},
// include the `updateCount` into the deps array
// so that translate changes it's reference whenever the language changes
[updateCount]);
return translate;
}