Skip to content

Commit 31316f9

Browse files
fix(compile): remove verbose output when using flow with template (#1388)
1 parent 8579090 commit 31316f9

File tree

9 files changed

+289
-23
lines changed

9 files changed

+289
-23
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"@testing-library/react": "^11.0.4",
4747
"@types/babel-types": "^7.0.9",
4848
"@types/jest": "^26.0.14",
49+
"@types/mock-fs": "^4.13.1",
4950
"@types/node": "14.14.31",
5051
"@types/ramda": "^0.27.23",
5152
"@types/react": "^16.9.51",
@@ -74,7 +75,7 @@
7475
"lint-staged": "^13.1.0",
7576
"memory-fs": "^0.5.0",
7677
"minimist": "^1.2.5",
77-
"mock-fs": "^4.13.0",
78+
"mock-fs": "^5.2.0",
7879
"mockdate": "^3.0.2",
7980
"ncp": "^2.0.0",
8081
"npm-cli-login": "^0.1.1",

packages/cli/src/api/catalog.ts

-5
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,6 @@ export class Catalog {
280280
) {
281281
const catalog = catalogs[locale] || {}
282282

283-
if (!catalog.hasOwnProperty(key)) {
284-
console.error(`Message with key ${key} is missing in locale ${locale}`)
285-
}
286-
287283
const getTranslation = (_locale: string) => {
288284
const configLocales = this.config.locales.join('", "')
289285
const localeCatalog = catalogs[_locale] || {}
@@ -299,7 +295,6 @@ export class Catalog {
299295
return null
300296
}
301297
if (!localeCatalog.hasOwnProperty(key)) {
302-
console.error(`Message with key ${key} is missing in locale ${_locale}`)
303298
return null
304299
}
305300

packages/cli/src/lingui-compile.ts

+20-10
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,18 @@ const noMessages: (catalogs: Object[]) => boolean = R.pipe(
1818
R.all(R.equals<any>(true))
1919
)
2020

21-
function command(config: LinguiConfig, options) {
21+
export type CliCompileOptions = {
22+
verbose?: boolean
23+
allowEmpty?: boolean,
24+
typescript?: boolean,
25+
watch?: boolean
26+
namespace?: string,
27+
}
28+
29+
export function command(config: LinguiConfig, options: CliCompileOptions) {
2230
const catalogs = getCatalogs(config)
2331

32+
// fixme: this is definitely doesn't work
2433
if (noMessages(catalogs)) {
2534
console.error("Nothing to compile, message catalogs are empty!\n")
2635
console.error(
@@ -35,23 +44,24 @@ function command(config: LinguiConfig, options) {
3544
const doMerge = !!config.catalogsMergePath
3645
let mergedCatalogs = {}
3746

38-
console.error("Compiling message catalogs…")
47+
console.log("Compiling message catalogs…")
3948

40-
config.locales.forEach((locale) => {
49+
for (const locale of config.locales) {
4150
const [language] = locale.split(/[_-]/)
51+
// todo: this validation should be in @lingui/conf
4252
if (locale !== config.pseudoLocale && !plurals[language]) {
43-
console.log(
53+
console.error(
4454
chalk.red(
4555
`Error: Invalid locale ${chalk.bold(locale)} (missing plural rules)!`
4656
)
4757
)
4858
console.error()
4959
}
5060

51-
catalogs.forEach((catalog) => {
61+
for (const catalog of catalogs) {
5262
const messages = catalog.getTranslations(locale, {
5363
fallbackLocales: config.fallbackLocales,
54-
sourceLocale: config.sourceLocale,
64+
sourceLocale: config.sourceLocale
5565
})
5666

5767
if (!options.allowEmpty) {
@@ -68,14 +78,14 @@ function command(config: LinguiConfig, options) {
6878

6979
if (options.verbose) {
7080
console.error(chalk.red("Missing translations:"))
71-
missingMsgIds.forEach((msgId) => console.log(msgId))
81+
missingMsgIds.forEach((msgId) => console.error(msgId))
7282
} else {
7383
console.error(
7484
chalk.red(`Missing ${missingMsgIds.length} translation(s)`)
7585
)
7686
}
7787
console.error()
78-
process.exit(1)
88+
return false
7989
}
8090
}
8191

@@ -112,7 +122,7 @@ function command(config: LinguiConfig, options) {
112122
options.verbose &&
113123
console.error(chalk.green(`${locale}${compiledPath}`))
114124
}
115-
})
125+
}
116126

117127
if (doMerge) {
118128
const compileCatalog = getCatalogForMerge(config)
@@ -130,7 +140,7 @@ function command(config: LinguiConfig, options) {
130140
)
131141
options.verbose && console.log(chalk.green(`${locale}${compiledPath}`))
132142
}
133-
})
143+
}
134144
return true
135145
}
136146

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`CLI Command: Compile Locales Validation Should throw error for invalid locale 1`] = `
4+
Error: Invalid locale abra (missing plural rules)!
5+
6+
`;
7+
8+
exports[`CLI Command: Compile allowEmpty = false Should show error and stop compilation of catalog if message doesnt have a translation (with template) 1`] = `
9+
Object {
10+
en: /*eslint-disable*/module.exports={messages:JSON.parse("{\\"Hello World\\":\\"Hello World\\"}")};,
11+
pl: undefined,
12+
}
13+
`;
14+
15+
exports[`CLI Command: Compile allowEmpty = false Should show error and stop compilation of catalog if message doesnt have a translation (with template) 2`] = `
16+
Error: Failed to compile catalog for locale pl!
17+
Missing 1 translation(s)
18+
19+
`;
20+
21+
exports[`CLI Command: Compile allowEmpty = false Should show error and stop compilation of catalog if message doesnt have a translation (no template) 1`] = `
22+
Error: Failed to compile catalog for locale pl!
23+
Missing 1 translation(s)
24+
25+
`;
26+
27+
exports[`CLI Command: Compile allowEmpty = false Should show missing messages verbosely when verbose = true 1`] = `
28+
en ⇒ /test/en.js
29+
Error: Failed to compile catalog for locale pl!
30+
Missing translations:
31+
Hello World
32+
Test String
33+
34+
`;

packages/cli/src/test/compile.test.ts

+203
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import {command} from "../lingui-compile"
2+
import {makeConfig} from "@lingui/conf"
3+
import path from "path"
4+
import {getConsoleMockCalls, mockConsole} from "@lingui/jest-mocks"
5+
import mockFs from "mock-fs"
6+
import fs from 'fs'
7+
8+
function readFsToJson(directory: string, filter?: (filename: string) => boolean) {
9+
const out = {}
10+
11+
fs
12+
.readdirSync(directory)
13+
.map((filename) => {
14+
const filepath = path.join(directory, filename)
15+
16+
if (fs.lstatSync(filepath).isDirectory()) {
17+
out[filename] = readFsToJson(filepath)
18+
return out
19+
}
20+
21+
if (!filter || filter(filename)) {
22+
out[filename] = fs.readFileSync(filepath).toString()
23+
}
24+
})
25+
26+
return out
27+
}
28+
29+
describe('CLI Command: Compile', () => {
30+
xit('Should return error if no messages', () => {
31+
const config = makeConfig({
32+
locales: ['en', 'pl'],
33+
rootDir: path.join(__dirname, 'fixtures/compile'),
34+
catalogs: [{
35+
path: '<rootDir>/{locale}',
36+
include: ['<rootDir>']
37+
}]
38+
})
39+
40+
const result = command(config, {})
41+
expect(result).toBeFalsy()
42+
})
43+
44+
describe('Merge Catalogs', () => {
45+
// todo
46+
})
47+
48+
describe('Locales Validation', () => {
49+
// todo: should be moved to @lingui/conf
50+
it('Should throw error for invalid locale', () => {
51+
const config = makeConfig({
52+
locales: ['abra'],
53+
rootDir: '/test',
54+
catalogs: [{
55+
path: '<rootDir>/{locale}',
56+
include: ['<rootDir>'],
57+
exclude: []
58+
}]
59+
})
60+
61+
mockFs()
62+
63+
mockConsole((console) => {
64+
const result = command(config, {})
65+
mockFs.restore()
66+
const log = getConsoleMockCalls(console.error)
67+
expect(log).toMatchSnapshot()
68+
69+
expect(result).toBeTruthy()
70+
})
71+
})
72+
73+
it('Should not throw error for pseudolocale', () => {
74+
const config = makeConfig({
75+
locales: ['abracadabra'],
76+
rootDir: '/test',
77+
pseudoLocale: 'abracadabra',
78+
catalogs: [{
79+
path: '<rootDir>/{locale}',
80+
include: ['<rootDir>'],
81+
exclude: []
82+
}]
83+
})
84+
85+
mockFs()
86+
87+
mockConsole((console) => {
88+
const result = command(config, {})
89+
mockFs.restore()
90+
expect(console.error).not.toBeCalled()
91+
expect(result).toBeTruthy()
92+
})
93+
})
94+
})
95+
96+
describe('allowEmpty = false', () => {
97+
const config = makeConfig({
98+
locales: ['en', 'pl'],
99+
sourceLocale: 'en',
100+
rootDir: '/test',
101+
catalogs: [{
102+
path: '<rootDir>/{locale}',
103+
include: ['<rootDir>'],
104+
exclude: []
105+
}]
106+
})
107+
108+
it('Should show error and stop compilation of catalog ' +
109+
'if message doesnt have a translation (no template)', () => {
110+
mockFs({
111+
'/test': {
112+
'en.po': `
113+
msgid "Hello World"
114+
msgstr "Hello World"
115+
`,
116+
'pl.po': `
117+
msgid "Hello World"
118+
msgstr "Cześć świat"
119+
120+
msgid "Test String"
121+
msgstr ""
122+
`
123+
}
124+
})
125+
126+
mockConsole((console) => {
127+
const result = command(config, {
128+
allowEmpty: false
129+
})
130+
const actualFiles = readFsToJson('/test')
131+
132+
expect(actualFiles['pl.js']).toBeFalsy()
133+
expect(actualFiles['en.js']).toBeTruthy()
134+
mockFs.restore()
135+
136+
const log = getConsoleMockCalls(console.error)
137+
expect(log).toMatchSnapshot()
138+
expect(result).toBeFalsy()
139+
})
140+
})
141+
142+
it('Should show error and stop compilation of catalog ' +
143+
' if message doesnt have a translation (with template)', () => {
144+
mockFs({
145+
'/test': {
146+
'messages.pot': `
147+
msgid "Hello World"
148+
msgstr ""
149+
`,
150+
'pl.po': ``
151+
}
152+
})
153+
154+
mockConsole((console) => {
155+
const result = command(config, {
156+
allowEmpty: false
157+
})
158+
159+
const actualFiles = readFsToJson('/test')
160+
161+
expect({
162+
pl: actualFiles['pl.js'],
163+
en: actualFiles['en.js']
164+
}).toMatchSnapshot()
165+
166+
mockFs.restore()
167+
168+
const log = getConsoleMockCalls(console.error)
169+
expect(log).toMatchSnapshot()
170+
expect(result).toBeFalsy()
171+
})
172+
})
173+
174+
175+
it('Should show missing messages verbosely when verbose = true', () => {
176+
mockFs({
177+
'/test': {
178+
'pl.po': `
179+
msgid "Hello World"
180+
msgstr ""
181+
182+
msgid "Test String"
183+
msgstr ""
184+
`
185+
}
186+
})
187+
188+
mockConsole((console) => {
189+
const result = command(config, {
190+
allowEmpty: false,
191+
verbose: true
192+
})
193+
194+
mockFs.restore()
195+
196+
const log = getConsoleMockCalls(console.error)
197+
expect(log).toMatchSnapshot()
198+
expect(result).toBeFalsy()
199+
})
200+
})
201+
202+
})
203+
})

packages/conf/index.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ export declare function getConfig({ cwd, configPath, skipValidation, }?: {
6262
configPath?: string;
6363
skipValidation?: boolean;
6464
}): LinguiConfig;
65+
66+
export declare function makeConfig(userConfig: Partial<LinguiConfig>, opts?: {
67+
skipValidation?: boolean
68+
}): LinguiConfig;
69+
6570
export declare const configValidation: {
6671
exampleConfig: {
6772
extractBabelOptions: {

0 commit comments

Comments
 (0)