localizationkeys-webpack
v2.0.0
Published
Webpack plugin that generates a TypeScript localization keys class from a JSONC file.
Maintainers
Readme
localizationkeys-webpack
Webpack 5 plugin that generates a TypeScript localization keys class from a JSONC file.
The generated class contains static fields whose values are paths to values in your localization file. This helps keep localization key usage type-safe: when a key is removed from the default localization JSONC file, the generated TypeScript class changes as well, so TypeScript can report usages of removed keys.
Requirements
- Node.js 18+
- Webpack 5
Installation
npm install --save-dev localizationkeys-webpackUsage
Given a localization file:
localization/default.jsoncConfigure the plugin in webpack.config.js:
const LocalizationKeysWebpackPlugin = require("localizationkeys-webpack");
module.exports = {
plugins: [
new LocalizationKeysWebpackPlugin({
input: "./localization/default.jsonc",
output: "./src/LocalizationKeys.ts",
className: "LocalizationKeys",
}),
],
};The plugin reads the configured JSONC file and writes the generated TypeScript file to the configured output path.
No webpack loader rule is required for key generation. If your application also imports JSONC localization files at runtime, keep using your own loader or parser for that separate runtime use case.
Example
localization/default.jsonc:
{
"Hello": "{0}! Hello World!", // {0} - user full name
"Boolean": {
"true": "Ja",
"nein": "Nein",
},
}Generated src/LocalizationKeys.ts:
export class LocalizationKeys {
/** {0}! Hello World! */
public static readonly Hello = "Hello";
public static readonly Boolean = {
AllKeys: "Boolean",
["true"]: "Boolean.true",
nein: "Boolean.nein",
} as const;
}Usage in application code:
import { LocalizationKeys } from "./LocalizationKeys";
const helloKey = LocalizationKeys.Hello;
const booleanGroupKey = LocalizationKeys.Boolean.AllKeys;
const trueKey = LocalizationKeys.Boolean["true"];
const neinKey = LocalizationKeys.Boolean.nein;Default export
By default, the generated class uses a named export:
export class LocalizationKeys {}To generate a default export instead, set isDefaultImport to true:
const LocalizationKeysWebpackPlugin = require("localizationkeys-webpack");
module.exports = {
plugins: [
new LocalizationKeysWebpackPlugin({
input: "./localization/default.jsonc",
output: "./src/LocalizationKeys.ts",
isDefaultImport: true,
}),
],
};Generated output:
export default class LocalizationKeys {}Usage:
import LocalizationKeys from "./LocalizationKeys";Options
| Option | Type | Default | Description |
| ----------------- | --------- | -------------------- | ----------------------------------------------------------------------------------------------------- |
| input | string | Required | Path to the source JSONC file. Relative paths are resolved from the webpack compiler context. |
| output | string | Required | Path to the generated TypeScript file. Relative paths are resolved from the webpack compiler context. |
| className | string | "LocalizationKeys" | Name of the generated TypeScript class. |
| isDefaultImport | boolean | false | Generates export default class instead of export class. |
| allKeysProperty | string | "AllKeys" | Property name used for the path of nested localization groups. |
| indent | string | Four spaces | Indentation used in the generated TypeScript file. |
Nested groups
For nested JSONC objects, the plugin generates nested readonly objects and adds an AllKeys property containing the path to the group itself.
Input:
{
"Menu": {
"File": {
"Open": "Open",
"Close": "Close",
},
},
}Generated usage:
LocalizationKeys.Menu.AllKeys; // "Menu"
LocalizationKeys.Menu.File.AllKeys; // "Menu.File"
LocalizationKeys.Menu.File.Open; // "Menu.File.Open"
LocalizationKeys.Menu.File.Close; // "Menu.File.Close"If your localization file contains a real key named AllKeys, use allKeysProperty to avoid a property name conflict:
new LocalizationKeysWebpackPlugin({
input: "./localization/default.jsonc",
output: "./src/LocalizationKeys.ts",
allKeysProperty: "$all",
});Watch mode
The plugin runs before a normal webpack build and during webpack watch rebuilds. When the input JSONC file changes, the generated TypeScript file is updated.
The output file is written only when generated content actually changes. This avoids unnecessary file writes and reduces redundant watch rebuilds.
Migration from v1
Version 2 is a breaking change. The package is now a webpack plugin, not a webpack loader.
Old v1 loader-style configuration:
module.exports = {
module: {
rules: [
{
test: /default\.jsonc$/,
type: "javascript/auto",
use: [
{
loader:
"localizationkeys-webpack?className=LocalizationKeys&output=./LocalizationKeys.ts",
},
],
},
],
},
};New v2 plugin-style configuration:
const LocalizationKeysWebpackPlugin = require("localizationkeys-webpack");
module.exports = {
plugins: [
new LocalizationKeysWebpackPlugin({
input: "./localization/default.jsonc",
output: "./LocalizationKeys.ts",
className: "LocalizationKeys",
}),
],
};If you need the old generated export default class shape, set isDefaultImport: true.
Notes
JSONC comments are supported in the input file. The generated TypeScript comments are created from localization values, not from JSONC comments.
Keys that are not valid TypeScript identifiers are generated with computed property syntax. For example, "some-key" becomes ["some-key"], and "true" becomes ["true"].
The generated key paths use dot notation. Avoid dots inside localization key names if those paths are later consumed by dot-path helpers.
Credits
License
MIT
