@vocab/core 1.0.3 → 1.1.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.
package/src/utils.ts DELETED
@@ -1,143 +0,0 @@
1
- import path from 'path';
2
-
3
- import type {
4
- LanguageName,
5
- LanguageTarget,
6
- TranslationsByKey,
7
- TranslationMessagesByKey,
8
- UserConfig,
9
- } from '@vocab/types';
10
- import { trace } from './logger';
11
-
12
- export const defaultTranslationDirSuffix = '.vocab';
13
- export const devTranslationFileName = 'translations.json';
14
-
15
- export type Fallback = 'none' | 'valid' | 'all';
16
-
17
- const globAnyPathWithOptionalPrefix = '**/?(*)';
18
-
19
- export function isDevLanguageFile(filePath: string) {
20
- return (
21
- filePath.endsWith(`/${devTranslationFileName}`) ||
22
- filePath === devTranslationFileName
23
- );
24
- }
25
- export function isAltLanguageFile(filePath: string) {
26
- return filePath.endsWith('.translations.json');
27
- }
28
- export function isTranslationDirectory(
29
- filePath: string,
30
- {
31
- translationsDirectorySuffix = defaultTranslationDirSuffix,
32
- }: {
33
- translationsDirectorySuffix?: string;
34
- },
35
- ) {
36
- return filePath.endsWith(translationsDirectorySuffix);
37
- }
38
-
39
- export function getTranslationFolderGlob({
40
- translationsDirectorySuffix = defaultTranslationDirSuffix,
41
- }: {
42
- translationsDirectorySuffix?: string;
43
- }) {
44
- const result = `${globAnyPathWithOptionalPrefix}${translationsDirectorySuffix}`;
45
-
46
- trace('getTranslationFolderGlob', result);
47
-
48
- return result;
49
- }
50
-
51
- export function getDevTranslationFileGlob({
52
- translationsDirectorySuffix = defaultTranslationDirSuffix,
53
- }: {
54
- translationsDirectorySuffix?: string;
55
- }) {
56
- const result = `${globAnyPathWithOptionalPrefix}${translationsDirectorySuffix}/${devTranslationFileName}`;
57
-
58
- trace('getDevTranslationFileGlob', result);
59
-
60
- return result;
61
- }
62
-
63
- export function getAltTranslationFileGlob(config: UserConfig) {
64
- const altLanguages = getAltLanguages(config);
65
- const langMatch =
66
- altLanguages.length === 1 ? altLanguages[0] : `{${altLanguages.join(',')}}`;
67
-
68
- const { translationsDirectorySuffix = defaultTranslationDirSuffix } = config;
69
- const result = `**/*${translationsDirectorySuffix}/${langMatch}.translations.json`;
70
-
71
- trace('getAltTranslationFileGlob', result);
72
-
73
- return result;
74
- }
75
-
76
- export function getAltLanguages({
77
- devLanguage,
78
- languages,
79
- }: {
80
- devLanguage: LanguageName;
81
- languages: Array<LanguageTarget>;
82
- }) {
83
- return languages.map((v) => v.name).filter((lang) => lang !== devLanguage);
84
- }
85
-
86
- export function getDevLanguageFileFromTsFile(tsFilePath: string) {
87
- const directory = path.dirname(tsFilePath);
88
- const result = path.normalize(path.join(directory, devTranslationFileName));
89
-
90
- trace(`Returning dev language path ${result} for path ${tsFilePath}`);
91
- return result;
92
- }
93
-
94
- export function getDevLanguageFileFromAltLanguageFile(
95
- altLanguageFilePath: string,
96
- ) {
97
- const directory = path.dirname(altLanguageFilePath);
98
- const result = path.normalize(path.join(directory, devTranslationFileName));
99
- trace(
100
- `Returning dev language path ${result} for path ${altLanguageFilePath}`,
101
- );
102
- return result;
103
- }
104
-
105
- export function getTSFileFromDevLanguageFile(devLanguageFilePath: string) {
106
- const directory = path.dirname(devLanguageFilePath);
107
- const result = path.normalize(path.join(directory, 'index.ts'));
108
-
109
- trace(`Returning TS path ${result} for path ${devLanguageFilePath}`);
110
- return result;
111
- }
112
-
113
- export function getAltLanguageFilePath(
114
- devLanguageFilePath: string,
115
- language: string,
116
- ) {
117
- const directory = path.dirname(devLanguageFilePath);
118
- const result = path.normalize(
119
- path.join(directory, `${language}.translations.json`),
120
- );
121
- trace(
122
- `Returning alt language path ${result} for path ${devLanguageFilePath}`,
123
- );
124
- return path.normalize(result);
125
- }
126
-
127
- export function mapValues<Key extends string, OriginalValue, ReturnValue>(
128
- obj: Record<Key, OriginalValue>,
129
- func: (val: OriginalValue) => ReturnValue,
130
- ): TranslationMessagesByKey<Key> {
131
- const newObj: any = {};
132
- const keys = Object.keys(obj) as Key[];
133
- for (const key of keys) {
134
- newObj[key] = func(obj[key]);
135
- }
136
- return newObj;
137
- }
138
-
139
- export function getTranslationMessages<Key extends string>(
140
- translations: TranslationsByKey<Key>,
141
- ): TranslationMessagesByKey<Key> {
142
- return mapValues(translations, (v) => v.message);
143
- }
@@ -1,64 +0,0 @@
1
- import { LoadedTranslation, LanguageName } from '@vocab/types';
2
- import { findMissingKeys } from './index';
3
-
4
- interface TestCase {
5
- loadedTranslation: LoadedTranslation;
6
- devLanguage: LanguageName;
7
- altLanguages: Array<LanguageName>;
8
- valid: boolean;
9
- missingKeys?: Record<LanguageName, Array<string>>;
10
- }
11
-
12
- const testCases: Array<TestCase> = [
13
- {
14
- loadedTranslation: {
15
- filePath: 'some-file.json',
16
- namespace: 'some-file',
17
- keys: ['key1', 'key2'],
18
- relativePath: 'some-file.json',
19
- languages: {
20
- en: { key1: { message: 'Hi' } },
21
- th: { key1: { message: 'Bye' } },
22
- },
23
- },
24
- devLanguage: 'en',
25
- altLanguages: ['th'],
26
- valid: true,
27
- },
28
- {
29
- loadedTranslation: {
30
- filePath: 'some-file.json',
31
- relativePath: 'some-file.json',
32
- namespace: 'some-file-2',
33
- keys: ['key1'],
34
- languages: {
35
- en: { key1: { message: 'Hi' } },
36
- th: {},
37
- },
38
- },
39
- devLanguage: 'en',
40
- altLanguages: ['th'],
41
- valid: false,
42
- missingKeys: {
43
- th: ['key1'],
44
- },
45
- },
46
- ];
47
-
48
- test.each(testCases)(
49
- 'validate',
50
- ({ loadedTranslation, devLanguage, altLanguages, valid, missingKeys }) => {
51
- const result = findMissingKeys(
52
- loadedTranslation,
53
- devLanguage,
54
- altLanguages,
55
- );
56
-
57
- expect(result[0]).toBe(valid);
58
-
59
- if (missingKeys) {
60
- // eslint-disable-next-line jest/no-conditional-expect
61
- expect(result[1]).toMatchObject(missingKeys);
62
- }
63
- },
64
- );
@@ -1,81 +0,0 @@
1
- /* eslint-disable no-console */
2
- import { UserConfig, LoadedTranslation, LanguageName } from '@vocab/types';
3
- import chalk from 'chalk';
4
-
5
- import { loadAllTranslations } from '../load-translations';
6
- import { getAltLanguages } from '../utils';
7
-
8
- export function findMissingKeys(
9
- loadedTranslation: LoadedTranslation,
10
- devLanguageName: LanguageName,
11
- altLangauges: Array<LanguageName>,
12
- ) {
13
- const devLanguage = loadedTranslation.languages[devLanguageName];
14
-
15
- if (!devLanguage) {
16
- throw new Error(
17
- `Failed to load dev language: ${loadedTranslation.filePath}`,
18
- );
19
- }
20
-
21
- const result: Record<LanguageName, Array<string>> = {};
22
- let valid = true;
23
-
24
- const requiredKeys = Object.keys(devLanguage);
25
-
26
- if (requiredKeys.length > 0) {
27
- for (const altLanguageName of altLangauges) {
28
- const altLanguage = loadedTranslation.languages[altLanguageName] ?? {};
29
-
30
- for (const key of requiredKeys) {
31
- if (typeof altLanguage[key]?.message !== 'string') {
32
- if (!result[altLanguageName]) {
33
- result[altLanguageName] = [];
34
- }
35
-
36
- result[altLanguageName].push(key);
37
- valid = false;
38
- }
39
- }
40
- }
41
- }
42
- return [valid, result] as const;
43
- }
44
-
45
- export async function validate(config: UserConfig) {
46
- const allTranslations = await loadAllTranslations(
47
- { fallbacks: 'valid', includeNodeModules: true },
48
- config,
49
- );
50
-
51
- let valid = true;
52
-
53
- for (const loadedTranslation of allTranslations) {
54
- const [translationValid, result] = findMissingKeys(
55
- loadedTranslation,
56
- config.devLanguage,
57
- getAltLanguages(config),
58
- );
59
-
60
- if (!translationValid) {
61
- valid = false;
62
- console.log(
63
- chalk.red`Incomplete translations: "${chalk.bold(
64
- loadedTranslation.relativePath,
65
- )}"`,
66
- );
67
-
68
- for (const lang of Object.keys(result)) {
69
- const missingKeys = result[lang];
70
-
71
- console.log(
72
- chalk.yellow(lang),
73
- '->',
74
- missingKeys.map((v) => `"${v}"`).join(', '),
75
- );
76
- }
77
- }
78
- }
79
-
80
- return valid;
81
- }