aiwf 0.1.0 → 0.3.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 +46 -0
- package/CLAUDE.md +19 -0
- package/LICENSE +1 -1
- package/README.ko.md +90 -62
- package/README.md +109 -62
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/01_PROJECT_DOCS/ARCHITECTURE.md +1 -1
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/02_REQUIREMENTS/M01_Backend_Setup/M01_milestone_meta.md +5 -1
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/02_REQUIREMENTS/M01_Backend_Setup/PRD_AMEND_01_Auth_Flow_Update.md +5 -1
- package/claude-code/{simone/.simone/03_SPRINTS/CLAUDE.MD → aiwf/en/.aiwf/03_SPRINTS/CLAUDE.md} +28 -7
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/03_SPRINTS/S01_M01_Initial_API/S01_sprint_meta.md +8 -1
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/03_SPRINTS/S01_M01_Initial_API/T01_S01_Setup_Project_Structure.md +5 -1
- package/claude-code/aiwf/en/.aiwf/04_GENERAL_TASKS/CLAUDE.md +96 -0
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/04_GENERAL_TASKS/T002_API_Rate_Limiting.md +7 -2
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/04_GENERAL_TASKS/TX001_Refactor_Logging_Module.md +7 -2
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/05_ARCHITECTURAL_DECISIONS/ADR001_Chosen_Database_System.md +7 -1
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/05_ARCHITECTURAL_DECISIONS/ADR002_API_Authentication_Method.md +7 -1
- package/claude-code/aiwf/en/.aiwf/10_STATE_OF_PROJECT/2025-06-12-12-00-needs-focus.md +139 -0
- package/claude-code/aiwf/en/.aiwf/10_STATE_OF_PROJECT/2025-06-12-12-00-test-alignment.md +155 -0
- package/claude-code/aiwf/en/.aiwf/10_STATE_OF_PROJECT/2025-06-13-00-50-solid-progress.md +122 -0
- package/claude-code/aiwf/en/.aiwf/10_STATE_OF_PROJECT/2025-06-14-08-30-infrastructure-challenges.md +141 -0
- package/claude-code/aiwf/en/.aiwf/10_STATE_OF_PROJECT/2025-06-16-21-48-critical-foundation-issues.md +177 -0
- package/claude-code/aiwf/en/.aiwf/10_STATE_OF_PROJECT/2025-06-17-15-08-solid-progress.md +149 -0
- package/claude-code/aiwf/en/.aiwf/10_STATE_OF_PROJECT/index.json +5 -0
- package/claude-code/aiwf/en/.aiwf/10_STATE_OF_PROJECT/sync-index.js +78 -0
- package/claude-code/aiwf/en/.aiwf/98_PROMPTS/github_integration.md +130 -0
- package/claude-code/aiwf/en/.aiwf/98_PROMPTS/useful-prompts.md +31 -0
- package/claude-code/aiwf/en/.aiwf/98_PROMPTS/vibe-front-prompts.md +89 -0
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/99_TEMPLATES/task_template.md +1 -0
- package/claude-code/{simone/.simone/CLAUDE.MD → aiwf/en/.aiwf/CLAUDE.md} +13 -4
- package/claude-code/{simone/.simone → aiwf/en/.aiwf}/README.md +6 -6
- package/claude-code/aiwf/en/.claude/CLAUDE_BE.md +276 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_changelog.md +82 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_code_review.md +88 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_commit.md +160 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_create_general_task.md +147 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_create_milestone_plan.md +194 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_create_prd.md +272 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_create_sprint_tasks.md +189 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_create_sprints_from_milestone.md +121 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_discuss_review.md +29 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_do_task.md +109 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_docs.md +225 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_infinite.md +202 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_initialize.md +134 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_issue_create.md +65 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_language_manager.md +287 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_language_status.md +246 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_mermaid.md +272 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_pr_create.md +76 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_prime.md +9 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_project_review.md +261 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_switch_language.md +160 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_test.md +125 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_testing_review.md +198 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_tm-run-all-subtask.md +206 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_ultrathink_code_advanced.md +460 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_ultrathink_code_basic.md +165 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_ultrathink_general.md +362 -0
- package/claude-code/aiwf/en/.claude/commands/aiwf/aiwf_yolo.md +300 -0
- package/claude-code/aiwf/en/.claude/mcp.json +31 -0
- package/claude-code/aiwf/en/.claude/settings.json +102 -0
- package/claude-code/aiwf/ko/.aiwf/00_PROJECT_MANIFEST.md +49 -0
- package/claude-code/aiwf/ko/.aiwf/01_PROJECT_DOCS/ARCHITECTURE.md +55 -0
- package/claude-code/aiwf/ko/.aiwf/02_REQUIREMENTS/CLAUDE.md +78 -0
- package/claude-code/aiwf/ko/.aiwf/02_REQUIREMENTS/M01_Backend_Setup/M01_milestone_meta.md +42 -0
- package/claude-code/aiwf/ko/.aiwf/02_REQUIREMENTS/M01_Backend_Setup/PRD_AMEND_01_Auth_Flow_Update.md +73 -0
- package/claude-code/aiwf/ko/.aiwf/02_REQUIREMENTS/M01_Backend_Setup/PRD_Backend_Setup.md +98 -0
- package/claude-code/aiwf/ko/.aiwf/02_REQUIREMENTS/M01_Backend_Setup/SPECS_API_V1.md +232 -0
- package/claude-code/aiwf/ko/.aiwf/03_SPRINTS/CLAUDE.md +83 -0
- package/claude-code/aiwf/ko/.aiwf/03_SPRINTS/S01_M01_Initial_API/S01_sprint_meta.md +49 -0
- package/claude-code/aiwf/ko/.aiwf/03_SPRINTS/S01_M01_Initial_API/T01_S01_Setup_Project_Structure.md +60 -0
- package/claude-code/aiwf/ko/.aiwf/04_GENERAL_TASKS/CLAUDE.md +96 -0
- package/claude-code/aiwf/ko/.aiwf/04_GENERAL_TASKS/T002_API_Rate_Limiting.md +54 -0
- package/claude-code/aiwf/ko/.aiwf/04_GENERAL_TASKS/TX001_Refactor_Logging_Module.md +58 -0
- package/claude-code/aiwf/ko/.aiwf/05_ARCHITECTURAL_DECISIONS/ADR001_Chosen_Database_System.md +119 -0
- package/claude-code/aiwf/ko/.aiwf/05_ARCHITECTURAL_DECISIONS/ADR002_API_Authentication_Method.md +124 -0
- package/claude-code/aiwf/ko/.aiwf/10_STATE_OF_PROJECT/2025-06-12-12-00-needs-focus.md +139 -0
- package/claude-code/aiwf/ko/.aiwf/10_STATE_OF_PROJECT/2025-06-12-12-00-test-alignment.md +155 -0
- package/claude-code/aiwf/ko/.aiwf/10_STATE_OF_PROJECT/2025-06-13-00-50-solid-progress.md +122 -0
- package/claude-code/aiwf/ko/.aiwf/10_STATE_OF_PROJECT/2025-06-14-08-30-infrastructure-challenges.md +141 -0
- package/claude-code/aiwf/ko/.aiwf/10_STATE_OF_PROJECT/2025-06-16-21-48-critical-foundation-issues.md +177 -0
- package/claude-code/aiwf/ko/.aiwf/10_STATE_OF_PROJECT/2025-06-17-15-08-solid-progress.md +149 -0
- package/claude-code/aiwf/ko/.aiwf/10_STATE_OF_PROJECT/index.json +5 -0
- package/claude-code/aiwf/ko/.aiwf/10_STATE_OF_PROJECT/sync-index.js +78 -0
- package/claude-code/aiwf/ko/.aiwf/98_PROMPTS/github_integration.md +130 -0
- package/claude-code/aiwf/ko/.aiwf/98_PROMPTS/useful-prompts.md +31 -0
- package/claude-code/aiwf/ko/.aiwf/98_PROMPTS/vibe-front-prompts.md +89 -0
- package/claude-code/aiwf/ko/.aiwf/99_TEMPLATES/adr_template.md +49 -0
- package/claude-code/aiwf/ko/.aiwf/99_TEMPLATES/milestone_meta_template.md +25 -0
- package/claude-code/aiwf/ko/.aiwf/99_TEMPLATES/project_manifest_template.md +39 -0
- package/claude-code/aiwf/ko/.aiwf/99_TEMPLATES/sprint_meta_template.md +23 -0
- package/claude-code/aiwf/ko/.aiwf/99_TEMPLATES/task_template.md +36 -0
- package/claude-code/aiwf/ko/.aiwf/CLAUDE.md +76 -0
- package/claude-code/aiwf/ko/.aiwf/README.md +97 -0
- package/claude-code/aiwf/ko/.claude/CLAUDE_BE.md +276 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_changelog.md +82 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_code_review.md +88 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_commit.md +160 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_create_general_task.md +147 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_create_milestone_plan.md +194 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_create_prd.md +280 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_create_sprint_tasks.md +189 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_create_sprints_from_milestone.md +121 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_discuss_review.md +29 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_do_task.md +109 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_docs.md +225 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_infinite.md +202 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_initialize.md +134 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_issue_create.md +65 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_language_manager.md +287 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_language_status.md +246 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_mermaid.md +272 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_pr_create.md +76 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_prime.md +9 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_project_review.md +261 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_switch_language.md +160 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_test.md +124 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_testing_review.md +198 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_tm-run-all-subtask.md +210 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_ultrathink_code_advanced.md +460 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_ultrathink_code_basic.md +165 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_ultrathink_general.md +305 -0
- package/claude-code/aiwf/ko/.claude/commands/aiwf/aiwf_yolo.md +300 -0
- package/claude-code/aiwf/ko/.claude/mcp.json +31 -0
- package/claude-code/aiwf/ko/.claude/settings.json +102 -0
- package/{AI-WORKFLOW.md → docs/AI-WORKFLOW.ko.md} +38 -24
- package/docs/AI-WORKFLOW.md +299 -0
- package/docs/COMMANDS_GUIDE.ko.md +727 -0
- package/docs/COMMANDS_GUIDE.md +726 -0
- package/docs/CONTRIBUTING.md +406 -0
- package/docs/DEVELOPMENT_GUIDE.md +727 -0
- package/docs/Enhanced_Installation_Flow_Design.md +498 -0
- package/docs/PRD.ko.md +148 -0
- package/docs/PRD.md +150 -0
- package/docs/moonklabs-metadata-system-prd.md +127 -0
- package/index.js +1493 -122
- package/jest.config.js +4 -0
- package/language-cli.js +279 -0
- package/language-utils.js +330 -0
- package/package.json +23 -10
- package/scripts/validate-commands.cjs +338 -0
- package/scripts/validate-commands.js +254 -0
- package/tests/basic.test.js +62 -0
- package/tests/commands.test.js +127 -0
- package/tests/installer.test.js +129 -0
- package/tests/language-utils.test.js +271 -0
- package/COMMANDS_GUIDE.md +0 -462
- package/PRD.ko.md +0 -96
- package/PRD.md +0 -98
- package/claude-code/simone/.simone/04_GENERAL_TASKS/CLAUDE.MD +0 -51
- package/claude-code/simone/CHANGELOG.md +0 -71
- package/claude-code/simone/LICENSE +0 -21
- package/claude-code/simone/README.md +0 -219
- package/claude-code/simone/SYNC_GUIDE.md +0 -172
- package/claude-code/simone/sync-simone.sh +0 -138
- /package/claude-code/{simone/.simone → aiwf/en/.aiwf}/00_PROJECT_MANIFEST.md +0 -0
- /package/claude-code/{simone/.simone → aiwf/en/.aiwf}/02_REQUIREMENTS/CLAUDE.md +0 -0
- /package/claude-code/{simone/.simone → aiwf/en/.aiwf}/02_REQUIREMENTS/M01_Backend_Setup/PRD_Backend_Setup.md +0 -0
- /package/claude-code/{simone/.simone → aiwf/en/.aiwf}/02_REQUIREMENTS/M01_Backend_Setup/SPECS_API_V1.md +0 -0
- /package/claude-code/{simone/.simone → aiwf/en/.aiwf}/99_TEMPLATES/adr_template.md +0 -0
- /package/claude-code/{simone/.simone → aiwf/en/.aiwf}/99_TEMPLATES/milestone_meta_template.md +0 -0
- /package/claude-code/{simone/.simone → aiwf/en/.aiwf}/99_TEMPLATES/project_manifest_template.md +0 -0
- /package/claude-code/{simone/.simone → aiwf/en/.aiwf}/99_TEMPLATES/sprint_meta_template.md +0 -0
package/jest.config.js
ADDED
package/language-cli.js
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 언어 관리 CLI 명령어
|
|
5
|
+
* AIWF 프레임워크의 언어 설정을 관리하는 CLI 도구입니다.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import prompts from 'prompts';
|
|
11
|
+
import {
|
|
12
|
+
detectLanguage,
|
|
13
|
+
loadUserLanguageConfig,
|
|
14
|
+
saveUserLanguageConfig,
|
|
15
|
+
switchLanguage,
|
|
16
|
+
getLanguageStatus,
|
|
17
|
+
getLocalizedMessage,
|
|
18
|
+
SUPPORTED_LANGUAGES,
|
|
19
|
+
DEFAULT_LANGUAGE
|
|
20
|
+
} from './language-utils.js';
|
|
21
|
+
|
|
22
|
+
const program = new Command();
|
|
23
|
+
|
|
24
|
+
// 다국어 CLI 메시지
|
|
25
|
+
const CLI_MESSAGES = {
|
|
26
|
+
ko: {
|
|
27
|
+
LANGUAGE_STATUS_TITLE: '🌐 AIWF 언어 설정 상태',
|
|
28
|
+
DETECTED_LANGUAGE: '감지된 언어',
|
|
29
|
+
CONFIGURED_LANGUAGE: '설정된 언어',
|
|
30
|
+
EFFECTIVE_LANGUAGE: '사용 중인 언어',
|
|
31
|
+
AUTO_DETECT: '자동 감지',
|
|
32
|
+
FALLBACK_LANGUAGE: '폴백 언어',
|
|
33
|
+
SUPPORTED_LANGUAGES: '지원 언어',
|
|
34
|
+
CONFIG_PATH: '설정 파일 경로',
|
|
35
|
+
ENABLED: '활성화',
|
|
36
|
+
DISABLED: '비활성화',
|
|
37
|
+
NOT_SET: '설정되지 않음',
|
|
38
|
+
SELECT_LANGUAGE: '사용할 언어를 선택하세요:',
|
|
39
|
+
ENABLE_AUTO_DETECT: '자동 언어 감지를 활성화하시겠습니까?',
|
|
40
|
+
LANGUAGE_CHANGED: '언어가 성공적으로 변경되었습니다',
|
|
41
|
+
OPERATION_CANCELLED: '작업이 취소되었습니다',
|
|
42
|
+
CURRENT_LANGUAGE: '현재 언어',
|
|
43
|
+
PREVIOUS_LANGUAGE: '이전 언어',
|
|
44
|
+
NEW_LANGUAGE: '새 언어'
|
|
45
|
+
},
|
|
46
|
+
en: {
|
|
47
|
+
LANGUAGE_STATUS_TITLE: '🌐 AIWF Language Configuration Status',
|
|
48
|
+
DETECTED_LANGUAGE: 'Detected Language',
|
|
49
|
+
CONFIGURED_LANGUAGE: 'Configured Language',
|
|
50
|
+
EFFECTIVE_LANGUAGE: 'Effective Language',
|
|
51
|
+
AUTO_DETECT: 'Auto Detection',
|
|
52
|
+
FALLBACK_LANGUAGE: 'Fallback Language',
|
|
53
|
+
SUPPORTED_LANGUAGES: 'Supported Languages',
|
|
54
|
+
CONFIG_PATH: 'Configuration Path',
|
|
55
|
+
ENABLED: 'Enabled',
|
|
56
|
+
DISABLED: 'Disabled',
|
|
57
|
+
NOT_SET: 'Not Set',
|
|
58
|
+
SELECT_LANGUAGE: 'Select language to use:',
|
|
59
|
+
ENABLE_AUTO_DETECT: 'Enable automatic language detection?',
|
|
60
|
+
LANGUAGE_CHANGED: 'Language changed successfully',
|
|
61
|
+
OPERATION_CANCELLED: 'Operation cancelled',
|
|
62
|
+
CURRENT_LANGUAGE: 'Current Language',
|
|
63
|
+
PREVIOUS_LANGUAGE: 'Previous Language',
|
|
64
|
+
NEW_LANGUAGE: 'New Language'
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 로컬라이즈된 CLI 메시지 가져오기
|
|
70
|
+
*/
|
|
71
|
+
function getCliMessage(key, language = DEFAULT_LANGUAGE) {
|
|
72
|
+
return CLI_MESSAGES[language]?.[key] || CLI_MESSAGES[DEFAULT_LANGUAGE]?.[key] || key;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 언어 설정 상태 표시
|
|
77
|
+
*/
|
|
78
|
+
async function showLanguageStatus() {
|
|
79
|
+
try {
|
|
80
|
+
const status = await getLanguageStatus();
|
|
81
|
+
const currentLang = status.effectiveLanguage;
|
|
82
|
+
|
|
83
|
+
console.log(chalk.blue.bold(`\n${getCliMessage('LANGUAGE_STATUS_TITLE', currentLang)}`));
|
|
84
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
85
|
+
|
|
86
|
+
console.log(chalk.white(`${getCliMessage('DETECTED_LANGUAGE', currentLang)}: `) +
|
|
87
|
+
chalk.green(status.detectedLanguage));
|
|
88
|
+
|
|
89
|
+
console.log(chalk.white(`${getCliMessage('CONFIGURED_LANGUAGE', currentLang)}: `) +
|
|
90
|
+
(status.configuredLanguage ? chalk.green(status.configuredLanguage) :
|
|
91
|
+
chalk.gray(getCliMessage('NOT_SET', currentLang))));
|
|
92
|
+
|
|
93
|
+
console.log(chalk.white(`${getCliMessage('EFFECTIVE_LANGUAGE', currentLang)}: `) +
|
|
94
|
+
chalk.cyan.bold(status.effectiveLanguage));
|
|
95
|
+
|
|
96
|
+
console.log(chalk.white(`${getCliMessage('AUTO_DETECT', currentLang)}: `) +
|
|
97
|
+
(status.autoDetect ?
|
|
98
|
+
chalk.green(getCliMessage('ENABLED', currentLang)) :
|
|
99
|
+
chalk.yellow(getCliMessage('DISABLED', currentLang))));
|
|
100
|
+
|
|
101
|
+
console.log(chalk.white(`${getCliMessage('FALLBACK_LANGUAGE', currentLang)}: `) +
|
|
102
|
+
chalk.gray(status.fallbackLanguage));
|
|
103
|
+
|
|
104
|
+
console.log(chalk.white(`${getCliMessage('SUPPORTED_LANGUAGES', currentLang)}: `) +
|
|
105
|
+
chalk.gray(status.supportedLanguages.join(', ')));
|
|
106
|
+
|
|
107
|
+
console.log(chalk.white(`${getCliMessage('CONFIG_PATH', currentLang)}: `) +
|
|
108
|
+
chalk.gray(status.configPath));
|
|
109
|
+
|
|
110
|
+
if (status.error) {
|
|
111
|
+
console.log(chalk.red('\n⚠️ Error: ' + status.error));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
115
|
+
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(chalk.red('Error showing language status:', error.message));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 언어 설정 변경
|
|
123
|
+
*/
|
|
124
|
+
async function setLanguage(language = null, options = {}) {
|
|
125
|
+
try {
|
|
126
|
+
let targetLanguage = language;
|
|
127
|
+
let autoDetect = options.autoDetect;
|
|
128
|
+
|
|
129
|
+
// 언어가 지정되지 않은 경우 사용자에게 선택 요청
|
|
130
|
+
if (!targetLanguage) {
|
|
131
|
+
const currentStatus = await getLanguageStatus();
|
|
132
|
+
const currentLang = currentStatus.effectiveLanguage;
|
|
133
|
+
|
|
134
|
+
const languageResponse = await prompts({
|
|
135
|
+
type: 'select',
|
|
136
|
+
name: 'language',
|
|
137
|
+
message: getCliMessage('SELECT_LANGUAGE', currentLang),
|
|
138
|
+
choices: SUPPORTED_LANGUAGES.map(lang => ({
|
|
139
|
+
title: lang === 'ko' ? '한국어 (Korean)' : 'English',
|
|
140
|
+
value: lang
|
|
141
|
+
}))
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (!languageResponse.language) {
|
|
145
|
+
console.log(chalk.yellow(getCliMessage('OPERATION_CANCELLED', currentLang)));
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
targetLanguage = languageResponse.language;
|
|
150
|
+
|
|
151
|
+
// 자동 감지 설정이 지정되지 않은 경우 사용자에게 묻기
|
|
152
|
+
if (autoDetect === undefined) {
|
|
153
|
+
const autoDetectResponse = await prompts({
|
|
154
|
+
type: 'confirm',
|
|
155
|
+
name: 'autoDetect',
|
|
156
|
+
message: getCliMessage('ENABLE_AUTO_DETECT', targetLanguage),
|
|
157
|
+
initial: true
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
autoDetect = autoDetectResponse.autoDetect;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 언어 전환 실행
|
|
165
|
+
const result = await switchLanguage(targetLanguage);
|
|
166
|
+
|
|
167
|
+
if (result.success) {
|
|
168
|
+
console.log(chalk.green(`\n✅ ${getCliMessage('LANGUAGE_CHANGED', targetLanguage)}`));
|
|
169
|
+
console.log(chalk.gray(` ${getCliMessage('PREVIOUS_LANGUAGE', targetLanguage)}: ${result.previousLanguage}`));
|
|
170
|
+
console.log(chalk.gray(` ${getCliMessage('NEW_LANGUAGE', targetLanguage)}: ${result.newLanguage}`));
|
|
171
|
+
|
|
172
|
+
// 자동 감지 설정 업데이트
|
|
173
|
+
if (autoDetect !== undefined) {
|
|
174
|
+
await saveUserLanguageConfig(targetLanguage, { autoDetect });
|
|
175
|
+
console.log(chalk.gray(` ${getCliMessage('AUTO_DETECT', targetLanguage)}: ${autoDetect ? getCliMessage('ENABLED', targetLanguage) : getCliMessage('DISABLED', targetLanguage)}`));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
} else {
|
|
179
|
+
console.error(chalk.red('\n❌ ' + result.message));
|
|
180
|
+
if (result.error) {
|
|
181
|
+
console.error(chalk.gray(' Error: ' + result.error));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error(chalk.red('Error setting language:', error.message));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 언어 설정 초기화
|
|
192
|
+
*/
|
|
193
|
+
async function resetLanguage() {
|
|
194
|
+
try {
|
|
195
|
+
const currentStatus = await getLanguageStatus();
|
|
196
|
+
const currentLang = currentStatus.effectiveLanguage;
|
|
197
|
+
|
|
198
|
+
const confirmResponse = await prompts({
|
|
199
|
+
type: 'confirm',
|
|
200
|
+
name: 'confirm',
|
|
201
|
+
message: currentLang === 'ko' ?
|
|
202
|
+
'언어 설정을 초기화하시겠습니까? (자동 감지 모드로 돌아갑니다)' :
|
|
203
|
+
'Reset language configuration? (Will return to auto-detection mode)',
|
|
204
|
+
initial: false
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
if (!confirmResponse.confirm) {
|
|
208
|
+
console.log(chalk.yellow(getCliMessage('OPERATION_CANCELLED', currentLang)));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// 설정 파일 삭제 (자동 감지 모드로 복원)
|
|
213
|
+
const fs = await import('fs/promises');
|
|
214
|
+
const { LANGUAGE_CONFIG_PATH } = await import('./language-utils.js');
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
await fs.unlink(LANGUAGE_CONFIG_PATH);
|
|
218
|
+
console.log(chalk.green('\n✅ ' + (currentLang === 'ko' ?
|
|
219
|
+
'언어 설정이 초기화되었습니다' :
|
|
220
|
+
'Language configuration reset successfully')));
|
|
221
|
+
console.log(chalk.gray(' ' + (currentLang === 'ko' ?
|
|
222
|
+
'이제 시스템 언어가 자동으로 감지됩니다' :
|
|
223
|
+
'System language will now be automatically detected')));
|
|
224
|
+
} catch (error) {
|
|
225
|
+
if (error.code === 'ENOENT') {
|
|
226
|
+
console.log(chalk.yellow('\n⚠️ ' + (currentLang === 'ko' ?
|
|
227
|
+
'설정 파일이 존재하지 않습니다' :
|
|
228
|
+
'Configuration file does not exist')));
|
|
229
|
+
} else {
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
} catch (error) {
|
|
235
|
+
console.error(chalk.red('Error resetting language configuration:', error.message));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// CLI 명령어 정의
|
|
240
|
+
program
|
|
241
|
+
.name('aiwf-lang')
|
|
242
|
+
.description('AIWF Language Management CLI / AIWF 언어 관리 CLI')
|
|
243
|
+
.version('1.0.0');
|
|
244
|
+
|
|
245
|
+
program
|
|
246
|
+
.command('status')
|
|
247
|
+
.alias('s')
|
|
248
|
+
.description('Show current language configuration / 현재 언어 설정 표시')
|
|
249
|
+
.action(showLanguageStatus);
|
|
250
|
+
|
|
251
|
+
program
|
|
252
|
+
.command('set [language]')
|
|
253
|
+
.alias('switch')
|
|
254
|
+
.description('Set or change language / 언어 설정 또는 변경')
|
|
255
|
+
.option('-a, --auto-detect [boolean]', 'Enable/disable auto detection / 자동 감지 활성화/비활성화')
|
|
256
|
+
.action(setLanguage);
|
|
257
|
+
|
|
258
|
+
program
|
|
259
|
+
.command('reset')
|
|
260
|
+
.alias('r')
|
|
261
|
+
.description('Reset language configuration to auto-detection / 언어 설정을 자동 감지로 초기화')
|
|
262
|
+
.action(resetLanguage);
|
|
263
|
+
|
|
264
|
+
// 기본 명령어 (인수 없이 실행 시)
|
|
265
|
+
program
|
|
266
|
+
.action(async () => {
|
|
267
|
+
await showLanguageStatus();
|
|
268
|
+
console.log(chalk.blue('\n💡 사용 가능한 명령어 / Available commands:'));
|
|
269
|
+
console.log(chalk.gray(' aiwf-lang status - 현재 설정 표시 / Show current configuration'));
|
|
270
|
+
console.log(chalk.gray(' aiwf-lang set - 언어 설정 / Set language'));
|
|
271
|
+
console.log(chalk.gray(' aiwf-lang reset - 설정 초기화 / Reset configuration'));
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// CLI 실행
|
|
275
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
276
|
+
program.parse(process.argv);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export default program;
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 언어 관리 유틸리티 모듈
|
|
5
|
+
* AIWF 프레임워크의 언어 감지, 설정 저장/복원, 라우팅을 담당합니다.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs/promises';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
// 지원되는 언어 목록
|
|
12
|
+
export const SUPPORTED_LANGUAGES = ['ko', 'en'];
|
|
13
|
+
export const DEFAULT_LANGUAGE = 'en';
|
|
14
|
+
export const LANGUAGE_CONFIG_PATH = '.aiwf/config/language.json';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 언어 감지 알고리즘
|
|
18
|
+
* 1. 사용자 명시적 설정 (.aiwf/config/language.json)
|
|
19
|
+
* 2. 환경 변수 (LANG, LC_ALL)
|
|
20
|
+
* 3. 시스템 로케일 (process.env.LANG)
|
|
21
|
+
* 4. 폴백: 영어 (en)
|
|
22
|
+
*/
|
|
23
|
+
export async function detectLanguage() {
|
|
24
|
+
try {
|
|
25
|
+
// 1. 사용자 설정 확인
|
|
26
|
+
const userConfig = await loadUserLanguageConfig();
|
|
27
|
+
if (userConfig?.language && SUPPORTED_LANGUAGES.includes(userConfig.language)) {
|
|
28
|
+
return userConfig.language;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 2. 환경 변수 확인
|
|
32
|
+
const envLang = process.env.LANG || process.env.LC_ALL;
|
|
33
|
+
if (envLang) {
|
|
34
|
+
// 한국어 로케일 감지
|
|
35
|
+
if (envLang.toLowerCase().startsWith('ko')) {
|
|
36
|
+
return 'ko';
|
|
37
|
+
}
|
|
38
|
+
// 영어 로케일 감지
|
|
39
|
+
if (envLang.toLowerCase().startsWith('en')) {
|
|
40
|
+
return 'en';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 3. 폴백: 기본 언어
|
|
45
|
+
return DEFAULT_LANGUAGE;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.warn(`언어 감지 중 오류 발생: ${error.message}`);
|
|
48
|
+
return DEFAULT_LANGUAGE;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 사용자 언어 설정 로드
|
|
54
|
+
*/
|
|
55
|
+
export async function loadUserLanguageConfig() {
|
|
56
|
+
try {
|
|
57
|
+
const configExists = await fs.access(LANGUAGE_CONFIG_PATH).then(() => true).catch(() => false);
|
|
58
|
+
if (!configExists) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const configContent = await fs.readFile(LANGUAGE_CONFIG_PATH, 'utf8');
|
|
63
|
+
const config = JSON.parse(configContent);
|
|
64
|
+
|
|
65
|
+
// 설정 유효성 검증
|
|
66
|
+
if (config.language && SUPPORTED_LANGUAGES.includes(config.language)) {
|
|
67
|
+
return config;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return null;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.warn(`언어 설정 로드 중 오류 발생: ${error.message}`);
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 사용자 언어 설정 저장
|
|
79
|
+
*/
|
|
80
|
+
export async function saveUserLanguageConfig(language, options = {}) {
|
|
81
|
+
try {
|
|
82
|
+
// 언어 유효성 검증
|
|
83
|
+
if (!SUPPORTED_LANGUAGES.includes(language)) {
|
|
84
|
+
throw new Error(`지원되지 않는 언어: ${language}. 지원 언어: ${SUPPORTED_LANGUAGES.join(', ')}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 설정 디렉토리 생성
|
|
88
|
+
const configDir = path.dirname(LANGUAGE_CONFIG_PATH);
|
|
89
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
90
|
+
|
|
91
|
+
// 설정 객체 생성
|
|
92
|
+
const config = {
|
|
93
|
+
language: language,
|
|
94
|
+
auto_detect: options.auto_detect !== undefined ? options.auto_detect : true,
|
|
95
|
+
last_updated: new Date().toISOString(),
|
|
96
|
+
fallback: options.fallback || DEFAULT_LANGUAGE
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// 설정 파일 저장
|
|
100
|
+
await fs.writeFile(LANGUAGE_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
|
|
101
|
+
|
|
102
|
+
return config;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error(`언어 설정 저장 중 오류 발생: ${error.message}`);
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 명령어 파일 경로 라우팅
|
|
111
|
+
* 언어별 명령어 파일 경로를 동적으로 생성합니다.
|
|
112
|
+
*/
|
|
113
|
+
export function getCommandPath(commandName, language = null) {
|
|
114
|
+
// 언어가 지정되지 않은 경우 현재 언어 사용
|
|
115
|
+
if (!language) {
|
|
116
|
+
language = DEFAULT_LANGUAGE; // 동기 버전에서는 기본 언어 사용
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 언어 유효성 검증
|
|
120
|
+
if (!SUPPORTED_LANGUAGES.includes(language)) {
|
|
121
|
+
language = DEFAULT_LANGUAGE;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 한국어 명령어 경로
|
|
125
|
+
if (language === 'ko') {
|
|
126
|
+
return `claude-code/aiwf/ko/.claude/commands/aiwf/${commandName}.md`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 영어 명령어 경로 (기본)
|
|
130
|
+
return `claude-code/aiwf/en/.claude/commands/aiwf/${commandName}.md`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 명령어 파일 존재 여부 확인 및 폴백
|
|
135
|
+
*/
|
|
136
|
+
export async function resolveCommandPath(commandName, preferredLanguage = null) {
|
|
137
|
+
try {
|
|
138
|
+
const language = preferredLanguage || await detectLanguage();
|
|
139
|
+
|
|
140
|
+
// 선호 언어로 명령어 파일 경로 생성
|
|
141
|
+
let commandPath = getCommandPath(commandName, language);
|
|
142
|
+
|
|
143
|
+
// 파일 존재 여부 확인
|
|
144
|
+
const exists = await fs.access(commandPath).then(() => true).catch(() => false);
|
|
145
|
+
if (exists) {
|
|
146
|
+
return {
|
|
147
|
+
path: commandPath,
|
|
148
|
+
language: language,
|
|
149
|
+
fallback: false
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 폴백 언어로 재시도
|
|
154
|
+
const fallbackLanguage = language === 'ko' ? 'en' : 'ko';
|
|
155
|
+
commandPath = getCommandPath(commandName, fallbackLanguage);
|
|
156
|
+
|
|
157
|
+
const fallbackExists = await fs.access(commandPath).then(() => true).catch(() => false);
|
|
158
|
+
if (fallbackExists) {
|
|
159
|
+
return {
|
|
160
|
+
path: commandPath,
|
|
161
|
+
language: fallbackLanguage,
|
|
162
|
+
fallback: true
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 둘 다 없는 경우
|
|
167
|
+
return {
|
|
168
|
+
path: null,
|
|
169
|
+
language: null,
|
|
170
|
+
fallback: false,
|
|
171
|
+
error: `명령어 파일을 찾을 수 없습니다: ${commandName}`
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
} catch (error) {
|
|
175
|
+
return {
|
|
176
|
+
path: null,
|
|
177
|
+
language: null,
|
|
178
|
+
fallback: false,
|
|
179
|
+
error: `명령어 경로 해결 중 오류: ${error.message}`
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 템플릿 파일 경로 라우팅
|
|
186
|
+
*/
|
|
187
|
+
export function getTemplatePath(templateName, language = null) {
|
|
188
|
+
if (!language) {
|
|
189
|
+
language = DEFAULT_LANGUAGE;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!SUPPORTED_LANGUAGES.includes(language)) {
|
|
193
|
+
language = DEFAULT_LANGUAGE;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return `.aiwf/99_TEMPLATES/${language}/${templateName}`;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 다국어 에러 메시지 시스템
|
|
201
|
+
*/
|
|
202
|
+
export const ERROR_MESSAGES = {
|
|
203
|
+
ko: {
|
|
204
|
+
LANGUAGE_NOT_SUPPORTED: '지원되지 않는 언어입니다',
|
|
205
|
+
CONFIG_LOAD_FAILED: '언어 설정을 불러올 수 없습니다',
|
|
206
|
+
CONFIG_SAVE_FAILED: '언어 설정을 저장할 수 없습니다',
|
|
207
|
+
COMMAND_NOT_FOUND: '명령어를 찾을 수 없습니다',
|
|
208
|
+
TEMPLATE_NOT_FOUND: '템플릿을 찾을 수 없습니다',
|
|
209
|
+
LANGUAGE_SWITCH_SUCCESS: '언어가 성공적으로 변경되었습니다',
|
|
210
|
+
LANGUAGE_SWITCH_FAILED: '언어 변경에 실패했습니다'
|
|
211
|
+
},
|
|
212
|
+
en: {
|
|
213
|
+
LANGUAGE_NOT_SUPPORTED: 'Language not supported',
|
|
214
|
+
CONFIG_LOAD_FAILED: 'Failed to load language configuration',
|
|
215
|
+
CONFIG_SAVE_FAILED: 'Failed to save language configuration',
|
|
216
|
+
COMMAND_NOT_FOUND: 'Command not found',
|
|
217
|
+
TEMPLATE_NOT_FOUND: 'Template not found',
|
|
218
|
+
LANGUAGE_SWITCH_SUCCESS: 'Language changed successfully',
|
|
219
|
+
LANGUAGE_SWITCH_FAILED: 'Failed to change language'
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* 다국어 메시지 가져오기
|
|
225
|
+
*/
|
|
226
|
+
export function getLocalizedMessage(messageKey, language = null) {
|
|
227
|
+
if (!language) {
|
|
228
|
+
language = DEFAULT_LANGUAGE;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (!SUPPORTED_LANGUAGES.includes(language)) {
|
|
232
|
+
language = DEFAULT_LANGUAGE;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return ERROR_MESSAGES[language]?.[messageKey] || ERROR_MESSAGES[DEFAULT_LANGUAGE]?.[messageKey] || messageKey;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* 언어 전환 함수
|
|
240
|
+
*/
|
|
241
|
+
export async function switchLanguage(newLanguage) {
|
|
242
|
+
try {
|
|
243
|
+
// 언어 유효성 검증
|
|
244
|
+
if (!SUPPORTED_LANGUAGES.includes(newLanguage)) {
|
|
245
|
+
throw new Error(getLocalizedMessage('LANGUAGE_NOT_SUPPORTED'));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 현재 언어 설정 로드
|
|
249
|
+
const currentConfig = await loadUserLanguageConfig() || {};
|
|
250
|
+
|
|
251
|
+
// 새 언어로 설정 저장
|
|
252
|
+
const newConfig = await saveUserLanguageConfig(newLanguage, {
|
|
253
|
+
autoDetect: currentConfig.auto_detect,
|
|
254
|
+
fallback: currentConfig.fallback
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
success: true,
|
|
259
|
+
previousLanguage: currentConfig.language || DEFAULT_LANGUAGE,
|
|
260
|
+
newLanguage: newLanguage,
|
|
261
|
+
message: getLocalizedMessage('LANGUAGE_SWITCH_SUCCESS', newLanguage)
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
} catch (error) {
|
|
265
|
+
return {
|
|
266
|
+
success: false,
|
|
267
|
+
error: error.message,
|
|
268
|
+
message: getLocalizedMessage('LANGUAGE_SWITCH_FAILED')
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* 언어 설정 상태 확인
|
|
275
|
+
*/
|
|
276
|
+
export async function getLanguageStatus() {
|
|
277
|
+
try {
|
|
278
|
+
const detectedLanguage = await detectLanguage();
|
|
279
|
+
const userConfig = await loadUserLanguageConfig();
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
detectedLanguage: detectedLanguage,
|
|
283
|
+
configuredLanguage: userConfig?.language || null,
|
|
284
|
+
effectiveLanguage: userConfig?.language || detectedLanguage,
|
|
285
|
+
autoDetect: userConfig?.auto_detect !== false,
|
|
286
|
+
fallbackLanguage: userConfig?.fallback || DEFAULT_LANGUAGE,
|
|
287
|
+
supportedLanguages: SUPPORTED_LANGUAGES,
|
|
288
|
+
configPath: LANGUAGE_CONFIG_PATH
|
|
289
|
+
};
|
|
290
|
+
} catch (error) {
|
|
291
|
+
return {
|
|
292
|
+
detectedLanguage: DEFAULT_LANGUAGE,
|
|
293
|
+
configuredLanguage: null,
|
|
294
|
+
effectiveLanguage: DEFAULT_LANGUAGE,
|
|
295
|
+
autoDetect: true,
|
|
296
|
+
fallbackLanguage: DEFAULT_LANGUAGE,
|
|
297
|
+
supportedLanguages: SUPPORTED_LANGUAGES,
|
|
298
|
+
configPath: LANGUAGE_CONFIG_PATH,
|
|
299
|
+
error: error.message
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* 언어별 설치 경로 생성
|
|
306
|
+
*/
|
|
307
|
+
export function getInstallationLanguagePath(language) {
|
|
308
|
+
if (!SUPPORTED_LANGUAGES.includes(language)) {
|
|
309
|
+
language = DEFAULT_LANGUAGE;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return language;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// 기본 내보내기
|
|
316
|
+
export default {
|
|
317
|
+
detectLanguage,
|
|
318
|
+
loadUserLanguageConfig,
|
|
319
|
+
saveUserLanguageConfig,
|
|
320
|
+
getCommandPath,
|
|
321
|
+
resolveCommandPath,
|
|
322
|
+
getTemplatePath,
|
|
323
|
+
getLocalizedMessage,
|
|
324
|
+
switchLanguage,
|
|
325
|
+
getLanguageStatus,
|
|
326
|
+
getInstallationLanguagePath,
|
|
327
|
+
SUPPORTED_LANGUAGES,
|
|
328
|
+
DEFAULT_LANGUAGE,
|
|
329
|
+
ERROR_MESSAGES
|
|
330
|
+
};
|
package/package.json
CHANGED
|
@@ -1,38 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiwf",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "AI Workflow Framework for
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "AI Workflow Framework for Claude Code with multi-language support (Korean/English)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"aiwf": "./index.js"
|
|
8
|
+
"aiwf": "./index.js",
|
|
9
|
+
"aiwf-lang": "./language-cli.js"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
|
-
"test": "
|
|
12
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
13
|
+
"lang:status": "node language-cli.js status",
|
|
14
|
+
"lang:set": "node language-cli.js set",
|
|
15
|
+
"lang:reset": "node language-cli.js reset",
|
|
16
|
+
"validate:commands": "node scripts/validate-commands.js"
|
|
12
17
|
},
|
|
13
18
|
"keywords": [
|
|
14
|
-
"
|
|
19
|
+
"aiwf",
|
|
15
20
|
"ai",
|
|
16
21
|
"workflow",
|
|
17
|
-
"framework"
|
|
22
|
+
"framework",
|
|
23
|
+
"claude-code",
|
|
24
|
+
"multilingual",
|
|
25
|
+
"korean",
|
|
26
|
+
"english",
|
|
27
|
+
"project-management"
|
|
18
28
|
],
|
|
19
29
|
"author": "moonklabs",
|
|
20
30
|
"license": "MIT",
|
|
21
31
|
"repository": {
|
|
22
32
|
"type": "git",
|
|
23
|
-
"url": "git+https://github.com/
|
|
33
|
+
"url": "git+https://github.com/aiwf/aiwf.git"
|
|
24
34
|
},
|
|
25
35
|
"bugs": {
|
|
26
|
-
"url": "https://github.com/
|
|
36
|
+
"url": "https://github.com/aiwf/aiwf/issues"
|
|
27
37
|
},
|
|
28
|
-
"homepage": "https://github.com/
|
|
38
|
+
"homepage": "https://github.com/aiwf/aiwf#readme",
|
|
29
39
|
"engines": {
|
|
30
40
|
"node": ">=14.0.0"
|
|
31
41
|
},
|
|
32
42
|
"dependencies": {
|
|
33
|
-
"commander": "^11.1.0",
|
|
34
43
|
"chalk": "^5.3.0",
|
|
44
|
+
"commander": "^11.1.0",
|
|
35
45
|
"ora": "^8.0.1",
|
|
36
46
|
"prompts": "^2.4.2"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"jest": "^30.0.3"
|
|
37
50
|
}
|
|
38
51
|
}
|