Skip to content

Instantly share code, notes, and snippets.

@gquittet
Last active April 10, 2023 10:51
Show Gist options
  • Save gquittet/0a858a9934bb05d1c23702c96f1a6d82 to your computer and use it in GitHub Desktop.
Save gquittet/0a858a9934bb05d1c23702c96f1a6d82 to your computer and use it in GitHub Desktop.
i18n typescript try
const locale = {
"en-us": {
greetings: {
hello: "Hello {{user}} and {{user}}",
goodMorning: "Good morning"
},
cat: {
"one": "% cat",
"many": "% cats"
},
name: "name",
bye: {
goodBye: "Good bye"
}
},
"fr-be": {
greetings: {
hello: "Bonjour {{user}}",
goodMorning: "Bon matin"
},
cat: {
"one": "% chat",
"many": "% chats"
},
name: "nom",
bye: {
goodBye: "Au revoir"
}
}
}
type LocaleMap = typeof locale
type LocaleName = keyof LocaleMap
type Locale = LocaleMap[LocaleName]
type PathInfo<T extends Record<string, any>> = keyof {
[K in keyof T as (T[K] extends string ? K : T[K] extends Record<string, any> ? `${K & string}.${PathInfo<T[K]> & string}` : never)]: any
}
const replace = (str: string, param: string | Record<string, string>) => {
if (typeof param === 'string') {
return str.replace(/%/g, param);
}
return Object.entries(param).reduce((_, [key, value]) => {
return str.replace(new RegExp(`{{${key}}}`, "g"), value);
}, str);
}
const i18n = (lang: LocaleName) => (key: PathInfo<Locale>, param?: string | Record<string, string>): string => {
const path = key.split(".");
let current: any = locale[lang];
for (const k of path) {
current = current[k];
if (current === undefined) break;
}
if (typeof current === 'string') {
return param ? replace(current, param) : current;
}
throw new Error("Invalid i18n key.")
}
const t = i18n("en-us")
// console.log(t("greetings.hello", { user: 'Guillaume' }))
console.log(t("cat.one", "0"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment