Skip to content

Commit 7a585d6

Browse files
committed
feat(i18n): expand language support to PT-BR, DE, FR (#1009)
Add Portuguese (Brazil), German, and French to all i18n surfaces: - buddy_renderer.py: greetings, farewells, headers in 3 new languages - keyword.types.ts: SUPPORTED_LANGUAGES and LOCALIZED_KEYWORD_MAP - keywords.types.ts: SupportedLanguage type and LANGUAGE_OPTIONS Language count: 5 → 8
1 parent 8b009fc commit 7a585d6

3 files changed

Lines changed: 69 additions & 3 deletions

File tree

apps/mcp-server/src/keyword/keyword.types.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,21 @@ export const LOCALIZED_KEYWORD_MAP: Record<string, Mode> = {
159159
ACTUAR: 'ACT',
160160
EVALUAR: 'EVAL',
161161
AUTOMÁTICO: 'AUTO',
162+
// Portuguese (Português) - stored uppercase, matched case-insensitively
163+
PLANEJAR: 'PLAN',
164+
EXECUTAR: 'ACT',
165+
AVALIAR: 'EVAL',
166+
AUTOMÁTICO_PT: 'AUTO',
167+
// German (Deutsch) - stored uppercase, matched case-insensitively
168+
PLANEN: 'PLAN',
169+
AUSFÜHREN: 'ACT',
170+
BEWERTEN: 'EVAL',
171+
AUTOMATISCH: 'AUTO',
172+
// French (Français) - stored uppercase, matched case-insensitively
173+
PLANIFIER: 'PLAN',
174+
EXÉCUTER: 'ACT',
175+
ÉVALUER: 'EVAL',
176+
AUTOMATIQUE: 'AUTO',
162177
} as const;
163178

164179
/**
@@ -205,6 +220,21 @@ export const SUPPORTED_LANGUAGES: Record<string, LanguageDisplayInfo> = {
205220
nativeName: 'Español',
206221
description: 'AI responses will be in Spanish',
207222
},
223+
pt: {
224+
name: 'Portuguese',
225+
nativeName: 'Português',
226+
description: 'AI responses will be in Portuguese',
227+
},
228+
de: {
229+
name: 'German',
230+
nativeName: 'Deutsch',
231+
description: 'AI responses will be in German',
232+
},
233+
fr: {
234+
name: 'French',
235+
nativeName: 'Français',
236+
description: 'AI responses will be in French',
237+
},
208238
} as const;
209239

210240
/** Default language code */

apps/mcp-server/src/skill/i18n/keywords.types.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
/**
22
* Supported languages for skill keyword matching
33
*/
4-
export type SupportedLanguage = 'en' | 'ko' | 'ja' | 'zh' | 'es';
4+
export type SupportedLanguage = 'en' | 'ko' | 'ja' | 'zh' | 'es' | 'pt' | 'de' | 'fr';
55

66
/**
77
* Keywords for a single concept across all supported languages
88
*/
99
export type ConceptKeywords = {
10-
[lang in SupportedLanguage]: string[];
11-
};
10+
[lang in SupportedLanguage]?: string[];
11+
} & { en: string[] };
1212

