refactor(i18n): route remaining extension labels through the catalog (T-468)
Migrate the user-facing strings in menubar, output, search, deeplink, editor, files, terminal, markdown, and vim to ClideSettings.i18n.string/.interpolated; extend the existing catalogs and create the missing ones (deeplink, output, search, markdown, menubar, vim). vim mode labels now resolve through builtin.vim (default still `-- NORMAL --`, now localizable). A dock-status test seeds builtin.output so the widget's own i18n lookups resolve instead of warning into the logRing it counts. No en_US behaviour change (D-21). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,18 +32,43 @@ class AboutDialog extends StatelessWidget {
|
||||
const SizedBox(height: 2),
|
||||
const ClideText(clideTagline, muted: true, fontSize: 13),
|
||||
const SizedBox(height: 16),
|
||||
_Kv(label: 'Version', value: clideVersion, tokens: tokens),
|
||||
_Kv(label: 'Commit', value: clideCommit, tokens: tokens),
|
||||
_Kv(label: 'Built', value: _formatDate(clideDate), tokens: tokens),
|
||||
_Kv(label: 'Repository', value: clideRepository, tokens: tokens),
|
||||
_Kv(
|
||||
label: ClideSettings.i18n.string(context, 'about.version', namespace: 'builtin.menubar', placeholder: 'Version'),
|
||||
value: clideVersion,
|
||||
tokens: tokens,
|
||||
),
|
||||
_Kv(
|
||||
label: ClideSettings.i18n.string(context, 'about.commit', namespace: 'builtin.menubar', placeholder: 'Commit'),
|
||||
value: clideCommit,
|
||||
tokens: tokens,
|
||||
),
|
||||
_Kv(
|
||||
label: ClideSettings.i18n.string(context, 'about.built', namespace: 'builtin.menubar', placeholder: 'Built'),
|
||||
value: _formatDate(clideDate),
|
||||
tokens: tokens,
|
||||
),
|
||||
_Kv(
|
||||
label: ClideSettings.i18n.string(context, 'about.repository', namespace: 'builtin.menubar', placeholder: 'Repository'),
|
||||
value: clideRepository,
|
||||
tokens: tokens,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ClideText('Bundled dependencies', fontSize: clideFontCaption, color: tokens.globalTextMuted),
|
||||
ClideText(
|
||||
ClideSettings.i18n.string(context, 'licenses.heading', namespace: 'builtin.menubar', placeholder: 'Bundled dependencies'),
|
||||
fontSize: clideFontCaption,
|
||||
color: tokens.globalTextMuted,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
_Licenses(tokens: tokens),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [ClideButton(label: 'Close', onPressed: onDismiss)],
|
||||
children: [
|
||||
ClideButton(
|
||||
label: ClideSettings.i18n.string(context, 'button.close', namespace: 'builtin.menubar', placeholder: 'Close'),
|
||||
onPressed: onDismiss,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -86,7 +111,13 @@ class _Licenses extends StatelessWidget {
|
||||
future: loadLicenses(),
|
||||
builder: (context, snap) {
|
||||
if (!snap.hasData) {
|
||||
return ClideText(snap.hasError ? 'Licenses unavailable.' : 'Loading…', fontSize: 12, color: tokens.globalTextMuted);
|
||||
return ClideText(
|
||||
snap.hasError
|
||||
? ClideSettings.i18n.string(context, 'licenses.unavailable', namespace: 'builtin.menubar', placeholder: 'Licenses unavailable.')
|
||||
: ClideSettings.i18n.string(context, 'licenses.loading', namespace: 'builtin.menubar', placeholder: 'Loading…'),
|
||||
fontSize: 12,
|
||||
color: tokens.globalTextMuted,
|
||||
);
|
||||
}
|
||||
final deps = snap.data!.dependencies;
|
||||
return Container(
|
||||
|
||||
@@ -123,9 +123,17 @@ class _OpenFolderDialogState extends State<OpenFolderDialog> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const ClideText('Open project', fontSize: 16, fontWeight: FontWeight.w600),
|
||||
ClideText(
|
||||
ClideSettings.i18n.string(context, 'dialog.openProject.title', namespace: 'builtin.menubar', placeholder: 'Open project'),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const ClideText('Enter the path to a git repository.', muted: true, fontSize: 13),
|
||||
ClideText(
|
||||
ClideSettings.i18n.string(context, 'dialog.openProject.body', namespace: 'builtin.menubar', placeholder: 'Enter the path to a git repository.'),
|
||||
muted: true,
|
||||
fontSize: 13,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
||||
@@ -148,14 +156,29 @@ class _OpenFolderDialogState extends State<OpenFolderDialog> {
|
||||
onSubmitted: (_) => unawaited(_submit()),
|
||||
),
|
||||
),
|
||||
if (_error != null) ...[const SizedBox(height: 8), ClideText(_error!, color: tokens.statusError, fontSize: 12)],
|
||||
if (_error != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
ClideText(
|
||||
ClideSettings.i18n.string(context, 'dialog.openProject.error', namespace: 'builtin.menubar', placeholder: 'Not a git repository'),
|
||||
color: tokens.statusError,
|
||||
fontSize: 12,
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ClideButton(label: 'Cancel', onPressed: widget.onCancel),
|
||||
ClideButton(
|
||||
label: ClideSettings.i18n.string(context, 'button.cancel', namespace: 'builtin.menubar', placeholder: 'Cancel'),
|
||||
onPressed: widget.onCancel,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
ClideButton(label: _loading ? 'Opening…' : 'Open', onPressed: _loading ? null : _submit),
|
||||
ClideButton(
|
||||
label: _loading
|
||||
? ClideSettings.i18n.string(context, 'button.opening', namespace: 'builtin.menubar', placeholder: 'Opening…')
|
||||
: ClideSettings.i18n.string(context, 'button.open', namespace: 'builtin.menubar', placeholder: 'Open'),
|
||||
onPressed: _loading ? null : _submit,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -186,15 +209,33 @@ class NotARepoDialog extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const ClideText('No git repo found', fontSize: 16, fontWeight: FontWeight.w600),
|
||||
ClideText(
|
||||
ClideSettings.i18n.string(context, 'dialog.notRepo.title', namespace: 'builtin.menubar', placeholder: 'No git repo found'),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ClideText(path, muted: true, fontSize: 13),
|
||||
const SizedBox(height: 8),
|
||||
const ClideText('A clide project root requires a git repository.', muted: true, fontSize: 13),
|
||||
ClideText(
|
||||
ClideSettings.i18n.string(
|
||||
context,
|
||||
'dialog.notRepo.body',
|
||||
namespace: 'builtin.menubar',
|
||||
placeholder: 'A clide project root requires a git repository.',
|
||||
),
|
||||
muted: true,
|
||||
fontSize: 13,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [ClideButton(label: 'OK', onPressed: () => onDismiss())],
|
||||
children: [
|
||||
ClideButton(
|
||||
label: ClideSettings.i18n.string(context, 'button.ok', namespace: 'builtin.menubar', placeholder: 'OK'),
|
||||
onPressed: () => onDismiss(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -187,10 +187,24 @@ class _TopMenuButtonState extends State<_TopMenuButton> {
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.symmetric(horizontal: clideInsetStandard),
|
||||
color: open || hovered ? tokens.listItemHoverBackground : null,
|
||||
child: ClideText(widget.menu.title, fontSize: 12, color: open || hovered ? tokens.globalForeground : tokens.chromeForeground),
|
||||
child: ClideText(_menuTitle(ctx, widget.menu.title), fontSize: 12, color: open || hovered ? tokens.globalForeground : tokens.chromeForeground),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Localize a curated top-menu title. The curated tree authors English
|
||||
/// titles ('File'/'View'/'Help'); resolve each to its catalog entry, falling
|
||||
/// back to the authored English (which also drives the Alt mnemonic).
|
||||
String _menuTitle(BuildContext context, String title) {
|
||||
final key = switch (title) {
|
||||
'File' => 'menu.file',
|
||||
'View' => 'menu.view',
|
||||
'Help' => 'menu.help',
|
||||
_ => null,
|
||||
};
|
||||
if (key == null) return title;
|
||||
return ClideSettings.i18n.string(context, key, namespace: 'builtin.menubar', placeholder: title);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user