@@ -34,7 +34,8 @@ var defaultConfig = {
3434 remove : false ,
3535 ci : false ,
3636 separator : '.' ,
37- noEmptyTranslation : ''
37+ noEmptyTranslation : '' ,
38+ missingTranslationString : ''
3839} ;
3940
4041function initCommand ( ) {
@@ -61,6 +62,14 @@ function resolveConfig() {
6162 return options ;
6263}
6364
65+ var DetectionType ;
66+
67+ ( function ( DetectionType ) {
68+ DetectionType [ "Missing" ] = "missing" ;
69+ DetectionType [ "Unused" ] = "unused" ;
70+ DetectionType [ "Dynamic" ] = "dynamic" ;
71+ } ) ( DetectionType || ( DetectionType = { } ) ) ;
72+
6473function readVueFiles ( src ) {
6574 // Replace backslash path segments to make the path work with the glob package.
6675 // https://github.com/Spittal/vue-i18n-extract/issues/159
@@ -218,13 +227,13 @@ function extractI18NLanguageFromLanguageFiles(languageFiles, dot = Dot) {
218227 return accumulator ;
219228 } , { } ) ;
220229}
221- function writeMissingToLanguageFiles ( parsedLanguageFiles , missingKeys , dot = Dot , noEmptyTranslation = '' ) {
230+ function writeMissingToLanguageFiles ( parsedLanguageFiles , missingKeys , dot = Dot , noEmptyTranslation = '' , missingTranslationString = '' ) {
222231 parsedLanguageFiles . forEach ( languageFile => {
223232 const languageFileContent = JSON . parse ( languageFile . content ) ;
224233 missingKeys . forEach ( item => {
225234 if ( item . language && languageFile . fileName . includes ( item . language ) || ! item . language ) {
226235 const addDefaultTranslation = noEmptyTranslation && ( noEmptyTranslation === '*' || noEmptyTranslation === item . language ) ;
227- dot . str ( item . path , addDefaultTranslation ? item . path : '' , languageFileContent ) ;
236+ dot . str ( item . path , addDefaultTranslation ? item . path : missingTranslationString === 'null' ? null : missingTranslationString , languageFileContent ) ;
228237 }
229238 } ) ;
230239 writeLanguageFile ( languageFile , languageFileContent ) ;
@@ -278,20 +287,31 @@ function mightBeDynamic(item) {
278287} // Looping through the arays multiple times might not be the most effecient, but it's the easiest to read and debug. Which at this scale is an accepted trade-off.
279288
280289
281- function extractI18NReport ( vueItems , languageFiles ) {
290+ function extractI18NReport ( vueItems , languageFiles , detect ) {
282291 const missingKeys = [ ] ;
283292 const unusedKeys = [ ] ;
284- const maybeDynamicKeys = vueItems . filter ( vueItem => mightBeDynamic ( vueItem ) ) . map ( vueItem => stripBounding ( vueItem ) ) ;
293+ const maybeDynamicKeys = [ ] ;
294+
295+ if ( detect . includes ( DetectionType . Dynamic ) ) {
296+ maybeDynamicKeys . push ( ...vueItems . filter ( vueItem => mightBeDynamic ( vueItem ) ) . map ( vueItem => stripBounding ( vueItem ) ) ) ;
297+ }
298+
285299 Object . keys ( languageFiles ) . forEach ( language => {
286300 const languageItems = languageFiles [ language ] ;
287- const missingKeysInLanguage = vueItems . filter ( vueItem => ! mightBeDynamic ( vueItem ) ) . filter ( vueItem => ! languageItems . some ( languageItem => vueItem . path === languageItem . path ) ) . map ( vueItem => _extends ( { } , stripBounding ( vueItem ) , {
288- language
289- } ) ) ;
290- const unusedKeysInLanguage = languageItems . filter ( languageItem => ! vueItems . some ( vueItem => languageItem . path === vueItem . path || languageItem . path . startsWith ( vueItem . path + '.' ) ) ) . map ( languageItem => _extends ( { } , languageItem , {
291- language
292- } ) ) ;
293- missingKeys . push ( ...missingKeysInLanguage ) ;
294- unusedKeys . push ( ...unusedKeysInLanguage ) ;
301+
302+ if ( detect . includes ( DetectionType . Missing ) ) {
303+ const missingKeysInLanguage = vueItems . filter ( vueItem => ! mightBeDynamic ( vueItem ) ) . filter ( vueItem => ! languageItems . some ( languageItem => vueItem . path === languageItem . path ) ) . map ( vueItem => _extends ( { } , stripBounding ( vueItem ) , {
304+ language
305+ } ) ) ;
306+ missingKeys . push ( ...missingKeysInLanguage ) ;
307+ }
308+
309+ if ( detect . includes ( DetectionType . Unused ) ) {
310+ const unusedKeysInLanguage = languageItems . filter ( languageItem => ! vueItems . some ( vueItem => languageItem . path === vueItem . path || languageItem . path . startsWith ( vueItem . path + '.' ) ) ) . map ( languageItem => _extends ( { } , languageItem , {
311+ language
312+ } ) ) ;
313+ unusedKeys . push ( ...unusedKeysInLanguage ) ;
314+ }
295315 } ) ;
296316 return {
297317 missingKeys,
@@ -323,16 +343,25 @@ async function createI18NReport(options) {
323343 exclude = [ ] ,
324344 ci,
325345 separator,
326- noEmptyTranslation = ''
346+ noEmptyTranslation = '' ,
347+ missingTranslationString = '' ,
348+ detect = [ DetectionType . Missing , DetectionType . Unused , DetectionType . Dynamic ]
327349 } = options ;
328350 if ( ! vueFilesGlob ) throw new Error ( 'Required configuration vueFiles is missing.' ) ;
329351 if ( ! languageFilesGlob ) throw new Error ( 'Required configuration languageFiles is missing.' ) ;
352+ let issuesToDetect = Array . isArray ( detect ) ? detect : [ detect ] ;
353+ const invalidDetectOptions = issuesToDetect . filter ( item => ! Object . values ( DetectionType ) . includes ( item ) ) ;
354+
355+ if ( invalidDetectOptions . length ) {
356+ throw new Error ( `Invalid 'detect' value(s): ${ invalidDetectOptions } ` ) ;
357+ }
358+
330359 const dot = typeof separator === 'string' ? new Dot ( separator ) : Dot ;
331360 const vueFiles = readVueFiles ( path . resolve ( process . cwd ( ) , vueFilesGlob ) ) ;
332361 const languageFiles = readLanguageFiles ( path . resolve ( process . cwd ( ) , languageFilesGlob ) ) ;
333362 const I18NItems = extractI18NItemsFromVueFiles ( vueFiles ) ;
334363 const I18NLanguage = extractI18NLanguageFromLanguageFiles ( languageFiles , dot ) ;
335- const report = extractI18NReport ( I18NItems , I18NLanguage ) ;
364+ const report = extractI18NReport ( I18NItems , I18NLanguage , issuesToDetect ) ;
336365 report . unusedKeys = report . unusedKeys . filter ( key => ! exclude . filter ( excluded => key . path . startsWith ( excluded ) ) . length ) ;
337366 if ( report . missingKeys . length ) console . info ( '\nMissing Keys' ) , console . table ( report . missingKeys ) ;
338367 if ( report . unusedKeys . length ) console . info ( '\nUnused Keys' ) , console . table ( report . unusedKeys ) ;
@@ -349,7 +378,7 @@ async function createI18NReport(options) {
349378 }
350379
351380 if ( add && report . missingKeys . length ) {
352- writeMissingToLanguageFiles ( languageFiles , report . missingKeys , dot , noEmptyTranslation ) ;
381+ writeMissingToLanguageFiles ( languageFiles , report . missingKeys , dot , noEmptyTranslation , missingTranslationString ) ;
353382 console . info ( '\nThe missing keys have been added to your language files.' ) ;
354383 }
355384
@@ -373,5 +402,5 @@ process.on('unhandledRejection', err => {
373402 process . exit ( 1 ) ;
374403} ) ;
375404
376- export { createI18NReport , extractI18NItemsFromVueFiles , extractI18NLanguageFromLanguageFiles , extractI18NReport , initCommand , parseVueFiles , parselanguageFiles , readLanguageFiles , readVueFiles , removeUnusedFromLanguageFiles , resolveConfig , writeMissingToLanguageFiles , writeReportToFile } ;
405+ export { DetectionType , createI18NReport , extractI18NItemsFromVueFiles , extractI18NLanguageFromLanguageFiles , extractI18NReport , initCommand , parseVueFiles , parselanguageFiles , readLanguageFiles , readVueFiles , removeUnusedFromLanguageFiles , resolveConfig , writeMissingToLanguageFiles , writeReportToFile } ;
377406//# sourceMappingURL=vue-i18n-extract.modern.mjs.map
0 commit comments