@localheroai/cli 0.0.5 → 0.0.6

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.
Files changed (116) hide show
  1. package/README +1 -1
  2. package/dist/api/auth.d.ts +2 -0
  3. package/dist/api/auth.js +28 -0
  4. package/dist/api/auth.js.map +1 -0
  5. package/dist/api/client.d.ts +3 -0
  6. package/dist/api/client.js +80 -0
  7. package/dist/api/client.js.map +1 -0
  8. package/dist/api/imports.d.ts +5 -0
  9. package/dist/api/imports.js +43 -0
  10. package/dist/api/imports.js.map +1 -0
  11. package/dist/api/projects.d.ts +2 -0
  12. package/dist/api/projects.js +42 -0
  13. package/dist/api/projects.js.map +1 -0
  14. package/dist/api/translations.d.ts +15 -0
  15. package/dist/api/translations.js +71 -0
  16. package/dist/api/translations.js.map +1 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +79 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/commands/_sync.js +22 -0
  21. package/dist/commands/_sync.js.map +1 -0
  22. package/dist/commands/_translate.js +3 -0
  23. package/dist/commands/_translate.js.map +1 -0
  24. package/dist/commands/init.d.ts +1 -0
  25. package/dist/commands/init.js +439 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/login.d.ts +16 -0
  28. package/dist/commands/login.js +58 -0
  29. package/dist/commands/login.js.map +1 -0
  30. package/dist/commands/pull.js +22 -0
  31. package/dist/commands/pull.js.map +1 -0
  32. package/dist/commands/push.js +56 -0
  33. package/dist/commands/push.js.map +1 -0
  34. package/dist/commands/sync.d.ts +20 -0
  35. package/dist/commands/sync.js +22 -0
  36. package/dist/commands/sync.js.map +1 -0
  37. package/dist/commands/translate.d.ts +14 -0
  38. package/dist/commands/translate.js +145 -0
  39. package/dist/commands/translate.js.map +1 -0
  40. package/dist/index.d.ts +5 -0
  41. package/dist/index.js +8 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/types/index.d.ts +75 -0
  44. package/dist/types/index.js +17 -0
  45. package/dist/types/index.js.map +1 -0
  46. package/dist/types/translate/index.js +2 -0
  47. package/dist/types/translate/index.js.map +1 -0
  48. package/dist/utils/auth.d.ts +2 -0
  49. package/dist/utils/auth.js +29 -0
  50. package/dist/utils/auth.js.map +1 -0
  51. package/dist/utils/common.js +9 -0
  52. package/dist/utils/common.js.map +1 -0
  53. package/dist/utils/config.d.ts +23 -0
  54. package/dist/utils/config.js +137 -0
  55. package/dist/utils/config.js.map +1 -0
  56. package/dist/utils/errors.js +37 -0
  57. package/dist/utils/errors.js.map +1 -0
  58. package/dist/utils/files.d.ts +32 -0
  59. package/dist/utils/files.js +347 -0
  60. package/dist/utils/files.js.map +1 -0
  61. package/dist/utils/git.d.ts +21 -0
  62. package/dist/utils/git.js +87 -0
  63. package/dist/utils/git.js.map +1 -0
  64. package/dist/utils/github.d.ts +241 -0
  65. package/dist/utils/github.js +161 -0
  66. package/dist/utils/github.js.map +1 -0
  67. package/dist/utils/import-service.d.ts +4 -0
  68. package/dist/utils/import-service.js +218 -0
  69. package/dist/utils/import-service.js.map +1 -0
  70. package/dist/utils/prompt-service.d.ts +44 -0
  71. package/dist/utils/prompt-service.js +104 -0
  72. package/dist/utils/prompt-service.js.map +1 -0
  73. package/dist/utils/sync-service.d.ts +58 -0
  74. package/dist/utils/sync-service.js +159 -0
  75. package/dist/utils/sync-service.js.map +1 -0
  76. package/dist/utils/translation-processor.js +197 -0
  77. package/dist/utils/translation-processor.js.map +1 -0
  78. package/dist/utils/translation-updater/common.d.ts +6 -0
  79. package/{src → dist}/utils/translation-updater/common.js +16 -10
  80. package/dist/utils/translation-updater/common.js.map +1 -0
  81. package/dist/utils/translation-updater/index.d.ts +5 -0
  82. package/{src → dist}/utils/translation-updater/index.js +21 -9
  83. package/dist/utils/translation-updater/index.js.map +1 -0
  84. package/dist/utils/translation-updater/json-handler.d.ts +5 -0
  85. package/dist/utils/translation-updater/json-handler.js +123 -0
  86. package/dist/utils/translation-updater/json-handler.js.map +1 -0
  87. package/dist/utils/translation-updater/yaml-handler.d.ts +5 -0
  88. package/dist/utils/translation-updater/yaml-handler.js +180 -0
  89. package/dist/utils/translation-updater/yaml-handler.js.map +1 -0
  90. package/dist/utils/translation-utils.d.ts +30 -0
  91. package/dist/utils/translation-utils.js +324 -0
  92. package/dist/utils/translation-utils.js.map +1 -0
  93. package/dist/utils/updater.js +38 -0
  94. package/dist/utils/updater.js.map +1 -0
  95. package/package.json +26 -26
  96. package/src/api/auth.js +0 -24
  97. package/src/api/client.js +0 -83
  98. package/src/api/imports.js +0 -22
  99. package/src/api/projects.js +0 -24
  100. package/src/api/translations.js +0 -58
  101. package/src/cli.js +0 -78
  102. package/src/commands/init.js +0 -485
  103. package/src/commands/login.js +0 -80
  104. package/src/commands/sync.js +0 -28
  105. package/src/commands/translate.js +0 -267
  106. package/src/utils/auth.js +0 -23
  107. package/src/utils/config.js +0 -125
  108. package/src/utils/files.js +0 -381
  109. package/src/utils/git.js +0 -72
  110. package/src/utils/github.js +0 -128
  111. package/src/utils/import-service.js +0 -128
  112. package/src/utils/prompt-service.js +0 -67
  113. package/src/utils/sync-service.js +0 -147
  114. package/src/utils/translation-updater/json-handler.js +0 -111
  115. package/src/utils/translation-updater/yaml-handler.js +0 -207
  116. package/src/utils/translation-utils.js +0 -278
@@ -0,0 +1,44 @@
1
+ interface ProjectService {
2
+ listProjects: () => Promise<Array<{
3
+ id: string;
4
+ name: string;
5
+ }>>;
6
+ }
7
+ interface ProjectSetup {
8
+ projectName: string;
9
+ sourceLocale: string;
10
+ outputLocales: string[];
11
+ translationPath: string;
12
+ ignorePaths: string[];
13
+ }
14
+ interface ProjectSelection {
15
+ choice: string;
16
+ project?: {
17
+ id: string;
18
+ name: string;
19
+ };
20
+ }
21
+ export declare function createPromptService(deps?: {
22
+ inquirer?: any;
23
+ }): {
24
+ getApiKey: () => Promise<string>;
25
+ getProjectSetup: () => Promise<ProjectSetup>;
26
+ select: <T>(options: {
27
+ message: string;
28
+ choices: Array<{
29
+ name: string;
30
+ value: T;
31
+ disabled?: boolean;
32
+ }>;
33
+ }) => Promise<T>;
34
+ input: (options: {
35
+ message: string;
36
+ default?: string;
37
+ }) => Promise<string>;
38
+ confirm: (options: {
39
+ message: string;
40
+ default?: boolean;
41
+ }) => Promise<boolean>;
42
+ selectProject: (projectService: ProjectService) => Promise<ProjectSelection>;
43
+ };
44
+ export {};
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Prompt service for handling CLI interactions with the user
3
+ */
4
+ /**
5
+ * Creates a prompt service for handling CLI interactions
6
+ * @param deps Dependencies for the prompt service
7
+ * @returns The prompt service object
8
+ */
9
+ export function createPromptService(deps = {}) {
10
+ const { inquirer = null } = deps;
11
+ return {
12
+ /**
13
+ * Prompts the user for an API key
14
+ * @returns The API key entered by the user
15
+ */
16
+ async getApiKey() {
17
+ if (!inquirer)
18
+ return '';
19
+ return inquirer.password({
20
+ message: 'API Key:',
21
+ mask: '*'
22
+ });
23
+ },
24
+ /**
25
+ * Gets project setup information - defaults to empty values when inquirer is not available
26
+ * @returns Project setup information
27
+ */
28
+ async getProjectSetup() {
29
+ if (!inquirer)
30
+ return {
31
+ projectName: '',
32
+ sourceLocale: '',
33
+ outputLocales: [],
34
+ translationPath: '',
35
+ ignorePaths: []
36
+ };
37
+ return {
38
+ projectName: '',
39
+ sourceLocale: '',
40
+ outputLocales: [],
41
+ translationPath: '',
42
+ ignorePaths: []
43
+ };
44
+ },
45
+ /**
46
+ * Prompts the user with a selection
47
+ * @param options Selection options
48
+ * @returns The selected value
49
+ */
50
+ async select(options) {
51
+ if (!inquirer)
52
+ return 'new';
53
+ return inquirer.select(options);
54
+ },
55
+ /**
56
+ * Prompts the user for text input
57
+ * @param options Input options
58
+ * @returns The entered text
59
+ */
60
+ async input(options) {
61
+ if (!inquirer)
62
+ return '';
63
+ return inquirer.input(options);
64
+ },
65
+ /**
66
+ * Prompts the user for confirmation
67
+ * @param options Confirmation options
68
+ * @returns True if confirmed, false otherwise
69
+ */
70
+ async confirm(options) {
71
+ if (!inquirer)
72
+ return false;
73
+ return inquirer.confirm(options);
74
+ },
75
+ /**
76
+ * Prompts the user to select a project or create a new one
77
+ * @param projectService Service providing project operations
78
+ * @returns The selection result with the chosen project
79
+ */
80
+ async selectProject(projectService) {
81
+ const projects = await projectService.listProjects();
82
+ if (!projects || projects.length === 0) {
83
+ return { choice: 'new' };
84
+ }
85
+ const choices = [
86
+ { name: '✨ Create new project', value: 'new' },
87
+ { name: '─────────────', value: 'separator', disabled: true },
88
+ ...projects.map(p => ({
89
+ name: p.name,
90
+ value: p.id
91
+ }))
92
+ ];
93
+ const projectChoice = await this.select({
94
+ message: 'Would you like to use an existing project or create a new one?',
95
+ choices
96
+ });
97
+ return {
98
+ choice: projectChoice,
99
+ project: projects.find(p => p.id === projectChoice)
100
+ };
101
+ }
102
+ };
103
+ }
104
+ //# sourceMappingURL=prompt-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-service.js","sourceRoot":"","sources":["../../src/utils/prompt-service.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0EH;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAkC,EAAE;IACtE,MAAM,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAEjC,OAAO;QACL;;;WAGG;QACH,KAAK,CAAC,SAAS;YACb,IAAI,CAAC,QAAQ;gBAAE,OAAO,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC,QAAQ,CAAC;gBACvB,OAAO,EAAE,UAAU;gBACnB,IAAI,EAAE,GAAG;aACV,CAAC,CAAC;QACL,CAAC;QAED;;;WAGG;QACH,KAAK,CAAC,eAAe;YACnB,IAAI,CAAC,QAAQ;gBAAE,OAAO;oBACpB,WAAW,EAAE,EAAE;oBACf,YAAY,EAAE,EAAE;oBAChB,aAAa,EAAE,EAAE;oBACjB,eAAe,EAAE,EAAE;oBACnB,WAAW,EAAE,EAAE;iBAChB,CAAC;YAEF,OAAO;gBACL,WAAW,EAAE,EAAE;gBACf,YAAY,EAAE,EAAE;gBAChB,aAAa,EAAE,EAAE;gBACjB,eAAe,EAAE,EAAE;gBACnB,WAAW,EAAE,EAAE;aAChB,CAAC;QACJ,CAAC;QAED;;;;WAIG;QACH,KAAK,CAAC,MAAM,CAAC,OAAsB;YACjC,IAAI,CAAC,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC5B,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QAED;;;;WAIG;QACH,KAAK,CAAC,KAAK,CAAC,OAAqB;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAED;;;;WAIG;QACH,KAAK,CAAC,OAAO,CAAC,OAAuB;YACnC,IAAI,CAAC,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC5B,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;QAED;;;;WAIG;QACH,KAAK,CAAC,aAAa,CAAC,cAAoF;YACtG,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,YAAY,EAAE,CAAC;YAErD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;YAC3B,CAAC;YAED,MAAM,OAAO,GAAG;gBACd,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,KAAK,EAAE;gBAC9C,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC7D,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACpB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,KAAK,EAAE,CAAC,CAAC,EAAE;iBACZ,CAAC,CAAC;aACJ,CAAC;YAEF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;gBACtC,OAAO,EAAE,gEAAgE;gBACzE,OAAO;aACR,CAAC,CAAC;YAEH,OAAO;gBACL,MAAM,EAAE,aAAa;gBACrB,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,aAAa,CAAC;aACpD,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,58 @@
1
+ export interface SyncOptions {
2
+ verbose?: boolean;
3
+ }
4
+ export interface Translation {
5
+ key: string;
6
+ value: string;
7
+ }
8
+ export interface Language {
9
+ code: string;
10
+ translations: Translation[];
11
+ }
12
+ export interface FileUpdate {
13
+ path: string;
14
+ languages: Language[];
15
+ }
16
+ export interface DeletedKey {
17
+ name: string;
18
+ }
19
+ export interface PaginationInfo {
20
+ current_page: number;
21
+ total_pages: number;
22
+ }
23
+ export interface UpdateResponse {
24
+ updates?: {
25
+ updated_keys?: FileUpdate[];
26
+ deleted_keys?: DeletedKey[];
27
+ };
28
+ pagination?: PaginationInfo;
29
+ }
30
+ export interface UpdatesContainer {
31
+ updates: {
32
+ files: FileUpdate[];
33
+ deleted_keys: DeletedKey[];
34
+ };
35
+ }
36
+ export interface CheckUpdatesResult {
37
+ hasUpdates: boolean;
38
+ updates?: UpdatesContainer;
39
+ }
40
+ export interface TranslationFile {
41
+ path: string;
42
+ locale: string;
43
+ }
44
+ export interface SourceFile {
45
+ path: string;
46
+ }
47
+ export interface FindTranslationFilesResult {
48
+ sourceFiles: SourceFile[];
49
+ [key: string]: any;
50
+ }
51
+ export interface SyncResult {
52
+ totalUpdates: number;
53
+ totalDeleted: number;
54
+ }
55
+ export declare const syncService: {
56
+ checkForUpdates({ verbose }?: SyncOptions): Promise<CheckUpdatesResult>;
57
+ applyUpdates(updates: UpdatesContainer, { verbose }?: SyncOptions): Promise<SyncResult>;
58
+ };
@@ -0,0 +1,159 @@
1
+ import chalk from 'chalk';
2
+ import { configService } from './config.js';
3
+ import { getUpdates } from '../api/translations.js';
4
+ import { updateTranslationFile, deleteKeysFromTranslationFile } from './translation-updater/index.js';
5
+ import { findTranslationFiles } from './files.js';
6
+ import path from 'path';
7
+ const MAX_PAGES = 20;
8
+ export const syncService = {
9
+ /**
10
+ * Check for updates since the last sync
11
+ * @param verbose Whether to show verbose output
12
+ * @returns Result with updates if any are available
13
+ */
14
+ async checkForUpdates(verbose = false) {
15
+ const config = await configService.getValidProjectConfig();
16
+ if (!config.projectId) {
17
+ throw new Error('Project not initialized. Please run `localhero init` first.');
18
+ }
19
+ const since = config.lastSyncedAt || new Date(0).toISOString();
20
+ if (verbose) {
21
+ console.log(chalk.blue(`Checking for updates since ${since}`));
22
+ }
23
+ let allFiles = [];
24
+ let deletedKeys = [];
25
+ let currentPage = 1;
26
+ let hasMorePages = true;
27
+ while (hasMorePages && currentPage <= MAX_PAGES) {
28
+ const params = { since, page: currentPage };
29
+ const response = await getUpdates(config.projectId, params);
30
+ if (response.updates?.updated_keys?.length) {
31
+ allFiles = allFiles.concat(response.updates.updated_keys);
32
+ }
33
+ if (response.updates?.deleted_keys?.length) {
34
+ deletedKeys = deletedKeys.concat(response.updates.deleted_keys);
35
+ }
36
+ if (response.pagination) {
37
+ const { current_page, total_pages } = response.pagination;
38
+ hasMorePages = current_page < total_pages;
39
+ currentPage++;
40
+ if (verbose && hasMorePages) {
41
+ if (total_pages > MAX_PAGES) {
42
+ console.log(chalk.yellow(` ⚠️ Limiting to ${MAX_PAGES} pages out of ${total_pages} total`));
43
+ }
44
+ else {
45
+ console.log(chalk.gray(` Fetching page ${currentPage} of ${total_pages}`));
46
+ }
47
+ }
48
+ }
49
+ else {
50
+ hasMorePages = false;
51
+ }
52
+ }
53
+ if (!allFiles.length && !deletedKeys.length) {
54
+ return { hasUpdates: false };
55
+ }
56
+ return {
57
+ hasUpdates: true,
58
+ updates: {
59
+ updates: {
60
+ files: allFiles,
61
+ deleted_keys: deletedKeys
62
+ }
63
+ }
64
+ };
65
+ },
66
+ /**
67
+ * Apply updates to translation files
68
+ * @param updates Updates to apply
69
+ * @param verbose Whether to show verbose output
70
+ * @returns Result with the number of updates and deletes
71
+ */
72
+ async applyUpdates(updates, verbose = false) {
73
+ let totalUpdates = 0;
74
+ let totalDeleted = 0;
75
+ // First, find all source files
76
+ const config = await configService.getValidProjectConfig();
77
+ const result = await findTranslationFiles(config, {
78
+ parseContent: false,
79
+ includeContent: false,
80
+ extractKeys: false,
81
+ returnFullResult: true,
82
+ verbose
83
+ });
84
+ const sourceFiles = result.sourceFiles;
85
+ // Create a map of source files by path
86
+ const sourceFilesByPath = {};
87
+ for (const sourceFile of sourceFiles) {
88
+ const dirName = path.dirname(sourceFile.path);
89
+ sourceFilesByPath[dirName] = sourceFile.path;
90
+ }
91
+ for (const file of updates.updates.files || []) {
92
+ // Find the corresponding source file
93
+ const dirName = path.dirname(file.path);
94
+ const sourceFilePath = sourceFilesByPath[dirName];
95
+ for (const lang of file.languages) {
96
+ if (verbose) {
97
+ console.log(chalk.blue(`Updating ${lang.code} translations in ${file.path}`));
98
+ }
99
+ const translations = {};
100
+ for (const translation of lang.translations) {
101
+ translations[translation.key] = translation.value;
102
+ if (verbose) {
103
+ const displayValue = translation.value.length > 100 ? `${translation.value.slice(0, 100)}…` : translation.value;
104
+ console.log(chalk.gray(` ${translation.key} = ${displayValue}`));
105
+ }
106
+ }
107
+ try {
108
+ await updateTranslationFile(file.path, translations, lang.code, sourceFilePath);
109
+ totalUpdates += Object.keys(translations).length;
110
+ }
111
+ catch (error) {
112
+ console.error(chalk.yellow(`⚠️ Failed to update ${file.path}: ${error.message}`));
113
+ }
114
+ }
115
+ }
116
+ const deletedKeys = updates.updates.deleted_keys || [];
117
+ if (deletedKeys.length > 0) {
118
+ if (verbose) {
119
+ console.log(chalk.blue(`\nProcessing ${deletedKeys.length} deleted keys`));
120
+ }
121
+ const translationFiles = await findTranslationFiles(config, {
122
+ parseContent: false,
123
+ includeContent: false,
124
+ extractKeys: false,
125
+ verbose
126
+ });
127
+ if (verbose) {
128
+ console.log(chalk.blue(`Found ${translationFiles.length} translation files to check for deleted keys`));
129
+ }
130
+ const keysToDelete = deletedKeys.map(key => key.name);
131
+ for (const file of translationFiles) {
132
+ try {
133
+ if (verbose) {
134
+ console.log(chalk.blue(`Checking for deleted keys in ${file.path} (${file.locale})`));
135
+ }
136
+ const deletedFromFile = await deleteKeysFromTranslationFile(file.path, keysToDelete, file.locale);
137
+ if (deletedFromFile.length > 0) {
138
+ totalDeleted += deletedFromFile.length;
139
+ if (verbose) {
140
+ console.log(chalk.green(`✓ Deleted ${deletedFromFile.length} keys from ${file.path}`));
141
+ for (const key of deletedFromFile) {
142
+ console.log(chalk.gray(` - ${key}`));
143
+ }
144
+ }
145
+ }
146
+ else if (verbose) {
147
+ console.log(chalk.gray(` No keys to delete in ${file.path}`));
148
+ }
149
+ }
150
+ catch (error) {
151
+ console.error(chalk.yellow(`⚠️ Failed to delete keys from ${file.path}: ${error.message}`));
152
+ }
153
+ }
154
+ }
155
+ await configService.updateLastSyncedAt();
156
+ return { totalUpdates, totalDeleted };
157
+ }
158
+ };
159
+ //# sourceMappingURL=sync-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-service.js","sourceRoot":"","sources":["../../src/utils/sync-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,197 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Creates a job request object for a batch of translations
4
+ *
5
+ * @param batch - The batch to create a job for
6
+ * @param missingByLocale - Missing translations by locale and file
7
+ * @param config - Project configuration
8
+ * @returns The job request object
9
+ */
10
+ function createJobRequest(batch, missingByLocale, config) {
11
+ const targetPaths = {};
12
+ batch.localeEntries.forEach(localeSourceKey => {
13
+ const entry = missingByLocale[localeSourceKey];
14
+ targetPaths[entry.locale] = entry.targetPath;
15
+ });
16
+ return {
17
+ projectId: config.projectId,
18
+ sourceFiles: [batch.sourceFile],
19
+ targetLocales: batch.locales,
20
+ targetPaths
21
+ };
22
+ }
23
+ /**
24
+ * Creates a mapping of job IDs to source files and locales
25
+ *
26
+ * @param jobs - Array of job objects from the API response
27
+ * @param sourceFilePath - Path to the source file
28
+ * @returns Mapping of job IDs to source information
29
+ */
30
+ function createJobSourceMapping(jobs, sourceFilePath) {
31
+ const jobSourceMapping = {};
32
+ jobs.forEach(job => {
33
+ jobSourceMapping[job.id] = {
34
+ sourceFilePath,
35
+ locale: job.language?.code || ''
36
+ };
37
+ });
38
+ return jobSourceMapping;
39
+ }
40
+ /**
41
+ * Monitors a job's status until completion
42
+ *
43
+ * @param jobId - The ID of the job to monitor
44
+ * @param verbose - Whether to show verbose output
45
+ * @param translationUtils - Translation utilities
46
+ * @param console - Console for logging
47
+ * @returns The job status when completed
48
+ * @throws Error If the job fails or times out
49
+ */
50
+ async function monitorJobStatus(jobId, verbose, translationUtils, console) {
51
+ if (verbose) {
52
+ console.log(chalk.blue(`\nℹ Checking job ${jobId}`));
53
+ }
54
+ let status;
55
+ let retries = 0;
56
+ const MAX_WAIT_MINUTES = 10;
57
+ const startTime = Date.now();
58
+ do {
59
+ status = await translationUtils.checkJobStatus(jobId, true);
60
+ if (status.status === 'failed') {
61
+ throw new Error(`Translation job failed: ${status.error_details || 'Unknown error'}`);
62
+ }
63
+ if (status.status === 'pending' || status.status === 'processing') {
64
+ const elapsed = Math.floor((Date.now() - startTime) / 1000);
65
+ if (elapsed > MAX_WAIT_MINUTES * 60) {
66
+ throw new Error(`Translation timed out after ${MAX_WAIT_MINUTES} minutes`);
67
+ }
68
+ const waitSeconds = Math.min(2 ** retries, 30);
69
+ if (verbose) {
70
+ console.log(chalk.blue(` Job ${jobId} is ${status.status}, checking again in ${waitSeconds}s...`));
71
+ }
72
+ await new Promise(resolve => setTimeout(resolve, waitSeconds * 1000));
73
+ retries = Math.min(retries + 1, 5);
74
+ return { jobId, status: 'pending' };
75
+ }
76
+ return { jobId, status: 'completed', data: status };
77
+ } while (status.status === 'pending' || status.status === 'processing');
78
+ }
79
+ /**
80
+ * Applies completed translations to the target files
81
+ *
82
+ * @param jobStatus - The job status with translation data
83
+ * @param jobSourceMapping - Mapping of job IDs to source information
84
+ * @param missingByLocale - Missing translations by locale and file
85
+ * @param translationUtils - Translation utilities
86
+ * @param verbose - Whether to show verbose output
87
+ * @param console - Console for logging
88
+ * @param processedEntries - Set of already processed entries
89
+ * @param uniqueKeysTranslated - Set of unique keys that were translated
90
+ * @param stats - Statistics object to update
91
+ * @returns Whether translations were applied
92
+ */
93
+ async function applyTranslations(jobStatus, jobSourceMapping, missingByLocale, translationUtils, verbose, console, processedEntries, uniqueKeysTranslated, stats) {
94
+ const { jobId, data } = jobStatus;
95
+ if (!data?.translations?.data || !data.language?.code) {
96
+ return false;
97
+ }
98
+ if (data.results_url && !stats.resultsBaseUrl) {
99
+ stats.resultsBaseUrl = data.results_url.split('?')[0];
100
+ }
101
+ const languageCode = data.language.code;
102
+ const sourceInfo = jobSourceMapping[jobId];
103
+ if (!sourceInfo || sourceInfo.locale !== languageCode) {
104
+ return false;
105
+ }
106
+ const localeSourceKey = `${languageCode}:${sourceInfo.sourceFilePath}`;
107
+ const entry = missingByLocale[localeSourceKey];
108
+ if (!entry || processedEntries.has(localeSourceKey)) {
109
+ return false;
110
+ }
111
+ const targetPath = entry.targetPath;
112
+ if (verbose) {
113
+ console.log(chalk.blue(` Updating translations for ${languageCode} in ${targetPath}`));
114
+ }
115
+ await translationUtils.updateTranslationFile(targetPath, data.translations.data, languageCode, entry.path);
116
+ Object.keys(entry.keys).forEach(key => uniqueKeysTranslated.add(key));
117
+ if (!processedEntries.has(`locale:${languageCode}`)) {
118
+ stats.totalLanguages++;
119
+ processedEntries.add(`locale:${languageCode}`);
120
+ }
121
+ processedEntries.add(localeSourceKey);
122
+ return true;
123
+ }
124
+ /**
125
+ * Processes a single batch of translations
126
+ *
127
+ * @param batch - The batch to process
128
+ * @param missingByLocale - Missing translations by locale and file
129
+ * @param config - Project configuration
130
+ * @param verbose - Whether to show verbose output
131
+ * @param deps - Dependencies (console, translationUtils)
132
+ * @param processedEntries - Set of already processed entries
133
+ * @param uniqueKeysTranslated - Set of unique keys that were translated
134
+ * @param allJobIds - Array of all job IDs
135
+ * @param stats - Statistics object to update
136
+ */
137
+ async function processBatch(batch, missingByLocale, config, verbose, deps, processedEntries, uniqueKeysTranslated, allJobIds, stats) {
138
+ const { console, translationUtils } = deps;
139
+ const sourceFilePath = batch.sourceFilePath;
140
+ const jobRequest = createJobRequest(batch, missingByLocale, config);
141
+ const response = await translationUtils.createTranslationJob(jobRequest);
142
+ const { jobs } = response;
143
+ const batchJobIds = jobs.map(job => job.id);
144
+ allJobIds.push(...batchJobIds);
145
+ const jobSourceMapping = createJobSourceMapping(jobs, sourceFilePath);
146
+ const pendingJobs = new Set(batchJobIds);
147
+ while (pendingJobs.size > 0) {
148
+ const jobPromises = Array.from(pendingJobs).map(async (jobId) => {
149
+ const jobStatus = await monitorJobStatus(jobId, verbose, translationUtils, console);
150
+ if (jobStatus.status === 'completed') {
151
+ await applyTranslations(jobStatus, jobSourceMapping, missingByLocale, translationUtils, verbose, console, processedEntries, uniqueKeysTranslated, stats);
152
+ }
153
+ return jobStatus;
154
+ });
155
+ // Wait for all jobs to be processed
156
+ const results = await Promise.all(jobPromises);
157
+ results.forEach(result => {
158
+ if (result.status === 'completed') {
159
+ pendingJobs.delete(result.jobId);
160
+ }
161
+ });
162
+ // If there are still pending jobs, wait before checking again
163
+ if (pendingJobs.size > 0) {
164
+ await new Promise(resolve => setTimeout(resolve, 2000));
165
+ }
166
+ }
167
+ }
168
+ /**
169
+ * Processes translation batches by creating translation jobs,
170
+ * monitoring their status, and applying translations when complete
171
+ *
172
+ * @param batches - Translation batches to process
173
+ * @param missingByLocale - Missing translations by locale and file
174
+ * @param config - Project configuration
175
+ * @param verbose - Whether to show verbose output
176
+ * @param deps - Dependencies (console, translationUtils)
177
+ * @returns Result containing statistics about the translation process
178
+ */
179
+ export async function processTranslationBatches(batches, missingByLocale, config, verbose, deps) {
180
+ const stats = {
181
+ totalLanguages: 0,
182
+ resultsBaseUrl: null
183
+ };
184
+ const processedEntries = new Set();
185
+ const allJobIds = [];
186
+ const uniqueKeysTranslated = new Set();
187
+ for (const batch of batches) {
188
+ await processBatch(batch, missingByLocale, config, verbose, deps, processedEntries, uniqueKeysTranslated, allJobIds, stats);
189
+ }
190
+ return {
191
+ totalLanguages: stats.totalLanguages,
192
+ allJobIds,
193
+ resultsBaseUrl: stats.resultsBaseUrl,
194
+ uniqueKeysTranslated
195
+ };
196
+ }
197
+ //# sourceMappingURL=translation-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translation-processor.js","sourceRoot":"","sources":["../../src/utils/translation-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export function fileExists(filePath: any): Promise<boolean>;
2
+ export function ensureDirectoryExists(filePath: any): Promise<void>;
3
+ export function tryParseJsonArray(value: any): any[] | null;
4
+ export const SPECIAL_CHARS_REGEX: RegExp;
5
+ export const INTERPOLATION: "%{";
6
+ export const MAX_ARRAY_LENGTH: 1000;
@@ -1,44 +1,50 @@
1
1
  import { promises as fs } from 'fs';
