Skip to content

Commit fde01f5

Browse files
committed
refactor(web): split i18n resources and localize inspector text
1 parent ecd1920 commit fde01f5

28 files changed

+4618
-4564
lines changed

apps/web/src/editor/features/design/inspector/classProtocol/ClassProtocolEditor.tsx

Lines changed: 88 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export function ClassProtocolEditor({
5555
mountedCssEntries = [],
5656
onOpenMountedCss,
5757
}: ClassProtocolEditorProps) {
58-
const { i18n, t } = useTranslation();
58+
const { t } = useTranslation('blueprint');
5959
const [draft, setDraft] = useState('');
6060
const [activeSuggestionIndex, setActiveSuggestionIndex] = useState(0);
6161
const { mode, inlineDraft, nextMode, setMode, setInlineDraft } =
@@ -124,15 +124,21 @@ export function ClassProtocolEditor({
124124
const getSuggestionLabel = (suggestion: ClassSuggestion) => {
125125
if (suggestion.kind === 'hint' && suggestion.hint) {
126126
if (suggestion.hint.type === 'arbitrary-length-template') {
127-
const templateText = i18n.resolvedLanguage?.startsWith('zh')
128-
? '带单位长度'
129-
: 'length with unit';
127+
const templateText = t(
128+
'inspector.fields.className.templates.lengthWithUnit',
129+
{
130+
defaultValue: 'length with unit',
131+
}
132+
);
130133
return `${suggestion.hint.prefix}-[${templateText}]`;
131134
}
132135
if (suggestion.hint.type === 'color-shade-template') {
133-
const templateText = i18n.resolvedLanguage?.startsWith('zh')
134-
? '颜色深度'
135-
: 'color shade';
136+
const templateText = t(
137+
'inspector.fields.className.templates.colorShade',
138+
{
139+
defaultValue: 'color shade',
140+
}
141+
);
136142
return `${suggestion.hint.prefix}-[${templateText}]`;
137143
}
138144
}
@@ -142,28 +148,34 @@ export function ClassProtocolEditor({
142148
const getSuggestionDetail = (suggestion: ClassSuggestion) => {
143149
if (suggestion.kind === 'hint' && suggestion.hint) {
144150
if (suggestion.hint.type === 'arbitrary-length-template') {
145-
const defaultValue = i18n.resolvedLanguage?.startsWith('zh')
146-
? '例如 {{exampleA}}, {{exampleB}}'
147-
: 'Example: {{exampleA}}, {{exampleB}}';
148-
return t(
149-
'blueprint.inspector.fields.className.hints.arbitraryLengthTemplate',
150-
{
151-
defaultValue,
152-
exampleA: `${suggestion.hint.prefix}-[12px]`,
153-
exampleB: `${suggestion.hint.prefix}-[1rem]`,
154-
}
155-
);
151+
const exampleA = `${suggestion.hint.prefix}-[12px]`;
152+
const exampleB = `${suggestion.hint.prefix}-[1rem]`;
153+
return t('inspector.fields.className.hints.arbitraryLengthTemplate', {
154+
defaultValue: `Example: ${exampleA}, ${exampleB}`,
155+
exampleA,
156+
exampleB,
157+
});
156158
}
157159
if (suggestion.hint.type === 'color-shade-template') {
158-
const defaultValue = i18n.resolvedLanguage?.startsWith('zh')
159-
? '例如 {{example}}'
160-
: 'Example: {{example}}';
161-
return t('blueprint.inspector.fields.className.hints.colorShade', {
162-
defaultValue,
163-
example: suggestion.hint.example,
160+
const example = suggestion.hint.example;
161+
return t('inspector.fields.className.hints.colorShade', {
162+
defaultValue: `Example: ${example}`,
163+
example,
164164
});
165165
}
166166
}
167+
const inferredFromScaleMatch = suggestion.detail?.match(
168+
/^Inferred from (-?(?:\d+|\d*\.\d+))px using default (-?(?:\d+|\d*\.\d+))px scale$/
169+
);
170+
if (inferredFromScaleMatch) {
171+
const amount = inferredFromScaleMatch[1];
172+
const base = inferredFromScaleMatch[2];
173+
return t('inspector.fields.className.hints.inferredFromScale', {
174+
defaultValue: `Inferred from ${amount}px using default ${base}px scale`,
175+
amount,
176+
base,
177+
});
178+
}
167179
return suggestion.detail;
168180
};
169181

@@ -182,6 +194,14 @@ export function ClassProtocolEditor({
182194
const emitTokens = (nextTokens: string[]) => {
183195
onChange(toClassNameValue(nextTokens));
184196
};
197+
const nextModeLabel =
198+
nextMode === 'token'
199+
? t('inspector.fields.className.modes.token', {
200+
defaultValue: 'token',
201+
})
202+
: t('inspector.fields.className.modes.inline', {
203+
defaultValue: 'inline',
204+
});
185205

186206
const commitToken = (rawToken: string) => {
187207
const token = rawToken.trim();
@@ -249,8 +269,13 @@ export function ClassProtocolEditor({
249269
title={
250270
isOverridden
251271
? overriddenBy
252-
? `Overridden by "${overriddenBy}"`
253-
: 'Overridden by another class'
272+
? t('inspector.fields.className.overriddenBy', {
273+
defaultValue: `Overridden by "${overriddenBy}"`,
274+
token: overriddenBy,
275+
})
276+
: t('inspector.fields.className.overriddenByUnknown', {
277+
defaultValue: 'Overridden by another class',
278+
})
254279
: undefined
255280
}
256281
>
@@ -301,8 +326,20 @@ export function ClassProtocolEditor({
301326
})
302327
}
303328
data-testid={`inspector-classname-open-mounted-css-${index}`}
304-
aria-label={`Open mounted CSS for ${token}`}
305-
title={`Open mounted CSS (${mountedCssTarget.path})`}
329+
aria-label={t(
330+
'inspector.fields.className.actions.openMountedCssFor',
331+
{
332+
defaultValue: `Open mounted CSS for ${token}`,
333+
token,
334+
}
335+
)}
336+
title={t(
337+
'inspector.fields.className.actions.openMountedCssPath',
338+
{
339+
defaultValue: `Open mounted CSS (${mountedCssTarget.path})`,
340+
path: mountedCssTarget.path,
341+
}
342+
)}
306343
>
307344
<ExternalLink size={11} />
308345
</button>
@@ -312,7 +349,13 @@ export function ClassProtocolEditor({
312349
className="inline-flex h-4 w-4 items-center justify-center rounded-sm border-0 bg-transparent p-0 text-(--color-6) hover:text-(--color-9)"
313350
onClick={() => removeTokenAt(index)}
314351
data-testid={`inspector-classname-token-remove-${index}`}
315-
aria-label={`Remove ${token}`}
352+
aria-label={t(
353+
'inspector.fields.className.actions.removeToken',
354+
{
355+
defaultValue: `Remove ${token}`,
356+
token,
357+
}
358+
)}
316359
>
317360
<X size={12} />
318361
</button>
@@ -384,8 +427,14 @@ export function ClassProtocolEditor({
384427
className="absolute right-1.5 top-1.5 inline-flex h-5 w-5 items-center justify-center rounded-md border-0 bg-transparent text-(--color-6) hover:text-(--color-9)"
385428
onClick={() => setMode(nextMode)}
386429
data-testid="inspector-classname-mode-toggle"
387-
aria-label={`Switch to ${nextMode} mode`}
388-
title={`Switch to ${nextMode} mode`}
430+
aria-label={t('inspector.fields.className.actions.switchMode', {
431+
defaultValue: `Switch to ${nextModeLabel} mode`,
432+
mode: nextModeLabel,
433+
})}
434+
title={t('inspector.fields.className.actions.switchMode', {
435+
defaultValue: `Switch to ${nextModeLabel} mode`,
436+
mode: nextModeLabel,
437+
})}
389438
>
390439
<ModeIcon size={12} />
391440
</button>
@@ -456,8 +505,14 @@ export function ClassProtocolEditor({
456505
className="absolute right-1 top-1 inline-flex h-5 w-5 items-center justify-center rounded-md border-0 bg-transparent text-(--color-6) hover:text-(--color-9)"
457506
onClick={() => setMode(nextMode)}
458507
data-testid="inspector-classname-mode-toggle"
459-
aria-label={`Switch to ${nextMode} mode`}
460-
title={`Switch to ${nextMode} mode`}
508+
aria-label={t('inspector.fields.className.actions.switchMode', {
509+
defaultValue: `Switch to ${nextModeLabel} mode`,
510+
mode: nextModeLabel,
511+
})}
512+
title={t('inspector.fields.className.actions.switchMode', {
513+
defaultValue: `Switch to ${nextModeLabel} mode`,
514+
mode: nextModeLabel,
515+
})}
461516
>
462517
<ModeIcon size={12} />
463518
</button>

apps/web/src/editor/features/design/inspector/classProtocol/MountedCssEditorModal.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,11 @@ export function MountedCssEditorModal({
151151
return [
152152
css(),
153153
colorGutter,
154-
lintCompartment.of(
155-
createSyntaxLinterExtension(DEFAULT_INVALID_CSS_MESSAGE)
156-
),
154+
lintCompartment.of(createSyntaxLinterExtension(invalidSyntaxMessage)),
157155
lintGutter(),
158156
lintTheme,
159157
];
160-
}, [lintCompartment]);
158+
}, [invalidSyntaxMessage, lintCompartment]);
161159
const editorRef = useRef<EditorView | null>(null);
162160

163161
useEffect(() => {

apps/web/src/editor/features/design/inspector/sections/InspectorAnimationSection.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ export function InspectorAnimationSection() {
8787
})}
8888
{isAnimationMounted && mountedAnimationBindingCount > 1 ? (
8989
<span className="text-(--color-5)">
90-
{` (${mountedAnimationBindingCount} bindings)`}
90+
{t('inspector.groups.animation.bindingCount', {
91+
defaultValue: `(${mountedAnimationBindingCount} bindings)`,
92+
count: mountedAnimationBindingCount,
93+
})}
9194
</span>
9295
) : null}
9396
</div>

apps/web/src/editor/features/design/inspector/sections/basic/InspectorNodeCapabilitiesFields.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,12 @@ export function InspectorNodeCapabilitiesFields() {
171171
<input
172172
data-testid="inspector-route-current-path"
173173
className="w-full rounded-md border border-black/10 bg-transparent px-2 py-1 text-xs dark:border-white/16"
174-
placeholder="/about/team"
174+
placeholder={t(
175+
'inspector.fields.routeCurrentPath.placeholder',
176+
{
177+
defaultValue: '/about/team',
178+
}
179+
)}
175180
value={currentPathValue}
176181
onChange={(event) => {
177182
const value = event.currentTarget.value;
@@ -196,7 +201,12 @@ export function InspectorNodeCapabilitiesFields() {
196201
<input
197202
data-testid="inspector-route-empty-text"
198203
className="w-full rounded-md border border-black/10 bg-transparent px-2 py-1 text-xs dark:border-white/16"
199-
placeholder="No route matched."
204+
placeholder={t(
205+
'inspector.fields.routeEmptyText.placeholder',
206+
{
207+
defaultValue: 'No route matched.',
208+
}
209+
)}
200210
value={emptyTextValue}
201211
onChange={(event) => {
202212
const value = event.currentTarget.value;
@@ -229,7 +239,9 @@ export function InspectorNodeCapabilitiesFields() {
229239
<input
230240
data-testid="inspector-route-child-path"
231241
className="w-full rounded-md border border-black/10 bg-transparent px-2 py-1 text-xs dark:border-white/16"
232-
placeholder="/about or details/:id"
242+
placeholder={t('inspector.fields.routePath.placeholder', {
243+
defaultValue: '/about or details/:id',
244+
})}
233245
value={routePathValue}
234246
disabled={routeIndexValue}
235247
onChange={(event) => {

0 commit comments

Comments
 (0)