🌐 Localized files

This commit is contained in:
2025-11-23 01:43:54 +08:00
parent f9a09599c9
commit 108a6da074
11 changed files with 288 additions and 124 deletions

View File

@@ -1,4 +1,5 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
@@ -33,7 +34,7 @@ class FileManagementActionSection extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'File Actions',
'fileActions'.tr(),
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
@@ -45,10 +46,8 @@ class FileManagementActionSection extends HookConsumerWidget {
Symbols.delete_forever,
color: theme.colorScheme.error,
),
title: const Text('Purge Files'),
subtitle: const Text(
'Remove all uploaded files from the site',
),
title: Text('purgeFiles'.tr()),
subtitle: Text('purgeFilesDescription'.tr()),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
onTap: () => _purgeFiles(context, ref),
),
@@ -58,10 +57,8 @@ class FileManagementActionSection extends HookConsumerWidget {
Symbols.upload,
color: theme.colorScheme.primary,
),
title: const Text('Deploy Site'),
subtitle: const Text(
'Upload and deploy a new version from ZIP archive',
),
title: Text('deploySite'.tr()),
subtitle: Text('deploySiteDescription'.tr()),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
onTap: () => _deploySite(context, ref),
),
@@ -79,21 +76,19 @@ class FileManagementActionSection extends HookConsumerWidget {
context: context,
builder:
(context) => AlertDialog(
title: const Text('Confirm Purge'),
content: const Text(
'This will permanently delete all files uploaded to this site. This action cannot be undone. Are you sure you want to continue?',
),
title: Text('confirmPurge'.tr()),
content: Text('purgeFilesConfirm'.tr()),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Cancel'),
child: Text('cancel'.tr()),
),
FilledButton(
onPressed: () => Navigator.pop(context, true),
style: FilledButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.error,
),
child: const Text('Purge All Files'),
child: Text('purgeAllFiles'.tr()),
),
],
),
@@ -105,13 +100,13 @@ class FileManagementActionSection extends HookConsumerWidget {
final apiClient = ref.read(apiClientProvider);
await apiClient.delete('/zone/sites/${site.id}/files/purge');
if (context.mounted) {
showSnackBar('All files purged successfully');
showSnackBar('allFilesPurgedSuccess'.tr());
// Refresh the file management section
ref.invalidate(siteFilesProvider(siteId: site.id));
}
} catch (e) {
if (context.mounted) {
showSnackBar('Failed to purge files: $e');
showSnackBar('failedToPurgeFiles'.tr(args: [e.toString()]));
}
}
}
@@ -147,13 +142,13 @@ class FileManagementActionSection extends HookConsumerWidget {
);
if (context.mounted) {
showSnackBar('Site deployed successfully');
showSnackBar('siteDeployedSuccess'.tr());
// Refresh the file management section
ref.invalidate(siteFilesProvider(siteId: site.id));
}
} catch (e) {
if (context.mounted) {
showSnackBar('Failed to deploy site: $e');
showSnackBar('failedToDeploySite'.tr(args: [e.toString()]));
}
}
}

View File

