Skip to content

Instantly share code, notes, and snippets.

@juliomerisio
Created November 28, 2022 13:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juliomerisio/94621a71857200a37dae1f8f74e52196 to your computer and use it in GitHub Desktop.
Save juliomerisio/94621a71857200a37dae1f8f74e52196 to your computer and use it in GitHub Desktop.
import { z } from 'zod';
type SupportedLocales = 'en-US' | 'pt-BR';
export const dictionaries: Record<
SupportedLocales,
Record<string, Record<string, string>>
> = {
'en-US': {
common: {
hello: 'Awesome!',
hi: 'Hello {{name}} {{age}}!',
bye: 'Goodbye {{name}}!',
how: 'blablabla',
banana: 'blablabla',
},
},
'pt-BR': {
common: {
hello: 'mundo',
hi: 'Ola {{name}} {{age}}!',
bye: 'Tchau {{name}}!',
how: 'xablau {{other}}',
banana: 'goiaba e {{bananinha}}',
},
},
};
let currentLocale: SupportedLocales = 'en-US';
export const initialTranslation = async (
locale: SupportedLocales = 'en-US'
) => {
await new Promise((resolve) => {
currentLocale = locale ?? currentLocale;
resolve(true);
});
};
const TranslationSchema = z.discriminatedUnion('key', [
z.object({
key: z.literal('common:hello'),
}),
z.object({
key: z.literal('common:hi'),
params: z.object({ name: z.string(), age: z.string() }),
}),
z.object({
key: z.literal('common:bye'),
params: z.object({ name: z.string() }),
}),
z.object({
key: z.literal('common:how'),
params: z.object({ other: z.string() }),
}),
z.object({
key: z.literal('common:banana'),
params: z.object({ bananinha: z.string() }),
}),
]);
export const t = (
key: z.infer<typeof TranslationSchema>,
locale: SupportedLocales = currentLocale
) => {
const [namespace, innerKey] = key.key.split(':');
const sentence = dictionaries[locale][namespace][innerKey];
let result = '';
if ('params' in key) {
Object.entries(key.params).forEach(([paramKey, paramValue]) => {
result = sentence.replace(`{{${paramKey}}}`, paramValue);
});
return result;
}
return sentence;
};
t({ key: 'common:hi', params: { name: 'John', age: '20' } }, 'pt-BR'); // Hello John 20!
t({ key: 'common:banana', params: { bananinha: 'banana' } }); // goiaba e banana
t({ key: 'common:hello' }); // Awesome!
@juliomerisio
Copy link
Author

TODO:

  • JSX components interpolation
  • Nested keys
  • Split namespaces into dedicated files (avoid merge conflicts)
  • Auto-generate Zod types based on RootDictionary
  • Secondary dictionaries implement RootDictionary contract

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment