@intlayer/cli 3.5.4 → 3.5.6
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/dist/cjs/audit.cjs +109 -0
- package/dist/cjs/audit.cjs.map +1 -0
- package/dist/cjs/cli.cjs +1 -1
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +1 -1
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/listContentDeclaration.cjs +1 -1
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/pull.cjs +8 -5
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push.cjs +21 -12
- package/dist/cjs/push.cjs.map +1 -1
- package/dist/esm/audit.mjs +74 -0
- package/dist/esm/audit.mjs.map +1 -0
- package/dist/esm/cli.mjs +1 -1
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +2 -2
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/listContentDeclaration.mjs +2 -2
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/pull.mjs +9 -6
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push.mjs +22 -13
- package/dist/esm/push.mjs.map +1 -1
- package/dist/types/{audit/index.d.ts → audit.d.ts} +2 -2
- package/dist/types/audit.d.ts.map +1 -0
- package/dist/types/push.d.ts.map +1 -1
- package/package.json +12 -13
- package/dist/cjs/audit/CJS_FORMAT.md +0 -23
- package/dist/cjs/audit/JSON_FORMAT.md +0 -26
- package/dist/cjs/audit/JSX_FORMAT.md +0 -28
- package/dist/cjs/audit/MJS_FORMAT.md +0 -23
- package/dist/cjs/audit/PROMPT.md +0 -146
- package/dist/cjs/audit/TSX_FORMAT.md +0 -28
- package/dist/cjs/audit/TS_FORMAT.md +0 -22
- package/dist/cjs/audit/index.cjs +0 -131
- package/dist/cjs/audit/index.cjs.map +0 -1
- package/dist/esm/audit/CJS_FORMAT.md +0 -23
- package/dist/esm/audit/JSON_FORMAT.md +0 -26
- package/dist/esm/audit/JSX_FORMAT.md +0 -28
- package/dist/esm/audit/MJS_FORMAT.md +0 -23
- package/dist/esm/audit/PROMPT.md +0 -146
- package/dist/esm/audit/TSX_FORMAT.md +0 -28
- package/dist/esm/audit/TS_FORMAT.md +0 -22
- package/dist/esm/audit/index.mjs +0 -96
- package/dist/esm/audit/index.mjs.map +0 -1
- package/dist/types/audit/index.d.ts.map +0 -1
package/dist/cjs/audit/PROMPT.md
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
You are an expert in internationalization and content management. Your task is to audit the content declaration files in the project and identify any potential issues or inconsistencies. Provide a detailed report of any issues found, including the file path, line number, and a brief explanation of the issue.
|
|
2
|
-
|
|
3
|
-
**Instructions:**
|
|
4
|
-
|
|
5
|
-
1. **File Location:**
|
|
6
|
-
|
|
7
|
-
- The content declaration files are located in the `{{filePath}}` directory relative to the project root.
|
|
8
|
-
|
|
9
|
-
2. **Locales:**
|
|
10
|
-
|
|
11
|
-
- Default locale: {{defaultLocale}}
|
|
12
|
-
- Required Locales: {{otherLocales}} (add the missing locales in `t({ ... })` function)
|
|
13
|
-
|
|
14
|
-
3. **Content Declaration Format:**
|
|
15
|
-
|
|
16
|
-
- Example format:
|
|
17
|
-
|
|
18
|
-
{{declarationsContentTemplate}}
|
|
19
|
-
|
|
20
|
-
4. **Audit Requirements:**
|
|
21
|
-
|
|
22
|
-
- **Consistency:** Ensure that all keys have translations for all specified locales.
|
|
23
|
-
- **Missing Content:** Identify any missing translations and specify the expected content.
|
|
24
|
-
- **Misplaced Content:** Detect if any translations are placed under incorrect keys.
|
|
25
|
-
- **Type Compliance:** Verify that the content types match the declarations (e.g., strings, string arrays).
|
|
26
|
-
|
|
27
|
-
5. **Modification Guidelines:**
|
|
28
|
-
|
|
29
|
-
- **Do Not Alter Structure:** If the file structure is correct, do not modify it. Only add, update, or remove content declarations as necessary.
|
|
30
|
-
- **Do Not Change a value type** If a key value is like `exampleKey: "exampleValue"`, avoid a maximum to not change the value type to `exampleKey: t({ en: "exampleValue" })`.
|
|
31
|
-
- **Return Only Final File Content:** Provide the updated file content without any additional comments or explanations.
|
|
32
|
-
- **Ensure No Translations are Missing:** If an element is a multilingual content and a translation is missing, add it. Including localized content as `es-MX` or `en-UK`.
|
|
33
|
-
- **Manage Localizations:** If the required languages contains similar languages, as `en` and `en-GB`, consider `en` as English US and `en-GB` as English UK, and insert or review both translations to maintain clarity and correctness.
|
|
34
|
-
- **Order Translations:** If the translations are not in the same order as the required languages list, consider reordering the translations to maintain clarity and correctness.
|
|
35
|
-
- **Escape Special Characters:** If the translations contain special characters, escape them using the appropriate escape sequence.
|
|
36
|
-
|
|
37
|
-
6. **Example Scenario:**
|
|
38
|
-
|
|
39
|
-
- **Example 1:**
|
|
40
|
-
|
|
41
|
-
- **Input File:**
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
import { t, type DeclarationContent } from "intlayer";
|
|
45
|
-
|
|
46
|
-
export default {
|
|
47
|
-
key: "creative-work-structured-data",
|
|
48
|
-
content: {
|
|
49
|
-
audienceType: t({
|
|
50
|
-
en: "Developers, Content Managers",
|
|
51
|
-
fr: "Développeurs, Responsables de contenu",
|
|
52
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
53
|
-
}),
|
|
54
|
-
},
|
|
55
|
-
} satisfies DeclarationContent;
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
- **Expected Output (No Changes Needed):**
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
import { t, type DeclarationContent } from "intlayer";
|
|
62
|
-
|
|
63
|
-
export default {
|
|
64
|
-
key: "creative-work-structured-data",
|
|
65
|
-
content: {
|
|
66
|
-
audienceType: t({
|
|
67
|
-
en: "Developers, Content Managers",
|
|
68
|
-
fr: "Développeurs, Responsables de contenu",
|
|
69
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
70
|
-
}),
|
|
71
|
-
},
|
|
72
|
-
} satisfies DeclarationContent;
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
- **Incorrect Output (Unwanted Structural Change):**
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { t, type DeclarationContent } from "intlayer";
|
|
79
|
-
|
|
80
|
-
export default {
|
|
81
|
-
key: "creative-work-structured-data",
|
|
82
|
-
content: {
|
|
83
|
-
audienceType: t({
|
|
84
|
-
en: "Developers, Content Managers",
|
|
85
|
-
fr: "Développeurs, Responsables de contenu",
|
|
86
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
87
|
-
}),
|
|
88
|
-
// Missing multilingual content for 'projectDescription'
|
|
89
|
-
projectDescription: t({
|
|
90
|
-
en: "This project involves structured data for creative work.",
|
|
91
|
-
fr: "Ce projet implique des données structurées pour le travail créatif.",
|
|
92
|
-
es: "Este proyecto involucra datos estructurados para trabajo creativo.",
|
|
93
|
-
}),
|
|
94
|
-
},
|
|
95
|
-
} satisfies DeclarationContent;
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
- **Clarification:** In this scenario, since the input file is already valid and complete, the expected output should be identical to the input without any additional fields or comments.
|
|
99
|
-
|
|
100
|
-
- **Example 2:**
|
|
101
|
-
|
|
102
|
-
- **Input File:**
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
import { t } from "react-intlayer";
|
|
106
|
-
|
|
107
|
-
const content = {
|
|
108
|
-
key: "creative-work-structured-data",
|
|
109
|
-
content: {
|
|
110
|
-
audienceType: t({
|
|
111
|
-
en: "Developers, Content Managers",
|
|
112
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
113
|
-
}),
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
- **Expected Output (No Changes Needed):**
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import { t, type DeclarationContent } from "intlayer";
|
|
122
|
-
|
|
123
|
-
const content = {
|
|
124
|
-
key: "creative-work-structured-data",
|
|
125
|
-
content: {
|
|
126
|
-
audienceType: t({
|
|
127
|
-
en: "Developers, Content Managers",
|
|
128
|
-
fr: "Développeurs, Responsables de contenu",
|
|
129
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
130
|
-
}),
|
|
131
|
-
},
|
|
132
|
-
} satisfies DeclarationContent;
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
- **Clarification:** In this scenario:
|
|
136
|
-
- A missing translation for the `audienceType` key was added.
|
|
137
|
-
- The import of the `t` function was imported from `react-intlayer` instead of `intlayer`.
|
|
138
|
-
- A type `DeclarationContent` was added to the file to strengthen the content declaration.
|
|
139
|
-
|
|
140
|
-
**File to Audit:**
|
|
141
|
-
|
|
142
|
-
{{fileContent}}
|
|
143
|
-
|
|
144
|
-
**Expected Response:**
|
|
145
|
-
|
|
146
|
-
After auditing, provide only the final content of the file as plain text without any Markdown or code block formatting. If no changes are needed, return the file content exactly as it is.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
```tsx
|
|
2
|
-
import React, { type ReactNode } from "react";
|
|
3
|
-
import { t, enu, type DeclarationContent } from "intlayer";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
key: "my-key",
|
|
7
|
-
content: {
|
|
8
|
-
exampleText: t({
|
|
9
|
-
en: "Example of content in English",
|
|
10
|
-
fr: "Example de contenu en français",
|
|
11
|
-
es: "Ejemplo de contenido en español",
|
|
12
|
-
}),
|
|
13
|
-
exampleOfReactNode: t<ReactNode>({
|
|
14
|
-
en: <h1>Example of ReactNode in English</h1>,
|
|
15
|
-
fr: <h1>Example de ReactNode en français</h1>,
|
|
16
|
-
es: <h1>Ejemplo de ReactNode en español</h1>,
|
|
17
|
-
}),
|
|
18
|
-
numberOfCar: enu({
|
|
19
|
-
"<-1": "Less than minus one car",
|
|
20
|
-
"-1": "Minus one car",
|
|
21
|
-
"0": "No cars",
|
|
22
|
-
"1": "One car",
|
|
23
|
-
">5": "Some cars",
|
|
24
|
-
">19": "Many cars",
|
|
25
|
-
}),
|
|
26
|
-
},
|
|
27
|
-
} satisfies DeclarationContent;
|
|
28
|
-
```
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
```typescript
|
|
2
|
-
import { t, enu, type DeclarationContent } from "intlayer";
|
|
3
|
-
|
|
4
|
-
export default {
|
|
5
|
-
key: "my-key",
|
|
6
|
-
content: {
|
|
7
|
-
exampleText: t({
|
|
8
|
-
en: "Example of content in English",
|
|
9
|
-
fr: "Example de contenu en français",
|
|
10
|
-
es: "Ejemplo de contenido en español",
|
|
11
|
-
}),
|
|
12
|
-
numberOfCar: enu({
|
|
13
|
-
"<-1": "Less than minus one car",
|
|
14
|
-
"-1": "Minus one car",
|
|
15
|
-
"0": "No cars",
|
|
16
|
-
"1": "One car",
|
|
17
|
-
">5": "Some cars",
|
|
18
|
-
">19": "Many cars",
|
|
19
|
-
}),
|
|
20
|
-
},
|
|
21
|
-
} satisfies DeclarationContent;
|
|
22
|
-
```
|
package/dist/cjs/audit/index.cjs
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var audit_exports = {};
|
|
30
|
-
__export(audit_exports, {
|
|
31
|
-
audit: () => audit,
|
|
32
|
-
auditFile: () => auditFile
|
|
33
|
-
});
|
|
34
|
-
module.exports = __toCommonJS(audit_exports);
|
|
35
|
-
var import_fs = require("fs");
|
|
36
|
-
var import_path = require("path");
|
|
37
|
-
var import_config = require("@intlayer/config");
|
|
38
|
-
var import_core = require("@intlayer/core");
|
|
39
|
-
var import_openai = require("openai");
|
|
40
|
-
var import_p_limit = __toESM(require("p-limit"));
|
|
41
|
-
var import_listContentDeclaration = require('../listContentDeclaration.cjs');
|
|
42
|
-
const projectPath = process.cwd();
|
|
43
|
-
const getFileContent = (filePath) => {
|
|
44
|
-
const fileContent = (0, import_fs.readFileSync)(filePath, "utf-8");
|
|
45
|
-
return fileContent;
|
|
46
|
-
};
|
|
47
|
-
const writeFileContent = (filePath, content) => {
|
|
48
|
-
(0, import_fs.writeFileSync)(filePath, content);
|
|
49
|
-
};
|
|
50
|
-
const getAbsolutePath = (filePath) => {
|
|
51
|
-
const absolutePath = (0, import_path.join)(__dirname, filePath);
|
|
52
|
-
return absolutePath;
|
|
53
|
-
};
|
|
54
|
-
const FILE_TEMPLATE = {
|
|
55
|
-
ts: getFileContent(getAbsolutePath("./TS_FORMAT.md")),
|
|
56
|
-
tsx: getFileContent(getAbsolutePath("./TSX_FORMAT.md")),
|
|
57
|
-
js: getFileContent(getAbsolutePath("./MJS_FORMAT.md")),
|
|
58
|
-
mjs: getFileContent(getAbsolutePath("./MJS_FORMAT.md")),
|
|
59
|
-
cjs: getFileContent(getAbsolutePath("./CJS_FORMAT.md")),
|
|
60
|
-
jsx: getFileContent(getAbsolutePath("./JSX_FORMAT.md")),
|
|
61
|
-
json: getFileContent(getAbsolutePath("./JSON_FORMAT.md"))
|
|
62
|
-
};
|
|
63
|
-
const CHAT_GPT_PROMPT = getFileContent(getAbsolutePath("./PROMPT.md"));
|
|
64
|
-
const formatLocaleWithName = (locale) => {
|
|
65
|
-
const localeName = (0, import_core.getLocaleName)(locale);
|
|
66
|
-
return `${locale}: ${localeName}`;
|
|
67
|
-
};
|
|
68
|
-
const auditFile = async (filePath, options) => {
|
|
69
|
-
try {
|
|
70
|
-
const relativePath = (0, import_path.relative)(projectPath, filePath);
|
|
71
|
-
console.info(`Auditing file: ${relativePath}`);
|
|
72
|
-
const { internationalization } = (0, import_config.getConfiguration)();
|
|
73
|
-
const { defaultLocale, locales } = internationalization;
|
|
74
|
-
const openai = new import_openai.OpenAI({
|
|
75
|
-
apiKey: options?.openAiApiKey
|
|
76
|
-
});
|
|
77
|
-
const fileContent = getFileContent(filePath);
|
|
78
|
-
const splitted = filePath.split(".");
|
|
79
|
-
const fileExtension = splitted[splitted.length - 1];
|
|
80
|
-
const prompt = options?.customPrompt ?? CHAT_GPT_PROMPT.replace("{{filePath}}", filePath).replace(
|
|
81
|
-
"{{defaultLocale}}",
|
|
82
|
-
`{${formatLocaleWithName(defaultLocale)}}`
|
|
83
|
-
).replace(
|
|
84
|
-
"{{otherLocales}}",
|
|
85
|
-
`{${locales.map(formatLocaleWithName).join(", ")}}`
|
|
86
|
-
).replace(
|
|
87
|
-
"{{declarationsContentTemplate}}",
|
|
88
|
-
FILE_TEMPLATE[fileExtension]
|
|
89
|
-
).replace("{{fileContent}}", fileContent);
|
|
90
|
-
const chatCompletion = await openai.chat.completions.create({
|
|
91
|
-
model: options?.model ?? "gpt-4o-mini",
|
|
92
|
-
messages: [{ role: "system", content: prompt }]
|
|
93
|
-
});
|
|
94
|
-
const newContent = chatCompletion.choices[0].message?.content;
|
|
95
|
-
if (newContent) {
|
|
96
|
-
writeFileContent(filePath, newContent);
|
|
97
|
-
console.info(`${options?.logPrefix ?? ""}File ${relativePath} updated`);
|
|
98
|
-
}
|
|
99
|
-
console.info(
|
|
100
|
-
`${options?.logPrefix ?? ""}${chatCompletion.usage?.total_tokens} tokens used in the request`
|
|
101
|
-
);
|
|
102
|
-
} catch (error) {
|
|
103
|
-
console.error(error);
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
const audit = async (options) => {
|
|
107
|
-
if (!options?.openAiApiKey) {
|
|
108
|
-
console.error(
|
|
109
|
-
"OpenAI API key is required to audit the content declaration files."
|
|
110
|
-
);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
let contentDeclarationFilesList = options?.files;
|
|
114
|
-
if (!contentDeclarationFilesList) {
|
|
115
|
-
const contentDeclarationFilesPath = (0, import_listContentDeclaration.getContentDeclaration)({
|
|
116
|
-
exclude: options?.excludedGlobs
|
|
117
|
-
});
|
|
118
|
-
contentDeclarationFilesList = contentDeclarationFilesPath;
|
|
119
|
-
}
|
|
120
|
-
const limit = (0, import_p_limit.default)(options?.asyncLimit ? Number(options?.asyncLimit) : 5);
|
|
121
|
-
const pushPromises = contentDeclarationFilesList.map(
|
|
122
|
-
(filePath) => limit(() => auditFile(filePath, options))
|
|
123
|
-
);
|
|
124
|
-
await Promise.all(pushPromises);
|
|
125
|
-
};
|
|
126
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
127
|
-
0 && (module.exports = {
|
|
128
|
-
audit,
|
|
129
|
-
auditFile
|
|
130
|
-
});
|
|
131
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/audit/index.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'fs';\nimport { join, relative } from 'path';\nimport { getConfiguration, Locales } from '@intlayer/config';\nimport { getLocaleName } from '@intlayer/core';\nimport { OpenAI } from 'openai';\nimport pLimit from 'p-limit';\nimport { getContentDeclaration } from '../listContentDeclaration';\n\n// Depending on your implementation, you may need the OpenAI API client.\n// For instance, you can use `openai` npm package (https://www.npmjs.com/package/openai).\n\ntype AuditOptions = {\n files?: string[];\n logPrefix?: string;\n model?: string;\n customPrompt?: string;\n asyncLimit?: number;\n openAiApiKey?: string;\n excludedGlobs?: string[];\n};\n\nconst projectPath = process.cwd();\n\n/**\n * Reads the content of a file synchronously.\n *\n * @function\n * @param filePath - The relative or absolute path to the target file.\n * @returns The entire contents of the specified file as a UTF-8 encoded string.\n */\nconst getFileContent = (filePath: string): string => {\n // Read the file content using Node.js fs module.\n const fileContent = readFileSync(filePath, 'utf-8');\n return fileContent;\n};\n\nconst writeFileContent = (filePath: string, content: string) => {\n writeFileSync(filePath, content);\n};\n\nconst getAbsolutePath = (filePath: string): string => {\n const absolutePath = join(__dirname, filePath);\n\n return absolutePath;\n};\n\nconst FILE_TEMPLATE: Record<string, string> = {\n ts: getFileContent(getAbsolutePath('./TS_FORMAT.md')),\n tsx: getFileContent(getAbsolutePath('./TSX_FORMAT.md')),\n js: getFileContent(getAbsolutePath('./MJS_FORMAT.md')),\n mjs: getFileContent(getAbsolutePath('./MJS_FORMAT.md')),\n cjs: getFileContent(getAbsolutePath('./CJS_FORMAT.md')),\n jsx: getFileContent(getAbsolutePath('./JSX_FORMAT.md')),\n json: getFileContent(getAbsolutePath('./JSON_FORMAT.md')),\n};\n\n// The prompt template to send to ChatGPT, requesting an audit of content declaration files.\nconst CHAT_GPT_PROMPT = getFileContent(getAbsolutePath('./PROMPT.md'));\n\n/**\n * Formats a locale with its full name and returns a string representation.\n *\n * @function\n * @param locale - A locale from the project's configuration (e.g., 'en-US', 'fr-FR').\n * @returns A formatted string combining the locale's name and code. Example: \"English (US): en-US\".\n */\nconst formatLocaleWithName = (locale: Locales): string => {\n // getLocaleName returns a human-readable name for the locale.\n const localeName = getLocaleName(locale);\n\n // Concatenate both the readable name and the locale code.\n return `${locale}: ${localeName}`;\n};\n\n/**\n * Audits a content declaration file by constructing a prompt for ChatGPT.\n * The prompt includes details about the project's locales, file paths of content declarations,\n * and requests for identifying issues or inconsistencies. It prints the prompt for each file,\n * and could be adapted to send requests to the ChatGPT model.\n *\n * @async\n * @function\n * @param filePath - The relative or absolute path to the target file.\n * @param options - Optional configuration for the audit process.\n * @returns This function returns a Promise that resolves once the audit is complete.\n */\nexport const auditFile = async (filePath: string, options?: AuditOptions) => {\n try {\n const relativePath = relative(projectPath, filePath);\n console.info(`Auditing file: ${relativePath}`);\n\n // Extract internationalization configuration, including locales and the default locale.\n const { internationalization } = getConfiguration();\n const { defaultLocale, locales } = internationalization;\n\n // Optionally, you could initialize and configure the OpenAI client here, if you intend to make API calls.\n // Uncomment and configure the following lines if you have `openai` installed and want to call the API:\n\n const openai = new OpenAI({\n apiKey: options?.openAiApiKey,\n });\n\n // Read the file's content.\n const fileContent = getFileContent(filePath);\n const splitted = filePath.split('.');\n const fileExtension = splitted[splitted.length - 1];\n\n // Prepare the prompt for ChatGPT by replacing placeholders with actual values.\n const prompt =\n options?.customPrompt ??\n CHAT_GPT_PROMPT.replace('{{filePath}}', filePath)\n .replace(\n '{{defaultLocale}}',\n `{${formatLocaleWithName(defaultLocale)}}`\n )\n .replace(\n '{{otherLocales}}',\n `{${locales.map(formatLocaleWithName).join(', ')}}`\n )\n .replace(\n '{{declarationsContentTemplate}}',\n FILE_TEMPLATE[fileExtension]\n )\n .replace('{{fileContent}}', fileContent);\n\n // Example of how you might request a completion from ChatGPT:\n const chatCompletion = await openai.chat.completions.create({\n model: options?.model ?? 'gpt-4o-mini',\n messages: [{ role: 'system', content: prompt }],\n });\n\n const newContent = chatCompletion.choices[0].message?.content;\n\n if (newContent) {\n writeFileContent(filePath, newContent);\n\n console.info(`${options?.logPrefix ?? ''}File ${relativePath} updated`);\n }\n\n console.info(\n `${options?.logPrefix ?? ''}${chatCompletion.usage?.total_tokens} tokens used in the request`\n );\n } catch (error) {\n console.error(error);\n }\n};\n\n/**\n * Audits the content declaration files by constructing a prompt for ChatGPT.\n * The prompt includes details about the project's locales, file paths of content declarations,\n * and requests for identifying issues or inconsistencies. It prints the prompt for each file,\n * and could be adapted to send requests to the ChatGPT model.\n *\n * @async\n * @function\n * @param options - Optional configuration for the audit process.\n * @returns This function returns a Promise that resolves once the audit is complete.\n */\nexport const audit = async (options: AuditOptions) => {\n if (!options?.openAiApiKey) {\n console.error(\n 'OpenAI API key is required to audit the content declaration files.'\n );\n return;\n }\n\n let contentDeclarationFilesList = options?.files;\n\n if (!contentDeclarationFilesList) {\n // Retrieve all content declaration file paths using a helper function.\n const contentDeclarationFilesPath = getContentDeclaration({\n exclude: options?.excludedGlobs,\n });\n\n contentDeclarationFilesList = contentDeclarationFilesPath;\n }\n\n const limit = pLimit(options?.asyncLimit ? Number(options?.asyncLimit) : 5); // Limit the number of concurrent requests\n const pushPromises = contentDeclarationFilesList.map((filePath) =>\n limit(() => auditFile(filePath, options))\n );\n await Promise.all(pushPromises);\n};\n"],"mappings":"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","names":["pLimit"]}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
```javascript
|
|
2
|
-
const { t, enu } = require("intlayer");
|
|
3
|
-
|
|
4
|
-
/** @type {import('intlayer').IntlayerConfig} */
|
|
5
|
-
module.exports = {
|
|
6
|
-
key: "my-key",
|
|
7
|
-
content: {
|
|
8
|
-
exampleText: t({
|
|
9
|
-
en: "Example of content in English",
|
|
10
|
-
fr: "Example de contenu en français",
|
|
11
|
-
es: "Ejemplo de contenido en español",
|
|
12
|
-
}),
|
|
13
|
-
numberOfCar: enu({
|
|
14
|
-
"<-1": "Less than minus one car",
|
|
15
|
-
"-1": "Minus one car",
|
|
16
|
-
0: "No cars",
|
|
17
|
-
1: "One car",
|
|
18
|
-
">5": "Some cars",
|
|
19
|
-
">19": "Many cars",
|
|
20
|
-
}),
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
```
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
```json
|
|
2
|
-
{
|
|
3
|
-
"key": "my-key",
|
|
4
|
-
"content": {
|
|
5
|
-
"profileText": {
|
|
6
|
-
"NodeType": "translation",
|
|
7
|
-
"translation": {
|
|
8
|
-
"en": "Manage profile",
|
|
9
|
-
"fr": "Gérer le profil",
|
|
10
|
-
"es": "Administrar perfil"
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"numberOfCar": {
|
|
14
|
-
"NodeType": "enumeration",
|
|
15
|
-
"enumeration": {
|
|
16
|
-
"<-1": "Less than minus one car",
|
|
17
|
-
"-1": "Minus one car",
|
|
18
|
-
"0": "No cars",
|
|
19
|
-
"1": "One car",
|
|
20
|
-
">5": "Some cars",
|
|
21
|
-
">19": "Many cars"
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
```
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
```tsx
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { t, enu, type DeclarationContent } from "intlayer";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
key: "my-key",
|
|
7
|
-
content: {
|
|
8
|
-
exampleText: t({
|
|
9
|
-
en: "Example of content in English",
|
|
10
|
-
fr: "Example de contenu en français",
|
|
11
|
-
es: "Ejemplo de contenido en español",
|
|
12
|
-
}),
|
|
13
|
-
exampleOfReactNode: t({
|
|
14
|
-
en: <h1>Example of ReactNode in English</h1>,
|
|
15
|
-
fr: <h1>Example de ReactNode en français</h1>,
|
|
16
|
-
es: <h1>Ejemplo de ReactNode en español</h1>,
|
|
17
|
-
}),
|
|
18
|
-
numberOfCar: enu({
|
|
19
|
-
"<-1": "Less than minus one car",
|
|
20
|
-
"-1": "Minus one car",
|
|
21
|
-
"0": "No cars",
|
|
22
|
-
"1": "One car",
|
|
23
|
-
">5": "Some cars",
|
|
24
|
-
">19": "Many cars",
|
|
25
|
-
}),
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
```
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
```javascript
|
|
2
|
-
import { t, enu } from "intlayer";
|
|
3
|
-
|
|
4
|
-
/** @type {import('intlayer').IntlayerConfig} */
|
|
5
|
-
export default {
|
|
6
|
-
key: "my-key",
|
|
7
|
-
content: {
|
|
8
|
-
exampleText: t({
|
|
9
|
-
en: "Example of content in English",
|
|
10
|
-
fr: "Example de contenu en français",
|
|
11
|
-
es: "Ejemplo de contenido en español",
|
|
12
|
-
}),
|
|
13
|
-
numberOfCar: enu({
|
|
14
|
-
"<-1": "Less than minus one car",
|
|
15
|
-
"-1": "Minus one car",
|
|
16
|
-
0: "No cars",
|
|
17
|
-
1: "One car",
|
|
18
|
-
">5": "Some cars",
|
|
19
|
-
">19": "Many cars",
|
|
20
|
-
}),
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
```
|
package/dist/esm/audit/PROMPT.md
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
You are an expert in internationalization and content management. Your task is to audit the content declaration files in the project and identify any potential issues or inconsistencies. Provide a detailed report of any issues found, including the file path, line number, and a brief explanation of the issue.
|
|
2
|
-
|
|
3
|
-
**Instructions:**
|
|
4
|
-
|
|
5
|
-
1. **File Location:**
|
|
6
|
-
|
|
7
|
-
- The content declaration files are located in the `{{filePath}}` directory relative to the project root.
|
|
8
|
-
|
|
9
|
-
2. **Locales:**
|
|
10
|
-
|
|
11
|
-
- Default locale: {{defaultLocale}}
|
|
12
|
-
- Required Locales: {{otherLocales}} (add the missing locales in `t({ ... })` function)
|
|
13
|
-
|
|
14
|
-
3. **Content Declaration Format:**
|
|
15
|
-
|
|
16
|
-
- Example format:
|
|
17
|
-
|
|
18
|
-
{{declarationsContentTemplate}}
|
|
19
|
-
|
|
20
|
-
4. **Audit Requirements:**
|
|
21
|
-
|
|
22
|
-
- **Consistency:** Ensure that all keys have translations for all specified locales.
|
|
23
|
-
- **Missing Content:** Identify any missing translations and specify the expected content.
|
|
24
|
-
- **Misplaced Content:** Detect if any translations are placed under incorrect keys.
|
|
25
|
-
- **Type Compliance:** Verify that the content types match the declarations (e.g., strings, string arrays).
|
|
26
|
-
|
|
27
|
-
5. **Modification Guidelines:**
|
|
28
|
-
|
|
29
|
-
- **Do Not Alter Structure:** If the file structure is correct, do not modify it. Only add, update, or remove content declarations as necessary.
|
|
30
|
-
- **Do Not Change a value type** If a key value is like `exampleKey: "exampleValue"`, avoid a maximum to not change the value type to `exampleKey: t({ en: "exampleValue" })`.
|
|
31
|
-
- **Return Only Final File Content:** Provide the updated file content without any additional comments or explanations.
|
|
32
|
-
- **Ensure No Translations are Missing:** If an element is a multilingual content and a translation is missing, add it. Including localized content as `es-MX` or `en-UK`.
|
|
33
|
-
- **Manage Localizations:** If the required languages contains similar languages, as `en` and `en-GB`, consider `en` as English US and `en-GB` as English UK, and insert or review both translations to maintain clarity and correctness.
|
|
34
|
-
- **Order Translations:** If the translations are not in the same order as the required languages list, consider reordering the translations to maintain clarity and correctness.
|
|
35
|
-
- **Escape Special Characters:** If the translations contain special characters, escape them using the appropriate escape sequence.
|
|
36
|
-
|
|
37
|
-
6. **Example Scenario:**
|
|
38
|
-
|
|
39
|
-
- **Example 1:**
|
|
40
|
-
|
|
41
|
-
- **Input File:**
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
import { t, type DeclarationContent } from "intlayer";
|
|
45
|
-
|
|
46
|
-
export default {
|
|
47
|
-
key: "creative-work-structured-data",
|
|
48
|
-
content: {
|
|
49
|
-
audienceType: t({
|
|
50
|
-
en: "Developers, Content Managers",
|
|
51
|
-
fr: "Développeurs, Responsables de contenu",
|
|
52
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
53
|
-
}),
|
|
54
|
-
},
|
|
55
|
-
} satisfies DeclarationContent;
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
- **Expected Output (No Changes Needed):**
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
import { t, type DeclarationContent } from "intlayer";
|
|
62
|
-
|
|
63
|
-
export default {
|
|
64
|
-
key: "creative-work-structured-data",
|
|
65
|
-
content: {
|
|
66
|
-
audienceType: t({
|
|
67
|
-
en: "Developers, Content Managers",
|
|
68
|
-
fr: "Développeurs, Responsables de contenu",
|
|
69
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
70
|
-
}),
|
|
71
|
-
},
|
|
72
|
-
} satisfies DeclarationContent;
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
- **Incorrect Output (Unwanted Structural Change):**
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { t, type DeclarationContent } from "intlayer";
|
|
79
|
-
|
|
80
|
-
export default {
|
|
81
|
-
key: "creative-work-structured-data",
|
|
82
|
-
content: {
|
|
83
|
-
audienceType: t({
|
|
84
|
-
en: "Developers, Content Managers",
|
|
85
|
-
fr: "Développeurs, Responsables de contenu",
|
|
86
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
87
|
-
}),
|
|
88
|
-
// Missing multilingual content for 'projectDescription'
|
|
89
|
-
projectDescription: t({
|
|
90
|
-
en: "This project involves structured data for creative work.",
|
|
91
|
-
fr: "Ce projet implique des données structurées pour le travail créatif.",
|
|
92
|
-
es: "Este proyecto involucra datos estructurados para trabajo creativo.",
|
|
93
|
-
}),
|
|
94
|
-
},
|
|
95
|
-
} satisfies DeclarationContent;
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
- **Clarification:** In this scenario, since the input file is already valid and complete, the expected output should be identical to the input without any additional fields or comments.
|
|
99
|
-
|
|
100
|
-
- **Example 2:**
|
|
101
|
-
|
|
102
|
-
- **Input File:**
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
import { t } from "react-intlayer";
|
|
106
|
-
|
|
107
|
-
const content = {
|
|
108
|
-
key: "creative-work-structured-data",
|
|
109
|
-
content: {
|
|
110
|
-
audienceType: t({
|
|
111
|
-
en: "Developers, Content Managers",
|
|
112
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
113
|
-
}),
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
- **Expected Output (No Changes Needed):**
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import { t, type DeclarationContent } from "intlayer";
|
|
122
|
-
|
|
123
|
-
const content = {
|
|
124
|
-
key: "creative-work-structured-data",
|
|
125
|
-
content: {
|
|
126
|
-
audienceType: t({
|
|
127
|
-
en: "Developers, Content Managers",
|
|
128
|
-
fr: "Développeurs, Responsables de contenu",
|
|
129
|
-
es: "Desarrolladores, Gestores de Contenido",
|
|
130
|
-
}),
|
|
131
|
-
},
|
|
132
|
-
} satisfies DeclarationContent;
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
- **Clarification:** In this scenario:
|
|
136
|
-
- A missing translation for the `audienceType` key was added.
|
|
137
|
-
- The import of the `t` function was imported from `react-intlayer` instead of `intlayer`.
|
|
138
|
-
- A type `DeclarationContent` was added to the file to strengthen the content declaration.
|
|
139
|
-
|
|
140
|
-
**File to Audit:**
|
|
141
|
-
|
|
142
|
-
{{fileContent}}
|
|
143
|
-
|
|
144
|
-
**Expected Response:**
|
|
145
|
-
|
|
146
|
-
After auditing, provide only the final content of the file as plain text without any Markdown or code block formatting. If no changes are needed, return the file content exactly as it is.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
```tsx
|
|
2
|
-
import React, { type ReactNode } from "react";
|
|
3
|
-
import { t, enu, type DeclarationContent } from "intlayer";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
key: "my-key",
|
|
7
|
-
content: {
|
|
8
|
-
exampleText: t({
|
|
9
|
-
en: "Example of content in English",
|
|
10
|
-
fr: "Example de contenu en français",
|
|
11
|
-
es: "Ejemplo de contenido en español",
|
|
12
|
-
}),
|
|
13
|
-
exampleOfReactNode: t<ReactNode>({
|
|
14
|
-
en: <h1>Example of ReactNode in English</h1>,
|
|
15
|
-
fr: <h1>Example de ReactNode en français</h1>,
|
|
16
|
-
es: <h1>Ejemplo de ReactNode en español</h1>,
|
|
17
|
-
}),
|
|
18
|
-
numberOfCar: enu({
|
|
19
|
-
"<-1": "Less than minus one car",
|
|
20
|
-
"-1": "Minus one car",
|
|
21
|
-
"0": "No cars",
|
|
22
|
-
"1": "One car",
|
|
23
|
-
">5": "Some cars",
|
|
24
|
-
">19": "Many cars",
|
|
25
|
-
}),
|
|
26
|
-
},
|
|
27
|
-
} satisfies DeclarationContent;
|
|
28
|
-
```
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
```typescript
|
|
2
|
-
import { t, enu, type DeclarationContent } from "intlayer";
|
|
3
|
-
|
|
4
|
-
export default {
|
|
5
|
-
key: "my-key",
|
|
6
|
-
content: {
|
|
7
|
-
exampleText: t({
|
|
8
|
-
en: "Example of content in English",
|
|
9
|
-
fr: "Example de contenu en français",
|
|
10
|
-
es: "Ejemplo de contenido en español",
|
|
11
|
-
}),
|
|
12
|
-
numberOfCar: enu({
|
|
13
|
-
"<-1": "Less than minus one car",
|
|
14
|
-
"-1": "Minus one car",
|
|
15
|
-
"0": "No cars",
|
|
16
|
-
"1": "One car",
|
|
17
|
-
">5": "Some cars",
|
|
18
|
-
">19": "Many cars",
|
|
19
|
-
}),
|
|
20
|
-
},
|
|
21
|
-
} satisfies DeclarationContent;
|
|
22
|
-
```
|