Last active
June 11, 2025 10:03
-
-
Save aryomuzakki/d5259dfbf7319c480e0dd999416f4dda to your computer and use it in GitHub Desktop.
Mirror keys in en/translation.json file into other languages.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Mirror keys in en/translation.json file into other languages. | |
| * Will not overwrite, but non existing key will be removed. | |
| * | |
| * Add `ts-node` and `typescript` to devDependencies or global dependencies. | |
| * Run with global package: `ts-node ./mirror-translation-file.ts` | |
| * or | |
| * Run with `bunx ts-node ./mirror-translation-file.ts` | |
| * or | |
| * Add to package.json scripts: `i18n-mirror: "bunx ts-node ./mirror-translation-file.ts" | |
| * Run with `bun run i18n-mirror` | |
| */ | |
| /* eslint-disable @typescript-eslint/no-explicit-any */ | |
| /* eslint-disable @typescript-eslint/no-var-requires */ | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| // optional declare language target or get target from existing config | |
| const { languages } = require('./i18n-config'); | |
| // config | |
| const SOURCE_LANG = 'en'; | |
| const DEFAULT_NS = 'translation'; | |
| const BASE_PATH = './src/i18n/locales'; | |
| const LANGUAGES: string[] = languages || ['id', 'th']; | |
| // Paths to the source and target JSON files | |
| const sourceJsonPath = `${BASE_PATH}/${SOURCE_LANG}/${DEFAULT_NS}.json`; | |
| const targetJsonPath: string[] = LANGUAGES.filter(lang => lang != SOURCE_LANG); | |
| // Function to ensure directories and files are created | |
| const ensureDirectoryAndFile = (filePath: string) => { | |
| const dirName = path.dirname(filePath); | |
| if (!fs.existsSync(dirName)) { | |
| fs.mkdirSync(dirName, { recursive: true }); | |
| } | |
| if (!fs.existsSync(filePath)) { | |
| // Create an empty JSON file if it doesn't exist | |
| fs.writeFileSync(filePath, JSON.stringify({}, null, 2)); | |
| } | |
| }; | |
| // Reusable function to merge source and target JSON objects | |
| const mergeObjects = (source: any, target: any): any => { | |
| const result: any = {}; | |
| // A Set to track the keys of the source for faster lookup | |
| const sourceKeys = Object.keys(source); | |
| // Copy source keys into result in the same order | |
| sourceKeys.forEach(key => { | |
| if (typeof source[key] === 'object' && source[key] !== null) { | |
| // Recursively merge nested objects | |
| result[key] = mergeObjects(source[key], target[key] || {}); | |
| } else { | |
| // Copy the key if it's missing in the target | |
| if (!(key in target)) { | |
| result[key] = source[key]; | |
| } else { | |
| result[key] = target[key]; | |
| } | |
| } | |
| }); | |
| // Ensure that the target object only contains keys present in the source object | |
| const targetKeys = Object.keys(target); | |
| targetKeys.forEach(key => { | |
| if (!sourceKeys.includes(key)) { | |
| delete result[key]; | |
| } | |
| }); | |
| return result; | |
| }; | |
| // Function to merge source JSON into multiple destination JSONs | |
| const mergeJsonFiles = (sourcePath: string, langs: string[], namespace: string = DEFAULT_NS) => { | |
| console.log('!!! Non Existing key will be removed from destination files'); | |
| try { | |
| // Read the source JSON file | |
| const sourceJson = JSON.parse(fs.readFileSync(sourcePath, 'utf-8')); | |
| // Iterate over the langs array for each destination language | |
| langs.forEach(lang => { | |
| // Generate target path for the current language | |
| const targetPath = `${BASE_PATH}/${lang}/${namespace}.json`; | |
| // Ensure the directory and file exist | |
| ensureDirectoryAndFile(targetPath); | |
| // Read the existing target JSON file | |
| const targetJson = JSON.parse(fs.readFileSync(targetPath, 'utf-8')); | |
| // Perform the merge operation | |
| const mergedJson = mergeObjects(sourceJson, targetJson); | |
| // Write the merged content back to the target JSON file | |
| const updatedJsonString = JSON.stringify(mergedJson, null, 2); | |
| fs.writeFileSync(targetPath, updatedJsonString, 'utf-8'); | |
| console.log(`Successfully updated target JSON: ${targetPath}`); | |
| }); | |
| } catch (error: any) { | |
| console.error(`Error: ${error.message}`); | |
| } | |
| }; | |
| // Call the function to merge JSON files | |
| mergeJsonFiles(sourceJsonPath, targetJsonPath); | |
| // output: | |
| // !!! Non Existing key will be removed from destination files | |
| // Successfully updated target JSON: ./src/i18n/locales/id/translation.json | |
| // Successfully updated target JSON: ./src/i18n/locales/th/translation.json |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment