angular-translation-checker
Version:
A comprehensive tool for analyzing translation keys in Angular projects using ngx-translate
136 lines • 5.48 kB
JavaScript
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
;