Skip to content

Commit

Permalink
feat: pass in custom config file. closes #4
Browse files Browse the repository at this point in the history
  • Loading branch information
radiovisual committed Oct 20, 2024
1 parent da06299 commit d996e8a
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 24 deletions.
64 changes: 49 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,29 @@

> Have you ever shipped "buggy" translation files to your users in production? **Probably!** I know I have!
Translated files in your software project are an often-overlooked source of problems that can affect the usability, reliability and reputation of your applications. These translated files are often edited manually, built automatically (without any integrity checks) or outsourced to third parties to provide translations. These files typically do not pass through any (or most) of your automated tests, or they get skipped in your manual tests...which means the hidden problems get shipped to your real users in production.
**Let's face it, we all make mistakes (developers, translators, copywriters, marketers, humans, etc)**. Our translation files in our software should be protected against the most common mistakes.

Translated files in your software project are an often-overlooked source of problems that can affect the usability, reliability and reputation of your application(s). These translated files are often edited manually, built automatically (without any integrity checks) or outsourced to third parties to provide translations. These files typically do not pass through any (or most) of your automated tests, or they easily get skipped in your manual tests...which means the hidden problems get shipped to your real users in production.

Furthermore, there are best practices we want to adhere to with our translated files, and these best practices should be enforceable with an integrity check.

## Roadmap to Version `1.0.0`
## Keeli to the rescue!

Keeli will help you automatically discover many problems with your translation files, including:

- ✅ Finds untranslated messages
- ✅ Finds empty messages
- ✅ Finds missing variables
- ✅ Finds accidentally translated variables
- ✅ Finds variable syntax errors
- ✅ Finds missing keys
- ✅ Finds unknown/un-balanced keys
- ✅ Finds keys violating your naming convention
- ✅ Finds extra whitespace
- ✅ Finds HTML in messages
-_...and more!_

We are getting close to the initial `1.0.0` release. :tada: Check out [this milestone](https://github.com/radiovisual/keeli/milestone/1) for details.
Most of these rules are configurable so you can customize keeli to your specific needs.

## Configuration

Expand Down Expand Up @@ -69,10 +85,12 @@ For each project where you want to run the keeli, you will need to have a file n
*
**/
rules: {
"no-untranslated-messages": "error",
"no-empty-messages": "error",
"no-extra-whitespace": "error",
"no-html-messages": "error",
"no-invalid-variables": "error",
"no-untranslated-messages": "error",
"no-malformed-keys": "error",
"no-missing-keys": "error",
},
/**
Expand All @@ -88,22 +106,38 @@ For each project where you want to run the keeli, you will need to have a file n
*
**/
enabled: true,
/**
* Enable or disable verbose logging mode.
*
**/
verbose: false,
}
```

# Rule Defaults

Each rule can have a default setting of `error`, `warn` or `off`, these defaults will apply if you do not provide a configuration for the rule in the configuration file.
Each rule (that allows you to configure the severity) can have a default setting of `error`, `warn` or `off`, these defaults will apply if you do not provide a configuration for the rule in the configuration file.

| Rule name | Default |
| ------------------------------------------------------------------------------------------------------------- | ------- |
| [no-empty-messages](https://github.com/radiovisual/keeli/tree/main/src/rules/no-empty-messages) | `error` |
| [no-extra-whitespace](https://github.com/radiovisual/keeli/tree/main/src/rules/no-extra-whitespace) | `error` |
| [no-html-messages](https://github.com/radiovisual/keeli/tree/main/src/rules/no-html-messages) | `error` |
| [no-untranslated-messages](https://github.com/radiovisual/keeli/tree/main/src/rules/no-untranslated-messages) | `error` |
| [no-invalid-variables](https://github.com/radiovisual/keeli/tree/main/src/rules/no-invalid-variables) | `error` |
| [no-malformed-keys](https://github.com/radiovisual/keeli/tree/main/src/rules/no-malformed-keys) | `error` |
| [no-missing-keys](https://github.com/radiovisual/keeli/tree/main/src/rules/no-missing-keys) | `error` |
| [no-invalid-configuration](https://github.com/radiovisual/keeli/tree/main/src/rules/no-missing-keys) | `error` |
| [no-invalid-severity](https://github.com/radiovisual/keeli/tree/main/src/rules/no-missing-keys) | `error` |

# Un-configurable Rule Defaults

The following rules are not configurable, meaning you should not add these rules to your configuration files, but these rules run with their default severity shown below:

| Rule name | Default |
| ------------------------ | ------- |
| no-untranslated-messages | `error` |
| no-empty-messages | `error` |
| no-invalid-variables | `error` |
| no-html-messages | `error` |
| no-missing-keys | `error` |
| no-malformed-keys | `error` |
| no-extra-whitespace | `error` |
| Rule name | Default |
| ------------------------------------------------------------------------------------------------------------- | ------- |
| [no-invalid-configuration](https://github.com/radiovisual/keeli/tree/main/src/rules/no-invalid-configuration) | `error` |
| [no-invalid-severity](https://github.com/radiovisual/keeli/tree/main/src/rules/no-invalid-severity) | `error` |

# Overriding Rules

Expand Down Expand Up @@ -160,4 +194,4 @@ If you have the repo cloned locally, you can test run the CLI by running:
---

:rainbow: :heart: :hamburger:
🌐 💻️
3 changes: 2 additions & 1 deletion keeli.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
}
},
"dryRun": false,
"enabled": true
"enabled": true,
"verbose": true
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.7",
"@types/minimist": "^1.2.5",
"@types/node": "^20.12.13",
"esbuild": "0.21.4",
"jest": "^29.7.0",
Expand All @@ -40,6 +41,7 @@
"cli-table3": "^0.6.5",
"flattie": "^1.1.1",
"lodash": "^4.17.21",
"minimist": "^1.2.8",
"terminal-link": "^2.1.1"
},
"keywords": [
Expand Down
9 changes: 6 additions & 3 deletions src/config/default-config.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { Config } from "../types.ts";

const config: Config = {
const defaultConfig: Config = {
defaultLocale: "",
sourceFile: "",
translationFiles: {},
pathToTranslatedFiles: "",
rules: {
"no-untranslated-messages": "error",
"no-empty-messages": "error",
"no-extra-whitespace": "error",
"no-invalid-variables": "error",
"no-malformed-keys": "error",
"no-untranslated-messages": "error",
"no-html-messages": "error",
"no-missing-keys": "error",
},
dryRun: false,
enabled: true,
verbose: false,
};

export { config };
export { defaultConfig };
18 changes: 13 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,29 @@
import fs from "node:fs";
import path from "node:path";
import chalk from "chalk";

import minimist, { type ParsedArgs } from "minimist";
import { runRules } from "./engine/rule-engine.ts";
import type { Config } from "./types.ts";
import { config } from "./config/default-config.ts";
import { defaultConfig } from "./config/default-config.ts";

const defaultConfig: Config = config;
const argv: ParsedArgs = minimist(process.argv.slice(2));

const configPath = path.join(__dirname, "../keeli.config.json");
const configPath =
typeof argv?.config === "string"
? path.join(process.cwd(), argv.config)
: path.join(process.cwd(), "../keeli.config.json");

// Only start keeli if the keeli configuration file is found.
if (fs.existsSync(configPath)) {
const userConfig: Config = JSON.parse(fs.readFileSync(configPath, "utf8"));

const config = { ...defaultConfig, ...userConfig };

if (config?.verbose || argv?.verbose) {
console.log(`Keeli config:`);
console.log(config);
}

if (!config.enabled) {
const message = `keeli is disabled. Exiting.`;
console.log(chalk.yellow(message));
Expand All @@ -26,7 +34,7 @@ if (fs.existsSync(configPath)) {

runRules(config);
} else {
const message = `You must have an keeli.config.js file in the project root to run the keeli.`;
const message = `keeli's config file was not found at path: ${configPath}`;
console.log(chalk.red(message));
process.exit(1);
}
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type Config = {
};
dryRun: boolean;
enabled: boolean;
verbose?: boolean;
};

export type Problem = {
Expand Down

0 comments on commit d996e8a

Please sign in to comment.