mta-mcp 1.9.0 → 2.2.0
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/README.md +140 -2
- package/build/core/analyzers/eslint.d.ts +51 -0
- package/build/core/analyzers/eslint.d.ts.map +1 -0
- package/build/core/analyzers/eslint.js +259 -0
- package/build/core/analyzers/eslint.js.map +1 -0
- package/build/core/analyzers/index.d.ts +9 -0
- package/build/core/analyzers/index.d.ts.map +1 -0
- package/build/core/analyzers/index.js +9 -0
- package/build/core/analyzers/index.js.map +1 -0
- package/build/core/analyzers/registry.d.ts +59 -0
- package/build/core/analyzers/registry.d.ts.map +1 -0
- package/build/core/analyzers/registry.js +241 -0
- package/build/core/analyzers/registry.js.map +1 -0
- package/build/core/analyzers/tsconfig.d.ts +45 -0
- package/build/core/analyzers/tsconfig.d.ts.map +1 -0
- package/build/core/analyzers/tsconfig.js +197 -0
- package/build/core/analyzers/tsconfig.js.map +1 -0
- package/build/core/analyzers/types.d.ts +176 -0
- package/build/core/analyzers/types.d.ts.map +1 -0
- package/build/core/analyzers/types.js +39 -0
- package/build/core/analyzers/types.js.map +1 -0
- package/build/core/analyzers/vite.d.ts +46 -0
- package/build/core/analyzers/vite.d.ts.map +1 -0
- package/build/core/analyzers/vite.js +211 -0
- package/build/core/analyzers/vite.js.map +1 -0
- package/build/core/enhancedProjectAnalyzer.d.ts +102 -0
- package/build/core/enhancedProjectAnalyzer.d.ts.map +1 -0
- package/build/core/enhancedProjectAnalyzer.js +312 -0
- package/build/core/enhancedProjectAnalyzer.js.map +1 -0
- package/build/core/errors.d.ts +84 -0
- package/build/core/errors.d.ts.map +1 -0
- package/build/core/errors.js +151 -0
- package/build/core/errors.js.map +1 -0
- package/build/core/index.d.ts +11 -0
- package/build/core/index.d.ts.map +1 -0
- package/build/core/index.js +14 -0
- package/build/core/index.js.map +1 -0
- package/build/core/logger.d.ts +91 -0
- package/build/core/logger.d.ts.map +1 -0
- package/build/core/logger.js +164 -0
- package/build/core/logger.js.map +1 -0
- package/build/core/mappings/index.d.ts +5 -0
- package/build/core/mappings/index.d.ts.map +1 -0
- package/build/core/mappings/index.js +5 -0
- package/build/core/mappings/index.js.map +1 -0
- package/build/core/mappings/scenarioMappings.d.ts +51 -0
- package/build/core/mappings/scenarioMappings.d.ts.map +1 -0
- package/build/core/mappings/scenarioMappings.js +105 -0
- package/build/core/mappings/scenarioMappings.js.map +1 -0
- package/build/core/matching/index.d.ts +8 -0
- package/build/core/matching/index.d.ts.map +1 -0
- package/build/core/matching/index.js +8 -0
- package/build/core/matching/index.js.map +1 -0
- package/build/core/matching/intentAnalyzer.d.ts +78 -0
- package/build/core/matching/intentAnalyzer.d.ts.map +1 -0
- package/build/core/matching/intentAnalyzer.js +255 -0
- package/build/core/matching/intentAnalyzer.js.map +1 -0
- package/build/core/matching/standardMatcher.d.ts +101 -0
- package/build/core/matching/standardMatcher.d.ts.map +1 -0
- package/build/core/matching/standardMatcher.js +299 -0
- package/build/core/matching/standardMatcher.js.map +1 -0
- package/build/core/matching/weights.d.ts +64 -0
- package/build/core/matching/weights.d.ts.map +1 -0
- package/build/core/matching/weights.js +334 -0
- package/build/core/matching/weights.js.map +1 -0
- package/build/core/scenarioDetector.d.ts +2 -0
- package/build/core/scenarioDetector.d.ts.map +1 -0
- package/build/core/scenarioDetector.js +2 -0
- package/build/core/scenarioDetector.js.map +1 -0
- package/build/core/templates/discovery.d.ts +41 -0
- package/build/core/templates/discovery.d.ts.map +1 -0
- package/build/core/templates/discovery.js +262 -0
- package/build/core/templates/discovery.js.map +1 -0
- package/build/core/templates/types.d.ts +80 -0
- package/build/core/templates/types.d.ts.map +1 -0
- package/build/core/templates/types.js +10 -0
- package/build/core/templates/types.js.map +1 -0
- package/build/core/types.d.ts +2 -0
- package/build/core/types.d.ts.map +1 -1
- package/build/core/types.js +4 -3
- package/build/core/types.js.map +1 -1
- package/build/index.js +136 -23
- package/build/index.js.map +1 -1
- package/build/tools/getStandardById.d.ts +42 -0
- package/build/tools/getStandardById.d.ts.map +1 -0
- package/build/tools/getStandardById.js +289 -0
- package/build/tools/getStandardById.js.map +1 -0
- package/build/tools/getTemplate.d.ts +37 -0
- package/build/tools/getTemplate.d.ts.map +1 -0
- package/build/tools/getTemplate.js +78 -0
- package/build/tools/getTemplate.js.map +1 -0
- package/build/tools/listTemplates.d.ts +41 -0
- package/build/tools/listTemplates.d.ts.map +1 -0
- package/build/tools/listTemplates.js +81 -0
- package/build/tools/listTemplates.js.map +1 -0
- package/build/tools/queryMappings.d.ts +55 -0
- package/build/tools/queryMappings.d.ts.map +1 -0
- package/build/tools/queryMappings.js +119 -0
- package/build/tools/queryMappings.js.map +1 -0
- package/package.json +25 -8
- package/src/core/autoInitializer.ts +0 -170
- package/src/core/codeValidator.ts +0 -357
- package/src/core/githubClient.ts +0 -64
- package/src/core/i18nDetector.ts +0 -357
- package/src/core/smartAgentMatcher.ts +0 -490
- package/src/core/standardsManager.ts +0 -769
- package/src/core/types.ts +0 -72
- package/src/index.ts +0 -519
- package/src/tools/analyzeProject.ts +0 -94
- package/src/tools/autoSetup.ts +0 -312
- package/src/tools/generateConfig.ts +0 -429
- package/src/tools/getCompactStandards.ts +0 -413
- package/src/tools/getSmartStandards.ts +0 -225
- package/src/tools/healthCheck.ts +0 -261
- package/src/tools/listAgents.ts +0 -91
- package/src/tools/matchAgents.ts +0 -80
- package/src/tools/usePreset.ts +0 -180
package/src/core/i18nDetector.ts
DELETED
|
@@ -1,357 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import glob from 'fast-glob';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 国际化配置信息
|
|
7
|
-
*/
|
|
8
|
-
export interface I18nConfig {
|
|
9
|
-
enabled: boolean; // 是否启用了国际化
|
|
10
|
-
type: 'vue-i18n' | 'flutter-intl' | 'react-i18n' | 'custom' | 'none'; // 国际化方案类型
|
|
11
|
-
configFiles: string[]; // 配置文件路径
|
|
12
|
-
messageFiles: string[]; // 消息文件路径
|
|
13
|
-
method: string; // 使用方法(如 $t、S.of(context))
|
|
14
|
-
example: string; // 使用示例
|
|
15
|
-
tips: string[]; // 提示信息
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 国际化检测器
|
|
20
|
-
* 支持检测 Vue、Flutter、React 等项目的国际化配置
|
|
21
|
-
*/
|
|
22
|
-
export class I18nDetector {
|
|
23
|
-
/**
|
|
24
|
-
* 检测项目的国际化配置
|
|
25
|
-
*/
|
|
26
|
-
static async detect(projectPath: string): Promise<I18nConfig> {
|
|
27
|
-
// 检测 package.json(前端项目)
|
|
28
|
-
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
29
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
30
|
-
return this.detectFrontendI18n(projectPath, packageJsonPath);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// 检测 pubspec.yaml(Flutter 项目)
|
|
34
|
-
const pubspecPath = path.join(projectPath, 'pubspec.yaml');
|
|
35
|
-
if (fs.existsSync(pubspecPath)) {
|
|
36
|
-
return this.detectFlutterI18n(projectPath, pubspecPath);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// 未检测到国际化
|
|
40
|
-
return {
|
|
41
|
-
enabled: false,
|
|
42
|
-
type: 'none',
|
|
43
|
-
configFiles: [],
|
|
44
|
-
messageFiles: [],
|
|
45
|
-
method: '',
|
|
46
|
-
example: '',
|
|
47
|
-
tips: ['项目未配置国际化,建议添加中英双语支持']
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* 检测前端项目的国际化配置(Vue/React)
|
|
53
|
-
*/
|
|
54
|
-
private static detectFrontendI18n(projectPath: string, packageJsonPath: string): I18nConfig {
|
|
55
|
-
const content = fs.readFileSync(packageJsonPath, 'utf-8');
|
|
56
|
-
const packageJson = JSON.parse(content);
|
|
57
|
-
const allDeps = {
|
|
58
|
-
...packageJson.dependencies,
|
|
59
|
-
...packageJson.devDependencies
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// 检测 vue-i18n
|
|
63
|
-
if (allDeps['vue-i18n']) {
|
|
64
|
-
return this.detectVueI18n(projectPath);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// 检测 react-i18next
|
|
68
|
-
if (allDeps['react-i18next'] || allDeps['i18next']) {
|
|
69
|
-
return this.detectReactI18n(projectPath);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// 检测 react-intl
|
|
73
|
-
if (allDeps['react-intl']) {
|
|
74
|
-
return this.detectReactIntl(projectPath);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 检测自定义国际化方案
|
|
78
|
-
return this.detectCustomI18n(projectPath);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* 检测 vue-i18n 配置
|
|
83
|
-
*/
|
|
84
|
-
private static detectVueI18n(projectPath: string): I18nConfig {
|
|
85
|
-
const configFiles: string[] = [];
|
|
86
|
-
const messageFiles: string[] = [];
|
|
87
|
-
|
|
88
|
-
// 查找配置文件
|
|
89
|
-
const possibleConfigPaths = [
|
|
90
|
-
'src/i18n/index.ts',
|
|
91
|
-
'src/i18n/index.js',
|
|
92
|
-
'src/locales/index.ts',
|
|
93
|
-
'src/locales/index.js',
|
|
94
|
-
'i18n.config.ts',
|
|
95
|
-
'i18n.config.js'
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
for (const configPath of possibleConfigPaths) {
|
|
99
|
-
const fullPath = path.join(projectPath, configPath);
|
|
100
|
-
if (fs.existsSync(fullPath)) {
|
|
101
|
-
configFiles.push(configPath);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// 查找消息文件
|
|
106
|
-
const possibleMessageDirs = ['src/i18n', 'src/locales', 'src/lang'];
|
|
107
|
-
for (const dir of possibleMessageDirs) {
|
|
108
|
-
const fullDir = path.join(projectPath, dir);
|
|
109
|
-
if (fs.existsSync(fullDir)) {
|
|
110
|
-
const files = fs.readdirSync(fullDir);
|
|
111
|
-
for (const file of files) {
|
|
112
|
-
if (/^(zh|en|ja|ko|fr|de|es).*\.(ts|js|json)$/.test(file)) {
|
|
113
|
-
messageFiles.push(path.join(dir, file));
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
enabled: true,
|
|
121
|
-
type: 'vue-i18n',
|
|
122
|
-
configFiles,
|
|
123
|
-
messageFiles,
|
|
124
|
-
method: '$t()',
|
|
125
|
-
example: `{{ $t('common.save') }} 或 :label="$t('user.username')"`,
|
|
126
|
-
tips: [
|
|
127
|
-
'使用命名空间格式:$t("common.save")',
|
|
128
|
-
'所有按钮、标签、提示文字必须使用 $t()',
|
|
129
|
-
'表单验证规则的 message 也需要国际化',
|
|
130
|
-
'确保 zh-CN.ts 和 en-US.ts 中的键名完全一致'
|
|
131
|
-
]
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 检测 react-i18next 配置
|
|
137
|
-
*/
|
|
138
|
-
private static detectReactI18n(projectPath: string): I18nConfig {
|
|
139
|
-
const configFiles: string[] = [];
|
|
140
|
-
const messageFiles: string[] = [];
|
|
141
|
-
|
|
142
|
-
// 查找配置文件
|
|
143
|
-
const possibleConfigPaths = [
|
|
144
|
-
'src/i18n.ts',
|
|
145
|
-
'src/i18n.js',
|
|
146
|
-
'src/i18n/config.ts',
|
|
147
|
-
'src/i18n/config.js'
|
|
148
|
-
];
|
|
149
|
-
|
|
150
|
-
for (const configPath of possibleConfigPaths) {
|
|
151
|
-
const fullPath = path.join(projectPath, configPath);
|
|
152
|
-
if (fs.existsSync(fullPath)) {
|
|
153
|
-
configFiles.push(configPath);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// 查找翻译文件
|
|
158
|
-
const possibleMessageDirs = ['public/locales', 'src/locales', 'src/i18n'];
|
|
159
|
-
for (const dir of possibleMessageDirs) {
|
|
160
|
-
const fullDir = path.join(projectPath, dir);
|
|
161
|
-
if (fs.existsSync(fullDir)) {
|
|
162
|
-
const pattern = path.join(fullDir, '**/*.json');
|
|
163
|
-
try {
|
|
164
|
-
const files = glob.sync(pattern);
|
|
165
|
-
messageFiles.push(...files.map(f => path.relative(projectPath, f)));
|
|
166
|
-
} catch (e) {
|
|
167
|
-
// 忽略错误
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return {
|
|
173
|
-
enabled: true,
|
|
174
|
-
type: 'react-i18n',
|
|
175
|
-
configFiles,
|
|
176
|
-
messageFiles,
|
|
177
|
-
method: 't() 或 useTranslation()',
|
|
178
|
-
example: `{t('common.save')} 或 const { t } = useTranslation()`,
|
|
179
|
-
tips: [
|
|
180
|
-
'使用 useTranslation() hook 获取 t 函数',
|
|
181
|
-
'命名空间格式:t("common.save")',
|
|
182
|
-
'所有文案必须通过 t() 函数包裹',
|
|
183
|
-
'确保所有语言的翻译文件同步更新'
|
|
184
|
-
]
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* 检测 react-intl 配置
|
|
190
|
-
*/
|
|
191
|
-
private static detectReactIntl(projectPath: string): I18nConfig {
|
|
192
|
-
return {
|
|
193
|
-
enabled: true,
|
|
194
|
-
type: 'react-i18n',
|
|
195
|
-
configFiles: [],
|
|
196
|
-
messageFiles: [],
|
|
197
|
-
method: 'formatMessage() 或 FormattedMessage',
|
|
198
|
-
example: `<FormattedMessage id="common.save" /> 或 intl.formatMessage({ id: 'common.save' })`,
|
|
199
|
-
tips: [
|
|
200
|
-
'使用 FormattedMessage 组件或 formatMessage 方法',
|
|
201
|
-
'消息 ID 格式:common.save',
|
|
202
|
-
'所有文案必须定义在消息文件中',
|
|
203
|
-
'确保多语言文件的消息 ID 保持一致'
|
|
204
|
-
]
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* 检测自定义国际化方案
|
|
210
|
-
*/
|
|
211
|
-
private static detectCustomI18n(projectPath: string): I18nConfig {
|
|
212
|
-
const messageFiles: string[] = [];
|
|
213
|
-
|
|
214
|
-
// 查找可能的消息文件
|
|
215
|
-
const possibleDirs = ['src/locales', 'src/i18n', 'src/lang'];
|
|
216
|
-
for (const dir of possibleDirs) {
|
|
217
|
-
const fullDir = path.join(projectPath, dir);
|
|
218
|
-
if (fs.existsSync(fullDir)) {
|
|
219
|
-
const files = fs.readdirSync(fullDir);
|
|
220
|
-
for (const file of files) {
|
|
221
|
-
if (/messages?\.(ts|js)$/i.test(file)) {
|
|
222
|
-
messageFiles.push(path.join(dir, file));
|
|
223
|
-
|
|
224
|
-
// 读取文件检测格式
|
|
225
|
-
const content = fs.readFileSync(path.join(fullDir, file), 'utf-8');
|
|
226
|
-
|
|
227
|
-
// 检测是否是双语数组格式 [英文, 中文]
|
|
228
|
-
if (content.includes('[') && content.includes('],')) {
|
|
229
|
-
return {
|
|
230
|
-
enabled: true,
|
|
231
|
-
type: 'custom',
|
|
232
|
-
configFiles: [],
|
|
233
|
-
messageFiles,
|
|
234
|
-
method: '$t()',
|
|
235
|
-
example: `{{ $t('保存') }} 或 :label="$t('用户名')"`,
|
|
236
|
-
tips: [
|
|
237
|
-
'使用直接键名格式:$t("保存")',
|
|
238
|
-
'所有按钮、标签、提示文字必须使用 $t()',
|
|
239
|
-
'表单验证规则的 message 也需要国际化',
|
|
240
|
-
'新增文案时需要同时添加中英文翻译'
|
|
241
|
-
]
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// 未检测到国际化配置
|
|
250
|
-
if (messageFiles.length > 0) {
|
|
251
|
-
return {
|
|
252
|
-
enabled: true,
|
|
253
|
-
type: 'custom',
|
|
254
|
-
configFiles: [],
|
|
255
|
-
messageFiles,
|
|
256
|
-
method: '$t()',
|
|
257
|
-
example: '请查看项目中现有页面的使用方式',
|
|
258
|
-
tips: [
|
|
259
|
-
'检测到国际化文件,但格式未知',
|
|
260
|
-
'请查看现有页面确认使用方式',
|
|
261
|
-
'确保所有新增文案都遵循项目规范'
|
|
262
|
-
]
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
return {
|
|
267
|
-
enabled: false,
|
|
268
|
-
type: 'none',
|
|
269
|
-
configFiles: [],
|
|
270
|
-
messageFiles: [],
|
|
271
|
-
method: '',
|
|
272
|
-
example: '',
|
|
273
|
-
tips: [
|
|
274
|
-
'⚠️ 项目未配置国际化',
|
|
275
|
-
'建议添加中英双语支持',
|
|
276
|
-
'推荐使用 vue-i18n(Vue)或 react-i18next(React)'
|
|
277
|
-
]
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* 检测 Flutter 项目的国际化配置
|
|
283
|
-
*/
|
|
284
|
-
private static detectFlutterI18n(projectPath: string, pubspecPath: string): I18nConfig {
|
|
285
|
-
const content = fs.readFileSync(pubspecPath, 'utf-8');
|
|
286
|
-
|
|
287
|
-
// 检测是否配置了 flutter_localizations
|
|
288
|
-
if (content.includes('flutter_localizations')) {
|
|
289
|
-
const messageFiles: string[] = [];
|
|
290
|
-
|
|
291
|
-
// 查找 .arb 文件
|
|
292
|
-
const l10nDir = path.join(projectPath, 'lib', 'l10n');
|
|
293
|
-
if (fs.existsSync(l10nDir)) {
|
|
294
|
-
const files = fs.readdirSync(l10nDir);
|
|
295
|
-
for (const file of files) {
|
|
296
|
-
if (file.endsWith('.arb')) {
|
|
297
|
-
messageFiles.push(`lib/l10n/${file}`);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// 检查是否有 l10n.yaml 配置文件
|
|
303
|
-
const l10nConfigPath = path.join(projectPath, 'l10n.yaml');
|
|
304
|
-
const configFiles = fs.existsSync(l10nConfigPath) ? ['l10n.yaml'] : [];
|
|
305
|
-
|
|
306
|
-
return {
|
|
307
|
-
enabled: true,
|
|
308
|
-
type: 'flutter-intl',
|
|
309
|
-
configFiles,
|
|
310
|
-
messageFiles,
|
|
311
|
-
method: 'AppLocalizations',
|
|
312
|
-
example: `AppLocalizations.of(context)!.save 或 S.of(context).save`,
|
|
313
|
-
tips: [
|
|
314
|
-
'使用 AppLocalizations.of(context)!.key',
|
|
315
|
-
'所有文本必须在 .arb 文件中定义',
|
|
316
|
-
'确保 app_en.arb 和 app_zh.arb 的键名完全一致',
|
|
317
|
-
'运行 flutter gen-l10n 生成代码'
|
|
318
|
-
]
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// 检测 easy_localization
|
|
323
|
-
if (content.includes('easy_localization')) {
|
|
324
|
-
return {
|
|
325
|
-
enabled: true,
|
|
326
|
-
type: 'flutter-intl',
|
|
327
|
-
configFiles: [],
|
|
328
|
-
messageFiles: [],
|
|
329
|
-
method: 'tr()',
|
|
330
|
-
example: `'save'.tr() 或 Text('save'.tr())`,
|
|
331
|
-
tips: [
|
|
332
|
-
'使用 .tr() 扩展方法',
|
|
333
|
-
'翻译文件通常在 assets/translations/',
|
|
334
|
-
'确保所有语言文件的键名一致'
|
|
335
|
-
]
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// 未检测到国际化配置
|
|
340
|
-
return {
|
|
341
|
-
enabled: false,
|
|
342
|
-
type: 'none',
|
|
343
|
-
configFiles: [],
|
|
344
|
-
messageFiles: [],
|
|
345
|
-
method: '',
|
|
346
|
-
example: '',
|
|
347
|
-
tips: [
|
|
348
|
-
'⚠️ Flutter 项目未配置国际化',
|
|
349
|
-
'建议添加 flutter_localizations',
|
|
350
|
-
'在 pubspec.yaml 中添加:',
|
|
351
|
-
' flutter_localizations:',
|
|
352
|
-
' sdk: flutter',
|
|
353
|
-
' intl: any'
|
|
354
|
-
]
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
}
|