1 const fs = require("fs");
3 const translationDir = "lemmy-translations/translations/";
4 const outDir = "src/shared/translations/";
5 fs.mkdirSync(outDir, { recursive: true });
6 fs.readdir(translationDir, (_err, files) => {
7 files.forEach(filename => {
8 const lang = filename.split(".")[0];
10 const json = JSON.parse(
11 fs.readFileSync(translationDir + filename, "utf8")
13 let data = `export const ${lang} = {\n translation: {`;
14 for (const key in json) {
16 const value = json[key].replace(/"/g, '\\"');
17 data += `\n ${key}: "${value}",`;
21 const target = outDir + lang + ".ts";
22 fs.writeFileSync(target, data);
29 // generate types for i18n keys
30 const baseLanguage = "en";
32 fs.readFile(`${translationDir}${baseLanguage}.json`, "utf8", (_, fileStr) => {
33 const noOptionKeys = [];
34 const optionKeys = [];
35 const optionRegex = /\{\{(.+?)\}\}/g;
36 const optionMap = new Map();
38 for (const [key, val] of Object.entries(JSON.parse(fileStr))) {
41 let match = optionRegex.exec(val);
43 match = optionRegex.exec(val)
45 options.push(match[1]);
48 if (options.length > 0) {
49 optionMap.set(key, options);
52 noOptionKeys.push(key);
58 const data = `import { i18n } from "i18next";
60 declare module "i18next" {
61 export type NoOptionI18nKeys =
62 ${noOptionKeys.map(key => `${indent}| "${key}"`).join("\n")};
64 export type OptionI18nKeys =
65 ${optionKeys.map(key => `${indent}| "${key}"`).join("\n")};
67 export type I18nKeys = NoOptionI18nKeys | OptionI18nKeys;
69 export type TTypedOptions<TKey extends OptionI18nKeys> =${Array.from(
72 (acc, [key, options]) =>
73 `${acc} TKey extends \"${key}\" ? ${
74 options.reduce((acc, cur) => acc + `${cur}: string | number; `, "{ ") +
78 )} (Record<string, unknown> | string);
80 export interface TFunctionTyped {
81 // Translation requires options
83 TKey extends OptionI18nKeys | OptionI18nKeys[],
84 TResult extends TFunctionResult = string,
85 TInterpolationMap extends TTypedOptions<TKey> = StringMap
88 options: TOptions<TInterpolationMap> | string
91 // Translation does not require options
93 TResult extends TFunctionResult = string,
94 TInterpolationMap extends Record<string, unknown> = StringMap
96 key: NoOptionI18nKeys | NoOptionI18nKeys[],
97 options?: TOptions<TInterpolationMap> | string
101 export interface i18nTyped extends i18n {
107 fs.writeFileSync(`${outDir}i18next.d.ts`, data);