@@ -1,4 +1,5 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@@ -42,7 +43,7 @@ class FileManagementSection extends HookConsumerWidget {
Icon(Symbols.folder, size: 20),
const Gap(8),
Text(
'File Management',
'fileManagement'.tr(),
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
@@ -75,9 +76,7 @@ class FileManagementSection extends HookConsumerWidget {
files =
results.map((m) => m['file'] as File).toList();
if (files.isEmpty) {
showSnackBar(
'No files found in the selected folder',
);
showSnackBar('noFilesFoundInFolder'.tr());
return;
}
}
@@ -112,23 +111,23 @@ class FileManagementSection extends HookConsumerWidget {
},
itemBuilder:
(BuildContext context) => [
const PopupMenuItem<String>(
PopupMenuItem<String>(
value: 'files',
child: Row(
children: [
Icon(Symbols.file_copy),
Gap(12),
Text('Files'),
Text('siteFiles'.tr()),
],
),
),
const PopupMenuItem<String>(
PopupMenuItem<String>(
value: 'folder',
child: Row(
children: [
Icon(Symbols.folder),
Gap(12),
Text('Folder'),
Text('siteFolder'.tr()),
],
),
),
@@ -182,7 +181,7 @@ class FileManagementSection extends HookConsumerWidget {
children: [
InkWell(
onTap: () => currentPath.value = null,
child: const Text('Root'),
child: Text('siteRoot'.tr()),
),
...() {
final parts =
@@ -230,12 +229,12 @@ class FileManagementSection extends HookConsumerWidget {
),
const Gap(16),
Text(
'No files uploaded yet',
'noFilesUploadedYet'.tr(),
style: theme.textTheme.bodyLarge,
),
const Gap(8),
Text(
'Upload your first file to get started',
'uploadFirstFile'.tr(),
style: theme.textTheme.bodySmall,
),
],
@@ -265,7 +264,7 @@ class FileManagementSection extends HookConsumerWidget {
(error, stack) => Center(
child: Column(
children: [
Text('Failed to load files'),
Text('failedToLoadFiles'.tr()),
const Gap(8),
ElevatedButton(
onPressed:
@@ -275,7 +274,7 @@ class FileManagementSection extends HookConsumerWidget {
path: currentPath.value,
),
),
child: const Text('Retry'),
child: Text('retry'.tr()),
),
],
),

View File

@@ -1,3 +1,4 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -29,7 +30,7 @@ class PagesSection extends HookConsumerWidget {
const Icon(Symbols.article, size: 20),
const Gap(8),
Text(
'Pages',
'sitePages'.tr(),
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
@@ -72,12 +73,12 @@ class PagesSection extends HookConsumerWidget {
),
const Gap(16),
Text(
'No pages yet',
'noPagesYet'.tr(),
style: theme.textTheme.bodyLarge,
),
const Gap(8),
Text(
'Create your first page to get started',
'createFirstPage'.tr(),
style: theme.textTheme.bodySmall,
),
],
@@ -101,14 +102,14 @@ class PagesSection extends HookConsumerWidget {
(error, stack) => Center(
child: Column(
children: [
Text('Failed to load pages'),
Text('failedToLoadPages'.tr()),
const Gap(8),
ElevatedButton(
onPressed:
() => ref.invalidate(
sitePagesProvider(pubName, site.slug),
),
child: const Text('Retry'),
child: Text('retry'.tr()),
),
],
),

View File

@@ -64,18 +64,16 @@ class SiteActionMenu extends HookConsumerWidget {
context: context,
builder:
(context) => AlertDialog(
title: const Text('Delete Site'),
content: const Text(
'Are you sure you want to delete this publication site? This action cannot be undone.',
),
title: Text('deleteSite'.tr()),
content: Text('publicationSiteDeleteConfirm'.tr()),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false),
child: const Text('Cancel'),
child: Text('cancel'.tr()),
),
TextButton(
onPressed: () => Navigator.of(context).pop(true),
child: const Text('Delete'),
child: Text('delete'.tr()),
),
],
),
@@ -86,7 +84,7 @@ class SiteActionMenu extends HookConsumerWidget {
final client = ref.read(apiClientProvider);
await client.delete('/zone/sites/${site.id}');
if (context.mounted) {
showSnackBar('Site deleted successfully');
showSnackBar('siteDeletedSuccess'.tr());
Navigator.of(context).pop();
}
} catch (e) {

View File

@@ -1,3 +1,4 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -42,20 +43,20 @@ class SiteDetailContent extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Site Information',
'siteInformation'.tr(),
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
const Gap(16),
InfoRow(
label: 'Name',
label: 'name'.tr(),
value: site.name,
icon: Symbols.title,
),
const Gap(8),
InfoRow(
label: 'Slug',
label: 'slug'.tr(),
value: site.slug,
icon: Symbols.tag,
monospace: true,
@@ -63,27 +64,30 @@ class SiteDetailContent extends HookConsumerWidget {
const Gap(8),
InfoRow(
label: 'Mode',
value: site.mode == 0 ? 'Fully Managed' : 'Self-Managed',
value:
site.mode == 0
? 'siteModeFullyManaged'.tr()
: 'siteModeSelfManaged'.tr(),
icon: Symbols.settings,
),
if (site.description != null &&
site.description!.isNotEmpty) ...[
const Gap(8),
InfoRow(
label: 'Description',
label: 'description'.tr(),
value: site.description!,
icon: Symbols.description,
),
],
const Gap(8),
InfoRow(
label: 'Created',
label: 'siteCreated'.tr(),
value: site.createdAt.formatSystem(),
icon: Symbols.calendar_add_on,
),
const Gap(8),
InfoRow(
label: 'Updated',
label: 'siteUpdated'.tr(),
value: site.updatedAt.formatSystem(),
icon: Symbols.update,
),