You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(service-settings): complete zh-CN coverage for auth/sms/ai settings (objectui#2851 P1) (#3598)
* fix(service-settings): complete zh-CN coverage for auth/sms/ai settings
The auth, sms and ai manifests grew new groups and fields (breach/complexity/
history/expiry password policy, anti-abuse, MFA, extra session controls,
network allow-list; the whole SMS Delivery namespace; DeepSeek/DashScope/
Cloudflare/SiliconFlow/OpenRouter providers + conversation-title options) but
the zh-CN bundle wasn't updated, so those settings rendered English under a
Chinese UI (objectui#2851 P1).
- Fill every missing zh-CN group title + field label/help for auth, sms, ai.
- Add a coverage guard test that pins zh-CN to full title/group/key coverage
of every built-in settings manifest (option labels excluded — several are
codes/format specimens that must not be translated).
localization option labels (timezones/currencies/format specimens) remain a
tracked follow-up; ja-JP / es-ES parity likewise.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(service-settings): zh-CN option labels + ja-JP/es-ES parity (objectui#2851 P1)
Follow-up to the zh-CN auth/sms/ai fix:
- zh-CN: translate the remaining localization option labels (timezone,
locale, date/number format, currency, fiscal-year-start) — the settings
bundle is now 100% covered, options included.
- ja-JP / es-ES: bring both to full structural parity — extend auth (policy /
anti-abuse / MFA / extra session controls / network) and ai (DeepSeek /
DashScope / Cloudflare / SiliconFlow / OpenRouter + conversation titles),
and add the previously-missing sms, company and localization namespaces.
- Generalize the coverage guard to all three shipped non-English locales
(renamed zh-CN.coverage.test.ts → settings-translation-coverage.test.ts).
Package suite: 12 files / 175 tests pass (31 coverage assertions).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
email_password_enabled: {label: 'Habilitar inicio de sesión con correo/contraseña'},
87
107
signup_enabled: {label: 'Permitir registro de autoservicio'},
88
108
require_email_verification: {label: 'Requerir verificación de correo'},
109
+
password_min_length: {label: 'Longitud mínima de contraseña'},
110
+
password_max_length: {label: 'Longitud máxima de contraseña',help: 'Un límite superior protege frente a la denegación de servicio por el hasheo de contraseñas muy largas.'},
111
+
password_reject_breached: {
112
+
label: 'Rechazar contraseñas filtradas',
113
+
help: 'Bloquea contraseñas presentes en corpus públicos de filtraciones mediante Have I Been Pwned (comprobación de rango con k-anonimato; la contraseña nunca se envía completa).',
114
+
},
115
+
password_require_complexity: {
116
+
label: 'Requerir contraseñas complejas',
117
+
help: 'Exige que las contraseñas combinen clases de caracteres (mayúsculas, minúsculas, dígitos, símbolos) en el registro y al cambiar/restablecer la contraseña.',
118
+
},
119
+
password_min_classes: {
120
+
label: 'Clases de caracteres mínimas',
121
+
help: 'Cuántas de las cuatro clases (mayúscula / minúscula / dígito / símbolo) debe incluir una contraseña.',
122
+
},
123
+
password_history_count: {
124
+
label: 'Historial de contraseñas (sin reutilización)',
125
+
help: 'Impide reutilizar este número de contraseñas anteriores al cambiar/restablecer. 0 desactiva la comprobación.',
126
+
},
127
+
password_expiry_days: {
128
+
label: 'Caducidad de contraseña (días)',
129
+
help: 'Fuerza un cambio de contraseña tras este número de días. 0 desactiva la caducidad. Mientras está caducada, el usuario no puede acceder a los datos hasta que la cambie.',
130
+
},
131
+
lockout_threshold: {
132
+
label: 'Umbral de bloqueo de cuenta',
133
+
help: 'Bloquea una cuenta tras este número de inicios de sesión fallidos consecutivos. 0 desactiva el bloqueo. Mientras está bloqueada, el inicio de sesión se rechaza incluso con la contraseña correcta.',
134
+
},
135
+
lockout_duration_minutes: {
136
+
label: 'Duración del bloqueo (minutos)',
137
+
help: 'Cuánto permanece bloqueada una cuenta una vez superado el umbral.',
138
+
},
139
+
rate_limit_max: {
140
+
label: 'Límite de tasa de autenticación: máx. solicitudes',
141
+
help: 'Máximo de solicitudes por IP y ventana a los endpoints de inicio de sesión / registro / restablecimiento de contraseña.',
142
+
},
143
+
rate_limit_window_seconds: {
144
+
label: 'Límite de tasa de autenticación: ventana (segundos)',
145
+
help: 'Ventana deslizante durante la cual se cuenta el tope de solicitudes anterior.',
146
+
},
147
+
mfa_required: {
148
+
label: 'Requerir autenticación multifactor',
149
+
help: 'Los usuarios sin un autenticador registrado quedan bloqueados del acceso a los datos al terminar su periodo de gracia. Activarlo también habilita la función de dos factores para que los usuarios puedan registrarse.',
150
+
},
151
+
mfa_grace_period_days: {
152
+
label: 'Periodo de gracia de MFA (días)',
153
+
help: 'Cuánto pueden aplazar el registro los usuarios antes del bloqueo definitivo. 0 bloquea de inmediato.',
154
+
},
155
+
session_expiry_days: {label: 'Duración de la sesión (días)',help: 'Una sesión caduca este número de días después del inicio de sesión.'},
156
+
session_refresh_days: {label: 'Umbral de renovación (días)',help: 'Una sesión activa se extiende cuando es más antigua que esto.'},
157
+
session_idle_timeout_minutes: {
158
+
label: 'Tiempo de inactividad (minutos)',
159
+
help: 'Cierra la sesión del usuario tras este número de minutos de inactividad. 0 desactiva.',
160
+
},
161
+
session_absolute_max_hours: {
162
+
label: 'Duración absoluta de la sesión (horas)',
163
+
help: 'Fuerza una reautenticación este número de horas después del inicio de sesión, independientemente de la actividad. 0 desactiva.',
164
+
},
165
+
max_concurrent_sessions_per_user: {
166
+
label: 'Máx. sesiones simultáneas por usuario',
167
+
help: 'Limita las sesiones iniciadas simultáneas por usuario; las más antiguas se cierran al superar el límite. 0 = ilimitado.',
168
+
},
169
+
allowed_ip_ranges: {
170
+
label: 'Rangos de IP permitidos',
171
+
help: 'Rangos CIDR o IP exactas (una por línea o separadas por comas), p. ej. 203.0.113.0/24. Cuando se define, se rechaza el inicio de sesión desde fuera de estos rangos. Vacío = sin restricción. Requiere un proxy de confianza que defina X-Forwarded-For.',
172
+
},
89
173
google_enabled: {
90
174
label: 'Habilitar inicio de sesión con Google',
91
175
help: 'Requiere un ID de cliente y un secreto de OAuth de Google desde Google Cloud Console.',
aliyun_sign_name: {label: 'Nombre de firma (短信签名)'},
204
+
aliyun_template_code: {
205
+
label: 'Código de plantilla predeterminado',
206
+
help: 'Se usa cuando un envío no lleva una plantilla explícita. Una plantilla genérica con una sola variable ${content} permite enviar SMS de notificación genéricos.',
207
+
},
208
+
twilio_account_sid: {label: 'Account SID'},
209
+
twilio_auth_token: {label: 'Token de autenticación'},
210
+
twilio_from_number: {
211
+
label: 'Número de origen',
212
+
help: 'Remitente en formato E.164, p. ej. +15005550006. Se necesita esto o un Messaging Service SID.',
213
+
},
214
+
twilio_messaging_service_sid: {label: 'Messaging Service SID'},
215
+
},
216
+
actions: {test: {label: 'Enviar SMS de prueba'}},
217
+
},
218
+
219
+
company: {
220
+
title: 'Empresa',
221
+
description: 'Identidad de la entidad legal: nombre registrado, dirección, identificadores fiscales y contacto principal.',
222
+
groups: {
223
+
identity: {title: 'Identidad'},
224
+
address: {title: 'Domicilio registrado'},
225
+
contact: {title: 'Contacto'},
226
+
},
227
+
keys: {
228
+
legal_name: {label: 'Razón social',help: 'Nombre legal registrado de la organización (puede diferir del nombre del espacio de trabajo).'},
229
+
registration_number: {label: 'Número de registro',help: 'Número de registro / constitución de la empresa (p. ej. EIN, n.º de sociedad).'},
230
+
tax_id: {label: 'ID fiscal / IVA',help: 'Identificador fiscal que aparece en las facturas (p. ej. IVA, GST, ABN).'},
primary_contact_name: {label: 'Nombre del contacto principal'},
240
+
primary_contact_email: {label: 'Correo del contacto principal',help: 'Ejemplo: ops@example.com'},
241
+
},
242
+
},
243
+
244
+
localization: {
245
+
title: 'Localización',
246
+
description: 'Zona horaria, idioma, moneda y formatos de fecha/número predeterminados.',
247
+
groups: {
248
+
region: {title: 'Región'},
249
+
formats: {title: 'Formatos'},
250
+
finance: {title: 'Finanzas'},
251
+
},
252
+
keys: {
253
+
timezone: {label: 'Zona horaria predeterminada',help: 'Zona IANA usada para resolver today()/daysFromNow, los buckets de fecha de analítica y las fechas/horas renderizadas.'},
254
+
locale: {label: 'Idioma predeterminado',help: 'Configuración regional BCP-47 para los catálogos de mensajes y el formato de números/fechas.'},
255
+
default_country: {label: 'País predeterminado',help: 'Código ISO 3166-1 alfa-2 (p. ej. US, GB, CN). Se usa para los valores por defecto de dirección y teléfono.'},
256
+
date_format: {label: 'Formato de fecha'},
257
+
time_format: {label: 'Formato de hora'},
258
+
number_format: {label: 'Formato de número',help: 'Separadores de miles y decimales para los números mostrados.'},
259
+
first_day_of_week: {label: 'Primer día de la semana',help: 'Ancla los buckets de analítica semanal y las cuadrículas de calendario.'},
260
+
currency: {label: 'Moneda predeterminada',help: 'Código ISO 4217 aplicado cuando un campo de moneda no indica la suya.'},
261
+
fiscal_year_start: {label: 'Inicio del año fiscal',help: 'Primer mes del año fiscal: determina «este trimestre / año fiscal» en los informes.'},
262
+
},
263
+
},
264
+
104
265
feature_flags: {
105
266
title: 'Indicadores de función',
106
267
description: 'Activa funciones experimentales y en beta para este espacio de trabajo.',
deepseek: {title: 'DeepSeek',description: 'API compatible con OpenAI en https://api.deepseek.com. La Base URL se rellena automáticamente.'},
336
+
dashscope: {title: '阿里通义 DashScope',description: 'Endpoint compatible con OpenAI en dashscope.aliyuncs.com/compatible-mode/v1. La Base URL se rellena automáticamente.'},
337
+
cloudflare: {title: 'Cloudflare AI Gateway',description: 'Proxy de modelos compatibles con OpenAI a través de Cloudflare AI Gateway.'},
338
+
siliconflow: {title: '硅基流动 SiliconFlow',description: 'Endpoint compatible con OpenAI en api.siliconflow.cn/v1. La Base URL se rellena automáticamente.'},
339
+
openrouter: {title: 'OpenRouter',description: 'Enrutador multiproveedor en openrouter.ai/api/v1. La Base URL se rellena automáticamente.'},
340
+
titles: {title: 'Títulos de conversación',description: 'Genera automáticamente un título de resumen breve para las conversaciones nuevas.'},
174
341
defaults: {title: 'Valores predeterminados de generación',
175
342
description: 'Se aplican cuando un agente o una solicitud de chat no especifica su propio valor.'},
title_generation_enabled: {label: 'Resumir automáticamente los títulos de conversación'},
394
+
title_max_length: {label: 'Longitud máx. del título (caracteres)',help: 'Tope estricto del título generado. Todo lo que exceda se trunca en el servidor.'},
0 commit comments