@i18n-auto/core 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,167 @@
1
+ import { readdirSync, existsSync, readFileSync } from 'fs';
2
+ import { createHash } from 'crypto';
3
+ import { readFile, mkdir, writeFile } from 'fs/promises';
4
+ import { join } from 'path';
5
+
6
+ // src/i18n-auto.ts
7
+ var FileCache = class {
8
+ cachePath;
9
+ /**
10
+ * @param cachePath - Directory path where locale JSON files are stored
11
+ */
12
+ constructor(cachePath) {
13
+ this.cachePath = cachePath;
14
+ }
15
+ /**
16
+ * Loads all translations for a given locale from its JSON file.
17
+ * @param locale - The locale to load (e.g., 'ur', 'fr')
18
+ * @returns Key-value map of translations, or empty object if file doesn't exist
19
+ */
20
+ async load(locale) {
21
+ const filePath = this.getFilePath(locale);
22
+ if (!existsSync(filePath)) {
23
+ return {};
24
+ }
25
+ const content = await readFile(filePath, "utf-8");
26
+ return JSON.parse(content);
27
+ }
28
+ /**
29
+ * Synchronously loads all translations for a given locale.
30
+ * Used by the runtime t() method for fast, synchronous lookups.
31
+ * @param locale - The locale to load
32
+ * @returns Key-value map of translations, or empty object if file doesn't exist
33
+ */
34
+ loadSync(locale) {
35
+ const filePath = this.getFilePath(locale);
36
+ if (!existsSync(filePath)) {
37
+ return {};
38
+ }
39
+ const content = readFileSync(filePath, "utf-8");
40
+ return JSON.parse(content);
41
+ }
42
+ /**
43
+ * Saves translations for a locale to its JSON file.
44
+ * Creates the directory if it doesn't exist.
45
+ * @param locale - The locale to save
46
+ * @param data - Key-value map of translations
47
+ */
48
+ async save(locale, data) {
49
+ await mkdir(this.cachePath, { recursive: true });
50
+ const filePath = this.getFilePath(locale);
51
+ const content = JSON.stringify(data, null, 2);
52
+ await writeFile(filePath, content, "utf-8");
53
+ }
54
+ /**
55
+ * Returns the set of keys that already have translations for a locale.
56
+ * Used by CLI to determine which strings are new and need translating.
57
+ * @param locale - The locale to check
58
+ * @returns Set of existing translation keys
59
+ */
60
+ async getExistingKeys(locale) {
61
+ const data = await this.load(locale);
62
+ return new Set(Object.keys(data));
63
+ }
64
+ /**
65
+ * Computes a short SHA-256 hash of a string.
66
+ * Used to detect source text changes without storing full text.
67
+ * @param text - The source text to hash
68
+ * @returns 8-character hex hash
69
+ */
70
+ static hash(text) {
71
+ return createHash("sha256").update(text).digest("hex").slice(0, 8);
72
+ }
73
+ /**
74
+ * Loads the metadata file (.meta.json) containing source text hashes.
75
+ * Used by CLI to detect when source text has changed for an existing key.
76
+ * @returns Key-value map of translation key to source text hash
77
+ */
78
+ async loadMeta() {
79
+ const filePath = join(this.cachePath, ".meta.json");
80
+ if (!existsSync(filePath)) {
81
+ return {};
82
+ }
83
+ const content = await readFile(filePath, "utf-8");
84
+ return JSON.parse(content);
85
+ }
86
+ /**
87
+ * Saves the metadata file (.meta.json) with updated source text hashes.
88
+ * @param data - Key-value map of translation key to source text hash
89
+ */
90
+ async saveMeta(data) {
91
+ await mkdir(this.cachePath, { recursive: true });
92
+ const filePath = join(this.cachePath, ".meta.json");
93
+ const content = JSON.stringify(data, null, 2);
94
+ await writeFile(filePath, content, "utf-8");
95
+ }
96
+ /**
97
+ * Builds the file path for a locale's JSON file.
98
+ * @param locale - The locale identifier
99
+ * @returns Full file path
100
+ */
101
+ getFilePath(locale) {
102
+ return join(this.cachePath, `${locale}.json`);
103
+ }
104
+ };
105
+
106
+ // src/i18n-auto.ts
107
+ var DEFAULT_CACHE_PATH = "./locales";
108
+ var DEFAULT_LOCALE = "en";
109
+ var translations = /* @__PURE__ */ new Map();
110
+ var config = {
111
+ defaultLocale: DEFAULT_LOCALE,
112
+ cachePath: DEFAULT_CACHE_PATH
113
+ };
114
+ function initI18n(options = {}) {
115
+ config = {
116
+ defaultLocale: options.defaultLocale ?? DEFAULT_LOCALE,
117
+ cachePath: options.cachePath ?? DEFAULT_CACHE_PATH
118
+ };
119
+ translations = /* @__PURE__ */ new Map();
120
+ const cache = new FileCache(config.cachePath);
121
+ try {
122
+ const files = readdirSync(config.cachePath);
123
+ for (const file of files) {
124
+ if (!file.endsWith(".json")) {
125
+ continue;
126
+ }
127
+ const locale = file.replace(".json", "");
128
+ const data = cache.loadSync(locale);
129
+ translations.set(locale, data);
130
+ }
131
+ } catch {
132
+ }
133
+ }
134
+ function i18nTranslate(text, options) {
135
+ const { key, locale, params } = options;
136
+ if (locale === config.defaultLocale) {
137
+ return interpolate(text, params);
138
+ }
139
+ const localeData = translations.get(locale);
140
+ if (!localeData) {
141
+ return interpolate(text, params);
142
+ }
143
+ const translated = localeData[key] || text;
144
+ return interpolate(translated, params);
145
+ }
146
+ function interpolate(text, params) {
147
+ if (!params) {
148
+ return text;
149
+ }
150
+ return text.replace(/\{\{\s*(\w+)\s*\}\}/g, (match, name) => {
151
+ return name in params ? String(params[name]) : match;
152
+ });
153
+ }
154
+ function reloadTranslations() {
155
+ initI18n(config);
156
+ }
157
+ function getTranslationStats() {
158
+ const stats = {};
159
+ for (const [locale, data] of translations) {
160
+ stats[locale] = Object.keys(data).length;
161
+ }
162
+ return stats;
163
+ }
164
+
165
+ export { getTranslationStats, i18nTranslate, initI18n, reloadTranslations };
166
+ //# sourceMappingURL=index.js.map
167
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cache/file-cache.ts","../src/i18n-auto.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { createHash } from 'crypto';\nimport { readFile, writeFile, mkdir } from 'fs/promises';\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\n\n/**\n * Manages reading and writing of locale JSON cache files.\n * Each locale has a separate JSON file: {cachePath}/{locale}.json\n */\nexport class FileCache {\n private readonly cachePath: string;\n\n /**\n * @param cachePath - Directory path where locale JSON files are stored\n */\n constructor(cachePath: string) {\n this.cachePath = cachePath;\n }\n\n /**\n * Loads all translations for a given locale from its JSON file.\n * @param locale - The locale to load (e.g., 'ur', 'fr')\n * @returns Key-value map of translations, or empty object if file doesn't exist\n */\n async load(locale: string): Promise<Record<string, string>> {\n const filePath = this.getFilePath(locale);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as Record<string, string>;\n }\n\n /**\n * Synchronously loads all translations for a given locale.\n * Used by the runtime t() method for fast, synchronous lookups.\n * @param locale - The locale to load\n * @returns Key-value map of translations, or empty object if file doesn't exist\n */\n loadSync(locale: string): Record<string, string> {\n const filePath = this.getFilePath(locale);\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as Record<string, string>;\n }\n\n /**\n * Saves translations for a locale to its JSON file.\n * Creates the directory if it doesn't exist.\n * @param locale - The locale to save\n * @param data - Key-value map of translations\n */\n async save(locale: string, data: Record<string, string>): Promise<void> {\n await mkdir(this.cachePath, { recursive: true });\n\n const filePath = this.getFilePath(locale);\n const content = JSON.stringify(data, null, 2);\n await writeFile(filePath, content, 'utf-8');\n }\n\n /**\n * Returns the set of keys that already have translations for a locale.\n * Used by CLI to determine which strings are new and need translating.\n * @param locale - The locale to check\n * @returns Set of existing translation keys\n */\n async getExistingKeys(locale: string): Promise<Set<string>> {\n const data = await this.load(locale);\n return new Set(Object.keys(data));\n }\n\n /**\n * Computes a short SHA-256 hash of a string.\n * Used to detect source text changes without storing full text.\n * @param text - The source text to hash\n * @returns 8-character hex hash\n */\n static hash(text: string): string {\n return createHash('sha256').update(text).digest('hex').slice(0, 8);\n }\n\n /**\n * Loads the metadata file (.meta.json) containing source text hashes.\n * Used by CLI to detect when source text has changed for an existing key.\n * @returns Key-value map of translation key to source text hash\n */\n async loadMeta(): Promise<Record<string, string>> {\n const filePath = join(this.cachePath, '.meta.json');\n\n if (!existsSync(filePath)) {\n return {};\n }\n\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as Record<string, string>;\n }\n\n /**\n * Saves the metadata file (.meta.json) with updated source text hashes.\n * @param data - Key-value map of translation key to source text hash\n */\n async saveMeta(data: Record<string, string>): Promise<void> {\n await mkdir(this.cachePath, { recursive: true });\n\n const filePath = join(this.cachePath, '.meta.json');\n const content = JSON.stringify(data, null, 2);\n await writeFile(filePath, content, 'utf-8');\n }\n\n /**\n * Builds the file path for a locale's JSON file.\n * @param locale - The locale identifier\n * @returns Full file path\n */\n private getFilePath(locale: string): string {\n return join(this.cachePath, `${locale}.json`);\n }\n}\n","import { readdirSync } from 'fs';\n\nimport { FileCache } from './cache/file-cache.js';\nimport type { I18nAutoOptions } from './interfaces/index.js';\nimport type { TranslateOptions } from './interfaces/index.js';\n\n/** Default path to locale JSON files */\nconst DEFAULT_CACHE_PATH = './locales';\n\n/** Default source locale */\nconst DEFAULT_LOCALE = 'en';\n\n/** In-memory store of all loaded translations: locale → { key → translation } */\nlet translations: Map<string, Record<string, string>> = new Map();\n\n/** Configured options */\nlet config: Required<Pick<I18nAutoOptions, 'defaultLocale' | 'cachePath'>> = {\n defaultLocale: DEFAULT_LOCALE,\n cachePath: DEFAULT_CACHE_PATH,\n};\n\n/**\n * Initializes the i18n runtime by loading all locale JSON files into memory.\n * Must be called once at application startup before using i18nTranslate().\n *\n * @param options - Configuration options\n */\nexport function initI18n(options: I18nAutoOptions = {}): void {\n config = {\n defaultLocale: options.defaultLocale ?? DEFAULT_LOCALE,\n cachePath: options.cachePath ?? DEFAULT_CACHE_PATH,\n };\n\n translations = new Map();\n const cache = new FileCache(config.cachePath);\n\n try {\n const files = readdirSync(config.cachePath);\n\n for (const file of files) {\n if (!file.endsWith('.json')) {\n continue;\n }\n\n const locale = file.replace('.json', '');\n const data = cache.loadSync(locale);\n translations.set(locale, data);\n }\n } catch {\n // Cache directory doesn't exist yet — that's fine, no translations loaded\n }\n}\n\n/**\n * Translates a string by looking up the key in the loaded locale data.\n * This is a synchronous function — all data is pre-loaded in memory.\n *\n * If the translation is not found, returns the original source text as fallback.\n * If the requested locale matches the default locale, returns the source text.\n *\n * @param text - The source text (used as fallback if translation not found)\n * @param options - Must include key and locale\n * @returns The translated string, or the original text if not found\n */\nexport function i18nTranslate(text: string, options: TranslateOptions): string {\n const { key, locale, params } = options;\n\n // If requesting the default locale, return source text\n if (locale === config.defaultLocale) {\n return interpolate(text, params);\n }\n\n const localeData = translations.get(locale);\n if (!localeData) {\n return interpolate(text, params);\n }\n\n const translated = localeData[key] || text;\n return interpolate(translated, params);\n}\n\n/**\n * Replaces {{placeholder}} patterns in a string with values from params.\n * Supports optional whitespace inside braces: {{ name }} and {{name}} both work.\n * If a placeholder has no matching param, it is left unchanged.\n *\n * @param text - The string containing {{placeholder}} patterns\n * @param params - Key-value map of placeholder names to values\n * @returns The interpolated string\n */\nfunction interpolate(text: string, params?: Record<string, string | number>): string {\n if (!params) {\n return text;\n }\n\n return text.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, (match, name: string) => {\n return name in params ? String(params[name]) : match;\n });\n}\n\n/**\n * Reloads all locale JSON files from disk into memory.\n * Call this after running the CLI to pick up new translations\n * without restarting the application.\n */\nexport function reloadTranslations(): void {\n initI18n(config);\n}\n\n/**\n * Returns the number of loaded translations per locale.\n * Useful for debugging and health checks.\n * @returns Map of locale → translation count\n */\nexport function getTranslationStats(): Record<string, number> {\n const stats: Record<string, number> = {};\n\n for (const [locale, data] of translations) {\n stats[locale] = Object.keys(data).length;\n }\n\n return stats;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@i18n-auto/core",
3
+ "version": "0.1.1",
4
+ "description": "Zero-config, auto-translating internationalization for Node.js",
5
+ "keywords": [
6
+ "i18n",
7
+ "internationalization",
8
+ "localization",
9
+ "translate",
10
+ "auto-translate"
11
+ ],
12
+ "homepage": "https://github.com/muhammadzubairasim/i18n-auto-core#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/muhammadzubairasim/i18n-auto-core/issues"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+ssh://git@github.com/muhammadzubairasim/i18n-auto-core.git"
19
+ },
20
+ "license": "MIT",
21
+ "author": "Muhammad Zubair Asim",
22
+ "type": "module",
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "engines": {
29
+ "node": ">=18"
30
+ },
31
+ "main": "dist/index.cjs",
32
+ "module": "dist/index.js",
33
+ "types": "dist/index.d.ts",
34
+ "bin": {
35
+ "i18n-auto": "dist/cli.js"
36
+ },
37
+ "exports": {
38
+ ".": {
39
+ "import": {
40
+ "types": "./dist/index.d.ts",
41
+ "default": "./dist/index.js"
42
+ },
43
+ "require": {
44
+ "types": "./dist/index.d.cts",
45
+ "default": "./dist/index.cjs"
46
+ }
47
+ }
48
+ },
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "dev": "tsup --watch",
52
+ "test": "vitest run",
53
+ "test:watch": "vitest",
54
+ "test:coverage": "vitest run --coverage",
55
+ "lint": "eslint src/ --ext .ts",
56
+ "lint:fix": "eslint src/ --ext .ts --fix",
57
+ "format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
58
+ "typecheck": "tsc --noEmit",
59
+ "ci": "npm run typecheck && npm run test && npm run build",
60
+ "prepublishOnly": "npm run ci",
61
+ "prepare": "husky",
62
+ "release": "standard-version",
63
+ "release:minor": "standard-version --release-as minor",
64
+ "release:major": "standard-version --release-as major"
65
+ },
66
+ "devDependencies": {
67
+ "@babel/traverse": "^7.29.0",
68
+ "@commitlint/cli": "^20.4.3",
69
+ "@commitlint/config-conventional": "^20.4.3",
70
+ "@types/babel__traverse": "^7.20.0",
71
+ "husky": "^9.1.7",
72
+ "standard-version": "^9.5.0",
73
+ "tsup": "^8.5.1",
74
+ "typescript": "^5.9.3",
75
+ "vitest": "^4.0.18"
76
+ },
77
+ "dependencies": {
78
+ "@babel/parser": "^7.29.0",
79
+ "@babel/types": "^7.29.0",
80
+ "@google-cloud/translate": "^9.3.0",
81
+ "commander": "^14.0.3",
82
+ "tinyglobby": "^0.2.15"
83
+ }
84
+ }