2024-08-31 15:39:05 +02:00
|
|
|
import { atom } from "jotai";
|
|
|
|
import en from "../locales/en.json";
|
|
|
|
import ru from "../locales/ru.json";
|
2024-09-01 14:01:45 +02:00
|
|
|
import ja from "../locales/ja.json";
|
2024-09-03 09:34:58 +02:00
|
|
|
import zh from "../locales/zh.json";
|
|
|
|
import es from "../locales/es.json";
|
|
|
|
import fr from "../locales/fr.json";
|
2024-08-31 15:39:05 +02:00
|
|
|
import { atomWithStorage } from "jotai/utils";
|
|
|
|
|
|
|
|
// Define the shape of the translations
|
|
|
|
type Translations = typeof en;
|
2024-09-03 09:34:58 +02:00
|
|
|
type Locales = "en" | "ru" | "ja" | "zh" | "es" | "fr";
|
2024-08-31 15:39:05 +02:00
|
|
|
|
2024-10-04 11:15:54 +02:00
|
|
|
const translations: Record<Locales, Translations> = {
|
|
|
|
en,
|
|
|
|
ru,
|
|
|
|
ja,
|
|
|
|
zh,
|
|
|
|
es,
|
|
|
|
fr,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Create a type for nested key paths
|
|
|
|
type NestedKeyOf<Object> = Object extends object
|
|
|
|
? {
|
|
|
|
[Key in keyof Object]: Key extends string | number
|
|
|
|
? Key | `${Key}.${NestedKeyOf<Object[Key]>}`
|
|
|
|
: never;
|
|
|
|
}[keyof Object]
|
|
|
|
: never;
|
|
|
|
|
2024-08-31 15:39:05 +02:00
|
|
|
// Utility function to access nested translation keys
|
2024-10-04 11:15:54 +02:00
|
|
|
const getNestedTranslation = (
|
|
|
|
obj: Translations,
|
|
|
|
key: NestedKeyOf<Translations>,
|
|
|
|
): string => {
|
|
|
|
// Split the key into an array of nested parts
|
|
|
|
const keyParts = key.split(".");
|
|
|
|
|
|
|
|
// Traverse the object using the key parts
|
|
|
|
const result = keyParts.reduce((currentObj, part) => {
|
|
|
|
// If currentObj is falsy or doesn't have the property, return undefined
|
|
|
|
return currentObj && currentObj[part];
|
|
|
|
}, obj);
|
|
|
|
|
|
|
|
// Return the found translation or the original key if not found
|
|
|
|
return result || key;
|
2024-08-31 15:39:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Atom to store the current locale
|
|
|
|
export const localeAtom = atomWithStorage<Locales>("language", "en");
|
|
|
|
|
|
|
|
// Atom to get the translation function based on the current locale
|
|
|
|
export const translationAtom = atom((get) => {
|
|
|
|
const locale = get(localeAtom);
|
|
|
|
|
2024-10-04 11:15:54 +02:00
|
|
|
return (
|
|
|
|
key: NestedKeyOf<Translations>,
|
|
|
|
params: Record<string, string> = {},
|
|
|
|
): string => {
|
2024-08-31 15:39:05 +02:00
|
|
|
const template = getNestedTranslation(translations[locale], key);
|
|
|
|
|
|
|
|
// Replace placeholders with parameters, e.g., {name} => John
|
|
|
|
return Object.keys(params).reduce(
|
|
|
|
(str, paramKey) => str.replace(`{${paramKey}}`, params[paramKey]),
|
|
|
|
template,
|
|
|
|
);
|
|
|
|
};
|
|
|
|
});
|