-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7b73d5c
commit a46e230
Showing
14 changed files
with
283 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import { noEmptyMessages } from "./no-empty-messages/no-empty-messages.js"; | ||
import { noUntranslatedMessages } from "./no-untranslated-messages/index.js"; | ||
|
||
export { noUntranslatedMessages }; | ||
export { noUntranslatedMessages, noEmptyMessages }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# no-empty-messages | ||
|
||
The no-empty-messages rule ensures that all messages in the translation files are not empty strings. It also verifies that messages in the base locale are not empty. | ||
|
||
The rule runs through all the messages in the translation files and checks for: | ||
|
||
1. Empty messages in the base locale file. | ||
2. Empty messages in the translation files that correspond to a non-empty message in the base locale file. | ||
|
||
Assuming `en.json` is where your default language is (the source file): | ||
|
||
❌ Example of **incorrect** setup for this rule (all messages are empty): | ||
|
||
```js | ||
en.json: { 'hello': '' } | ||
fr.json: { 'hello': '' } | ||
de.json: { 'hello': '' } | ||
``` | ||
|
||
❌ Example of an **incorrect** setup for this rule (some locales have empty messages): | ||
|
||
```js | ||
en.json: { 'hello': '' } | ||
fr.json: { 'hello': 'Salut!' } | ||
de.json: { 'hello': 'Hi!' } | ||
``` | ||
|
||
✅ Examples of a **correct** setup for this rule (all messages are non-empty): | ||
|
||
```js | ||
en.json: { 'hello': 'Hi!' } | ||
fr.json: { 'hello': 'Salut!' } | ||
de.json: { 'hello': 'Hallo!' } | ||
``` | ||
|
||
## Example Configuration | ||
|
||
```json | ||
{ | ||
"rules": { | ||
"no-empty-messages": "error" | ||
} | ||
} | ||
``` | ||
|
||
## Version | ||
|
||
This rule was introduced in i18n-validator v1.0.0. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { noEmptyMessages } from "./no-empty-messages.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { createMockProblemReporter } from "../../tests/utils/test-helpers.ts"; | ||
import { | ||
Config, | ||
RuleContext, | ||
RuleSeverity, | ||
TranslationFiles, | ||
} from "../../types.ts"; | ||
import { noEmptyMessages } from "./no-empty-messages.ts"; | ||
import { | ||
getEmptySourceMessageProblem, | ||
getEmptyTranslatedMessageProblem, | ||
} from "./problems.ts"; | ||
|
||
const ruleMeta = noEmptyMessages.meta; | ||
const rule = noEmptyMessages; | ||
|
||
const defaultLocale = "en"; | ||
|
||
const baseConfig: Config = { | ||
defaultLocale, | ||
sourceFile: "en.json", | ||
translationFiles: { fr: "fr.json" }, | ||
pathToTranslatedFiles: "i18n", | ||
rules: { | ||
"no-empty-messages": "error", | ||
}, | ||
dryRun: false, | ||
enabled: true, | ||
}; | ||
|
||
describe.each([["error"], ["warning"]])(`${rule.meta.name}`, (severity) => { | ||
const context: RuleContext = { | ||
severity: severity as RuleSeverity, | ||
}; | ||
|
||
it(`should report empty messages in the source file with severity: ${severity}`, () => { | ||
const problemReporter = createMockProblemReporter(); | ||
|
||
const translationFiles: TranslationFiles = { | ||
en: { greeting: "Hello", empty: "" }, | ||
fr: { greeting: "Bonjour", empty: "not empty" }, | ||
}; | ||
|
||
rule.run(translationFiles, baseConfig, problemReporter, context); | ||
|
||
const expectedProblem = getEmptySourceMessageProblem({ | ||
key: "empty", | ||
locale: "en", | ||
severity: severity as RuleSeverity, | ||
ruleMeta, | ||
}); | ||
|
||
expect(problemReporter.report).toHaveBeenCalledWith(expectedProblem); | ||
expect(problemReporter.report).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it(`should report empty messages in translation file with severity: ${severity}`, () => { | ||
const problemReporter = createMockProblemReporter(); | ||
|
||
const translationFiles: TranslationFiles = { | ||
en: { greeting: "Hello", empty: "not empty" }, | ||
fr: { greeting: "Bonjour", empty: "" }, | ||
}; | ||
|
||
rule.run(translationFiles, baseConfig, problemReporter, context); | ||
|
||
const expectedProblem = getEmptyTranslatedMessageProblem({ | ||
key: "empty", | ||
locale: "fr", | ||
severity: severity as RuleSeverity, | ||
ruleMeta, | ||
}); | ||
|
||
expect(problemReporter.report).toHaveBeenCalledWith(expectedProblem); | ||
expect(problemReporter.report).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it("should not report non-empty messages", () => { | ||
const problemReporter = createMockProblemReporter(); | ||
|
||
const translationFiles: TranslationFiles = { | ||
en: { greeting: "Hello", farewell: "Goodbye" }, | ||
fr: { greeting: "Bonjour", farewell: "Au revoir" }, | ||
}; | ||
|
||
rule.run(translationFiles, baseConfig, problemReporter, context); | ||
|
||
expect(problemReporter.report).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe(`${rule.meta.name}: off`, () => { | ||
it("should not report problems when severity = off", () => { | ||
const problemReporter = createMockProblemReporter(); | ||
|
||
const context: RuleContext = { | ||
severity: "off", | ||
}; | ||
|
||
const translationFiles: TranslationFiles = { | ||
en: { greeting: "Hello", empty: "" }, | ||
fr: { greeting: "Bonjour", empty: "" }, | ||
}; | ||
|
||
rule.run(translationFiles, baseConfig, problemReporter, context); | ||
expect(problemReporter.report).not.toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { SEVERITY_LEVEL } from "../../constants.ts"; | ||
import { | ||
Config, | ||
Rule, | ||
RuleContext, | ||
RuleMeta, | ||
TranslationFiles, | ||
} from "../../types.ts"; | ||
import { | ||
getEmptySourceMessageProblem, | ||
getEmptyTranslatedMessageProblem, | ||
} from "./problems.ts"; | ||
|
||
const ruleMeta: RuleMeta = { | ||
name: "no-empty-messages", | ||
description: `Checks for empty messages in translations.`, | ||
url: "TBD", | ||
type: "validation", | ||
defaultSeverity: "error", | ||
}; | ||
|
||
const noEmptyMessages: Rule = { | ||
meta: ruleMeta, | ||
run: ( | ||
translationFiles: TranslationFiles, | ||
config: Config, | ||
problemReporter, | ||
context: RuleContext | ||
) => { | ||
const { defaultLocale } = config; | ||
const { severity } = context; | ||
const baseLocale = translationFiles[defaultLocale]; | ||
|
||
if (severity === SEVERITY_LEVEL.off) { | ||
return; | ||
} | ||
|
||
for (const [locale, data] of Object.entries(translationFiles)) { | ||
for (const [key, message] of Object.entries(data)) { | ||
const baseMessage = baseLocale[key].trim(); | ||
|
||
const hasEmptyBaseMessage = locale === defaultLocale && !baseMessage; | ||
const hasEmptyTranslation = | ||
locale !== defaultLocale && message.trim() === ""; | ||
|
||
if (hasEmptyBaseMessage) { | ||
problemReporter.report( | ||
getEmptySourceMessageProblem({ key, locale, severity, ruleMeta }) | ||
); | ||
} else if (hasEmptyTranslation) { | ||
problemReporter.report( | ||
getEmptyTranslatedMessageProblem({ | ||
key, | ||
locale, | ||
severity, | ||
ruleMeta, | ||
}) | ||
); | ||
} | ||
} | ||
} | ||
}, | ||
}; | ||
|
||
export { noEmptyMessages }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Problem } from "../../classes/problem.class.ts"; | ||
import { RuleMeta, RuleSeverity } from "../../types.ts"; | ||
|
||
type ProblemContext = { | ||
key: string; | ||
locale: string; | ||
severity: RuleSeverity; | ||
ruleMeta: RuleMeta; | ||
}; | ||
|
||
export function getEmptySourceMessageProblem( | ||
problemContext: ProblemContext | ||
): Problem { | ||
const { key, locale, severity, ruleMeta } = problemContext; | ||
|
||
return Problem.Builder.withRuleMeta(ruleMeta) | ||
.withSeverity(severity) | ||
.withLocale(locale) | ||
.withMessage(`Empty message found in source key: ${key}`) | ||
.build(); | ||
} | ||
|
||
export function getEmptyTranslatedMessageProblem( | ||
problemContext: ProblemContext | ||
): Problem { | ||
const { key, locale, severity, ruleMeta } = problemContext; | ||
|
||
return Problem.Builder.withRuleMeta(ruleMeta) | ||
.withSeverity(severity) | ||
.withLocale(locale) | ||
.withMessage(`Empty message found in translated key: ${key}`) | ||
.build(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
{ | ||
"hi": "Hi!" | ||
"untranslated-message": "Hi!", | ||
"empty-string": "", | ||
"only-empty-in-en": "[DE] not empty" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
{ | ||
"hi": "Hi!" | ||
"untranslated-message": "Hi!", | ||
"empty-string": "", | ||
"only-empty-in-en": "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
{ | ||
"hi": "Hi!" | ||
"untranslated-message": "Hi!", | ||
"empty-string": "", | ||
"only-empty-in-en": "[FR] not empty" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters