Convert Astah diagrams (.asta) and SVG files with Japanese text to Korean using DeepL translation API. Full-stack development helper for Spring Boot + React translation workflow.
A Claude Code skill for working with JaToKo, a full-stack application that extracts Japanese text from Astah Professional diagram files (.asta) and SVG files, then applies translations using DeepL API.
**Backend**: Spring Boot 3.5.7 REST API (Java 21)
**Frontend**: React + Vite + Zustand
**Translation**: DeepL API integration
```bash
cd backend
./gradlew clean build
./gradlew bootRun
./gradlew test
./gradlew analyzeTestAsta
```
```bash
cd frontend
npm install
npm run dev
npm run build
```
```bash
docker compose up -d
docker compose logs -f
docker compose down
```
```bash
lsof -ti:8080 | xargs kill -9 # Backend
lsof -ti:5173 | xargs kill -9 # Frontend
```
```
BaseParserService<T> (abstract)
├── AstahParserService (DiagramNode)
└── SvgParserService (SvgTextNode)
```
**Common workflow** (in `BaseParserService`):
1. `extractNodes()`: Extract Japanese text from file
2. `translateNodes()`: Translate via DeepL API (deduplication optimization)
3. `applyTranslationsInternal()`: Apply translations to file
**Critical constraints:**
1. **Synchronous processing required**: Astah SDK's `ProjectAccessor` can only open one project at a time
2. **Session-based workflow**: Upload → Extract → Translate → Apply → Download (strict order)
3. **Recursive model traversal**: Package → Class → Attribute/Method tree structure
**Key components** (`backend/src/main/java/com/jatoko/service/`):
**Using Apache Batik** (`SvgParserService`):
**Key components**:
**`JapaneseDetector`** (`backend/src/main/java/com/jatoko/util/JapaneseDetector.java`):
- `uploads/`: Original files
- `target/`: Extraction result JSON
- `translated/`: Translated files
**Astah files**:
1. `POST /api/upload/astah` - Upload .asta file, returns `sessionId`
2. `POST /api/apply-translation-integrated` - Extract + Translate + Apply (integrated)
3. `GET /api/download/{sessionId}` - Download translated .asta file
**SVG files**:
1. `POST /api/svg/upload` - Upload SVG file, returns `sessionId`
2. `POST /api/svg/apply-translation-integrated` - Extract + Translate + Apply (integrated)
3. `GET /api/svg/download/{sessionId}` - Download translated SVG file
**Astah files**:
1. `POST /api/upload/astah` - Upload .asta file
2. `POST /api/extract` - Extract Japanese nodes
3. `POST /api/download/json` - Download extraction result JSON
4. (User manually edits `translatedName` fields in JSON)
5. `POST /api/upload/translation?sessionId={id}` - Upload translation JSON
6. `POST /api/apply-translation` - Apply translations to .asta file
7. `GET /api/download/{sessionId}` - Download translated .asta file
**SVG files**: Same flow with `/api/svg/*` endpoints
**curl example (Integrated API)**:
```bash
SESSION_ID=$(curl -X POST http://localhost:8080/api/upload/astah \
-F "[email protected]" -s | jq -r '.sessionId')
curl -X POST http://localhost:8080/api/apply-translation-integrated \
-H "Content-Type: application/json" \
-d "{\"sessionId\": \"$SESSION_ID\"}" -s
curl -X GET "http://localhost:8080/api/download/$SESSION_ID" \
-o "translated.asta"
```
**Backend**:
- `astah-api.jar`
- `astah-professional.jar`
- `rlm-1601.jar`
**Frontend**:
**Zustand Store Separation Pattern** (`frontend/src/stores/translationStore.ts`):
```typescript
// State: Data only (immutable)
type TranslationStore = {
sessionId: string;
selectedFile: File | null;
// ...
};
// Actions: Separate object
const store = {
setSelectedFile: (file: File | null) => { /* ... */ },
uploadFile: async () => { /* ... */ },
// ...
};
// Export
export const useTranslationStore = create<TranslationStore>(/* ... */);
export const translationStore = store;
```
Usage in components:
```typescript
// Read state
const status = useTranslationStore((s) => s.status);
// Call action
translationStore.uploadFile();
```
**Backend**: Allow partial success
```java
try {
// Astah API call
} catch (Exception e) {
// Continue even if some elements fail
System.err.println("Warning: " + e.getMessage());
}
```
**Frontend**: AxiosError type checking
```typescript
catch (error) {
const axiosError = error as AxiosError<ApiErrorResponse>;
console.error(axiosError.response?.data?.error);
}
```
`backend/src/main/resources/application.yml`:
```yaml
deepl:
api-key: ${DEEPL_API_KEY:your-api-key-here}
```
Set environment variable:
```bash
export DEEPL_API_KEY="your-actual-key"
```
`docker-compose.yml` - Integrated frontend + backend:
Use this skill when you need to:
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/jatoko-astahsvg-translator/raw