From 81a8aa78685ca84c522e32d0fb2e4a99e32189f0 Mon Sep 17 00:00:00 2001 From: jingsam Date: Wed, 10 Jul 2024 13:35:20 +0800 Subject: [PATCH] Partially i18n table editor --- ...build_studio_image.yml => build-image.yml} | 2 +- .github/workflows/prettier.yml | 2 +- .github/workflows/studio-tests.yml | 4 +- .github/workflows/typecheck.yml | 2 +- .../components/common/DropdownControl.tsx | 4 +- .../components/grid/components/grid/Grid.tsx | 12 +-- .../grid/components/header/Header.tsx | 36 ++++---- .../grid/components/header/RefreshButton.tsx | 2 +- .../header/filter/Filter.constants.ts | 20 ++--- .../header/filter/FilterPopover.tsx | 16 ++-- .../components/header/filter/FilterRow.tsx | 2 +- .../components/header/sort/SortPopover.tsx | 14 +-- .../grid/components/header/sort/SortRow.tsx | 4 +- .../Database/ProtectedSchemaWarning.tsx | 20 ++--- .../RoleImpersonationPopover.tsx | 2 +- .../RoleImpersonationRadio.tsx | 2 +- .../RoleImpersonationSelector.tsx | 15 ++-- .../UserImpersonationSelector.tsx | 18 ++-- .../interfaces/TableGridEditor/EmptyState.tsx | 8 +- .../TableGridEditor/GridHeaderActions.tsx | 86 +++++++++---------- .../TableGridEditor/NotFoundState.tsx | 2 +- .../SidePanelEditor/RowEditor/HeaderTitle.tsx | 4 +- .../SidePanelEditor/RowEditor/InputField.tsx | 4 +- .../SidePanelEditor/RowEditor/RowEditor.tsx | 8 +- .../SidePanelEditor/SchemaEditor.tsx | 14 +-- .../TableGridEditor/TableDefinition.tsx | 2 +- .../TableGridEditor/TableGridEditor.tsx | 14 +-- .../TableEditorLayout/TableEditorMenu.tsx | 20 ++--- apps/studio/components/ui/APIDocsButton.tsx | 2 +- apps/studio/components/ui/SchemaSelector.tsx | 14 +-- .../ui-patterns/Dialogs/ConfirmDialog.tsx | 4 +- .../ui-patterns/Dialogs/ConfirmationModal.tsx | 4 +- packages/ui-patterns/InnerSideMenu/index.tsx | 2 +- 33 files changed, 180 insertions(+), 185 deletions(-) rename .github/workflows/{build_studio_image.yml => build-image.yml} (97%) diff --git a/.github/workflows/build_studio_image.yml b/.github/workflows/build-image.yml similarity index 97% rename from .github/workflows/build_studio_image.yml rename to .github/workflows/build-image.yml index 88256875bb851e..07b005ab0b112d 100644 --- a/.github/workflows/build_studio_image.yml +++ b/.github/workflows/build-image.yml @@ -3,7 +3,7 @@ name: Build studio multiarch image with buildx on: # run this action every day at 04:00 UTC (Singapore noon) schedule: - - cron: '0 4 * * *' + - cron: '0 4 * * 1' workflow_dispatch: jobs: diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index 9d7053db16be89..44324949f3fb2c 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -3,7 +3,7 @@ name: Check Code with Prettier on: pull_request: branches: - - 'master' + - 'foxgis' # Cancel old builds on new commit for same workflow + branch/PR concurrency: diff --git a/.github/workflows/studio-tests.yml b/.github/workflows/studio-tests.yml index 1dbc0bd8dd638f..9ec5829383e4f6 100644 --- a/.github/workflows/studio-tests.yml +++ b/.github/workflows/studio-tests.yml @@ -5,12 +5,12 @@ name: Studio Unit Tests & Build Check on: push: - branches: [master, studio] + branches: [foxgis] paths: - 'apps/studio/**' - 'package-lock.json' pull_request: - branches: [master, studio] + branches: [foxgis] paths: - 'apps/studio/**' - 'package-lock.json' diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index eb4e5885a555a3..c3f72a6c58f314 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -3,7 +3,7 @@ name: Check code with TypeScript on: pull_request: branches: - - 'master' + - 'foxgis' # Cancel old builds on new commit for same workflow + branch/PR concurrency: diff --git a/apps/studio/components/grid/components/common/DropdownControl.tsx b/apps/studio/components/grid/components/common/DropdownControl.tsx index fe724a76f37775..6f1894fa97d14b 100644 --- a/apps/studio/components/grid/components/common/DropdownControl.tsx +++ b/apps/studio/components/grid/components/common/DropdownControl.tsx @@ -29,10 +29,10 @@ export const DropdownControl = ({ {options.map((x) => { return ( onSelect(x.value)}> -
+
{x.preLabel && {x.preLabel}} {x.label} - {x.postLabel && {x.postLabel}} + {x.postLabel && {x.postLabel}}
) diff --git a/apps/studio/components/grid/components/grid/Grid.tsx b/apps/studio/components/grid/components/grid/Grid.tsx index 49472b8ee286cb..9865d3499f647c 100644 --- a/apps/studio/components/grid/components/grid/Grid.tsx +++ b/apps/studio/components/grid/components/grid/Grid.tsx @@ -195,7 +195,7 @@ export const Grid = memo( )} {isError && (
- +
)} {isSuccess && ( @@ -205,16 +205,16 @@ export const Grid = memo( style={{ height: `calc(100% - 35px)` }} className="flex flex-col items-center justify-center col-span-full" > -

This table is empty

+

这张表是空的

{onAddRow !== undefined && onImportData !== undefined && ( <>

- Add rows to your table to get started. + 开始给这张表添加数据吧。

{onAddRow !== undefined && onImportData !== undefined && ( )}
@@ -227,11 +227,11 @@ export const Grid = memo( className="flex flex-col items-center justify-center col-span-full" >

- The filters applied has returned no results from this table + 应用筛选条件后没有返回任何结果

diff --git a/apps/studio/components/grid/components/header/Header.tsx b/apps/studio/components/grid/components/header/Header.tsx index 8aa92cef08fc31..df8650a52341af 100644 --- a/apps/studio/components/grid/components/header/Header.tsx +++ b/apps/studio/components/grid/components/header/Header.tsx @@ -120,7 +120,7 @@ const DefaultHeader = ({ table, onAddColumn, onAddRow, onImportData }: DefaultHe size="tiny" icon={} > - Insert + 插入 @@ -143,9 +143,9 @@ const DefaultHeader = ({ table, onAddColumn, onAddRow, onImportData }: DefaultHe />
-

Insert row

+

插入行

- Insert a new row into {table.name} + 向 {table.name} 插入新行

, @@ -169,9 +169,9 @@ const DefaultHeader = ({ table, onAddColumn, onAddRow, onImportData }: DefaultHe />
-

Insert column

+

插入

- Insert a new column into {table.name} + 向 {table.name} 插入新列

, @@ -200,8 +200,8 @@ const DefaultHeader = ({ table, onAddColumn, onAddRow, onImportData }: DefaultHe />
-

Import data from CSV

-

Insert new rows from a CSV

+

导入 CSV

+

通过 CSV 批量插入新行

, ] @@ -288,13 +288,13 @@ const RowHeader = ({ table, sorts, filters }: RowHeaderProps) => { if (allRowsSelected && totalRows > MAX_EXPORT_ROW_COUNT) { toast.error( - `Sorry! We're unable to support exporting of CSV for row counts larger than ${MAX_EXPORT_ROW_COUNT.toLocaleString()} at the moment.` + `抱歉!我们暂时无法支持导出超过 ${MAX_EXPORT_ROW_COUNT.toLocaleString()} 行的 CSV。` ) return setIsExporting(false) } if (!project) { - toast.error('Project is required') + toast.error('未找到项目') return setIsExporting(false) } @@ -349,14 +349,14 @@ const RowHeader = ({ table, sorts, filters }: RowHeaderProps) => { )} @@ -370,7 +370,7 @@ const RowHeader = ({ table, sorts, filters }: RowHeaderProps) => { disabled={isExporting} onClick={onRowsExportCSV} > - Export to CSV + 导出为 CSV {editable && ( @@ -383,10 +383,10 @@ const RowHeader = ({ table, sorts, filters }: RowHeaderProps) => { disabled={allRowsSelected && isImpersonatingRole} > {allRowsSelected - ? `Delete ${totalRows} rows` + ? `删除 ${totalRows} 行` : selectedRows.size > 1 - ? `Delete ${selectedRows.size} rows` - : `Delete ${selectedRows.size} row`} + ? `删除 ${selectedRows.size} 行` + : `删除 ${selectedRows.size} 行`} @@ -401,7 +401,7 @@ const RowHeader = ({ table, sorts, filters }: RowHeaderProps) => { ].join(' ')} > - Table truncation is not supported when impersonating a role + 模拟角色不支持清空表操作 diff --git a/apps/studio/components/grid/components/header/RefreshButton.tsx b/apps/studio/components/grid/components/header/RefreshButton.tsx index 9c557e2b43c1cc..b4b39aa1426817 100644 --- a/apps/studio/components/grid/components/header/RefreshButton.tsx +++ b/apps/studio/components/grid/components/header/RefreshButton.tsx @@ -28,7 +28,7 @@ const RefreshButton = ({ table, isRefetching }: RefreshButtonProps) => { icon={} onClick={() => onClick()} > - Refresh + 刷新 ) } diff --git a/apps/studio/components/grid/components/header/filter/Filter.constants.ts b/apps/studio/components/grid/components/header/filter/Filter.constants.ts index 7a31a236f361c0..1d3e0fb4c61586 100644 --- a/apps/studio/components/grid/components/header/filter/Filter.constants.ts +++ b/apps/studio/components/grid/components/header/filter/Filter.constants.ts @@ -1,16 +1,16 @@ export const FilterOperatorOptions = [ - { value: '=', label: 'equals', preLabel: '[ = ]', abbrev: 'eq' }, - { value: '<>', label: 'not equal', preLabel: '[ <> ]', abbrev: 'neq' }, - { value: '>', label: 'greater than', preLabel: '[ > ]', abbrev: 'gt' }, - { value: '<', label: 'less than', preLabel: '[ < ]', abbrev: 'lt' }, - { value: '>=', label: 'greater than or equal', preLabel: '[ >= ]', abbrev: 'gte' }, - { value: '<=', label: 'less than or equal', preLabel: '[ <= ]', abbrev: 'lte' }, - { value: '~~', label: 'like operator', preLabel: '[ ~~ ]', abbrev: 'like' }, - { value: '~~*', label: 'ilike operator', preLabel: '[ ~~* ]', abbrev: 'ilike' }, - { value: 'in', label: 'one of a list of values', preLabel: '[ in ]', abbrev: 'in' }, + { value: '=', label: '等于', preLabel: '[ = ]', abbrev: 'eq' }, + { value: '<>', label: '不等于', preLabel: '[ <> ]', abbrev: 'neq' }, + { value: '>', label: '大于', preLabel: '[ > ]', abbrev: 'gt' }, + { value: '<', label: '小于', preLabel: '[ < ]', abbrev: 'lt' }, + { value: '>=', label: '大于等于', preLabel: '[ >= ]', abbrev: 'gte' }, + { value: '<=', label: '小于等于', preLabel: '[ <= ]', abbrev: 'lte' }, + { value: '~~', label: '模糊匹配', preLabel: '[ ~~ ]', abbrev: 'like' }, + { value: '~~*', label: '不区分大小写的模糊匹配', preLabel: '[ ~~* ]', abbrev: 'ilike' }, + { value: 'in', label: '属于', preLabel: '[ in ]', abbrev: 'in' }, { value: 'is', - label: 'checking for (null,not null,true,false)', + label: '检查是否为(null, not null, true, false)', preLabel: '[ is ]', abbrev: 'is', }, diff --git a/apps/studio/components/grid/components/header/filter/FilterPopover.tsx b/apps/studio/components/grid/components/header/filter/FilterPopover.tsx index 9caaed755ceb34..9ac6041c806da1 100644 --- a/apps/studio/components/grid/components/header/filter/FilterPopover.tsx +++ b/apps/studio/components/grid/components/header/filter/FilterPopover.tsx @@ -27,8 +27,8 @@ const FilterPopover = ({ table, filters, setParams }: FilterPopoverProps) => { const btnText = (filters || []).length > 0 - ? `Filtered by ${filters.length} rule${filters.length > 1 ? 's' : ''}` - : 'Filter' + ? `已按${filters.length}个条件筛选` + : '筛选' const onApplyFilters = (appliedFilters: Filter[]) => { setParams((prevParams) => { @@ -130,22 +130,26 @@ const FilterOverlay = ({ table, filters: filtersFromUrl, onApplyFilters }: Filte ))} {filters.length == 0 && (
-
No filters applied to this view
-

Add a column below to filter the view

+
+ 此视图未应用任何筛选条件 +
+

+ 请在下方添加列以筛选此视图 +

)}
diff --git a/apps/studio/components/grid/components/header/filter/FilterRow.tsx b/apps/studio/components/grid/components/header/filter/FilterRow.tsx index 79e4867d38a4a6..ff6faa99fcddf5 100644 --- a/apps/studio/components/grid/components/header/filter/FilterRow.tsx +++ b/apps/studio/components/grid/components/header/filter/FilterRow.tsx @@ -27,7 +27,7 @@ const FilterRow = ({ table, filter, filterIdx, onChange, onDelete, onKeyDown }: ? 'yyyy-mm-dd hh:mm:ss+zz' : column?.format === 'timestamp' ? 'yyyy-mm-dd hh:mm:ss' - : 'Enter a value' + : '输入值' return (
diff --git a/apps/studio/components/grid/components/header/sort/SortPopover.tsx b/apps/studio/components/grid/components/header/sort/SortPopover.tsx index c0ff288a5abf33..74663495296c06 100644 --- a/apps/studio/components/grid/components/header/sort/SortPopover.tsx +++ b/apps/studio/components/grid/components/header/sort/SortPopover.tsx @@ -27,8 +27,8 @@ const SortPopover = ({ table, sorts, setParams }: SortPopoverProps) => { const btnText = (sorts || []).length > 0 - ? `Sorted by ${sorts.length} rule${sorts.length > 1 ? 's' : ''}` - : 'Sort' + ? `已按${sorts.length}条规则排序` + : '排序' const onApplySorts = (appliedSorts: Sort[]) => { setParams((prevParams) => { @@ -128,8 +128,8 @@ const SortOverlay = ({ table, sorts: sortsFromUrl, onApplySorts }: SortOverlayPr ))} {sorts.length === 0 && (
-
No sorts applied to this view
-

Add a column below to sort the view

+
此视图未应用任何排序规则
+

在下方添加一列,对视图进行排序

)} @@ -149,11 +149,11 @@ const SortOverlay = ({ table, sorts: sortsFromUrl, onApplySorts }: SortOverlayPr className="sb-grid-dropdown__item-trigger" data-testid="table-editor-pick-column-to-sort-button" > - Pick {sorts.length > 1 ? 'another' : 'a'} column to sort by + 选择{sorts.length > 1 ? '另一列' : '一列'}对视图进行排序 ) : ( -

All columns have been added

+

所有列都已添加

)}
diff --git a/apps/studio/components/grid/components/header/sort/SortRow.tsx b/apps/studio/components/grid/components/header/sort/SortRow.tsx index 6fdeb0a63c7892..6f75a036cdcaa3 100644 --- a/apps/studio/components/grid/components/header/sort/SortRow.tsx +++ b/apps/studio/components/grid/components/header/sort/SortRow.tsx @@ -109,13 +109,13 @@ const SortRow = ({ table, index, columnName, sort, onDelete, onToggle, onDrag }:
- {index > 0 ? 'then by' : 'sort by'} + {index > 0 ? '然后按' : '排序按'} {column.name}
- +
} @@ -33,8 +33,7 @@ export const ProtectedSchemaModal = ({ >

- The following schemas are managed by Supabase and are currently protected from write - access through the dashboard. + 以下模式由系统管理,当前被设置为只读,无法通过表编辑器进行编辑。

{EXCLUDED_SCHEMAS.map((schema) => ( @@ -44,12 +43,10 @@ export const ProtectedSchemaModal = ({ ))}

- These schemas are critical to the functionality of your Supabase project and hence we - highly recommend not altering them. + 这些模式与系统的核心功能有关,我们强烈建议不要对它们进行修改。

- You can, however, still interact with those schemas through the SQL Editor although we - advise you only do so if you know what you are doing. + 尽管如此,你仍然可以通过 SQL 编辑器与这些模式进行交互,但是我们建议你在十分清楚影响的情况下进行操作。

@@ -63,14 +60,13 @@ const ProtectedSchemaWarning = ({ schema, entity }: { schema: string; entity: st <> - Currently viewing {entity} from a protected schema + 当前正在查看一个受保护的模式 {entity}

- The {schema} schema is managed by Supabase and is - read-only through the dashboard. + 模式 {schema} 是由系统管理的,当前被设置为只读,无法通过表编辑器进行编辑。

diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx index 216963c7a3dd9b..6b85a328d44224 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx @@ -38,7 +38,7 @@ const RoleImpersonationPopover = ({ )} >
- role + 角色 {currentRole} {state.role?.type === 'postgrest' && state.role.role === 'authenticated' && ( diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationRadio.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationRadio.tsx index 25895706f7209c..5cf943cc75402b 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationRadio.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationRadio.tsx @@ -61,7 +61,7 @@ function RoleImpersonationRadio({ isSelected && 'text-foreground' )} > - {label ?? value} role + {label ?? value} 角色 ) diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx index 248b2545ada20b..70e08e4f0c3f05 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx @@ -56,7 +56,7 @@ const RoleImpersonationSelector = ({ return ( <>
-

Database role settings

+

数据库角色设置

{ @@ -94,24 +94,25 @@ const RoleImpersonationSelector = ({ {selectedOption === 'service_role' && (

- The default Postgres/superuser role. This has admin privileges. + 默认的 Postgres/superuser 角色。此角色具有管理员权限。
- It will bypass Row Level Security (RLS) policies. + 它会绕过行级安全策略(RLS)。

)} {selectedOption === 'anon' && (

- For "anonymous access". This is the role which the API (PostgREST) will use when a user + 用于“匿名访问”。此角色是 API(PostgREST)在用户未登录时使用的角色。
- is not logged in. It will respect Row Level Security (RLS) policies. + 它将遵守行级安全策略(RLS)。

)} {selectedOption === 'authenticated' && (

- For "authenticated access". This is the role which the API (PostgREST) will use when -
a user is logged in. It will respect Row Level Security (RLS) policies. + 用于“已认证访问”。此角色是 API(PostgREST)在用户登录时使用的角色。 +
+ 它将遵守行级安全策略(RLS)。

)}
diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx index fe801037454cd1..1d4b02985ff0e5 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx @@ -53,14 +53,14 @@ const UserImpersonationSelector = () => { impersonatingUser.email ?? impersonatingUser.phone ?? impersonatingUser.id ?? - 'Unknown' + '未知用户' )}` - : 'Impersonate a User'} + : '模拟用户'}

{!impersonatingUser - ? "Select a user to respect your database's Row-Level Security policies for that particular user." - : "Results will respect your database's Row-Level Security policies for this user."} + ? '选择一个遵守数据库行级安全策略的用户。' + : '查询结果将遵守数据库的行级安全策略。'}

{!impersonatingUser ? ( @@ -78,7 +78,7 @@ const UserImpersonationSelector = () => { ) } - placeholder="Search for a user.." + placeholder="查找用户..." onChange={(e) => setSearchText(e.target.value.trim())} value={searchText} size="small" @@ -94,7 +94,7 @@ const UserImpersonationSelector = () => { {isLoading && (
- Loading users... + 加载用户...
)} @@ -112,7 +112,7 @@ const UserImpersonationSelector = () => { ) : (

- No users found + 未找到用户

))} @@ -162,7 +162,7 @@ const UserImpersonatingRow = ({ user, onClick, isImpersonating = false }: UserRo onClick(user) }} > - {isImpersonating ? 'Stop Impersonating' : 'Impersonate'} + {isImpersonating ? '停止模拟' : '模拟'}
) @@ -200,7 +200,7 @@ const UserRow = ({ user, onClick, isImpersonating = false }: UserRowProps) => { onClick(user) }} > - {isImpersonating ? 'Stop Impersonating' : 'Impersonate'} + {isImpersonating ? '停止模拟' : '模拟'} ) diff --git a/apps/studio/components/interfaces/TableGridEditor/EmptyState.tsx b/apps/studio/components/interfaces/TableGridEditor/EmptyState.tsx index 57f63f0e7fafdb..36b3a7d409d518 100644 --- a/apps/studio/components/interfaces/TableGridEditor/EmptyState.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/EmptyState.tsx @@ -34,19 +34,19 @@ const EmptyState = ({}: EmptyStateProps) => {
{totalCount === 0 ? (

- There are no tables available in this schema. + 这个模式下没有可查看的表。

) : (

diff --git a/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index 2a50c2917d6104..776d1f68f9fb32 100644 --- a/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -53,7 +53,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { const { mutate: updateTable } = useTableUpdateMutation({ onError: (error) => { - toast.error(`Failed to toggle RLS: ${error.message}`) + toast.error(`启用 RLS 失败:${error.message}`) }, onSettled: () => { closeConfirmModal() @@ -89,7 +89,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { setShowEnableRealtime(false) }, onError: (error) => { - toast.error(`Failed to toggle realtime for ${table.name}: ${error.message}`) + toast.error(`为 ${table.name} 启用实时消息失败:${error.message}`) }, }) @@ -117,8 +117,8 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { ) const toggleRealtime = async () => { - if (!project) return console.error('Project is required') - if (!realtimePublication) return console.error('Unable to find realtime publication') + if (!project) return console.error('未找到项目') + if (!realtimePublication) return console.error('未发现实时消息发布') const exists = realtimeEnabledTables.some((x: any) => x.id == table.id) const tables = !exists @@ -162,7 +162,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {

- Viewing as read-only + 以只读模式查看
@@ -175,7 +175,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { ].join(' ')} > - You need additional permissions to manage your project's data + 您需要额外的权限才能管理您的项目数据
@@ -199,7 +199,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { passHref href={`/project/${projectRef}/auth/policies?search=${table.id}&schema=${table.schema}`} > - Add RLS policy + 添加 RLS 策略 @@ -213,9 +213,9 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { ].join(' ')} >
-

RLS is enabled for this table, but no policies are set.

+

此表启用了 RLS,但没有设置策略。

- Select queries will return an empty array of results. + Select 查询将返回一个空数组的结果。

@@ -241,7 +241,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { passHref href={`/project/${projectRef}/auth/policies?search=${table.id}&schema=${table.schema}`} > - Auth {policies.length > 1 ? 'policies' : 'policy'} + 认证策略 )} @@ -250,21 +250,19 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { setOpen(!open)} modal={false}>

- Row Level Security (RLS) + 行级安全策略(RLS)

- You can restrict and control who can read, write and update data in this table - using Row Level Security. + 在这张表中,您可以使用行级安全性来限制和控制谁可以读取、写入和更新数据。

- With RLS enabled, anonymous users will not be able to read/write data in the - table. + 启用 RLS 后,匿名用户将无法在表中读取/写入数据。

{!isLocked && (
@@ -272,7 +270,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { type="default" onClick={() => setRlsConfirmModalOpen(!rlsConfirmModalOpen)} > - Enable RLS for this table + 启用此表的 RLS
)} @@ -286,21 +284,20 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { setOpen(!open)} modal={false}>

- Secure your View + 保护你的视图

- This view is defined with the Security Definer property, giving it permissions of - the view's creator (Postgres), rather than the permissions of the querying user. + 这个视图是用 Security Definer 属性定义的,它赋予了它创建者(Postgres)的权限,而不是查询用户的权限。

- Since this view is in the public schema, it is accessible via your project's APIs. + 由于这个视图在 public 模式下,所以可以通过你的项目的 API 访问。

@@ -309,7 +306,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { target="_blank" href={`/project/${ref}/advisors/security?preset=${matchingViewLint?.level}&id=${matchingViewLint?.cache_key}`} > - Learn more + 了解更多
@@ -322,21 +319,20 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { setOpen(!open)} modal={false}>

- Secure your View + 保护你的物化视图

- This view is defined with the Security Definer property, giving it permissions of - the view's creator (Postgres), rather than the permissions of the querying user. + 这个视图是用 Security Definer 属性定义的,它赋予了它创建者(Postgres)的权限,而不是查询用户的权限。

- Since this view is in the public schema, it is accessible via your project's APIs. + 由于这个视图在 public 模式下,所以可以通过你的项目的 API 访问。

@@ -345,7 +341,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { target="_blank" href={`/project/${ref}/advisors/security?preset=${matchingMaterializedViewLint?.level}&id=${matchingMaterializedViewLint?.cache_key}`} > - Learn more + 了解更多
@@ -363,18 +359,17 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {

- Secure Foreign table + 保护外部表

- Foreign tables do not enforce RLS. Move them to a private schema not exposed to - Postgrest or disable Postgrest. + 外部表无法应用 RLS。请将它们移动到一个私有的模式,使其不被暴露给 Postgrest 或禁用 Postgrest。

@@ -396,7 +391,7 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { } onClick={() => setShowEnableRealtime(true)} > - Realtime {isRealtimeEnabled ? 'on' : 'off'} + 实时消息 {isRealtimeEnabled ? '已开启' : '已关闭'} )} @@ -406,24 +401,23 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { setShowEnableRealtime(false)} onConfirm={() => toggleRealtime()} >

- Once realtime has been {isRealtimeEnabled ? 'disabled' : 'enabled'}, the table will{' '} - {isRealtimeEnabled ? 'no longer ' : ''}broadcast any changes to authorized subscribers. + 一旦实时消息被{isRealtimeEnabled ? '禁用' : '启用'},将{isRealtimeEnabled ? '不再' : ''}向授权的订阅者广播表的任何更新事件。

{!isRealtimeEnabled && (

- You may also select which events to broadcast to subscribers on the{' '} + 您也可以在{' '} - database publications + 数据库消息发布 {' '} - settings. + 设置中选择要向订阅者广播的事件。

)}
@@ -433,10 +427,10 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { diff --git a/apps/studio/components/interfaces/TableGridEditor/NotFoundState.tsx b/apps/studio/components/interfaces/TableGridEditor/NotFoundState.tsx index fbe4893ac90bc6..74a54fd70228b5 100644 --- a/apps/studio/components/interfaces/TableGridEditor/NotFoundState.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/NotFoundState.tsx @@ -12,7 +12,7 @@ const NotFoundState = ({ id }: NotFoundStateProps) => {
} - title={`Unable to find your table with ID ${id}`} + title={`无法找到 ID 为 ${id} 的表`} />
diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/HeaderTitle.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/HeaderTitle.tsx index cfa43f090fd2c3..9d4b0dc23fb43d 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/HeaderTitle.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/HeaderTitle.tsx @@ -4,12 +4,12 @@ interface HeaderTitleProps { } const HeaderTitle = ({ isNewRecord, tableName }: HeaderTitleProps) => { - let header = `${isNewRecord ? 'Add new' : 'Update'} row ${isNewRecord ? 'to' : 'from'} ` + let header = `${isNewRecord ? '添加新行' : '更新行'}` return ( <> - {header} {tableName && {tableName}} + {header} ) } diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx index 9303c52acc0861..0f51ab82affb28 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx @@ -55,8 +55,8 @@ const InputField = ({ field.defaultValue === null ? '' : typeof field.defaultValue === 'string' && field.defaultValue.length === 0 - ? 'EMPTY' - : `Default: ${field.defaultValue}` + ? '空字符' + : `默认值:${field.defaultValue}` } onChange={(event: any) => onUpdateField({ [field.name]: event.target.value })} /> diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx index ac46996af561ac..c2383991a035fa 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx @@ -173,9 +173,9 @@ const RowEditor = ({
-

Optional Fields

+

可选字段

- These are columns that do not need any value + 这些列不一定需要设置值

{optionalFields.map((field: RowField) => { @@ -221,8 +221,8 @@ const RowEditor = ({
diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx index d072fe906c4677..221ea5bf467a26 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx @@ -28,20 +28,20 @@ const SchemaEditor = ({ visible, closePanel }: SchemaEditorProps) => { const onSaveChanges = (resolve: any) => { const errors: any = {} - if (name.length === 0) errors.name = 'Please provide a name for your schema' + if (name.length === 0) errors.name = '请为模式指定名称' if (Object.keys(errors).length > 0) { resolve() return setErrors(errors) } - if (project === undefined) return console.error('Project is required') + if (project === undefined) return console.error('未找到项目') createSchema( { projectRef: project.ref, connectionString: project.connectionString, name }, { onSuccess: () => { resolve() closePanel() - toast.success(`Successfully created schema "${name}"`) + toast.success(`成功创建了模式 "${name}"`) }, } ) @@ -52,14 +52,14 @@ const SchemaEditor = ({ visible, closePanel }: SchemaEditorProps) => { size="large" key="SchemaEditor" visible={visible} - header={'Create a new schema'} + header={'创建模式'} className="transition-all duration-100 ease-in" onCancel={closePanel} onConfirm={() => (resolve: () => void) => onSaveChanges(resolve)} customFooter={ void) => onSaveChanges(resolve)} /> @@ -69,7 +69,7 @@ const SchemaEditor = ({ visible, closePanel }: SchemaEditorProps) => {
{ formattedDefinition ?? '' )}`} > - 在SQL编辑中打开 + 在 SQL 编辑中打开 ) as any, description: ( ), action: ( @@ -255,7 +255,7 @@ const TableGridEditor = ({ rel="noreferrer" href="https://supabase.com/docs/guides/database/tables#primary-keys" > - Documentation + 查看文档
@@ -315,9 +315,9 @@ const TableGridEditor = ({ (isViewSelected || isTableSelected) && selectedView === 'definition' ? (

- SQL Definition of {selectedTable.name}{' '} + {selectedTable.name}的 SQL 定义{' '}

-

(Read only)

+

(只读)

) : null } diff --git a/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx b/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx index b7122376bdab42..2794fa6bf092d0 100644 --- a/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx @@ -123,7 +123,7 @@ const TableEditorMenu = () => { } @@ -133,16 +133,16 @@ const TableEditorMenu = () => { tooltip={{ content: { side: 'bottom', - text: '您需要获取额外的权限才能创建表', + text: '您需要获取额外的权限才能新建表', }, }} > - New table + 新建表 ) : ( - 查询受保护的模式 + 查看受保护的模式

@@ -176,13 +176,13 @@ const TableEditorMenu = () => { value="alphabetical" className="flex gap-2" > - Alphabetical + 名称 - Entity Type + 实体类型 @@ -196,7 +196,7 @@ const TableEditorMenu = () => {

-

Show entity types

+

显示的实体类型

{Object.entries(ENTITY_TYPE).map(([key, value]) => (
@@ -223,7 +223,7 @@ const TableEditorMenu = () => { onClick={() => setVisibleTypes([value])} className="transition opacity-0 group-hover:opacity-100 h-auto px-1 py-0.5" > - Select only + 单选
))} @@ -244,7 +244,7 @@ const TableEditorMenu = () => { {searchText.length === 0 && (entityTypes?.length ?? 0) <= 0 && ( )} @@ -252,7 +252,7 @@ const TableEditorMenu = () => { )} {(entityTypes?.length ?? 0) > 0 && ( diff --git a/apps/studio/components/ui/APIDocsButton.tsx b/apps/studio/components/ui/APIDocsButton.tsx index dcc0a5b2b3a898..b8db5f542581a5 100644 --- a/apps/studio/components/ui/APIDocsButton.tsx +++ b/apps/studio/components/ui/APIDocsButton.tsx @@ -19,7 +19,7 @@ const APIDocsButton = ({ section }: APIDocsButtonProps) => { }} icon={} > - API Docs + API 文档 ) } diff --git a/apps/studio/components/ui/SchemaSelector.tsx b/apps/studio/components/ui/SchemaSelector.tsx index c69ab9993bb016..c9be2b37d98ffc 100644 --- a/apps/studio/components/ui/SchemaSelector.tsx +++ b/apps/studio/components/ui/SchemaSelector.tsx @@ -70,20 +70,20 @@ const SchemaSelector = ({
{isSchemasLoading && ( )} {showError && isSchemasError && ( - Failed to load schemas + 加载模式失败 - Error: {(schemasError as any)?.message} + 错误:{(schemasError as any)?.message} )} @@ -101,7 +101,7 @@ const SchemaSelector = ({ } >
-

schema:

+

模式:

{selectedSchemaName === '*' ? 'All schemas' : selectedSchemaName}

@@ -110,7 +110,7 @@ const SchemaSelector = ({ - + No schemas found @@ -171,7 +171,7 @@ const SchemaSelector = ({ }} > - Create a new schema + 创建模式 diff --git a/packages/ui-patterns/Dialogs/ConfirmDialog.tsx b/packages/ui-patterns/Dialogs/ConfirmDialog.tsx index 80aba0f849b63b..cd01e1e3b12d73 100644 --- a/packages/ui-patterns/Dialogs/ConfirmDialog.tsx +++ b/packages/ui-patterns/Dialogs/ConfirmDialog.tsx @@ -71,7 +71,7 @@ const ConfirmModal = ({ onClick={onSelectCancel} disabled={loading} > - Cancel + 取消
diff --git a/packages/ui-patterns/Dialogs/ConfirmationModal.tsx b/packages/ui-patterns/Dialogs/ConfirmationModal.tsx index 4ed5633bf516ed..2e8d3bf6467b67 100644 --- a/packages/ui-patterns/Dialogs/ConfirmationModal.tsx +++ b/packages/ui-patterns/Dialogs/ConfirmationModal.tsx @@ -45,8 +45,8 @@ const ConfirmationModal = forwardRef< onCancel, onConfirm, loading: loading_ = false, - cancelLabel = 'Cancel', - confirmLabel = 'Submit', + cancelLabel = '取消', + confirmLabel = '确定', confirmLabelLoading, alert = undefined, children, diff --git a/packages/ui-patterns/InnerSideMenu/index.tsx b/packages/ui-patterns/InnerSideMenu/index.tsx index 07958e3352f830..9bfae6799f265f 100644 --- a/packages/ui-patterns/InnerSideMenu/index.tsx +++ b/packages/ui-patterns/InnerSideMenu/index.tsx @@ -158,7 +158,7 @@ const InnerSideBarFilterSortDropdown = forwardRef< - Sort By + 排序