UNPKG

angular-translation-checker

Version:

A comprehensive tool for analyzing translation keys in Angular projects using ngx-translate

136 lines 5.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CoreAnalyzer = void 0; class CoreAnalyzer { constructor() { this.name = 'core-analyzer'; this.version = '1.0.0'; this.description = 'Core translation analysis functionality'; } async initialize(context) { this.logger = context.logger; this.logger.debug('Core analyzer initialized'); } async analyze(context) { const { config, translationFiles, extractedKeys } = context; // Get all available translation keys const allTranslationKeys = this.getAllTranslationKeys(translationFiles); // Get used keys (extracted from source) const usedKeys = this.filterStaticKeys(extractedKeys); const usedKeyStrings = new Set(usedKeys.map(k => k.key)); // Apply ignore patterns const ignoredKeys = this.applyIgnorePatterns(allTranslationKeys, config.ignoreKeys || []); const ignoredKeySet = new Set(ignoredKeys); // Calculate unused keys const unusedKeys = allTranslationKeys.filter(key => !usedKeyStrings.has(key) && !ignoredKeySet.has(key)); // Calculate missing keys const translationKeySet = new Set(allTranslationKeys); const missingKeys = usedKeys.filter(key => !translationKeySet.has(key.key) && !ignoredKeySet.has(key.key)); // Handle dynamic patterns const dynamicPatterns = this.processDynamicPatterns(extractedKeys.filter(k => k.context === 'dynamic'), allTranslationKeys, config.ignoreDynamicKeys || false); // Calculate coverage const totalTranslations = allTranslationKeys.length; const totalUsedKeys = usedKeyStrings.size; const coverage = totalTranslations > 0 ? Math.round((totalUsedKeys / totalTranslations) * 100) : 0; const result = { summary: { totalTranslations, totalUsedKeys, totalUnusedKeys: unusedKeys.length, totalMissingKeys: missingKeys.length, coverage, languages: translationFiles.map(f => f.language) }, usedKeys, unusedKeys, missingKeys, dynamicPatterns, ignoredKeys }; this.logger.debug(`Analysis complete: ${totalUsedKeys} used, ${unusedKeys.length} unused, ${missingKeys.length} missing`); return result; } getAllTranslationKeys(translationFiles) { const keys = new Set(); for (const file of translationFiles) { this.extractKeysFromObject(file.keys, '', keys); } return Array.from(keys); } extractKeysFromObject(obj, prefix, keys) { for (const [key, value] of Object.entries(obj)) { const fullKey = prefix ? `${prefix}.${key}` : key; if (typeof value === 'object' && value !== null && !Array.isArray(value)) { this.extractKeysFromObject(value, fullKey, keys); } else { keys.add(fullKey); } } } filterStaticKeys(keys) { return keys.filter(key => key.context !== 'dynamic'); } applyIgnorePatterns(keys, ignorePatterns) { const ignoredKeys = []; for (const key of keys) { for (const pattern of ignorePatterns) { if (this.matchesPattern(key, pattern)) { ignoredKeys.push(key); break; } } } return ignoredKeys; } matchesPattern(key, pattern) { // Convert wildcard pattern to regex let regexPattern = pattern .replace(/\*\*/g, '.*') // ** matches anything .replace(/\*/g, '[^.]*') // * matches anything except dots .replace(/\./g, '\\.') // Escape dots .replace(/\?/g, '.'); // ? matches single character const regex = new RegExp(`^${regexPattern}$`); return regex.test(key); } processDynamicPatterns(dynamicKeys, allKeys, ignoreDynamic) { if (ignoreDynamic) { return []; } const patterns = new Map(); for (const dynamicKey of dynamicKeys) { const pattern = this.extractPattern(dynamicKey.key); if (pattern) { const matches = allKeys.filter(key => this.matchesPattern(key, pattern)); if (matches.length > 0) { patterns.set(pattern, matches); } } } return Array.from(patterns.entries()).map(([pattern, matches]) => ({ pattern, matches })); } extractPattern(dynamicKey) { // Try to extract a pattern from dynamic key construction // This is a simplified version - in practice, you might use AST analysis // Handle template literals like `errors.${type}.message` if (dynamicKey.includes('${')) { return dynamicKey.replace(/\$\{[^}]+\}/g, '*'); } // Handle variable concatenation patterns if (dynamicKey.includes('+')) { // This would require more sophisticated parsing return null; } // Handle property access patterns if (dynamicKey.includes('.')) { return dynamicKey + '.*'; } return null; } } exports.CoreAnalyzer = CoreAnalyzer; //# sourceMappingURL=core-analyzer.js.map