Skip to content

Commit 76a0043

Browse files
feat(i18n): add Spanish language support (#272)
Add Spanish locale registration, UI language selection, translated i18n strings, and Spanish templates/examples. Also remove internal .claude scheduled task files from the repository and extend locale error-code coverage. Signed-off-by: hqhq1025 <1506751656@qq.com>
1 parent b01c24e commit 76a0043

17 files changed

Lines changed: 1340 additions & 14 deletions

File tree

.changeset/add-spanish-support.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@open-codesign/desktop': minor
3+
'@open-codesign/i18n': patch
4+
'@open-codesign/templates': patch
5+
---
6+
7+
feat(i18n): add full Spanish (ES) language support
8+
9+
Added comprehensive Spanish (Neutral Latin American) localization.
10+
- Translated 889 core i18n keys in `packages/i18n`.
11+
- Translated dashboard templates and examples catalog in `packages/templates`.
12+
- Registered 'es' locale in the UI (LanguageToggle and Settings).
13+
- Updated IPC handlers in `apps/desktop` to support Spanish locale persistence.

.claude/scheduled_tasks.json

Lines changed: 0 additions & 3 deletions
This file was deleted.

.claude/scheduled_tasks.lock

Lines changed: 0 additions & 1 deletion
This file was deleted.

apps/desktop/src/main/locale-ipc.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,13 @@ export function registerLocaleIpc(): void {
8080
lower.startsWith('zh-hans') ||
8181
lower === 'zh-cn' ||
8282
lower === 'zh_cn' ||
83-
lower.startsWith('en');
83+
lower.startsWith('en') ||
84+
lower === 'pt-br' ||
85+
lower.startsWith('pt-') ||
86+
lower === 'pt_br' ||
87+
lower === 'es' ||
88+
lower.startsWith('es-') ||
89+
lower === 'es_';
8490
if (!recognized) {
8591
throw new Error(
8692
`locale:set received unsupported locale "${raw}"; expected one of: ${availableLocales.join(', ')}`,

apps/desktop/src/renderer/src/components/LanguageToggle.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useEffect, useState } from 'react';
66

77
const noDragStyle = { WebkitAppRegion: 'no-drag' } as CSSProperties;
88

9-
const LOCALE_CYCLE: Locale[] = ['en', 'zh-CN', 'pt-BR'];
9+
const LOCALE_CYCLE: Locale[] = ['en', 'es', 'pt-BR', 'zh-CN'];
1010

1111
function nextLocale(locale: Locale): Locale {
1212
const i = LOCALE_CYCLE.indexOf(locale);
@@ -16,6 +16,7 @@ function nextLocale(locale: Locale): Locale {
1616
function localeLabel(locale: Locale): string {
1717
if (locale === 'zh-CN') return 'ZH';
1818
if (locale === 'pt-BR') return 'PT';
19+
if (locale === 'es') return 'ES';
1920
return 'EN';
2021
}
2122

apps/desktop/src/renderer/src/components/Settings.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2153,8 +2153,9 @@ function AppearanceTab() {
21532153
onChange={handleLocaleChange}
21542154
options={[
21552155
{ value: 'en', label: t('settings.appearance.langEn') },
2156-
{ value: 'zh-CN', label: t('settings.appearance.langZhCN') },
2156+
{ value: 'es', label: t('settings.appearance.langEs') },
21572157
{ value: 'pt-BR', label: t('settings.appearance.langPtBR') },
2158+
{ value: 'zh-CN', label: t('settings.appearance.langZhCN') },
21582159
]}
21592160
/>
21602161
</Row>

packages/i18n/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
"exports": {
99
".": "./src/index.ts",
1010
"./locales/en": "./src/locales/en.json",
11+
"./locales/es": "./src/locales/es.json",
12+
"./locales/pt-BR": "./src/locales/pt-BR.json",
1113
"./locales/zh-CN": "./src/locales/zh-CN.json"
1214
},
1315
"scripts": {

packages/i18n/src/err-codes.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import { ERROR_CODES } from '@open-codesign/shared';
22
import { describe, expect, it } from 'vitest';
33
import en from './locales/en.json';
4+
import es from './locales/es.json';
5+
import ptBR from './locales/pt-BR.json';
46
import zhCN from './locales/zh-CN.json';
57

68
describe('error-code i18n coverage', () => {
79
const locales = [
810
{ name: 'en', data: en as unknown as { err?: Record<string, string> } },
911
{ name: 'zh-CN', data: zhCN as unknown as { err?: Record<string, string> } },
12+
{ name: 'pt-BR', data: ptBR as unknown as { err?: Record<string, string> } },
13+
{ name: 'es', data: es as unknown as { err?: Record<string, string> } },
1014
];
1115

1216
for (const locale of locales) {

packages/i18n/src/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,20 @@ import i18next from 'i18next';
1616
import { useCallback } from 'react';
1717
import { initReactI18next, useTranslation } from 'react-i18next';
1818
import en from './locales/en.json';
19+
import es from './locales/es.json';
1920
import ptBR from './locales/pt-BR.json';
2021
import zhCN from './locales/zh-CN.json';
2122

22-
export const availableLocales = ['en', 'zh-CN', 'pt-BR'] as const;
23+
export const availableLocales = ['en', 'es', 'pt-BR', 'zh-CN'] as const;
2324
export type Locale = (typeof availableLocales)[number];
2425

2526
const DEFAULT_LOCALE: Locale = 'en';
2627

2728
const resources = {
2829
en: { translation: en },
29-
'zh-CN': { translation: zhCN },
30+
es: { translation: es },
3031
'pt-BR': { translation: ptBR },
32+
'zh-CN': { translation: zhCN },
3133
} as const;
3234

3335
export function isSupportedLocale(value: string | undefined | null): value is Locale {
@@ -45,6 +47,9 @@ export function normalizeLocale(value: string | undefined | null): Locale {
4547
if (lower === 'pt-br' || lower === 'pt_br' || lower === 'pt' || lower.startsWith('pt-')) {
4648
return 'pt-BR';
4749
}
50+
if (lower === 'es' || lower.startsWith('es-') || lower === 'es_') {
51+
return 'es';
52+
}
4853
if (lower.startsWith('en')) return 'en';
4954
console.warn(
5055
`[i18n] unsupported locale "${value}", falling back to "${DEFAULT_LOCALE}". ` +

packages/i18n/src/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,8 @@
397397
"languageLoadFailed": "Failed to load language",
398398
"langEn": "English",
399399
"langZhCN": "中文 (简体)",
400-
"langPtBR": "Português (BR)"
400+
"langPtBR": "Português (BR)",
401+
"langEs": "Español"
401402
},
402403
"language": {
403404
"label": "Language",

0 commit comments

Comments
 (0)