Skip to content

feat: Add Vertex AI Chinese translation support#42

Merged
Jing-yilin merged 4 commits intodevelopfrom
feature/chinese-translation
Feb 28, 2026
Merged

feat: Add Vertex AI Chinese translation support#42
Jing-yilin merged 4 commits intodevelopfrom
feature/chinese-translation

Conversation

@Jing-yilin
Copy link
Contributor

@Jing-yilin Jing-yilin commented Feb 28, 2026

Summary

Add complete Chinese localization for KickWatch using Vertex AI to automatically translate all Kickstarter campaign content.

Changes

Backend

  • ✅ Add name_zh, blurb_zh, creator_name_zh fields to Campaign model
  • ✅ Add name_zh field to Category model
  • ✅ Integrate Vertex AI Gemini 2.0 Flash translation service
  • ✅ Auto-translate during nightly crawl and backfill
  • ✅ All 26 categories with hardcoded Chinese names
  • ✅ Batch translation optimization (10 campaigns/batch) for cost savings

Infrastructure

  • ✅ GCP Project: rescience-lab-465304
  • ✅ Service Account: kickwatch-translator@rescience-lab-465304.iam.gserviceaccount.com
  • ✅ AWS Secrets Manager configured:
    • kickwatch-dev/google-service-account (credentials)
    • kickwatch-dev/vertex-ai-config (project config)

Cost Control

  • 💰 Uses $1,773 GCP startup credits
  • 📊 Batch translation reduces API calls
  • ⚡ Fast model (gemini-2.0-flash-exp) for cost efficiency

Deployment Configuration

Add these environment variables to ECS task definition:

{
  "name": "VERTEX_AI_PROJECT_ID",
  "value": "rescience-lab-465304"
},
{
  "name": "VERTEX_AI_LOCATION",
  "value": "us-central1"
},
{
  "name": "GOOGLE_SERVICE_ACCOUNT_JSON",
  "valueFrom": "arn:aws:secretsmanager:us-east-2:739654145647:secret:kickwatch-dev/google-service-account"
}

TODO

  • iOS frontend adaptation (display Chinese fields)
  • Update GitHub Actions workflow with env vars
  • UI text localization (buttons, labels)
  • Test translation quality

Testing Plan

  1. Local test translation service
  2. Run nightly crawl in dev environment
  3. Verify Chinese fields populated in database
  4. iOS frontend verification

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

Implement complete Chinese localization for KickWatch:

**Database Schema:**
- Add `name_zh`, `blurb_zh`, `creator_name_zh` to Campaign model
- Add `name_zh` to Category model

**Vertex AI Translation Service:**
- New TranslatorService using Vertex AI Gemini 2.0 Flash
- Batch translation (10 campaigns per API call) to optimize costs
- Uses GCP startup credits from rescience-lab-465304 project
- Automatic translation during nightly crawl and backfill

**Category Localization:**
- All 14 root categories with Chinese names
- 12 subcategories with Chinese names

**Configuration:**
- Add VERTEX_AI_PROJECT_ID and VERTEX_AI_LOCATION env vars
- Service account credentials via GOOGLE_SERVICE_ACCOUNT_JSON
- AWS Secrets Manager integration ready

**Infrastructure:**
- GCP Project: rescience-lab-465304
- Service Account: kickwatch-translator@rescience-lab-465304.iam.gserviceaccount.com
- AWS Secrets: kickwatch-dev/google-service-account, kickwatch-dev/vertex-ai-config

**Technical Details:**
- Translator gracefully degrades if not configured (no blocking)
- Continues crawl even if translation fails
- Temperature=0.3 for consistent translations
- 500ms delay between batches to avoid rate limits

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@Jing-yilin Jing-yilin changed the title feat: 添加 Vertex AI 中文翻译支持 feat: Add Vertex AI Chinese translation support Feb 28, 2026
Jing-yilin and others added 2 commits February 28, 2026 16:21
Update iOS app to display translated Chinese content:

**CampaignDTO & CategoryDTO:**
- Add `name_zh`, `blurb_zh`, `creator_name_zh` fields
- Add computed properties `displayName`, `displayBlurb`, `displayCreatorName`
- Automatically fallback to English if Chinese translation unavailable

**Views Updated:**
- CampaignRowView: Use displayName/displayCreatorName
- CampaignDetailView: Use displayName/displayBlurb/displayCreatorName
- DiscoverView: Use displayName for categories
- WatchlistView: Updated DTO initialization

**User Experience:**
- Chinese content shows first when available
- Seamless fallback to English
- No code changes needed when backend adds translations

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add Vertex AI configuration to GitHub Actions workflow:
- VERTEX_AI_PROJECT_ID=rescience-lab-465304
- VERTEX_AI_LOCATION=us-central1
- GOOGLE_SERVICE_ACCOUNT_JSON from AWS Secrets Manager

This enables automatic Chinese translation during nightly crawls.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Contributor Author

@Jing-yilin Jing-yilin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. P1 - ios/KickWatch/Tests/MockAPIClient.swift:102

The new CampaignDTO initializer now requires name_zh, blurb_zh, and creator_name_zh, but the shared test factory was not updated. As a result the iOS test target does not compile anymore. Repro:

cd ios && xcodegen generate
xcodebuild test -project KickWatch.xcodeproj -scheme KickWatch -destination "platform=iOS Simulator,name=iPhone 17,OS=26.2" CODE_SIGNING_ALLOWED=NO DEVELOPMENT_TEAM=7Q28CBP3S5

That fails with missing arguments for parameters 'name_zh', 'blurb_zh', 'creator_name_zh' in call from MockAPIClient.swift.

  1. P1 - ios/KickWatch/Sources/Services/APIClient.swift:41-61, backend/internal/model/model.go:13-26,57

The Chinese-first fallback currently uses nil-coalescing (name_zh ?? name, etc.), but the backend model fields are plain Go strings. For untranslated rows JSON will contain empty strings, not null, and Swift decodes "" into a non-nil String?. That means existing campaigns/categories without a translation will prefer the empty localized field over the English one, so names can render blank and creator rows can become by until every record is backfilled. The fallback needs to treat empty strings as missing.

  1. P2 - backend/internal/service/cron.go:84-88

syncCategories() still only upserts name and parent_id. Because ListCategories() serves directly from the DB once any category rows exist, upgraded environments with already-seeded categories will never get name_zh populated, so the new localized category chips will not show up there.

Test results:

  • cd backend && go test ./...
  • iOS unit tests/build ❌ (compile failure above)

Fixes 3 issues identified in PR #42 code review:

1. MockAPIClient.swift: Add missing Chinese fields (name_zh, blurb_zh,
   creator_name_zh) to CampaignDTO test factory

2. APIClient.swift: Handle empty string fallback in computed properties.
   Backend emits empty strings for untranslated fields, so nil-coalescing
   alone is insufficient. Check for both nil AND empty string.

3. cron.go: Include name_zh in syncCategories() upsert columns so existing
   category rows get Chinese names on deployment

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@Jing-yilin Jing-yilin merged commit 71dd293 into develop Feb 28, 2026
2 checks passed
@Jing-yilin Jing-yilin deleted the feature/chinese-translation branch February 28, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant