- Create Economist SubmissionTracking package correctly: * mainArticle = full blog post content * coverLetter = 216-word SIR— letter * Links to blog post via blogPostId - Archive 'Letter to The Economist' from blog posts (it's the cover letter) - Fix date display on article cards (use published_at) - Target publication already displaying via blue badge Database changes: - Make blogPostId optional in SubmissionTracking model - Economist package ID: 68fa85ae49d4900e7f2ecd83 - Le Monde package ID: 68fa2abd2e6acd5691932150 Next: Enhanced modal with tabs, validation, export 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
5.2 KiB
5.2 KiB
Translation Approach for Task 19: Te Reo Māori & Multilanguage Support
Date: October 12, 2025 Status: Planning - To be implemented after Task 12 (API Documentation) Priority: CRITICAL (Values - Te Tiriti commitment)
Translation Service: DeepL
Decision: Use DeepL API for translation services instead of i18next manual translations
Deployment Architecture
Local Development (Port 9000):
- DeepL API integration in Node.js
- Local environment variable:
DEEPL_API_KEY - Translation caching in MongoDB
Production Server (vps-93a693da.vps.ovh.net):
- DeepL API integration deployed
- Secure environment variable configuration
- Production translation cache
Implementation Plan
1. DeepL API Integration
// Example integration approach
const deepl = require('deepl-node');
const translator = new deepl.Translator(process.env.DEEPL_API_KEY);
async function translateContent(text, targetLang) {
const result = await translator.translateText(text, null, targetLang);
return result.text;
}
2. Language Selector UI
- Location: Navigation bar (all pages)
- Languages: English (en), Te Reo Māori (mi)
- Storage: Browser localStorage + cookie
- Behavior: Persist selection across sessions
3. Translation Cache
MongoDB Collection: translations
{
source_text: String,
source_lang: String,
target_lang: String,
translated_text: String,
verified: Boolean,
created_at: Date,
updated_at: Date
}
Benefits:
- Reduces API calls
- Faster page loads
- Cost optimization
- Human verification workflow
4. Priority Pages for Translation
Phase 1 (Task 19):
- Homepage (index.html)
- About/Values page (about.html)
- Core Framework Documentation
Phase 2 (Future):
- All audience paths (researcher, implementer, advocate)
- Interactive demos
- Blog posts
- API documentation
5. Māori Language Consultation
Critical: Despite using DeepL, Māori language consultation is REQUIRED
Why:
- Cultural appropriateness review
- Technical term accuracy
- Idiomatic expressions
- Values alignment
Process:
- DeepL generates initial translation
- Store in database as
verified: false - Submit to Māori language consultant
- Update with corrections
- Mark as
verified: true
6. Rate Limiting & Cost Management
DeepL API Limits:
- Free tier: 500,000 characters/month
- Pro tier: Pay per character
Strategy:
- Cache all translations
- Batch translation requests
- Monitor character usage
- Set monthly budget alerts
Technical Implementation
Routes
// POST /api/translate
// Translate text to specified language
router.post('/translate', async (req, res) => {
const { text, targetLang } = req.body;
// Check cache first
const cached = await Translation.findOne({
source_text: text,
target_lang: targetLang,
verified: true
});
if (cached) {
return res.json({ translation: cached.translated_text });
}
// Call DeepL API
const translation = await translateContent(text, targetLang);
// Store in cache
await Translation.create({
source_text: text,
source_lang: 'en',
target_lang: targetLang,
translated_text: translation,
verified: false
});
res.json({ translation });
});
Frontend Integration
// Language selector component
class LanguageSelector {
constructor() {
this.currentLang = localStorage.getItem('lang') || 'en';
}
async switchLanguage(lang) {
localStorage.setItem('lang', lang);
await this.translatePage(lang);
}
async translatePage(lang) {
if (lang === 'en') {
// Reload original content
location.reload();
return;
}
// Translate all translatable elements
const elements = document.querySelectorAll('[data-translate]');
for (const el of elements) {
const originalText = el.textContent;
const translation = await this.translate(originalText, lang);
el.textContent = translation;
}
}
}
Configuration
Environment Variables
Development (.env):
DEEPL_API_KEY=your_dev_key
DEEPL_API_FREE_TIER=true
TRANSLATION_CACHE_ENABLED=true
Production (remote):
DEEPL_API_KEY=your_prod_key
DEEPL_API_FREE_TIER=false
TRANSLATION_CACHE_ENABLED=true
TRANSLATION_VERIFICATION_REQUIRED=true
Success Criteria
- DeepL API integrated on both dev and production
- Language selector functional in navigation
- Translation caching working
- Homepage, About, Core Docs translated to Te Reo Māori
- Māori language consultant review completed
- All translations marked as verified
- User preference persists across sessions
- Performance: <500ms translation load time (cached)
Notes
- Cost Estimate: Homepage + About + Core Docs ≈ 50,000 characters
- DeepL Free Tier: Sufficient for Phase 1
- Future: Add more languages (Samoan, Tongan, Cook Islands Māori, etc.)
- Accessibility: Ensure
langattribute updated on<html>tag - SEO: Consider separate URLs vs. client-side switching
To Be Implemented: After Task 12 (API Documentation) completion Dependencies: DeepL API account, MongoDB translations collection, Māori language consultant Timeline: 5-7 days estimated