1313
/**
1414
* Skill keyword configuration
@@ -31,4 +31,7 @@ export const LANGUAGE_OPTIONS: Record<SupportedLanguage, { useWordBoundary: bool
3131
ja: { useWordBoundary: false }, // 교착어
3232
zh: { useWordBoundary: false }, // 고립어
3333
es: { useWordBoundary: true },
34+
pt: { useWordBoundary: true },
35+
de: { useWordBoundary: true },
36+
fr: { useWordBoundary: true },
3437
};

packages/claude-code-plugin/hooks/lib/buddy_renderer.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,19 @@
2626
"ja": "\u3084\u3042\uff01\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u30b9\u30ad\u30e3\u30f3\u3057\u307e\u3059...",
2727
"zh": "\u55e8\uff01\u8ba9\u6211\u626b\u63cf\u4f60\u7684\u9879\u76ee...",
2828
"es": "\u00a1Hola! Voy a escanear tu proyecto...",
29+
"pt": "Oi! Vou escanear seu projeto...",
30+
"de": "Hallo! Ich scanne dein Projekt...",
31+
"fr": "Salut\u202f! Je scanne ton projet...",
2932
},
3033
"formal": {
3134
"en": "Scanning project environment...",
3235
"ko": "\ud504\ub85c\uc81d\ud2b8 \ud658\uacbd\uc744 \uc2a4\uce94\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4...",
3336
"ja": "\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u74b0\u5883\u3092\u30b9\u30ad\u30e3\u30f3\u4e2d...",
3437
"zh": "\u6b63\u5728\u626b\u63cf\u9879\u76ee\u73af\u5883...",
3538
"es": "Escaneando el entorno del proyecto...",
39+
"pt": "Escaneando o ambiente do projeto...",
40+
"de": "Projektumgebung wird gescannt...",
41+
"fr": "Analyse de l\u2019environnement du projet...",
3642
},
3743
}
3844

@@ -43,6 +49,9 @@
4349
"ja": {"recommendations": "\u30d0\u30c7\u30a3\u63a8\u85a6"},
4450
"zh": {"recommendations": "\u4f19\u4f34\u63a8\u8350"},
4551
"es": {"recommendations": "Recomendaciones de Buddy"},
52+
"pt": {"recommendations": "Recomenda\u00e7\u00f5es do Buddy"},
53+
"de": {"recommendations": "Buddy-Empfehlungen"},
54+
"fr": {"recommendations": "Recommandations de Buddy"},
4655
}
4756

4857
# Scan result labels by language
@@ -128,13 +137,19 @@ def get_buddy_config(config: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
128137
"ja": "\u304a\u304b\u3048\u308a\u306a\u3055\u3044\uff01\u524d\u56de\u306e\u7d9a\u304d\u3092\u3057\u307e\u3057\u3087\u3046\u304b\uff1f",
129138
"zh": "\u4f60\u56de\u6765\u4e86\uff01\u8981\u7ee7\u7eed\u4e0a\u6b21\u7684\u5de5\u4f5c\u5417\uff1f",
130139
"es": "\u00a1Has vuelto! \u00bfQuieres continuar donde lo dejaste?",
140+
"pt": "Voc\u00ea voltou! Quer continuar de onde parou?",
141+
"de": "Du bist zur\u00fcck! Weitermachen wo wir aufgeh\u00f6rt haben?",
142+
"fr": "Te revoil\u00e0\u202f! On reprend o\u00f9 on s\u2019\u00e9tait arr\u00eat\u00e9\u202f?",
131143
},
132144
"formal": {
133145
"en": "Welcome back. Resuming previous session context.",
134146
"ko": "\ub2e4\uc2dc \uc624\uc168\uc2b5\ub2c8\ub2e4. \uc774\uc804 \uc138\uc158 \ub9e5\ub77d\uc744 \ubd88\ub7ec\uc635\ub2c8\ub2e4.",
135147
"ja": "\u304a\u5e30\u308a\u306a\u3055\u3044\u3002\u524d\u56de\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u5fa9\u5143\u3057\u307e\u3059\u3002",
136148
"zh": "\u6b22\u8fce\u56de\u6765\u3002\u6b63\u5728\u6062\u590d\u4e0a\u6b21\u7684\u4f1a\u8bdd\u3002",
137149
"es": "Bienvenido de vuelta. Restaurando el contexto anterior.",
150+
"pt": "Bem-vindo de volta. Restaurando o contexto anterior.",
151+
"de": "Willkommen zur\u00fcck. Vorheriger Sitzungskontext wird wiederhergestellt.",
152+
"fr": "Bon retour. Restauration du contexte pr\u00e9c\u00e9dent.",
138153
},
139154
}
140155

@@ -145,6 +160,9 @@ def get_buddy_config(config: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
145160
"ja": {"last_session": "\u524d\u56de\u306e\u30bb\u30c3\u30b7\u30e7\u30f3", "pending": "\u672a\u5b8c\u4e86\u306e\u4f5c\u696d"},
146161
"zh": {"last_session": "\u4e0a\u6b21\u4f1a\u8bdd\u6458\u8981", "pending": "\u672a\u5b8c\u6210\u5de5\u4f5c"},
147162
"es": {"last_session": "Resumen de sesi\u00f3n anterior", "pending": "Trabajo pendiente"},
163+
"pt": {"last_session": "Resumo da sess\u00e3o anterior", "pending": "Trabalho pendente"},
164+
"de": {"last_session": "Letzte Sitzungs\u00fcbersicht", "pending": "Ausstehende Arbeit"},
165+
"fr": {"last_session": "R\u00e9sum\u00e9 de la derni\u00e8re session", "pending": "Travail en attente"},
148166
}
149167

150168
# Farewell greetings by tone and language (stop hook)
@@ -155,13 +173,19 @@ def get_buddy_config(config: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
155173
"ja": "\u304a\u75b2\u308c\u69d8\uff01",
156174
"zh": "\u4eca\u5929\u8f9b\u82e6\u4e86\uff01",
157175
"es": "\u00a1Buen trabajo hoy!",
176+
"pt": "\u00d3timo trabalho hoje!",
177+
"de": "Gute Arbeit heute!",
178+
"fr": "Bon travail aujourd\u2019hui\u202f!",
158179
},
159180
"formal": {
160181
"en": "Session complete.",
161182
"ko": "\uc138\uc158\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.",
162183
"ja": "\u30bb\u30c3\u30b7\u30e7\u30f3\u5b8c\u4e86\u3002",
163184
"zh": "\u4f1a\u8bdd\u5b8c\u6210\u3002",
164185
"es": "Sesi\u00f3n completada.",
186+
"pt": "Sess\u00e3o conclu\u00edda.",
187+
"de": "Sitzung abgeschlossen.",
188+
"fr": "Session termin\u00e9e.",
165189
},
166190
}
167191

@@ -172,13 +196,19 @@ def get_buddy_config(config: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
172196
"ja": "\u307e\u305f\u6b21\u56de\uff01",
173197
"zh": "\u4e0b\u6b21\u518d\u89c1\uff01",
174198
"es": "\u00a1Hasta la pr\u00f3xima!",
199+
"pt": "At\u00e9 a pr\u00f3xima!",
200+
"de": "Bis zum n\u00e4chsten Mal!",
201+
"fr": "\u00c0 la prochaine\u202f!",
175202
},
176203
"formal": {
177204
"en": "Session ended.",
178205
"ko": "\uc138\uc158\uc774 \uc885\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.",
179206
"ja": "\u30bb\u30c3\u30b7\u30e7\u30f3\u7d42\u4e86\u3002",
180207
"zh": "\u4f1a\u8bdd\u5df2\u7ed3\u675f\u3002",
181208
"es": "Sesi\u00f3n finalizada.",
209+
"pt": "Sess\u00e3o encerrada.",
210+
"de": "Sitzung beendet.",
211+
"fr": "Session termin\u00e9e.",
182212
},
183213
}
184214

@@ -188,6 +218,9 @@ def get_buddy_config(config: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
188218
"ja": {"summary": "\u30bb\u30c3\u30b7\u30e7\u30f3\u6982\u8981", "agents": "\u30a2\u30af\u30c6\u30a3\u30d6\u30a8\u30fc\u30b8\u30a7\u30f3\u30c8"},
189219
"zh": {"summary": "\u4f1a\u8bdd\u6458\u8981", "agents": "\u6d3b\u8dc3\u4ee3\u7406"},
190220
"es": {"summary": "Resumen de sesi\u00f3n", "agents": "Agentes activos"},
221+
"pt": {"summary": "Resumo da sess\u00e3o", "agents": "Agentes ativos"},
222+
"de": {"summary": "Sitzungs\u00fcbersicht", "agents": "Aktive Agenten"},
223+
"fr": {"summary": "R\u00e9sum\u00e9 de session", "agents": "Agents actifs"},
191224
}
192225

193226

0 commit comments

Comments
 (0)