Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add json5 support #194

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions dist/create-report/report.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference types="node" />
import { I18NItemWithBounding, I18NLanguage, I18NReport } from '../types';
export declare function extractI18NReport(vueItems: I18NItemWithBounding[], languageFiles: I18NLanguage): I18NReport;
import { DetectionType, I18NItemWithBounding, I18NLanguage, I18NReport } from '../types';
export declare function extractI18NReport(vueItems: I18NItemWithBounding[], languageFiles: I18NLanguage, detect: DetectionType[]): I18NReport;
export declare function writeReportToFile(report: I18NReport, writePath: string): Promise<NodeJS.ErrnoException | void>;
6 changes: 6 additions & 0 deletions dist/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ export declare type ReportOptions = {
ci?: boolean;
separator?: string;
noEmptyTranslation?: string;
detect?: DetectionType[];
};
export declare enum DetectionType {
Missing = "missing",
Unused = "unused",
Dynamic = "dynamic"
}
export declare type SimpleFile = {
fileName: string;
path: string;
Expand Down
57 changes: 44 additions & 13 deletions dist/vue-i18n-extract.modern.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import isValidGlob from 'is-valid-glob';
import glob from 'glob';
import Dot from 'dot-object';
import yaml from 'js-yaml';
import JSON5 from 'json5';

function _extends() {
_extends = Object.assign || function (target) {
Expand Down Expand Up @@ -61,6 +62,14 @@ function resolveConfig() {
return options;
}

var DetectionType;

(function (DetectionType) {
DetectionType["Missing"] = "missing";
DetectionType["Unused"] = "unused";
DetectionType["Dynamic"] = "dynamic";
})(DetectionType || (DetectionType = {}));

function readVueFiles(src) {
// Replace backslash path segments to make the path work with the glob package.
// https://github.com/Spittal/vue-i18n-extract/issues/159
Expand Down Expand Up @@ -181,11 +190,14 @@ function readLanguageFiles(src) {
const langPath = path.resolve(process.cwd(), f);
const extension = langPath.substring(langPath.lastIndexOf('.')).toLowerCase();
const isJSON = extension === '.json';
const isJSON5 = extension === '.json5';
const isYAML = extension === '.yaml' || extension === '.yml';
let langObj;

if (isJSON) {
langObj = JSON.parse(fs.readFileSync(langPath, 'utf8'));
} else if (isJSON5) {
langObj = JSON5.parse(fs.readFileSync(langPath, 'utf8'));
} else if (isYAML) {
langObj = yaml.load(fs.readFileSync(langPath, 'utf8'));
} else {
Expand Down Expand Up @@ -278,20 +290,31 @@ function mightBeDynamic(item) {
} // 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.


function extractI18NReport(vueItems, languageFiles) {
function extractI18NReport(vueItems, languageFiles, detect) {
const missingKeys = [];
const unusedKeys = [];
const maybeDynamicKeys = vueItems.filter(vueItem => mightBeDynamic(vueItem)).map(vueItem => stripBounding(vueItem));
const maybeDynamicKeys = [];

if (detect.includes(DetectionType.Dynamic)) {
maybeDynamicKeys.push(...vueItems.filter(vueItem => mightBeDynamic(vueItem)).map(vueItem => stripBounding(vueItem)));
}

Object.keys(languageFiles).forEach(language => {
const languageItems = languageFiles[language];
const missingKeysInLanguage = vueItems.filter(vueItem => !mightBeDynamic(vueItem)).filter(vueItem => !languageItems.some(languageItem => vueItem.path === languageItem.path)).map(vueItem => _extends({}, stripBounding(vueItem), {
language
}));
const unusedKeysInLanguage = languageItems.filter(languageItem => !vueItems.some(vueItem => languageItem.path === vueItem.path || languageItem.path.startsWith(vueItem.path + '.'))).map(languageItem => _extends({}, languageItem, {
language
}));
missingKeys.push(...missingKeysInLanguage);
unusedKeys.push(...unusedKeysInLanguage);

if (detect.includes(DetectionType.Missing)) {
const missingKeysInLanguage = vueItems.filter(vueItem => !mightBeDynamic(vueItem)).filter(vueItem => !languageItems.some(languageItem => vueItem.path === languageItem.path)).map(vueItem => _extends({}, stripBounding(vueItem), {
language
}));
missingKeys.push(...missingKeysInLanguage);
}

if (detect.includes(DetectionType.Unused)) {
const unusedKeysInLanguage = languageItems.filter(languageItem => !vueItems.some(vueItem => languageItem.path === vueItem.path || languageItem.path.startsWith(vueItem.path + '.'))).map(languageItem => _extends({}, languageItem, {
language
}));
unusedKeys.push(...unusedKeysInLanguage);
}
});
return {
missingKeys,
Expand Down Expand Up @@ -323,16 +346,24 @@ async function createI18NReport(options) {
exclude = [],
ci,
separator,
noEmptyTranslation = ''
noEmptyTranslation = '',
detect = [DetectionType.Missing, DetectionType.Unused, DetectionType.Dynamic]
} = options;
if (!vueFilesGlob) throw new Error('Required configuration vueFiles is missing.');
if (!languageFilesGlob) throw new Error('Required configuration languageFiles is missing.');
let issuesToDetect = Array.isArray(detect) ? detect : [detect];
const invalidDetectOptions = issuesToDetect.filter(item => !Object.values(DetectionType).includes(item));

if (invalidDetectOptions.length) {
throw new Error(`Invalid 'detect' value(s): ${invalidDetectOptions}`);
}

const dot = typeof separator === 'string' ? new Dot(separator) : Dot;
const vueFiles = readVueFiles(path.resolve(process.cwd(), vueFilesGlob));
const languageFiles = readLanguageFiles(path.resolve(process.cwd(), languageFilesGlob));
const I18NItems = extractI18NItemsFromVueFiles(vueFiles);
const I18NLanguage = extractI18NLanguageFromLanguageFiles(languageFiles, dot);
const report = extractI18NReport(I18NItems, I18NLanguage);
const report = extractI18NReport(I18NItems, I18NLanguage, issuesToDetect);
report.unusedKeys = report.unusedKeys.filter(key => !exclude.filter(excluded => key.path.startsWith(excluded)).length);
if (report.missingKeys.length) console.info('\nMissing Keys'), console.table(report.missingKeys);
if (report.unusedKeys.length) console.info('\nUnused Keys'), console.table(report.unusedKeys);
Expand Down Expand Up @@ -373,5 +404,5 @@ process.on('unhandledRejection', err => {
process.exit(1);
});

export { createI18NReport, extractI18NItemsFromVueFiles, extractI18NLanguageFromLanguageFiles, extractI18NReport, initCommand, parseVueFiles, parselanguageFiles, readLanguageFiles, readVueFiles, removeUnusedFromLanguageFiles, resolveConfig, writeMissingToLanguageFiles, writeReportToFile };
export { DetectionType, createI18NReport, extractI18NItemsFromVueFiles, extractI18NLanguageFromLanguageFiles, extractI18NReport, initCommand, parseVueFiles, parselanguageFiles, readLanguageFiles, readVueFiles, removeUnusedFromLanguageFiles, resolveConfig, writeMissingToLanguageFiles, writeReportToFile };
//# sourceMappingURL=vue-i18n-extract.modern.mjs.map
2 changes: 1 addition & 1 deletion dist/vue-i18n-extract.modern.mjs.map

Large diffs are not rendered by default.

63 changes: 47 additions & 16 deletions dist/vue-i18n-extract.umd.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/vue-i18n-extract.umd.js.map

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"dot-object": "^2.1.4",
"glob": "^8.0.1",
"is-valid-glob": "^1.0.0",
"js-yaml": "^4.1.0"
"js-yaml": "^4.1.0",
"json5": "^2.2.1"
},
"devDependencies": {
"@types/dot-object": "^2.1.2",
Expand Down
2 changes: 1 addition & 1 deletion src/config-file/vue-i18n-extract.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default {
// Options documented in vue-i18n-extract readme.
vueFiles: './src/**/*.?(js|vue)',
languageFiles: './lang/**/*.?(json|yaml|yml|js)',
languageFiles: './lang/**/*.?(json|json5|yaml|yml|js)',
exclude: [],
output: false,
add: false,
Expand Down
4 changes: 4 additions & 0 deletions src/create-report/language-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Dot from 'dot-object';
import yaml from 'js-yaml';
import isValidGlob from 'is-valid-glob';
import { SimpleFile, I18NLanguage, I18NItem } from '../types';
import JSON5 from 'json5'

export function readLanguageFiles (src: string): SimpleFile[] {
// Replace backslash path segments to make the path work with the glob package.
Expand All @@ -25,11 +26,14 @@ export function readLanguageFiles (src: string): SimpleFile[] {

const extension = langPath.substring(langPath.lastIndexOf('.')).toLowerCase();
const isJSON = extension === '.json';
const isJSON5 = extension === '.json5'
const isYAML = extension === '.yaml' || extension === '.yml';

let langObj;
if (isJSON) {
langObj = JSON.parse(fs.readFileSync(langPath, 'utf8'));
} else if (isJSON5) {
langObj = JSON5.parse(fs.readFileSync(langPath, 'utf8'))
} else if (isYAML) {
langObj = yaml.load(fs.readFileSync(langPath, 'utf8'));
} else {
Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8470,6 +8470,7 @@ __metadata:
jest: ^27.1.4
jest-config: ^28.0.2
js-yaml: ^4.1.0
json5: ^2.2.1
microbundle: ^0.15.0
rimraf: ^3.0.2
ts-jest: ^27.1.4
Expand Down