@ollang-dev/sdk 0.3.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.
Files changed (64) hide show
  1. package/bin/tms.js +47 -0
  2. package/dist/browser/index.d.ts +143 -0
  3. package/dist/browser/index.js +2336 -0
  4. package/dist/browser/ollang-browser.min.js +1 -0
  5. package/dist/browser/script-loader.d.ts +1 -0
  6. package/dist/browser/script-loader.js +53 -0
  7. package/dist/client.d.ts +13 -0
  8. package/dist/client.js +60 -0
  9. package/dist/index.d.ts +34 -0
  10. package/dist/index.js +74 -0
  11. package/dist/resources/cms.d.ts +29 -0
  12. package/dist/resources/cms.js +34 -0
  13. package/dist/resources/customInstructions.d.ts +11 -0
  14. package/dist/resources/customInstructions.js +24 -0
  15. package/dist/resources/orders.d.ts +13 -0
  16. package/dist/resources/orders.js +65 -0
  17. package/dist/resources/projects.d.ts +8 -0
  18. package/dist/resources/projects.js +29 -0
  19. package/dist/resources/revisions.d.ts +9 -0
  20. package/dist/resources/revisions.js +18 -0
  21. package/dist/resources/scans.d.ts +38 -0
  22. package/dist/resources/scans.js +52 -0
  23. package/dist/resources/uploads.d.ts +8 -0
  24. package/dist/resources/uploads.js +25 -0
  25. package/dist/tms/config.d.ts +16 -0
  26. package/dist/tms/config.js +172 -0
  27. package/dist/tms/detector/audio-detector.d.ts +27 -0
  28. package/dist/tms/detector/audio-detector.js +168 -0
  29. package/dist/tms/detector/auto-detect.d.ts +1 -0
  30. package/dist/tms/detector/auto-detect.js +152 -0
  31. package/dist/tms/detector/cms-detector.d.ts +17 -0
  32. package/dist/tms/detector/cms-detector.js +94 -0
  33. package/dist/tms/detector/content-type-detector.d.ts +79 -0
  34. package/dist/tms/detector/content-type-detector.js +2 -0
  35. package/dist/tms/detector/hardcoded-detector.d.ts +11 -0
  36. package/dist/tms/detector/hardcoded-detector.js +154 -0
  37. package/dist/tms/detector/i18n-detector.d.ts +16 -0
  38. package/dist/tms/detector/i18n-detector.js +311 -0
  39. package/dist/tms/detector/image-detector.d.ts +11 -0
  40. package/dist/tms/detector/image-detector.js +170 -0
  41. package/dist/tms/detector/text-detector.d.ts +9 -0
  42. package/dist/tms/detector/text-detector.js +35 -0
  43. package/dist/tms/detector/video-detector.d.ts +12 -0
  44. package/dist/tms/detector/video-detector.js +188 -0
  45. package/dist/tms/index.d.ts +12 -0
  46. package/dist/tms/index.js +38 -0
  47. package/dist/tms/multi-content-tms.d.ts +42 -0
  48. package/dist/tms/multi-content-tms.js +230 -0
  49. package/dist/tms/server/index.d.ts +1 -0
  50. package/dist/tms/server/index.js +1473 -0
  51. package/dist/tms/server/strapi-pusher.d.ts +31 -0
  52. package/dist/tms/server/strapi-pusher.js +296 -0
  53. package/dist/tms/server/strapi-schema.d.ts +47 -0
  54. package/dist/tms/server/strapi-schema.js +93 -0
  55. package/dist/tms/tms.d.ts +48 -0
  56. package/dist/tms/tms.js +875 -0
  57. package/dist/tms/types.d.ts +189 -0
  58. package/dist/tms/types.js +2 -0
  59. package/dist/tms/ui-dist/assets/index-5U1Hw3uo.css +1 -0
  60. package/dist/tms/ui-dist/assets/index-HvrqZV5Z.js +149 -0
  61. package/dist/tms/ui-dist/index.html +14 -0
  62. package/dist/types/index.d.ts +174 -0
  63. package/dist/types/index.js +2 -0
  64. package/package.json +98 -0
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Revisions = void 0;
4
+ class Revisions {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ async create(orderId, params) {
9
+ return this.client.post(`/integration/revision/${orderId}`, params);
10
+ }
11
+ async delete(orderId, revisionId) {
12
+ return this.client.delete(`/integration/revision/${orderId}/${revisionId}`);
13
+ }
14
+ async list(orderId) {
15
+ return this.client.get(`/integration/revision/${orderId}`);
16
+ }
17
+ }
18
+ exports.Revisions = Revisions;
@@ -0,0 +1,38 @@
1
+ import { OllangClient } from '../client';
2
+ export interface ScanSessionResponse {
3
+ id: string;
4
+ projectId: string;
5
+ userId: string;
6
+ isActive: boolean;
7
+ scannedDocs?: ScannedDocResponse[];
8
+ createdAt: string;
9
+ updatedAt: string;
10
+ }
11
+ export interface ScannedDocResponse {
12
+ id: string;
13
+ sessionId: string;
14
+ docId: string;
15
+ originalUrl: string;
16
+ processedUrl?: string;
17
+ scanData: any;
18
+ status: 'pending' | 'processing' | 'completed' | 'failed';
19
+ createdAt: string;
20
+ updatedAt: string;
21
+ }
22
+ export interface CreateScanInput {
23
+ file?: Buffer | Blob;
24
+ url?: string;
25
+ scanData: any;
26
+ originalFilename?: string;
27
+ folderName?: string;
28
+ }
29
+ export declare class Scans {
30
+ private client;
31
+ constructor(client: OllangClient);
32
+ getOrCreateSession(projectId?: string, folderName?: string): Promise<ScanSessionResponse>;
33
+ createScan(input: CreateScanInput): Promise<ScannedDocResponse>;
34
+ listScans(): Promise<ScannedDocResponse[]>;
35
+ getScan(scanId: string): Promise<ScannedDocResponse>;
36
+ deleteScan(scanId: string): Promise<void>;
37
+ updateScan(scanId: string, input: Partial<CreateScanInput>): Promise<ScannedDocResponse>;
38
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Scans = void 0;
4
+ class Scans {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ async getOrCreateSession(projectId, folderName) {
9
+ return this.client.post('/scans/session', { projectId, folderName });
10
+ }
11
+ async createScan(input) {
12
+ const formData = new FormData();
13
+ if (input.file) {
14
+ if (Buffer.isBuffer(input.file)) {
15
+ const blob = new Blob([input.file]);
16
+ formData.append('file', blob, input.originalFilename || 'scan.jpg');
17
+ }
18
+ else {
19
+ formData.append('file', input.file, input.originalFilename || 'scan.jpg');
20
+ }
21
+ }
22
+ if (input.url) {
23
+ formData.append('url', input.url);
24
+ }
25
+ formData.append('scanData', JSON.stringify(input.scanData));
26
+ if (input.originalFilename) {
27
+ formData.append('originalFilename', input.originalFilename);
28
+ }
29
+ if (input.folderName) {
30
+ formData.append('folderName', input.folderName);
31
+ }
32
+ return this.client.postFormData('/scans', formData);
33
+ }
34
+ async listScans() {
35
+ return this.client.get('/scans');
36
+ }
37
+ async getScan(scanId) {
38
+ return this.client.get(`/scans/${scanId}`);
39
+ }
40
+ async deleteScan(scanId) {
41
+ return this.client.delete(`/scans/${scanId}`);
42
+ }
43
+ async updateScan(scanId, input) {
44
+ return this.client.patch(`/scans/${scanId}`, {
45
+ scanData: input.scanData,
46
+ url: input.url,
47
+ originalFilename: input.originalFilename,
48
+ folderName: input.folderName,
49
+ });
50
+ }
51
+ }
52
+ exports.Scans = Scans;
@@ -0,0 +1,8 @@
1
+ import { OllangClient } from '../client';
2
+ import { DirectUploadParams, DirectUploadResponse, UploadVttParams, UploadVttResponse } from '../types';
3
+ export declare class Uploads {
4
+ private client;
5
+ constructor(client: OllangClient);
6
+ direct(params: DirectUploadParams): Promise<DirectUploadResponse>;
7
+ vtt(params: UploadVttParams): Promise<UploadVttResponse>;
8
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Uploads = void 0;
4
+ class Uploads {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ async direct(params) {
9
+ const formData = new FormData();
10
+ formData.append('file', params.file);
11
+ formData.append('name', params.name);
12
+ formData.append('sourceLanguage', params.sourceLanguage);
13
+ if (params.notes) {
14
+ formData.append('notes', JSON.stringify(params.notes));
15
+ }
16
+ return this.client.uploadFile('/integration/upload/direct', formData);
17
+ }
18
+ async vtt(params) {
19
+ const formData = new FormData();
20
+ formData.append('file', params.file);
21
+ formData.append('orderId', params.orderId);
22
+ return this.client.uploadFile('/integration/upload/vtt', formData);
23
+ }
24
+ }
25
+ exports.Uploads = Uploads;
@@ -0,0 +1,16 @@
1
+ import { TMSConfig, ControlPanelConfig } from './types.js';
2
+ export declare const DEFAULT_PANEL_CONFIG: ControlPanelConfig;
3
+ export declare const DEFAULT_TMS_CONFIG: Partial<TMSConfig>;
4
+ export declare class ConfigManager {
5
+ private config;
6
+ load(customConfig?: Partial<TMSConfig>, projectRoot?: string): TMSConfig;
7
+ private loadConfigFile;
8
+ private loadFromEnv;
9
+ get(): TMSConfig;
10
+ update(updates: Partial<TMSConfig>): TMSConfig;
11
+ private validate;
12
+ toJSON(): string;
13
+ fromJSON(json: string): TMSConfig;
14
+ }
15
+ export declare const configManager: ConfigManager;
16
+ export declare function createConfig(customConfig?: Partial<TMSConfig>): TMSConfig;
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configManager = exports.ConfigManager = exports.DEFAULT_TMS_CONFIG = exports.DEFAULT_PANEL_CONFIG = void 0;
4
+ exports.createConfig = createConfig;
5
+ exports.DEFAULT_PANEL_CONFIG = {
6
+ position: 'bottom-right',
7
+ theme: 'auto',
8
+ hotkey: 'Ctrl+Shift+T',
9
+ width: 400,
10
+ height: 600,
11
+ minimized: false,
12
+ zIndex: 10000,
13
+ };
14
+ exports.DEFAULT_TMS_CONFIG = {
15
+ version: '1.0.0',
16
+ sourceLanguage: 'en',
17
+ targetLanguages: ['tr'],
18
+ detection: {
19
+ includePaths: ['src', 'pages', 'components', 'app'],
20
+ excludePaths: ['node_modules', '.git', 'dist', 'build', '.next', 'out'],
21
+ includePatterns: ['**/*.{ts,tsx,js,jsx,vue}', '**/locales/**/*.{json,yaml,yml}'],
22
+ detectI18n: true,
23
+ detectHardcoded: true,
24
+ detectCMS: false,
25
+ },
26
+ i18n: {
27
+ framework: 'none',
28
+ translationDir: 'public/locales',
29
+ defaultNamespace: 'common',
30
+ keyStyle: 'nested',
31
+ },
32
+ ollang: {
33
+ apiKey: '',
34
+ baseUrl: 'http://localhost:8080', // TODO: Change to 'https://api-integration.ollang.com' before npm publish
35
+ defaultLevel: 0,
36
+ },
37
+ ui: exports.DEFAULT_PANEL_CONFIG,
38
+ };
39
+ class ConfigManager {
40
+ constructor() {
41
+ this.config = null;
42
+ }
43
+ load(customConfig = {}, projectRoot = process.cwd()) {
44
+ const configFile = this.loadConfigFile(projectRoot);
45
+ const envConfig = this.loadFromEnv();
46
+ this.config = {
47
+ ...exports.DEFAULT_TMS_CONFIG,
48
+ ...configFile,
49
+ ...envConfig,
50
+ ...customConfig,
51
+ projectRoot,
52
+ detection: {
53
+ ...exports.DEFAULT_TMS_CONFIG.detection,
54
+ ...configFile?.detection,
55
+ ...envConfig?.detection,
56
+ ...customConfig.detection,
57
+ },
58
+ i18n: {
59
+ ...exports.DEFAULT_TMS_CONFIG.i18n,
60
+ ...configFile?.i18n,
61
+ ...envConfig?.i18n,
62
+ ...customConfig.i18n,
63
+ },
64
+ ollang: {
65
+ ...exports.DEFAULT_TMS_CONFIG.ollang,
66
+ ...configFile?.ollang,
67
+ ...envConfig?.ollang,
68
+ ...customConfig.ollang,
69
+ },
70
+ ui: {
71
+ ...exports.DEFAULT_TMS_CONFIG.ui,
72
+ ...configFile?.ui,
73
+ ...envConfig?.ui,
74
+ ...customConfig.ui,
75
+ },
76
+ };
77
+ this.validate(this.config);
78
+ return this.config;
79
+ }
80
+ loadConfigFile(projectRoot) {
81
+ const fs = require('fs');
82
+ const path = require('path');
83
+ const configPaths = [
84
+ path.join(projectRoot, '.tmsrc.json'),
85
+ path.join(projectRoot, 'tms.config.json'),
86
+ path.join(projectRoot, '.tmsrc'),
87
+ ];
88
+ for (const configPath of configPaths) {
89
+ try {
90
+ if (fs.existsSync(configPath)) {
91
+ const content = fs.readFileSync(configPath, 'utf-8');
92
+ const config = JSON.parse(content);
93
+ console.log(`✅ Loaded config from: ${path.basename(configPath)}`);
94
+ return config;
95
+ }
96
+ }
97
+ catch (error) {
98
+ console.warn(`⚠️ Failed to load config from ${configPath}:`, error);
99
+ }
100
+ }
101
+ return null;
102
+ }
103
+ loadFromEnv() {
104
+ const config = {};
105
+ if (process.env.OLLANG_API_KEY || process.env.OLLANG_BASE_URL) {
106
+ const ollangConfig = {};
107
+ if (process.env.OLLANG_API_KEY) {
108
+ ollangConfig.apiKey = process.env.OLLANG_API_KEY;
109
+ }
110
+ if (process.env.OLLANG_BASE_URL) {
111
+ ollangConfig.baseUrl = process.env.OLLANG_BASE_URL;
112
+ }
113
+ config.ollang = ollangConfig;
114
+ }
115
+ if (process.env.TMS_SOURCE_LANGUAGE) {
116
+ config.sourceLanguage = process.env.TMS_SOURCE_LANGUAGE;
117
+ }
118
+ if (process.env.TMS_TARGET_LANGUAGES) {
119
+ config.targetLanguages = process.env.TMS_TARGET_LANGUAGES.split(',').map((l) => l.trim());
120
+ }
121
+ return config;
122
+ }
123
+ get() {
124
+ if (!this.config) {
125
+ throw new Error('Configuration not loaded. Call load() first.');
126
+ }
127
+ return this.config;
128
+ }
129
+ update(updates) {
130
+ if (!this.config) {
131
+ throw new Error('Configuration not loaded. Call load() first.');
132
+ }
133
+ this.config = {
134
+ ...this.config,
135
+ ...updates,
136
+ };
137
+ this.validate(this.config);
138
+ return this.config;
139
+ }
140
+ validate(config) {
141
+ if (!config.projectRoot) {
142
+ throw new Error('Project root is required');
143
+ }
144
+ if (!config.sourceLanguage) {
145
+ throw new Error('Source language is required');
146
+ }
147
+ if (!config.targetLanguages || config.targetLanguages.length === 0) {
148
+ throw new Error('At least one target language is required');
149
+ }
150
+ if (!config.detection.includePaths || config.detection.includePaths.length === 0) {
151
+ throw new Error('At least one include path is required for detection');
152
+ }
153
+ if (!config.ollang.apiKey) {
154
+ console.warn('⚠️ OLLANG_API_KEY not set. Translation features will not work.');
155
+ }
156
+ }
157
+ toJSON() {
158
+ if (!this.config) {
159
+ throw new Error('Configuration not loaded');
160
+ }
161
+ return JSON.stringify(this.config, null, 2);
162
+ }
163
+ fromJSON(json) {
164
+ const parsed = JSON.parse(json);
165
+ return this.load(parsed, parsed.projectRoot);
166
+ }
167
+ }
168
+ exports.ConfigManager = ConfigManager;
169
+ exports.configManager = new ConfigManager();
170
+ function createConfig(customConfig = {}) {
171
+ return exports.configManager.load(customConfig);
172
+ }
@@ -0,0 +1,27 @@
1
+ import { ContentDetector, DetectionConfig } from './content-type-detector.js';
2
+ export interface AudioContent {
3
+ id: string;
4
+ type: 'audio';
5
+ path: string;
6
+ filename?: string;
7
+ url?: string;
8
+ line?: number;
9
+ column?: number;
10
+ metadata: {
11
+ duration: number;
12
+ format: string;
13
+ size?: number;
14
+ isUrl?: boolean;
15
+ sourceFile?: string;
16
+ };
17
+ }
18
+ export declare class AudioDetector implements ContentDetector<AudioContent> {
19
+ supports(filePath: string): boolean;
20
+ detect(projectRoot: string, config: DetectionConfig): Promise<AudioContent[]>;
21
+ private scanDirectory;
22
+ private analyzeAudio;
23
+ private shouldExclude;
24
+ private scanForAudioUrls;
25
+ private extractAudioUrls;
26
+ private getFormatFromUrl;
27
+ }
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AudioDetector = void 0;
37
+ const fs = __importStar(require("fs/promises"));
38
+ const path = __importStar(require("path"));
39
+ const AUDIO_EXTENSIONS = ['.mp3', '.wav', '.m4a', '.aac', '.ogg', '.flac', '.wma', '.opus'];
40
+ const AUDIO_URL_PATTERNS = [
41
+ /https?:\/\/[^\s"']+\.mp3/gi,
42
+ /https?:\/\/[^\s"']+\.wav/gi,
43
+ /https?:\/\/[^\s"']+\.m4a/gi,
44
+ /https?:\/\/[^\s"']+\.aac/gi,
45
+ /https?:\/\/[^\s"']+\.ogg/gi,
46
+ /https?:\/\/[^\s"']+\.flac/gi,
47
+ /https?:\/\/[^\s"']*amazonaws\.com[^\s"']*\.(mp3|wav|m4a|aac|ogg|flac)/gi,
48
+ /https?:\/\/[^\s"']*cloudfront\.net[^\s"']*\.(mp3|wav|m4a|aac|ogg|flac)/gi,
49
+ ];
50
+ class AudioDetector {
51
+ supports(filePath) {
52
+ const ext = path.extname(filePath).toLowerCase();
53
+ return AUDIO_EXTENSIONS.includes(ext);
54
+ }
55
+ async detect(projectRoot, config) {
56
+ const audios = [];
57
+ for (const includePath of config.includePaths) {
58
+ const fullPath = path.join(projectRoot, includePath);
59
+ const physicalAudios = await this.scanDirectory(fullPath, config.excludePaths);
60
+ audios.push(...physicalAudios);
61
+ const urlAudios = await this.scanForAudioUrls(fullPath, config.excludePaths);
62
+ audios.push(...urlAudios);
63
+ }
64
+ return audios;
65
+ }
66
+ async scanDirectory(dirPath, excludePaths) {
67
+ const audios = [];
68
+ const items = await fs.readdir(dirPath, { withFileTypes: true });
69
+ for (const item of items) {
70
+ const fullPath = path.join(dirPath, item.name);
71
+ if (this.shouldExclude(fullPath, excludePaths)) {
72
+ continue;
73
+ }
74
+ if (item.isDirectory()) {
75
+ const subAudios = await this.scanDirectory(fullPath, excludePaths);
76
+ audios.push(...subAudios);
77
+ }
78
+ else if (item.isFile() && this.supports(item.name)) {
79
+ const audioContent = await this.analyzeAudio(fullPath);
80
+ audios.push(audioContent);
81
+ }
82
+ }
83
+ return audios;
84
+ }
85
+ async analyzeAudio(filePath) {
86
+ const stat = await fs.stat(filePath);
87
+ const filename = path.basename(filePath);
88
+ return {
89
+ id: `audio-${filePath}`,
90
+ type: 'audio',
91
+ path: filePath,
92
+ filename,
93
+ metadata: {
94
+ duration: 0,
95
+ format: path.extname(filePath).substring(1),
96
+ size: stat.size,
97
+ },
98
+ };
99
+ }
100
+ shouldExclude(filePath, excludePaths) {
101
+ return excludePaths.some((exclude) => filePath.includes(exclude));
102
+ }
103
+ async scanForAudioUrls(dirPath, excludePaths) {
104
+ const audios = [];
105
+ const codeExtensions = ['.ts', '.tsx', '.js', '.jsx', '.vue', '.html'];
106
+ const items = await fs.readdir(dirPath, { withFileTypes: true });
107
+ for (const item of items) {
108
+ const fullPath = path.join(dirPath, item.name);
109
+ if (this.shouldExclude(fullPath, excludePaths)) {
110
+ continue;
111
+ }
112
+ if (item.isDirectory()) {
113
+ const subAudios = await this.scanForAudioUrls(fullPath, excludePaths);
114
+ audios.push(...subAudios);
115
+ }
116
+ else if (item.isFile() && codeExtensions.includes(path.extname(item.name).toLowerCase())) {
117
+ const foundUrls = await this.extractAudioUrls(fullPath);
118
+ audios.push(...foundUrls);
119
+ }
120
+ }
121
+ return audios;
122
+ }
123
+ async extractAudioUrls(filePath) {
124
+ const audios = [];
125
+ const content = await fs.readFile(filePath, 'utf-8');
126
+ const foundUrls = new Set();
127
+ const lines = content.split('\n');
128
+ for (const pattern of AUDIO_URL_PATTERNS) {
129
+ const matches = content.matchAll(pattern);
130
+ for (const match of matches) {
131
+ foundUrls.add(match[0]);
132
+ }
133
+ }
134
+ for (const url of foundUrls) {
135
+ const format = this.getFormatFromUrl(url);
136
+ let lineNumber = 0;
137
+ let columnNumber = 0;
138
+ for (let i = 0; i < lines.length; i++) {
139
+ const index = lines[i].indexOf(url);
140
+ if (index !== -1) {
141
+ lineNumber = i + 1;
142
+ columnNumber = index;
143
+ break;
144
+ }
145
+ }
146
+ audios.push({
147
+ id: `audio-url-${url}`,
148
+ type: 'audio',
149
+ path: filePath,
150
+ url,
151
+ line: lineNumber,
152
+ column: columnNumber,
153
+ metadata: {
154
+ duration: 0,
155
+ format,
156
+ isUrl: true,
157
+ sourceFile: filePath,
158
+ },
159
+ });
160
+ }
161
+ return audios;
162
+ }
163
+ getFormatFromUrl(url) {
164
+ const match = url.match(/\.(mp3|wav|m4a|aac|ogg|flac)(\?|$)/i);
165
+ return match ? match[1].toLowerCase() : 'mp3';
166
+ }
167
+ }
168
+ exports.AudioDetector = AudioDetector;
@@ -0,0 +1 @@
1
+ export declare function autoDetectI18nDirs(projectRoot: string): Promise<string[]>;
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.autoDetectI18nDirs = autoDetectI18nDirs;
37
+ const fs = __importStar(require("fs/promises"));
38
+ const path = __importStar(require("path"));
39
+ const I18N_PATTERNS = [
40
+ // Next.js
41
+ 'public/locales',
42
+ 'messages',
43
+ 'locales',
44
+ // React
45
+ 'src/locales',
46
+ 'src/i18n',
47
+ 'src/messages',
48
+ 'locales',
49
+ 'i18n',
50
+ // Angular
51
+ 'src/assets/i18n',
52
+ 'src/assets/locales',
53
+ 'assets/i18n',
54
+ // Vue
55
+ 'src/locales',
56
+ 'locales',
57
+ // General
58
+ 'translations',
59
+ 'lang',
60
+ 'languages',
61
+ ];
62
+ async function autoDetectI18nDirs(projectRoot) {
63
+ const foundDirs = [];
64
+ for (const pattern of I18N_PATTERNS) {
65
+ const fullPath = path.join(projectRoot, pattern);
66
+ if (await dirExists(fullPath)) {
67
+ if (await hasI18nFiles(fullPath)) {
68
+ foundDirs.push(pattern);
69
+ }
70
+ }
71
+ }
72
+ if (foundDirs.length === 0) {
73
+ const shallowDirs = await shallowSearch(projectRoot);
74
+ foundDirs.push(...shallowDirs);
75
+ }
76
+ return foundDirs;
77
+ }
78
+ async function dirExists(dirPath) {
79
+ try {
80
+ const stat = await fs.stat(dirPath);
81
+ return stat.isDirectory();
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ async function hasI18nFiles(dirPath) {
88
+ try {
89
+ const items = await fs.readdir(dirPath, { withFileTypes: true });
90
+ const hasFiles = items.some((item) => item.isFile() &&
91
+ (item.name.endsWith('.json') || item.name.endsWith('.yaml') || item.name.endsWith('.yml')));
92
+ if (hasFiles)
93
+ return true;
94
+ const hasLangDirs = items.some((item) => {
95
+ if (!item.isDirectory())
96
+ return false;
97
+ const langCodes = ['en', 'tr', 'fr', 'es', 'de', 'it', 'pt', 'ja', 'ko', 'zh', 'ar', 'ru'];
98
+ return langCodes.includes(item.name.toLowerCase());
99
+ });
100
+ return hasLangDirs;
101
+ }
102
+ catch {
103
+ return false;
104
+ }
105
+ }
106
+ async function shallowSearch(dirPath, depth = 0, maxDepth = 3) {
107
+ if (depth >= maxDepth)
108
+ return [];
109
+ const foundDirs = [];
110
+ const items = await fs.readdir(dirPath, { withFileTypes: true });
111
+ for (const item of items) {
112
+ if (shouldSkip(item.name))
113
+ continue;
114
+ if (item.isDirectory()) {
115
+ const fullPath = path.join(dirPath, item.name);
116
+ const relativePath = path.relative(process.cwd(), fullPath);
117
+ if (looksLikeI18nDir(item.name) && (await hasI18nFiles(fullPath))) {
118
+ foundDirs.push(relativePath);
119
+ }
120
+ const subDirs = await shallowSearch(fullPath, depth + 1, maxDepth);
121
+ foundDirs.push(...subDirs);
122
+ }
123
+ }
124
+ return foundDirs;
125
+ }
126
+ function looksLikeI18nDir(name) {
127
+ const lowerName = name.toLowerCase();
128
+ return (lowerName.includes('i18n') ||
129
+ lowerName.includes('locale') ||
130
+ lowerName.includes('translation') ||
131
+ lowerName.includes('lang') ||
132
+ lowerName.includes('message') ||
133
+ lowerName === 'translations' ||
134
+ lowerName === 'messages');
135
+ }
136
+ function shouldSkip(name) {
137
+ const skipDirs = [
138
+ 'node_modules',
139
+ '.git',
140
+ '.next',
141
+ 'dist',
142
+ 'build',
143
+ 'out',
144
+ '.angular',
145
+ 'coverage',
146
+ '.vscode',
147
+ '.idea',
148
+ 'tmp',
149
+ 'temp',
150
+ ];
151
+ return skipDirs.includes(name) || name.startsWith('.');
152
+ }