2
2
  import path from 'path';
3
-
4
3
  export const SPECIAL_CHARS_REGEX = /[:@#,[\]{}?|>&*!\n]/;
5
4
  export const INTERPOLATION = '%{';
6
5
  export const MAX_ARRAY_LENGTH = 1000;
7
-
6
+ /**
7
+ * Checks if a file exists at the specified path
8
+ */
8
9
  export async function fileExists(filePath) {
9
10
  try {
10
11
  await fs.access(filePath);
11
12
  return true;
12
- } catch {
13
+ }
14
+ catch {
13
15
  return false;
14
16
  }
15
17
  }
16
-
18
+ /**
19
+ * Ensures the directory for the provided file path exists
20
+ */
17
21
  export async function ensureDirectoryExists(filePath) {
18
22
  const dir = path.dirname(filePath);
19
23
  if (dir !== '.') {
20
24
  await fs.mkdir(dir, { recursive: true });
21
25
  }
22
26
  }
23
-
27
+ /**
28
+ * Attempts to parse a string as a JSON array
29
+ * Returns the parsed array or null if parsing fails
30
+ */
24
31
  export function tryParseJsonArray(value) {
25
32
  if (typeof value !== 'string' || !value.startsWith('["') || !value.endsWith('"]')) {
26
33
  return null;
27
34
  }
28
-
29
35
  try {
30
36
  const parsed = JSON.parse(value);
31
37
  if (!Array.isArray(parsed)) {
32
38
  return null;
33
39
  }
34
-
35
40
  if (parsed.length > MAX_ARRAY_LENGTH) {
36
41
  console.warn(`Array length ${parsed.length} exceeds maximum allowed length of ${MAX_ARRAY_LENGTH}`);
37
42
  return null;
38
43
  }
39
-
40
44
  return parsed;
41
- } catch {
45
+ }
46
+ catch {
42
47
  return null;
43
48
  }
44
- }
49
+ }
50
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/utils/translation-updater/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AACzD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAClC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,QAAgB;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;QAChB,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAClF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,MAAM,sCAAsC,gBAAgB,EAAE,CAAC,CAAC;YACpG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export function updateTranslationFile(filePath: any, translations: any, languageCode?: string, sourceFilePath?: null): Promise<{
2
+ updatedKeys: string[];
3
+ created: boolean;
4
+ }>;
5
+ export function deleteKeysFromTranslationFile(filePath: any, keysToDelete: any, languageCode?: string): Promise<any[]>;