ai-localize-config 2.0.0 → 2.0.1
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/CHANGELOG.md +8 -0
- package/dist/index.d.mts +75 -1
- package/dist/index.d.ts +75 -1
- package/dist/index.js +111 -2
- package/dist/index.mjs +111 -2
- package/package.json +2 -2
- package/src/loader.ts +103 -17
- package/src/schema.ts +47 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# ai-localize-config
|
|
2
2
|
|
|
3
|
+
## 2.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix config schema validation (aws optional/nullable, framework type), ignore className CSS values in AST scanner, add includePatterns config support for selective file scanning, add --extract-cdns flag to scan command to dump CDN URLs to a JSON file
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- ai-localize-shared@2.0.1
|
|
10
|
+
|
|
3
11
|
## 2.0.0
|
|
4
12
|
|
|
5
13
|
### Major Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -10,6 +10,7 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
10
10
|
keyPrefix: z.ZodOptional<z.ZodString>;
|
|
11
11
|
namespaces: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
12
12
|
ignorePatterns: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
13
|
+
includePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
13
14
|
incrementalCache: z.ZodDefault<z.ZodBoolean>;
|
|
14
15
|
cacheDir: z.ZodDefault<z.ZodString>;
|
|
15
16
|
aws: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
@@ -38,6 +39,57 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
38
39
|
profile?: string | undefined;
|
|
39
40
|
}>>>;
|
|
40
41
|
plugins: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
42
|
+
/** Codemod behaviour overrides — all fields are optional. */
|
|
43
|
+
codemods: z.ZodOptional<z.ZodObject<{
|
|
44
|
+
/**
|
|
45
|
+
* The npm package to import from.
|
|
46
|
+
* React default: "react-i18next"
|
|
47
|
+
* Vue default: "vue-i18n"
|
|
48
|
+
* Angular default: "@ngx-translate/core"
|
|
49
|
+
*/
|
|
50
|
+
importPackage: z.ZodOptional<z.ZodString>;
|
|
51
|
+
/**
|
|
52
|
+
* The hook / function name to import and call.
|
|
53
|
+
* React default: "useTranslation"
|
|
54
|
+
* Vue default: "useI18n"
|
|
55
|
+
*/
|
|
56
|
+
hookName: z.ZodOptional<z.ZodString>;
|
|
57
|
+
/**
|
|
58
|
+
* The translation function identifier returned by the hook (default: "t").
|
|
59
|
+
*/
|
|
60
|
+
translationFunction: z.ZodOptional<z.ZodString>;
|
|
61
|
+
/**
|
|
62
|
+
* Namespace to pass as the first argument to the hook call.
|
|
63
|
+
* When omitted no namespace argument is injected.
|
|
64
|
+
*/
|
|
65
|
+
namespace: z.ZodOptional<z.ZodString>;
|
|
66
|
+
/**
|
|
67
|
+
* How the translation accessor is written in generated code.
|
|
68
|
+
* "function" (default) — t('key')
|
|
69
|
+
* "bracket" — t['key']
|
|
70
|
+
*/
|
|
71
|
+
accessorStyle: z.ZodOptional<z.ZodEnum<["function", "bracket"]>>;
|
|
72
|
+
}, "strip", z.ZodTypeAny, {
|
|
73
|
+
importPackage?: string | undefined;
|
|
74
|
+
hookName?: string | undefined;
|
|
75
|
+
translationFunction?: string | undefined;
|
|
76
|
+
namespace?: string | undefined;
|
|
77
|
+
accessorStyle?: "function" | "bracket" | undefined;
|
|
78
|
+
}, {
|
|
79
|
+
importPackage?: string | undefined;
|
|
80
|
+
hookName?: string | undefined;
|
|
81
|
+
translationFunction?: string | undefined;
|
|
82
|
+
namespace?: string | undefined;
|
|
83
|
+
accessorStyle?: "function" | "bracket" | undefined;
|
|
84
|
+
}>>;
|
|
85
|
+
/**
|
|
86
|
+
* Locale file layout.
|
|
87
|
+
* "nested" (default) — one file per language + namespace:
|
|
88
|
+
* locales/en/common.json, locales/fr/dashboard.json
|
|
89
|
+
* "flat" — one file per language, all keys merged:
|
|
90
|
+
* locales/en.json, locales/fr.json
|
|
91
|
+
*/
|
|
92
|
+
localeStructure: z.ZodDefault<z.ZodEnum<["nested", "flat"]>>;
|
|
41
93
|
}, "strip", z.ZodTypeAny, {
|
|
42
94
|
framework: "react" | "react-cra" | "react-vite" | "react-nextjs" | "angular" | "angular-ngx" | "angular-i18n" | "vue" | "vue-i18n" | "jquery" | "vanilla-js" | "jsp" | "unknown";
|
|
43
95
|
defaultLanguage: string;
|
|
@@ -48,8 +100,10 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
48
100
|
incrementalCache: boolean;
|
|
49
101
|
cacheDir: string;
|
|
50
102
|
plugins: string[];
|
|
103
|
+
localeStructure: "flat" | "nested";
|
|
51
104
|
keyPrefix?: string | undefined;
|
|
52
105
|
namespaces?: string[] | undefined;
|
|
106
|
+
includePatterns?: string[] | undefined;
|
|
53
107
|
aws?: {
|
|
54
108
|
region: string;
|
|
55
109
|
bucket: string;
|
|
@@ -59,6 +113,13 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
59
113
|
legacyCdnPattern?: string | undefined;
|
|
60
114
|
profile?: string | undefined;
|
|
61
115
|
} | null | undefined;
|
|
116
|
+
codemods?: {
|
|
117
|
+
importPackage?: string | undefined;
|
|
118
|
+
hookName?: string | undefined;
|
|
119
|
+
translationFunction?: string | undefined;
|
|
120
|
+
namespace?: string | undefined;
|
|
121
|
+
accessorStyle?: "function" | "bracket" | undefined;
|
|
122
|
+
} | undefined;
|
|
62
123
|
}, {
|
|
63
124
|
framework?: "react" | "react-cra" | "react-vite" | "react-nextjs" | "angular" | "angular-ngx" | "angular-i18n" | "vue" | "vue-i18n" | "jquery" | "vanilla-js" | "jsp" | "unknown" | undefined;
|
|
64
125
|
defaultLanguage?: string | undefined;
|
|
@@ -68,6 +129,7 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
68
129
|
keyPrefix?: string | undefined;
|
|
69
130
|
namespaces?: string[] | undefined;
|
|
70
131
|
ignorePatterns?: string[] | undefined;
|
|
132
|
+
includePatterns?: string[] | undefined;
|
|
71
133
|
incrementalCache?: boolean | undefined;
|
|
72
134
|
cacheDir?: string | undefined;
|
|
73
135
|
aws?: {
|
|
@@ -80,6 +142,14 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
80
142
|
profile?: string | undefined;
|
|
81
143
|
} | null | undefined;
|
|
82
144
|
plugins?: string[] | undefined;
|
|
145
|
+
codemods?: {
|
|
146
|
+
importPackage?: string | undefined;
|
|
147
|
+
hookName?: string | undefined;
|
|
148
|
+
translationFunction?: string | undefined;
|
|
149
|
+
namespace?: string | undefined;
|
|
150
|
+
accessorStyle?: "function" | "bracket" | undefined;
|
|
151
|
+
} | undefined;
|
|
152
|
+
localeStructure?: "flat" | "nested" | undefined;
|
|
83
153
|
}>;
|
|
84
154
|
type LocalizationConfigInput = z.input<typeof LocalizationConfigSchema>;
|
|
85
155
|
type LocalizationConfigOutput = z.output<typeof LocalizationConfigSchema>;
|
|
@@ -94,7 +164,11 @@ interface ConfigLoadResult {
|
|
|
94
164
|
*/
|
|
95
165
|
declare function loadConfig(cwd?: string, overrides?: Partial<LocalizationConfig>): Promise<ConfigLoadResult>;
|
|
96
166
|
/**
|
|
97
|
-
* Writes a default config file to the project root.
|
|
167
|
+
* Writes a fully-populated default config file to the project root.
|
|
168
|
+
*
|
|
169
|
+
* Every supported configuration field is included so users can see all
|
|
170
|
+
* available options and edit them directly. Fields that are optional/unused
|
|
171
|
+
* are set to their default values or left as empty strings / empty arrays.
|
|
98
172
|
*/
|
|
99
173
|
declare function writeDefaultConfig(cwd?: string, framework?: string): string;
|
|
100
174
|
/** Validate an existing config file */
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
10
10
|
keyPrefix: z.ZodOptional<z.ZodString>;
|
|
11
11
|
namespaces: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
12
12
|
ignorePatterns: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
13
|
+
includePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
13
14
|
incrementalCache: z.ZodDefault<z.ZodBoolean>;
|
|
14
15
|
cacheDir: z.ZodDefault<z.ZodString>;
|
|
15
16
|
aws: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
@@ -38,6 +39,57 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
38
39
|
profile?: string | undefined;
|
|
39
40
|
}>>>;
|
|
40
41
|
plugins: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
42
|
+
/** Codemod behaviour overrides — all fields are optional. */
|
|
43
|
+
codemods: z.ZodOptional<z.ZodObject<{
|
|
44
|
+
/**
|
|
45
|
+
* The npm package to import from.
|
|
46
|
+
* React default: "react-i18next"
|
|
47
|
+
* Vue default: "vue-i18n"
|
|
48
|
+
* Angular default: "@ngx-translate/core"
|
|
49
|
+
*/
|
|
50
|
+
importPackage: z.ZodOptional<z.ZodString>;
|
|
51
|
+
/**
|
|
52
|
+
* The hook / function name to import and call.
|
|
53
|
+
* React default: "useTranslation"
|
|
54
|
+
* Vue default: "useI18n"
|
|
55
|
+
*/
|
|
56
|
+
hookName: z.ZodOptional<z.ZodString>;
|
|
57
|
+
/**
|
|
58
|
+
* The translation function identifier returned by the hook (default: "t").
|
|
59
|
+
*/
|
|
60
|
+
translationFunction: z.ZodOptional<z.ZodString>;
|
|
61
|
+
/**
|
|
62
|
+
* Namespace to pass as the first argument to the hook call.
|
|
63
|
+
* When omitted no namespace argument is injected.
|
|
64
|
+
*/
|
|
65
|
+
namespace: z.ZodOptional<z.ZodString>;
|
|
66
|
+
/**
|
|
67
|
+
* How the translation accessor is written in generated code.
|
|
68
|
+
* "function" (default) — t('key')
|
|
69
|
+
* "bracket" — t['key']
|
|
70
|
+
*/
|
|
71
|
+
accessorStyle: z.ZodOptional<z.ZodEnum<["function", "bracket"]>>;
|
|
72
|
+
}, "strip", z.ZodTypeAny, {
|
|
73
|
+
importPackage?: string | undefined;
|
|
74
|
+
hookName?: string | undefined;
|
|
75
|
+
translationFunction?: string | undefined;
|
|
76
|
+
namespace?: string | undefined;
|
|
77
|
+
accessorStyle?: "function" | "bracket" | undefined;
|
|
78
|
+
}, {
|
|
79
|
+
importPackage?: string | undefined;
|
|
80
|
+
hookName?: string | undefined;
|
|
81
|
+
translationFunction?: string | undefined;
|
|
82
|
+
namespace?: string | undefined;
|
|
83
|
+
accessorStyle?: "function" | "bracket" | undefined;
|
|
84
|
+
}>>;
|
|
85
|
+
/**
|
|
86
|
+
* Locale file layout.
|
|
87
|
+
* "nested" (default) — one file per language + namespace:
|
|
88
|
+
* locales/en/common.json, locales/fr/dashboard.json
|
|
89
|
+
* "flat" — one file per language, all keys merged:
|
|
90
|
+
* locales/en.json, locales/fr.json
|
|
91
|
+
*/
|
|
92
|
+
localeStructure: z.ZodDefault<z.ZodEnum<["nested", "flat"]>>;
|
|
41
93
|
}, "strip", z.ZodTypeAny, {
|
|
42
94
|
framework: "react" | "react-cra" | "react-vite" | "react-nextjs" | "angular" | "angular-ngx" | "angular-i18n" | "vue" | "vue-i18n" | "jquery" | "vanilla-js" | "jsp" | "unknown";
|
|
43
95
|
defaultLanguage: string;
|
|
@@ -48,8 +100,10 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
48
100
|
incrementalCache: boolean;
|
|
49
101
|
cacheDir: string;
|
|
50
102
|
plugins: string[];
|
|
103
|
+
localeStructure: "flat" | "nested";
|
|
51
104
|
keyPrefix?: string | undefined;
|
|
52
105
|
namespaces?: string[] | undefined;
|
|
106
|
+
includePatterns?: string[] | undefined;
|
|
53
107
|
aws?: {
|
|
54
108
|
region: string;
|
|
55
109
|
bucket: string;
|
|
@@ -59,6 +113,13 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
59
113
|
legacyCdnPattern?: string | undefined;
|
|
60
114
|
profile?: string | undefined;
|
|
61
115
|
} | null | undefined;
|
|
116
|
+
codemods?: {
|
|
117
|
+
importPackage?: string | undefined;
|
|
118
|
+
hookName?: string | undefined;
|
|
119
|
+
translationFunction?: string | undefined;
|
|
120
|
+
namespace?: string | undefined;
|
|
121
|
+
accessorStyle?: "function" | "bracket" | undefined;
|
|
122
|
+
} | undefined;
|
|
62
123
|
}, {
|
|
63
124
|
framework?: "react" | "react-cra" | "react-vite" | "react-nextjs" | "angular" | "angular-ngx" | "angular-i18n" | "vue" | "vue-i18n" | "jquery" | "vanilla-js" | "jsp" | "unknown" | undefined;
|
|
64
125
|
defaultLanguage?: string | undefined;
|
|
@@ -68,6 +129,7 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
68
129
|
keyPrefix?: string | undefined;
|
|
69
130
|
namespaces?: string[] | undefined;
|
|
70
131
|
ignorePatterns?: string[] | undefined;
|
|
132
|
+
includePatterns?: string[] | undefined;
|
|
71
133
|
incrementalCache?: boolean | undefined;
|
|
72
134
|
cacheDir?: string | undefined;
|
|
73
135
|
aws?: {
|
|
@@ -80,6 +142,14 @@ declare const LocalizationConfigSchema: z.ZodObject<{
|
|
|
80
142
|
profile?: string | undefined;
|
|
81
143
|
} | null | undefined;
|
|
82
144
|
plugins?: string[] | undefined;
|
|
145
|
+
codemods?: {
|
|
146
|
+
importPackage?: string | undefined;
|
|
147
|
+
hookName?: string | undefined;
|
|
148
|
+
translationFunction?: string | undefined;
|
|
149
|
+
namespace?: string | undefined;
|
|
150
|
+
accessorStyle?: "function" | "bracket" | undefined;
|
|
151
|
+
} | undefined;
|
|
152
|
+
localeStructure?: "flat" | "nested" | undefined;
|
|
83
153
|
}>;
|
|
84
154
|
type LocalizationConfigInput = z.input<typeof LocalizationConfigSchema>;
|
|
85
155
|
type LocalizationConfigOutput = z.output<typeof LocalizationConfigSchema>;
|
|
@@ -94,7 +164,11 @@ interface ConfigLoadResult {
|
|
|
94
164
|
*/
|
|
95
165
|
declare function loadConfig(cwd?: string, overrides?: Partial<LocalizationConfig>): Promise<ConfigLoadResult>;
|
|
96
166
|
/**
|
|
97
|
-
* Writes a default config file to the project root.
|
|
167
|
+
* Writes a fully-populated default config file to the project root.
|
|
168
|
+
*
|
|
169
|
+
* Every supported configuration field is included so users can see all
|
|
170
|
+
* available options and edit them directly. Fields that are optional/unused
|
|
171
|
+
* are set to their default values or left as empty strings / empty arrays.
|
|
98
172
|
*/
|
|
99
173
|
declare function writeDefaultConfig(cwd?: string, framework?: string): string;
|
|
100
174
|
/** Validate an existing config file */
|
package/dist/index.js
CHANGED
|
@@ -63,6 +63,36 @@ var FrameworkSchema = import_zod.z.enum([
|
|
|
63
63
|
"jsp",
|
|
64
64
|
"unknown"
|
|
65
65
|
]);
|
|
66
|
+
var CodemodConfigSchema = import_zod.z.object({
|
|
67
|
+
/**
|
|
68
|
+
* The npm package to import from.
|
|
69
|
+
* React default: "react-i18next"
|
|
70
|
+
* Vue default: "vue-i18n"
|
|
71
|
+
* Angular default: "@ngx-translate/core"
|
|
72
|
+
*/
|
|
73
|
+
importPackage: import_zod.z.string().optional(),
|
|
74
|
+
/**
|
|
75
|
+
* The hook / function name to import and call.
|
|
76
|
+
* React default: "useTranslation"
|
|
77
|
+
* Vue default: "useI18n"
|
|
78
|
+
*/
|
|
79
|
+
hookName: import_zod.z.string().optional(),
|
|
80
|
+
/**
|
|
81
|
+
* The translation function identifier returned by the hook (default: "t").
|
|
82
|
+
*/
|
|
83
|
+
translationFunction: import_zod.z.string().optional(),
|
|
84
|
+
/**
|
|
85
|
+
* Namespace to pass as the first argument to the hook call.
|
|
86
|
+
* When omitted no namespace argument is injected.
|
|
87
|
+
*/
|
|
88
|
+
namespace: import_zod.z.string().optional(),
|
|
89
|
+
/**
|
|
90
|
+
* How the translation accessor is written in generated code.
|
|
91
|
+
* "function" (default) — t('key')
|
|
92
|
+
* "bracket" — t['key']
|
|
93
|
+
*/
|
|
94
|
+
accessorStyle: import_zod.z.enum(["function", "bracket"]).optional()
|
|
95
|
+
});
|
|
66
96
|
var LocalizationConfigSchema = import_zod.z.object({
|
|
67
97
|
framework: FrameworkSchema.default("unknown"),
|
|
68
98
|
defaultLanguage: import_zod.z.string().default("en"),
|
|
@@ -72,10 +102,21 @@ var LocalizationConfigSchema = import_zod.z.object({
|
|
|
72
102
|
keyPrefix: import_zod.z.string().optional(),
|
|
73
103
|
namespaces: import_zod.z.array(import_zod.z.string()).optional(),
|
|
74
104
|
ignorePatterns: import_zod.z.array(import_zod.z.string()).default(["node_modules", "dist", ".git", "coverage"]),
|
|
105
|
+
includePatterns: import_zod.z.array(import_zod.z.string()).optional(),
|
|
75
106
|
incrementalCache: import_zod.z.boolean().default(true),
|
|
76
107
|
cacheDir: import_zod.z.string().default(".ai-localize-cache"),
|
|
77
108
|
aws: AwsConfigSchema.optional().nullable(),
|
|
78
|
-
plugins: import_zod.z.array(import_zod.z.string()).default([])
|
|
109
|
+
plugins: import_zod.z.array(import_zod.z.string()).default([]),
|
|
110
|
+
/** Codemod behaviour overrides — all fields are optional. */
|
|
111
|
+
codemods: CodemodConfigSchema.optional(),
|
|
112
|
+
/**
|
|
113
|
+
* Locale file layout.
|
|
114
|
+
* "nested" (default) — one file per language + namespace:
|
|
115
|
+
* locales/en/common.json, locales/fr/dashboard.json
|
|
116
|
+
* "flat" — one file per language, all keys merged:
|
|
117
|
+
* locales/en.json, locales/fr.json
|
|
118
|
+
*/
|
|
119
|
+
localeStructure: import_zod.z.enum(["nested", "flat"]).default("nested")
|
|
79
120
|
});
|
|
80
121
|
|
|
81
122
|
// src/loader.ts
|
|
@@ -136,22 +177,90 @@ function extractAwsFromEnv() {
|
|
|
136
177
|
function writeDefaultConfig(cwd = process.cwd(), framework = "unknown") {
|
|
137
178
|
const configPath = path.join(cwd, import_ai_localize_shared.CONFIG_FILE_NAME);
|
|
138
179
|
const defaultConfig = {
|
|
180
|
+
// ── Framework ────────────────────────────────────────────────────────────
|
|
181
|
+
// Detected automatically by ai-localize init.
|
|
182
|
+
// Values: "react" | "react-cra" | "react-vite" | "react-nextjs"
|
|
183
|
+
// | "angular" | "angular-ngx" | "angular-i18n"
|
|
184
|
+
// | "vue" | "vue-i18n" | "jquery" | "vanilla-js" | "jsp" | "unknown"
|
|
139
185
|
framework,
|
|
186
|
+
// ── Languages ────────────────────────────────────────────────────────────
|
|
187
|
+
// Source language — used as reference for missing-translation detection.
|
|
140
188
|
defaultLanguage: "en",
|
|
189
|
+
// Additional languages to generate locale files for.
|
|
190
|
+
// All target files are seeded with the source value (no blank entries).
|
|
141
191
|
targetLanguages: ["fr", "de"],
|
|
192
|
+
// ── Directories ──────────────────────────────────────────────────────────
|
|
193
|
+
// Root of your source code — scanning starts here.
|
|
194
|
+
// Keys are generated relative to this directory.
|
|
142
195
|
sourceDir: "src",
|
|
196
|
+
// Where locale JSON files are written.
|
|
143
197
|
localesDir: "locales",
|
|
198
|
+
// ── Locale file layout ───────────────────────────────────────────────────
|
|
199
|
+
// "nested" (default): one file per language + namespace
|
|
200
|
+
// locales/en/common.json, locales/en/dashboard.json
|
|
201
|
+
// "flat": one file per language, all keys merged
|
|
202
|
+
// locales/en.json (non-default namespace keys are prefixed: "dashboard.header.title")
|
|
203
|
+
localeStructure: "nested",
|
|
204
|
+
// ── Scan filtering ───────────────────────────────────────────────────────
|
|
205
|
+
// Directories/patterns to skip during scanning.
|
|
144
206
|
ignorePatterns: ["node_modules", "dist", ".git", "coverage"],
|
|
207
|
+
// Optional: only scan files matching these glob patterns.
|
|
208
|
+
// If empty/omitted, all files under sourceDir are scanned.
|
|
209
|
+
// Example: ["src/components/**/*.tsx", "src/pages/**/*.tsx"]
|
|
210
|
+
includePatterns: [],
|
|
211
|
+
// ── Key generation ───────────────────────────────────────────────────────
|
|
212
|
+
// Optional prefix prepended to every generated key.
|
|
213
|
+
// Example: "myapp" → "myapp.components.button.save"
|
|
214
|
+
keyPrefix: "",
|
|
215
|
+
// Optional explicit list of namespace names.
|
|
216
|
+
// If omitted, namespace is derived from the first path segment after sourceDir.
|
|
217
|
+
namespaces: [],
|
|
218
|
+
// ── Incremental scanning ─────────────────────────────────────────────────
|
|
219
|
+
// Cache file hashes between runs — only re-scan changed files.
|
|
145
220
|
incrementalCache: true,
|
|
146
221
|
cacheDir: ".ai-localize-cache",
|
|
222
|
+
// ── Codemod behaviour ────────────────────────────────────────────────────
|
|
223
|
+
// Controls what the codemod injects when wrapping hardcoded strings.
|
|
224
|
+
//
|
|
225
|
+
// importPackage: npm package name OR project-relative path to the hook file.
|
|
226
|
+
// npm package: "react-i18next"
|
|
227
|
+
// local hook path: "src/hooks/useTranslation" (path relative to project root)
|
|
228
|
+
// The codemod computes the correct relative import path per file automatically.
|
|
229
|
+
//
|
|
230
|
+
// hookName: the hook function to import and call.
|
|
231
|
+
// Default: "useTranslation"
|
|
232
|
+
//
|
|
233
|
+
// translationFunction: the accessor destructured from the hook.
|
|
234
|
+
// Default: "t"
|
|
235
|
+
//
|
|
236
|
+
// namespace: passed as argument to the hook, e.g. useTranslation("common").
|
|
237
|
+
// Leave empty to omit the argument.
|
|
238
|
+
//
|
|
239
|
+
// accessorStyle:
|
|
240
|
+
// "function" (default) → t('key')
|
|
241
|
+
// "bracket" → t['key']
|
|
242
|
+
codemods: {
|
|
243
|
+
importPackage: "react-i18next",
|
|
244
|
+
hookName: "useTranslation",
|
|
245
|
+
translationFunction: "t",
|
|
246
|
+
namespace: "",
|
|
247
|
+
accessorStyle: "function"
|
|
248
|
+
},
|
|
249
|
+
// ── AWS / CloudFront (optional) ──────────────────────────────────────────
|
|
250
|
+
// Required only for CDN migration commands (migrate-cdn, upload-assets, replace-cdn).
|
|
251
|
+
// Leave all fields empty if not using CDN migration.
|
|
252
|
+
// Credentials can also be supplied via environment variables (see docs).
|
|
147
253
|
aws: {
|
|
148
254
|
region: "us-east-1",
|
|
149
255
|
bucket: "",
|
|
150
256
|
distributionId: "",
|
|
151
257
|
cdnBaseUrl: "",
|
|
152
258
|
legacyCdnPattern: "",
|
|
153
|
-
assetsPrefix: "assets"
|
|
259
|
+
assetsPrefix: "assets",
|
|
260
|
+
profile: ""
|
|
154
261
|
},
|
|
262
|
+
// ── Plugins ──────────────────────────────────────────────────────────────
|
|
263
|
+
// Paths to custom plugin modules. See docs/PLUGIN_SYSTEM.md for details.
|
|
155
264
|
plugins: []
|
|
156
265
|
};
|
|
157
266
|
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2) + "\n", "utf-8");
|
package/dist/index.mjs
CHANGED
|
@@ -24,6 +24,36 @@ var FrameworkSchema = z.enum([
|
|
|
24
24
|
"jsp",
|
|
25
25
|
"unknown"
|
|
26
26
|
]);
|
|
27
|
+
var CodemodConfigSchema = z.object({
|
|
28
|
+
/**
|
|
29
|
+
* The npm package to import from.
|
|
30
|
+
* React default: "react-i18next"
|
|
31
|
+
* Vue default: "vue-i18n"
|
|
32
|
+
* Angular default: "@ngx-translate/core"
|
|
33
|
+
*/
|
|
34
|
+
importPackage: z.string().optional(),
|
|
35
|
+
/**
|
|
36
|
+
* The hook / function name to import and call.
|
|
37
|
+
* React default: "useTranslation"
|
|
38
|
+
* Vue default: "useI18n"
|
|
39
|
+
*/
|
|
40
|
+
hookName: z.string().optional(),
|
|
41
|
+
/**
|
|
42
|
+
* The translation function identifier returned by the hook (default: "t").
|
|
43
|
+
*/
|
|
44
|
+
translationFunction: z.string().optional(),
|
|
45
|
+
/**
|
|
46
|
+
* Namespace to pass as the first argument to the hook call.
|
|
47
|
+
* When omitted no namespace argument is injected.
|
|
48
|
+
*/
|
|
49
|
+
namespace: z.string().optional(),
|
|
50
|
+
/**
|
|
51
|
+
* How the translation accessor is written in generated code.
|
|
52
|
+
* "function" (default) — t('key')
|
|
53
|
+
* "bracket" — t['key']
|
|
54
|
+
*/
|
|
55
|
+
accessorStyle: z.enum(["function", "bracket"]).optional()
|
|
56
|
+
});
|
|
27
57
|
var LocalizationConfigSchema = z.object({
|
|
28
58
|
framework: FrameworkSchema.default("unknown"),
|
|
29
59
|
defaultLanguage: z.string().default("en"),
|
|
@@ -33,10 +63,21 @@ var LocalizationConfigSchema = z.object({
|
|
|
33
63
|
keyPrefix: z.string().optional(),
|
|
34
64
|
namespaces: z.array(z.string()).optional(),
|
|
35
65
|
ignorePatterns: z.array(z.string()).default(["node_modules", "dist", ".git", "coverage"]),
|
|
66
|
+
includePatterns: z.array(z.string()).optional(),
|
|
36
67
|
incrementalCache: z.boolean().default(true),
|
|
37
68
|
cacheDir: z.string().default(".ai-localize-cache"),
|
|
38
69
|
aws: AwsConfigSchema.optional().nullable(),
|
|
39
|
-
plugins: z.array(z.string()).default([])
|
|
70
|
+
plugins: z.array(z.string()).default([]),
|
|
71
|
+
/** Codemod behaviour overrides — all fields are optional. */
|
|
72
|
+
codemods: CodemodConfigSchema.optional(),
|
|
73
|
+
/**
|
|
74
|
+
* Locale file layout.
|
|
75
|
+
* "nested" (default) — one file per language + namespace:
|
|
76
|
+
* locales/en/common.json, locales/fr/dashboard.json
|
|
77
|
+
* "flat" — one file per language, all keys merged:
|
|
78
|
+
* locales/en.json, locales/fr.json
|
|
79
|
+
*/
|
|
80
|
+
localeStructure: z.enum(["nested", "flat"]).default("nested")
|
|
40
81
|
});
|
|
41
82
|
|
|
42
83
|
// src/loader.ts
|
|
@@ -97,22 +138,90 @@ function extractAwsFromEnv() {
|
|
|
97
138
|
function writeDefaultConfig(cwd = process.cwd(), framework = "unknown") {
|
|
98
139
|
const configPath = path.join(cwd, CONFIG_FILE_NAME);
|
|
99
140
|
const defaultConfig = {
|
|
141
|
+
// ── Framework ────────────────────────────────────────────────────────────
|
|
142
|
+
// Detected automatically by ai-localize init.
|
|
143
|
+
// Values: "react" | "react-cra" | "react-vite" | "react-nextjs"
|
|
144
|
+
// | "angular" | "angular-ngx" | "angular-i18n"
|
|
145
|
+
// | "vue" | "vue-i18n" | "jquery" | "vanilla-js" | "jsp" | "unknown"
|
|
100
146
|
framework,
|
|
147
|
+
// ── Languages ────────────────────────────────────────────────────────────
|
|
148
|
+
// Source language — used as reference for missing-translation detection.
|
|
101
149
|
defaultLanguage: "en",
|
|
150
|
+
// Additional languages to generate locale files for.
|
|
151
|
+
// All target files are seeded with the source value (no blank entries).
|
|
102
152
|
targetLanguages: ["fr", "de"],
|
|
153
|
+
// ── Directories ──────────────────────────────────────────────────────────
|
|
154
|
+
// Root of your source code — scanning starts here.
|
|
155
|
+
// Keys are generated relative to this directory.
|
|
103
156
|
sourceDir: "src",
|
|
157
|
+
// Where locale JSON files are written.
|
|
104
158
|
localesDir: "locales",
|
|
159
|
+
// ── Locale file layout ───────────────────────────────────────────────────
|
|
160
|
+
// "nested" (default): one file per language + namespace
|
|
161
|
+
// locales/en/common.json, locales/en/dashboard.json
|
|
162
|
+
// "flat": one file per language, all keys merged
|
|
163
|
+
// locales/en.json (non-default namespace keys are prefixed: "dashboard.header.title")
|
|
164
|
+
localeStructure: "nested",
|
|
165
|
+
// ── Scan filtering ───────────────────────────────────────────────────────
|
|
166
|
+
// Directories/patterns to skip during scanning.
|
|
105
167
|
ignorePatterns: ["node_modules", "dist", ".git", "coverage"],
|
|
168
|
+
// Optional: only scan files matching these glob patterns.
|
|
169
|
+
// If empty/omitted, all files under sourceDir are scanned.
|
|
170
|
+
// Example: ["src/components/**/*.tsx", "src/pages/**/*.tsx"]
|
|
171
|
+
includePatterns: [],
|
|
172
|
+
// ── Key generation ───────────────────────────────────────────────────────
|
|
173
|
+
// Optional prefix prepended to every generated key.
|
|
174
|
+
// Example: "myapp" → "myapp.components.button.save"
|
|
175
|
+
keyPrefix: "",
|
|
176
|
+
// Optional explicit list of namespace names.
|
|
177
|
+
// If omitted, namespace is derived from the first path segment after sourceDir.
|
|
178
|
+
namespaces: [],
|
|
179
|
+
// ── Incremental scanning ─────────────────────────────────────────────────
|
|
180
|
+
// Cache file hashes between runs — only re-scan changed files.
|
|
106
181
|
incrementalCache: true,
|
|
107
182
|
cacheDir: ".ai-localize-cache",
|
|
183
|
+
// ── Codemod behaviour ────────────────────────────────────────────────────
|
|
184
|
+
// Controls what the codemod injects when wrapping hardcoded strings.
|
|
185
|
+
//
|
|
186
|
+
// importPackage: npm package name OR project-relative path to the hook file.
|
|
187
|
+
// npm package: "react-i18next"
|
|
188
|
+
// local hook path: "src/hooks/useTranslation" (path relative to project root)
|
|
189
|
+
// The codemod computes the correct relative import path per file automatically.
|
|
190
|
+
//
|
|
191
|
+
// hookName: the hook function to import and call.
|
|
192
|
+
// Default: "useTranslation"
|
|
193
|
+
//
|
|
194
|
+
// translationFunction: the accessor destructured from the hook.
|
|
195
|
+
// Default: "t"
|
|
196
|
+
//
|
|
197
|
+
// namespace: passed as argument to the hook, e.g. useTranslation("common").
|
|
198
|
+
// Leave empty to omit the argument.
|
|
199
|
+
//
|
|
200
|
+
// accessorStyle:
|
|
201
|
+
// "function" (default) → t('key')
|
|
202
|
+
// "bracket" → t['key']
|
|
203
|
+
codemods: {
|
|
204
|
+
importPackage: "react-i18next",
|
|
205
|
+
hookName: "useTranslation",
|
|
206
|
+
translationFunction: "t",
|
|
207
|
+
namespace: "",
|
|
208
|
+
accessorStyle: "function"
|
|
209
|
+
},
|
|
210
|
+
// ── AWS / CloudFront (optional) ──────────────────────────────────────────
|
|
211
|
+
// Required only for CDN migration commands (migrate-cdn, upload-assets, replace-cdn).
|
|
212
|
+
// Leave all fields empty if not using CDN migration.
|
|
213
|
+
// Credentials can also be supplied via environment variables (see docs).
|
|
108
214
|
aws: {
|
|
109
215
|
region: "us-east-1",
|
|
110
216
|
bucket: "",
|
|
111
217
|
distributionId: "",
|
|
112
218
|
cdnBaseUrl: "",
|
|
113
219
|
legacyCdnPattern: "",
|
|
114
|
-
assetsPrefix: "assets"
|
|
220
|
+
assetsPrefix: "assets",
|
|
221
|
+
profile: ""
|
|
115
222
|
},
|
|
223
|
+
// ── Plugins ──────────────────────────────────────────────────────────────
|
|
224
|
+
// Paths to custom plugin modules. See docs/PLUGIN_SYSTEM.md for details.
|
|
116
225
|
plugins: []
|
|
117
226
|
};
|
|
118
227
|
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2) + "\n", "utf-8");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-localize-config",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Configuration loader and schema validator for ai-localize-core",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"zod": "^3.22.4",
|
|
17
17
|
"cosmiconfig": "^9.0.0",
|
|
18
18
|
"dotenv": "^16.4.1",
|
|
19
|
-
"ai-localize-shared": "2.0.
|
|
19
|
+
"ai-localize-shared": "2.0.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"tsup": "^8.0.1",
|
package/src/loader.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { CONFIG_FILE_NAME } from 'ai-localize-shared';
|
|
|
8
8
|
import { LocalizationConfigSchema } from './schema.js';
|
|
9
9
|
|
|
10
10
|
export interface ConfigLoadResult {
|
|
11
|
-
|
|
11
|
+
config: LocalizationConfig;
|
|
12
12
|
filePath: string | null;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -27,12 +27,12 @@ export async function loadConfig(
|
|
|
27
27
|
const explorer = cosmiconfig('ai-localize', {
|
|
28
28
|
searchPlaces: [
|
|
29
29
|
CONFIG_FILE_NAME,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
'.ai-localizerc',
|
|
30
|
+
'ai-localize.config.js',
|
|
31
|
+
'ai-localize.config.ts',
|
|
32
|
+
'.ai-localizerc',
|
|
33
33
|
'.ai-localizerc.json',
|
|
34
34
|
'.ai-localizerc.js',
|
|
35
|
-
|
|
35
|
+
'package.json',
|
|
36
36
|
],
|
|
37
37
|
packageProp: 'aiLocalize',
|
|
38
38
|
});
|
|
@@ -42,12 +42,12 @@ export async function loadConfig(
|
|
|
42
42
|
|
|
43
43
|
try {
|
|
44
44
|
const result = await explorer.search(cwd);
|
|
45
|
-
|
|
45
|
+
if (result) {
|
|
46
46
|
rawConfig = result.config as Record<string, unknown>;
|
|
47
47
|
filePath = result.filepath;
|
|
48
48
|
}
|
|
49
49
|
} catch (err) {
|
|
50
|
-
// Config not found
|
|
50
|
+
// Config not found — use defaults
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Merge env vars for AWS
|
|
@@ -69,43 +69,129 @@ export async function loadConfig(
|
|
|
69
69
|
function extractAwsFromEnv(): Record<string, string> | null {
|
|
70
70
|
const bucket = process.env.AI_LOCALIZE_S3_BUCKET || process.env.AWS_S3_BUCKET;
|
|
71
71
|
const distributionId =
|
|
72
|
-
|
|
72
|
+
process.env.AI_LOCALIZE_CF_DISTRIBUTION_ID || process.env.AWS_CF_DISTRIBUTION_ID;
|
|
73
73
|
|
|
74
74
|
if (!bucket || !distributionId) return null;
|
|
75
75
|
|
|
76
76
|
return {
|
|
77
|
-
|
|
77
|
+
bucket,
|
|
78
78
|
distributionId,
|
|
79
79
|
region: process.env.AWS_REGION || process.env.AI_LOCALIZE_AWS_REGION || 'us-east-1',
|
|
80
|
-
|
|
80
|
+
cdnBaseUrl: process.env.AI_LOCALIZE_CDN_BASE_URL || '',
|
|
81
81
|
legacyCdnPattern: process.env.AI_LOCALIZE_LEGACY_CDN_PATTERN || '',
|
|
82
82
|
profile: process.env.AWS_PROFILE || '',
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
|
-
* Writes a default config file to the project root.
|
|
87
|
+
* Writes a fully-populated default config file to the project root.
|
|
88
|
+
*
|
|
89
|
+
* Every supported configuration field is included so users can see all
|
|
90
|
+
* available options and edit them directly. Fields that are optional/unused
|
|
91
|
+
* are set to their default values or left as empty strings / empty arrays.
|
|
88
92
|
*/
|
|
89
93
|
export function writeDefaultConfig(cwd = process.cwd(), framework = 'unknown'): string {
|
|
90
94
|
const configPath = path.join(cwd, CONFIG_FILE_NAME);
|
|
95
|
+
|
|
91
96
|
const defaultConfig = {
|
|
97
|
+
// ── Framework ────────────────────────────────────────────────────────────
|
|
98
|
+
// Detected automatically by ai-localize init.
|
|
99
|
+
// Values: "react" | "react-cra" | "react-vite" | "react-nextjs"
|
|
100
|
+
// | "angular" | "angular-ngx" | "angular-i18n"
|
|
101
|
+
// | "vue" | "vue-i18n" | "jquery" | "vanilla-js" | "jsp" | "unknown"
|
|
92
102
|
framework,
|
|
103
|
+
|
|
104
|
+
// ── Languages ────────────────────────────────────────────────────────────
|
|
105
|
+
// Source language — used as reference for missing-translation detection.
|
|
93
106
|
defaultLanguage: 'en',
|
|
107
|
+
|
|
108
|
+
// Additional languages to generate locale files for.
|
|
109
|
+
// All target files are seeded with the source value (no blank entries).
|
|
94
110
|
targetLanguages: ['fr', 'de'],
|
|
111
|
+
|
|
112
|
+
// ── Directories ──────────────────────────────────────────────────────────
|
|
113
|
+
// Root of your source code — scanning starts here.
|
|
114
|
+
// Keys are generated relative to this directory.
|
|
95
115
|
sourceDir: 'src',
|
|
116
|
+
|
|
117
|
+
// Where locale JSON files are written.
|
|
96
118
|
localesDir: 'locales',
|
|
119
|
+
|
|
120
|
+
// ── Locale file layout ───────────────────────────────────────────────────
|
|
121
|
+
// "nested" (default): one file per language + namespace
|
|
122
|
+
// locales/en/common.json, locales/en/dashboard.json
|
|
123
|
+
// "flat": one file per language, all keys merged
|
|
124
|
+
// locales/en.json (non-default namespace keys are prefixed: "dashboard.header.title")
|
|
125
|
+
localeStructure: 'nested',
|
|
126
|
+
|
|
127
|
+
// ── Scan filtering ───────────────────────────────────────────────────────
|
|
128
|
+
// Directories/patterns to skip during scanning.
|
|
97
129
|
ignorePatterns: ['node_modules', 'dist', '.git', 'coverage'],
|
|
98
|
-
|
|
130
|
+
|
|
131
|
+
// Optional: only scan files matching these glob patterns.
|
|
132
|
+
// If empty/omitted, all files under sourceDir are scanned.
|
|
133
|
+
// Example: ["src/components/**/*.tsx", "src/pages/**/*.tsx"]
|
|
134
|
+
includePatterns: [],
|
|
135
|
+
|
|
136
|
+
// ── Key generation ───────────────────────────────────────────────────────
|
|
137
|
+
// Optional prefix prepended to every generated key.
|
|
138
|
+
// Example: "myapp" → "myapp.components.button.save"
|
|
139
|
+
keyPrefix: '',
|
|
140
|
+
|
|
141
|
+
// Optional explicit list of namespace names.
|
|
142
|
+
// If omitted, namespace is derived from the first path segment after sourceDir.
|
|
143
|
+
namespaces: [],
|
|
144
|
+
|
|
145
|
+
// ── Incremental scanning ─────────────────────────────────────────────────
|
|
146
|
+
// Cache file hashes between runs — only re-scan changed files.
|
|
147
|
+
incrementalCache: true,
|
|
99
148
|
cacheDir: '.ai-localize-cache',
|
|
100
|
-
|
|
149
|
+
|
|
150
|
+
// ── Codemod behaviour ────────────────────────────────────────────────────
|
|
151
|
+
// Controls what the codemod injects when wrapping hardcoded strings.
|
|
152
|
+
//
|
|
153
|
+
// importPackage: npm package name OR project-relative path to the hook file.
|
|
154
|
+
// npm package: "react-i18next"
|
|
155
|
+
// local hook path: "src/hooks/useTranslation" (path relative to project root)
|
|
156
|
+
// The codemod computes the correct relative import path per file automatically.
|
|
157
|
+
//
|
|
158
|
+
// hookName: the hook function to import and call.
|
|
159
|
+
// Default: "useTranslation"
|
|
160
|
+
//
|
|
161
|
+
// translationFunction: the accessor destructured from the hook.
|
|
162
|
+
// Default: "t"
|
|
163
|
+
//
|
|
164
|
+
// namespace: passed as argument to the hook, e.g. useTranslation("common").
|
|
165
|
+
// Leave empty to omit the argument.
|
|
166
|
+
//
|
|
167
|
+
// accessorStyle:
|
|
168
|
+
// "function" (default) → t('key')
|
|
169
|
+
// "bracket" → t['key']
|
|
170
|
+
codemods: {
|
|
171
|
+
importPackage: 'react-i18next',
|
|
172
|
+
hookName: 'useTranslation',
|
|
173
|
+
translationFunction: 't',
|
|
174
|
+
namespace: '',
|
|
175
|
+
accessorStyle: 'function',
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
// ── AWS / CloudFront (optional) ──────────────────────────────────────────
|
|
179
|
+
// Required only for CDN migration commands (migrate-cdn, upload-assets, replace-cdn).
|
|
180
|
+
// Leave all fields empty if not using CDN migration.
|
|
181
|
+
// Credentials can also be supplied via environment variables (see docs).
|
|
182
|
+
aws: {
|
|
101
183
|
region: 'us-east-1',
|
|
102
|
-
|
|
184
|
+
bucket: '',
|
|
103
185
|
distributionId: '',
|
|
104
186
|
cdnBaseUrl: '',
|
|
105
187
|
legacyCdnPattern: '',
|
|
106
188
|
assetsPrefix: 'assets',
|
|
189
|
+
profile: '',
|
|
107
190
|
},
|
|
108
|
-
|
|
191
|
+
|
|
192
|
+
// ── Plugins ──────────────────────────────────────────────────────────────
|
|
193
|
+
// Paths to custom plugin modules. See docs/PLUGIN_SYSTEM.md for details.
|
|
194
|
+
plugins: [],
|
|
109
195
|
};
|
|
110
196
|
|
|
111
197
|
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2) + '\n', 'utf-8');
|
|
@@ -125,11 +211,11 @@ export function validateConfig(configPath: string): {
|
|
|
125
211
|
} catch (err: unknown) {
|
|
126
212
|
if (err && typeof err === 'object' && 'errors' in err) {
|
|
127
213
|
const zodError = err as { errors: Array<{ path: unknown[]; message: string }> };
|
|
128
|
-
|
|
214
|
+
return {
|
|
129
215
|
valid: false,
|
|
130
216
|
errors: zodError.errors.map((e) => `${e.path.join('.')}: ${e.message}`),
|
|
131
217
|
};
|
|
132
|
-
}
|
|
218
|
+
}
|
|
133
219
|
return {
|
|
134
220
|
valid: false,
|
|
135
221
|
errors: [err instanceof Error ? err.message : String(err)],
|
package/src/schema.ts
CHANGED
|
@@ -12,7 +12,7 @@ const AwsConfigSchema = z.object({
|
|
|
12
12
|
|
|
13
13
|
const FrameworkSchema = z.enum([
|
|
14
14
|
'react',
|
|
15
|
-
'react-cra',
|
|
15
|
+
'react-cra',
|
|
16
16
|
'react-vite',
|
|
17
17
|
'react-nextjs',
|
|
18
18
|
'angular',
|
|
@@ -26,6 +26,41 @@ const FrameworkSchema = z.enum([
|
|
|
26
26
|
'unknown',
|
|
27
27
|
]);
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Optional codemod behaviour overrides.
|
|
31
|
+
* Controls which i18n library / hook / pipe the codemod injects.
|
|
32
|
+
*/
|
|
33
|
+
const CodemodConfigSchema = z.object({
|
|
34
|
+
/**
|
|
35
|
+
* The npm package to import from.
|
|
36
|
+
* React default: "react-i18next"
|
|
37
|
+
* Vue default: "vue-i18n"
|
|
38
|
+
* Angular default: "@ngx-translate/core"
|
|
39
|
+
*/
|
|
40
|
+
importPackage: z.string().optional(),
|
|
41
|
+
/**
|
|
42
|
+
* The hook / function name to import and call.
|
|
43
|
+
* React default: "useTranslation"
|
|
44
|
+
* Vue default: "useI18n"
|
|
45
|
+
*/
|
|
46
|
+
hookName: z.string().optional(),
|
|
47
|
+
/**
|
|
48
|
+
* The translation function identifier returned by the hook (default: "t").
|
|
49
|
+
*/
|
|
50
|
+
translationFunction: z.string().optional(),
|
|
51
|
+
/**
|
|
52
|
+
* Namespace to pass as the first argument to the hook call.
|
|
53
|
+
* When omitted no namespace argument is injected.
|
|
54
|
+
*/
|
|
55
|
+
namespace: z.string().optional(),
|
|
56
|
+
/**
|
|
57
|
+
* How the translation accessor is written in generated code.
|
|
58
|
+
* "function" (default) — t('key')
|
|
59
|
+
* "bracket" — t['key']
|
|
60
|
+
*/
|
|
61
|
+
accessorStyle: z.enum(['function', 'bracket']).optional(),
|
|
62
|
+
});
|
|
63
|
+
|
|
29
64
|
export const LocalizationConfigSchema = z.object({
|
|
30
65
|
framework: FrameworkSchema.default('unknown'),
|
|
31
66
|
defaultLanguage: z.string().default('en'),
|
|
@@ -37,10 +72,21 @@ export const LocalizationConfigSchema = z.object({
|
|
|
37
72
|
ignorePatterns: z
|
|
38
73
|
.array(z.string())
|
|
39
74
|
.default(['node_modules', 'dist', '.git', 'coverage']),
|
|
75
|
+
includePatterns: z.array(z.string()).optional(),
|
|
40
76
|
incrementalCache: z.boolean().default(true),
|
|
41
77
|
cacheDir: z.string().default('.ai-localize-cache'),
|
|
42
78
|
aws: AwsConfigSchema.optional().nullable(),
|
|
43
79
|
plugins: z.array(z.string()).default([]),
|
|
80
|
+
/** Codemod behaviour overrides — all fields are optional. */
|
|
81
|
+
codemods: CodemodConfigSchema.optional(),
|
|
82
|
+
/**
|
|
83
|
+
* Locale file layout.
|
|
84
|
+
* "nested" (default) — one file per language + namespace:
|
|
85
|
+
* locales/en/common.json, locales/fr/dashboard.json
|
|
86
|
+
* "flat" — one file per language, all keys merged:
|
|
87
|
+
* locales/en.json, locales/fr.json
|
|
88
|
+
*/
|
|
89
|
+
localeStructure: z.enum(['nested', 'flat']).default('nested'),
|
|
44
90
|
});
|
|
45
91
|
|
|
46
92
|
export type LocalizationConfigInput = z.input<typeof LocalizationConfigSchema>;
|