Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions openspec/changes/add-multilingual-support/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Why

OpenSpec 目前只支持英文,这限制了非英语用户的使用体验。添加多语言支持可以让更多开发者使用他们熟悉的语言来使用 OpenSpec,降低使用门槛并提高采用率。通过在初始化时选择语言,后续生成的所有配置文件和模板内容都将使用所选语言,确保一致的用户体验。

## What Changes

- 在 `openspec init` 命令中添加语言选择步骤,让用户在初始化时选择语言(如:中文、英文等)
- 扩展 `OpenSpecConfig` 接口,添加 `language` 字段用于存储用户选择的语言
- 修改所有模板生成逻辑(`AGENTS.md`、`project.md`、各种 AI 工具配置文件等),根据选择的语言生成对应语言的内容
- 在 `openspec/` 目录下创建配置文件(如 `config.json`)存储语言设置,以便后续命令(如 `openspec update`)能够读取并使用相同的语言
- 更新 `openspec update` 命令,使其能够读取并应用已配置的语言设置
- 支持的语言:默认英文(en-US),可选中文(zh-CN)、法语(fr-FR)、日语(ja-JP)、阿拉伯语(ar-SA)等,后续可扩展

### Breaking Changes

- 无 - 这是新增功能,默认行为保持不变(默认使用英文)

## Impact

- Affected specs: `specs/cli-init`(需要添加语言选择相关需求)
- Affected code:
- `src/core/config.ts`(扩展 `OpenSpecConfig` 接口)
- `src/core/init.ts`(添加语言选择提示和配置存储逻辑)
- `src/core/update.ts`(读取并应用语言配置)
- `src/core/templates/`(所有模板文件需要支持多语言)
- `src/core/configurators/`(所有配置器需要支持多语言模板)
- `src/utils/file-system.ts`(可能需要添加配置文件读写功能)

139 changes: 139 additions & 0 deletions openspec/changes/add-multilingual-support/specs/cli-init/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
## ADDED Requirements

### Requirement: Language Selection

The command SHALL prompt users to select their preferred language during initialization, and all generated content SHALL use the selected language. The default language SHALL be English (en-US), with optional support for Chinese (zh-CN), French (fr-FR), Japanese (ja-JP), Arabic (ar-SA), and other languages as they become available.

#### Scenario: Prompting for language selection in interactive mode

- **WHEN** `openspec init` is executed interactively
- **THEN** present a language selection prompt before AI tool selection
- **AND** display available languages with their native names (e.g., "English (en-US)", "中文 (zh-CN)", "Français (fr-FR)", "日本語 (ja-JP)", "العربية (ar-SA)")
- **AND** default to English (en-US) if no selection is made
- **AND** store the selected language in `openspec/config.json` for future use
- **AND** supported language codes include: `en-US` (default), `zh-CN`, `fr-FR`, `ja-JP`, `ar-SA`

#### Scenario: Language selection in non-interactive mode

- **WHEN** `openspec init` is executed with `--language` option
- **THEN** validate the provided language code against supported languages
- **AND** use the specified language for all generated content
- **AND** store the language setting in `openspec/config.json`
- **AND** exit with code 1 if an invalid language code is provided, displaying available language codes

#### Scenario: Reading existing language configuration

- **GIVEN** `openspec/config.json` exists with a language setting
- **WHEN** `openspec init` is executed in extend mode
- **THEN** read the existing language configuration
- **AND** use the stored language for generating new content
- **AND** allow users to change the language during extend mode if desired

### Requirement: Language Configuration Storage

The command SHALL persist language settings in a configuration file for consistency across commands.

#### Scenario: Creating language configuration file

- **WHEN** language is selected during initialization
- **THEN** create `openspec/config.json` with the language setting
- **AND** store the language code in the format: `{ "language": "en-US" }`
- **AND** ensure the file is created even if only the directory structure is being extended

#### Scenario: Configuration file format

- **WHEN** `openspec/config.json` is created or updated
- **THEN** use valid JSON format
- **AND** include the `language` field with a valid language code
- **AND** preserve any existing configuration fields if the file already exists

### Requirement: Multilingual Template Generation

All generated templates and configuration files SHALL use content in the selected language.

#### Scenario: Generating AGENTS.md in selected language

- **WHEN** initializing OpenSpec with a selected language
- **THEN** generate `openspec/AGENTS.md` with content in the selected language
- **AND** ensure all instructions, examples, and guidance text are translated appropriately

#### Scenario: Generating project.md in selected language

- **WHEN** initializing OpenSpec with a selected language
- **THEN** generate `openspec/project.md` with template content in the selected language
- **AND** ensure all section headers, placeholders, and guidance text are in the selected language

#### Scenario: Generating AI tool configuration files in selected language

- **WHEN** configuring AI tools with a selected language
- **THEN** generate all tool-specific configuration files (e.g., `CLAUDE.md`, `.cursor/commands/*.md`) with content in the selected language
- **AND** ensure stub instructions and managed block content are translated appropriately

#### Scenario: Generating slash command files in selected language

- **WHEN** generating slash command files for selected AI tools
- **THEN** populate all command files with instructions in the selected language
- **AND** ensure workflow descriptions and guidance text match the selected language

## MODIFIED Requirements

### Requirement: File Generation

The command SHALL generate required template files with appropriate content for immediate use in the user's selected language.

#### Scenario: Generating template files

- **WHEN** initializing OpenSpec
- **THEN** generate `openspec/AGENTS.md` containing complete OpenSpec instructions for AI assistants in the selected language
- **AND** generate `project.md` with project context template in the selected language
- **AND** use the language setting from `openspec/config.json` if it exists, otherwise use the language selected during initialization

### Requirement: Directory Creation

The command SHALL create the complete OpenSpec directory structure with all required directories and files, including the configuration file.

#### Scenario: Creating OpenSpec structure

- **WHEN** `openspec init` is executed
- **THEN** create the following directory structure:
```
openspec/
├── project.md
├── AGENTS.md
├── config.json
├── specs/
└── changes/
└── archive/
```

### Requirement: Non-Interactive Mode

The command SHALL support non-interactive operation through command-line options for automation and CI/CD use cases, including language selection.

#### Scenario: Select all tools non-interactively

- **WHEN** run with `--tools all` and `--language <lang-code>`
- **THEN** automatically select every available AI tool without prompting
- **AND** use the specified language for all generated content
- **AND** proceed with initialization using the selected tools and language

#### Scenario: Select specific tools non-interactively

- **WHEN** run with `--tools claude,cursor` and `--language <lang-code>`
- **THEN** parse the comma-separated tool IDs and validate against available tools
- **AND** use the specified language for all generated content
- **AND** proceed with initialization using only the specified valid tools

#### Scenario: Skip tool configuration non-interactively

- **WHEN** run with `--tools none` and `--language <lang-code>`
- **THEN** skip AI tool configuration entirely
- **AND** use the specified language for generated template files
- **AND** only create the OpenSpec directory structure and template files

#### Scenario: Help text lists available tool IDs and language codes

- **WHEN** displaying CLI help for `openspec init`
- **THEN** show the `--tools` option description with the valid values derived from the AI tool registry
- **AND** show the `--language` option description with supported language codes (e.g., `en-US` (default), `zh-CN`, `fr-FR`, `ja-JP`, `ar-SA`)

29 changes: 29 additions & 0 deletions openspec/changes/add-multilingual-support/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## 1. 配置和数据结构
- [x] 1.1 扩展 `OpenSpecConfig` 接口,添加 `language: string` 字段
- [x] 1.2 创建语言配置文件结构(`openspec/config.json` 或类似),用于持久化语言设置
- [x] 1.3 定义支持的语言列表和语言代码(默认:`en-US`,可选:`zh-CN`, `fr-FR`, `ja-JP`, `ar-SA` 等)
- [x] 1.4 创建语言资源文件结构,用于存储各语言的模板内容

## 2. 语言选择功能
- [x] 2.1 在 `init.ts` 中添加语言选择提示(在 AI 工具选择之前或之后)
- [x] 2.2 实现语言选择交互界面,支持从可用语言列表中选择
- [x] 2.3 将选择的语言保存到配置文件中
- [x] 2.4 在非交互模式下支持 `--language` 命令行参数

## 3. 模板多语言化
- [x] 3.1 创建多语言模板系统,为每种语言准备模板内容
- [x] 3.2 修改 `agents-template.ts`,支持根据语言生成不同内容(已完成完整翻译:中文、法语、日语、阿拉伯语)
- [x] 3.3 修改 `project-template.ts`,支持根据语言生成不同内容
- [x] 3.4 修改所有 AI 工具配置器模板,支持多语言内容
- [x] 3.5 修改 slash command 模板,支持多语言内容

## 4. 更新命令支持
- [x] 4.1 修改 `update.ts`,使其能够读取配置文件中的语言设置
- [x] 4.2 确保 `openspec update` 使用相同的语言生成更新后的内容

## 5. 测试和文档
- [x] 5.1 添加单元测试,验证语言选择功能
- [x] 5.2 添加集成测试,验证多语言模板生成
- [x] 5.3 更新 CLI 帮助文档,说明 `--language` 参数
- [ ] 5.4 更新 `AGENTS.md` 中的文档,说明多语言功能(可选,因为多语言功能本身已包含在模板中)

101 changes: 91 additions & 10 deletions openspec/specs/cli-init/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The command SHALL display progress indicators during initialization to provide c
- Then success: "✔ AI tools configured"

### Requirement: Directory Creation
The command SHALL create the complete OpenSpec directory structure with all required directories and files.
The command SHALL create the complete OpenSpec directory structure with all required directories and files, including the configuration file.

#### Scenario: Creating OpenSpec structure
- **WHEN** `openspec init` is executed
Expand All @@ -28,18 +28,20 @@ The command SHALL create the complete OpenSpec directory structure with all requ
openspec/
├── project.md
├── AGENTS.md
├── config.json
├── specs/
└── changes/
└── archive/
```

### Requirement: File Generation
The command SHALL generate required template files with appropriate content for immediate use.
The command SHALL generate required template files with appropriate content for immediate use in the user's selected language.

#### Scenario: Generating template files
- **WHEN** initializing OpenSpec
- **THEN** generate `openspec/AGENTS.md` containing complete OpenSpec instructions for AI assistants
- **AND** generate `project.md` with project context template
- **THEN** generate `openspec/AGENTS.md` containing complete OpenSpec instructions for AI assistants in the selected language
- **AND** generate `project.md` with project context template in the selected language
- **AND** use the language setting from `openspec/config.json` if it exists, otherwise use the language selected during initialization

### Requirement: AI Tool Configuration
The command SHALL configure AI coding assistants with OpenSpec instructions using a grouped selection experience so teams can enable native integrations while always provisioning guidance for other assistants.
Expand Down Expand Up @@ -232,30 +234,34 @@ The init command SHALL generate slash command files for supported editors using
- **AND** each template includes instructions for the relevant OpenSpec workflow stage

### Requirement: Non-Interactive Mode
The command SHALL support non-interactive operation through command-line options for automation and CI/CD use cases.
The command SHALL support non-interactive operation through command-line options for automation and CI/CD use cases, including language selection.

#### Scenario: Select all tools non-interactively
- **WHEN** run with `--tools all`
- **WHEN** run with `--tools all` and `--language <lang-code>`
- **THEN** automatically select every available AI tool without prompting
- **AND** proceed with initialization using the selected tools
- **AND** use the specified language for all generated content
- **AND** proceed with initialization using the selected tools and language

#### Scenario: Select specific tools non-interactively
- **WHEN** run with `--tools claude,cursor`
- **WHEN** run with `--tools claude,cursor` and `--language <lang-code>`
- **THEN** parse the comma-separated tool IDs and validate against available tools
- **AND** use the specified language for all generated content
- **AND** proceed with initialization using only the specified valid tools

#### Scenario: Skip tool configuration non-interactively
- **WHEN** run with `--tools none`
- **WHEN** run with `--tools none` and `--language <lang-code>`
- **THEN** skip AI tool configuration entirely
- **AND** use the specified language for generated template files
- **AND** only create the OpenSpec directory structure and template files

#### Scenario: Invalid tool specification
- **WHEN** run with `--tools` containing any IDs not present in the AI tool registry
- **THEN** exit with code 1 and display available values (`all`, `none`, or the supported tool IDs)

#### Scenario: Help text lists available tool IDs
#### Scenario: Help text lists available tool IDs and language codes
- **WHEN** displaying CLI help for `openspec init`
- **THEN** show the `--tools` option description with the valid values derived from the AI tool registry
- **AND** show the `--language` option description with supported language codes (e.g., `en-US` (default), `zh-CN`, `fr-FR`, `ja-JP`, `ar-SA`)

### Requirement: Root instruction stub
`openspec init` SHALL always scaffold the root-level `AGENTS.md` hand-off so every teammate finds the primary OpenSpec instructions.
Expand All @@ -267,6 +273,81 @@ The command SHALL support non-interactive operation through command-line options
- **AND** preserve any existing content outside the managed markers while replacing the stub text inside them
- **AND** create the stub regardless of which native AI tools are selected

### Requirement: Language Selection

The command SHALL prompt users to select their preferred language during initialization, and all generated content SHALL use the selected language. The default language SHALL be English (en-US), with optional support for Chinese (zh-CN), French (fr-FR), Japanese (ja-JP), Arabic (ar-SA), and other languages as they become available.

#### Scenario: Prompting for language selection in interactive mode

- **WHEN** `openspec init` is executed interactively
- **THEN** present a language selection prompt before AI tool selection
- **AND** display available languages with their native names (e.g., "English (en-US)", "中文 (zh-CN)", "Français (fr-FR)", "日本語 (ja-JP)", "العربية (ar-SA)")
- **AND** default to English (en-US) if no selection is made
- **AND** store the selected language in `openspec/config.json` for future use
- **AND** supported language codes include: `en-US` (default), `zh-CN`, `fr-FR`, `ja-JP`, `ar-SA`

#### Scenario: Language selection in non-interactive mode

- **WHEN** `openspec init` is executed with `--language` option
- **THEN** validate the provided language code against supported languages
- **AND** use the specified language for all generated content
- **AND** store the language setting in `openspec/config.json`
- **AND** exit with code 1 if an invalid language code is provided, displaying available language codes

#### Scenario: Reading existing language configuration

- **GIVEN** `openspec/config.json` exists with a language setting
- **WHEN** `openspec init` is executed in extend mode
- **THEN** read the existing language configuration
- **AND** use the stored language for generating new content
- **AND** allow users to change the language during extend mode if desired

### Requirement: Language Configuration Storage

The command SHALL persist language settings in a configuration file for consistency across commands.

#### Scenario: Creating language configuration file

- **WHEN** language is selected during initialization
- **THEN** create `openspec/config.json` with the language setting
- **AND** store the language code in the format: `{ "language": "en-US" }`
- **AND** ensure the file is created even if only the directory structure is being extended

#### Scenario: Configuration file format

- **WHEN** `openspec/config.json` is created or updated
- **THEN** use valid JSON format
- **AND** include the `language` field with a valid language code
- **AND** preserve any existing configuration fields if the file already exists

### Requirement: Multilingual Template Generation

All generated templates and configuration files SHALL use content in the selected language.

#### Scenario: Generating AGENTS.md in selected language

- **WHEN** initializing OpenSpec with a selected language
- **THEN** generate `openspec/AGENTS.md` with content in the selected language
- **AND** ensure all instructions, examples, and guidance text are translated appropriately

#### Scenario: Generating project.md in selected language

- **WHEN** initializing OpenSpec with a selected language
- **THEN** generate `openspec/project.md` with template content in the selected language
- **AND** ensure all section headers, placeholders, and guidance text are in the selected language

#### Scenario: Generating AI tool configuration files in selected language

- **WHEN** configuring AI tools with a selected language
- **THEN** generate all tool-specific configuration files (e.g., `CLAUDE.md`, `.cursor/commands/*.md`) with content in the selected language
- **AND** ensure stub instructions and managed block content are translated appropriately

#### Scenario: Generating slash command files in selected language

- **WHEN** generating slash command files for selected AI tools
- **THEN** populate all command files with instructions in the selected language
- **AND** ensure workflow descriptions and guidance text match the selected language

## Why

Manual creation of OpenSpec structure is error-prone and creates adoption friction. A standardized init command ensures:
Expand Down
4 changes: 3 additions & 1 deletion src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ program
.command('init [path]')
.description('Initialize OpenSpec in your project')
.option('--tools <tools>', toolsOptionDescription)
.action(async (targetPath = '.', options?: { tools?: string }) => {
.option('--language <language>', 'Set language for generated content (e.g., en-US, zh-CN, fr-FR, ja-JP, ar-SA). Default: en-US')
.action(async (targetPath = '.', options?: { tools?: string; language?: string }) => {
try {
// Validate that the path is a valid directory
const resolvedPath = path.resolve(targetPath);
Expand All @@ -64,6 +65,7 @@ program

const initCommand = new InitCommand({
tools: options?.tools,
language: options?.language,
});
await initCommand.execute(targetPath);
} catch (error) {
Expand Down
Loading