@supunlakmal/hooks
Version:
A collection of reusable React hooks
90 lines • 3.77 kB
JavaScript
import { useState, useEffect, useCallback } from 'react';
// Helper function to get nested values from the translation object
const getNestedValue = (obj, key) => {
const keys = key.split('.');
let current = obj;
for (const k of keys) {
if (current && typeof current === 'object' && k in current) {
current = current[k];
}
else {
return undefined; // Key path not found
}
}
return typeof current === 'string' ? current : undefined;
};
/**
* Custom hook for basic internationalization (i18n).
* Manages language state, loads translations (statically defined here), and provides a translation function.
*
* @param {Record<string, () => Promise<{ default: Translations }>>} resources - An object where keys are language codes (e.g., 'en')
* and values are functions that return a Promise resolving to the translation module (e.g., `() => import('./locales/en.json')`).
* **Note**: For this basic example, we'll simulate static loading directly in the hook.
* @param {string} initialLanguage - The default language code to use.
* @returns {UseTranslationResult} An object with language state, setter, translation function, loaded translations, and loading status.
*/
export const useTranslation = (
// In a real app, resources would likely be passed in or configured globally.
// For simplicity, we'll define some static resources here.
staticResources = {
en: {
greeting: 'Hello',
farewell: 'Goodbye',
button: {
submit: 'Submit',
cancel: 'Cancel',
},
message: 'This is a sample message.',
},
es: {
greeting: 'Hola',
farewell: 'Adiós',
button: {
submit: 'Enviar',
cancel: 'Cancelar',
},
message: 'Este es un mensaje de ejemplo.',
},
}, initialLanguage = 'en' // Default to English
) => {
const [language, setLanguage] = useState(initialLanguage);
const [translations, setTranslations] = useState({});
const [isLoaded, setIsLoaded] = useState(false);
// Effect to "load" translations when the language changes
useEffect(() => {
setIsLoaded(false);
const loadTranslations = async () => {
// Simulate loading based on the static resources provided
if (staticResources[language]) {
setTranslations(staticResources[language]);
}
else {
console.warn(`Translations for language "${language}" not found. Falling back to initial language or empty.`);
// Optionally fall back to the initial language or default
const fallbackLang = Object.keys(staticResources)[0] || '';
setTranslations(staticResources[fallbackLang] || {});
// Optionally set language back to fallback if desired
// setLanguage(fallbackLang);
}
setIsLoaded(true);
};
loadTranslations();
}, [language, staticResources, initialLanguage]);
// The translation function `t`
const t = useCallback((key, fallback) => {
var _a;
if (!isLoaded) {
return fallback !== null && fallback !== void 0 ? fallback : key; // Return fallback or key if not loaded yet
}
const translatedValue = getNestedValue(translations, key);
return (_a = translatedValue !== null && translatedValue !== void 0 ? translatedValue : fallback) !== null && _a !== void 0 ? _a : key; // Return translation, fallback, or the key itself
}, [translations, isLoaded]);
return {
language,
setLanguage,
t,
translations,
isLoaded,
};
};
//# sourceMappingURL=useTranslation.js.map