Content Management
Overview
Content management focuses on data management for a single content repository, which can be understood as similar to maintaining data tables in an online spreadsheet. It mainly involves displaying, editing, querying, filtering, sorting, and other operations on large amounts of data, as well as a flexible filter builder.
Row Status
- New: Initial import
- Outdated: Key remains unchanged, but content has been updated
- Partial Completed: Some target languages have translations
- Completed: All target languages have translations
When an order is delivered, the system checks whether all translations for the current row have been filled. If so, it is marked as Completed; otherwise, it is marked as Partial Completed. The status can be manually changed by users to their desired state. When a user modifies the source text, if the status is Completed or Partial Completed, it changes to Outdated.
About Query Builder
The query builder can create reusable query conditions that are saved in the data table. A set of query conditions can specify different query criteria for different fields, such as contains, does not contain, equals, not equals, greater than, less than, greater than or equal to, less than or equal to, range, etc.
Fields and Conditions
The following table lists the query conditions supported by various fields in the content management system:
| Field | Supported Conditions |
|---|---|
| Key | Equals, Contains, Starts with |
| Status | In options |
| Source | Equals, Contains |
| Target (all languages) | Equals, Contains, Is Empty |
| CreatedAt | Greater than, Less than, Greater than or equal to, Less than or equal to, Range |
| UpdatedAt | Greater than, Less than, Greater than or equal to, Less than or equal to, Range |
| Locked | Is Locked |
| Color | Color picker (In options) |
About Tag Rules
Tag rules refer to a set of regular expressions used to lock parts of the source text that need to be protected. The protected parts do not need to be translated and are not included in the quotation.
Sharing Scope of Query Builders and Tag Rules
Shared within the workspace, can be deleted by the creator.
About Content Snapshots
A content snapshot refers to a series of information recorded based on the state of the content repository when an order is created. Through this information, the unique content to be localized for the order can be determined. A snapshot record includes:
- Content repository ID
- Current Content Version being viewed by the customer
- Current filter conditions
- Current tag rules
The above information constitutes a snapshot record, which can definitely determine a unique content that will not change during the order lifecycle. The filter conditions and tag rules record the actual content at that time, not IDs, and are not associated with external tables. For traceability and other requirements, and since snapshots are also part of the order, snapshot information does not need to be deleted and should be stored long-term.
Version Behavior
Version Creation
The following actions will cause the content repository to generate a new version:
- When triggering data import
- When an order updates target language translations
Version Rollback
- Version rollback can be used to undo import actions
- Order preview: if the user has not confirmed and accepted the order, the preview is a temporary version that can be revoked
Locking Behavior
- When there is an active order, it means that the original text and updated translations in the content repository must be locked to the current version. If another import occurs at this time, the version increments by one, which would cause version conflicts. Therefore, under the premise of having an order, the locked repository does not allow imports. In practical implementation, whether it's Excel or UE, there should be tasks in a Pending state. When the order is delivered, the system should check the Pending state tasks to start them. Conversely, if there are tasks that are In Progress, orders cannot be created.
- Future improvements: The future goal is to implement parallel imports and order production. In that scenario, there needs to be a relationship between the original version and the order version, equivalent to the order version being a sub-version of the import version, or introducing the concept of branches.
Related External Systems
None at present
Interface Design
1. Content List Query Interface
- Description: Get a list of data from the content repository, supporting pagination, sorting, and filtering
- Method: GET
- URL: /api/v1/repositories/{repositoryId}/contents
- Request Parameters:json
{ "page": 1, "page_size": 20, "sort": [ { "field": "created_at", "order": "desc" } ], "filters": [ { "field": "status", "operator": "in", "value": ["new", "updated"] } ], "query_builder_id": "query_builder_uuid", "search": "welcome" } - Response Example:json
{ "code": 200, "message": "Query successful", "data": { "total": 100, "items": [ { "id": "content_uuid", "content_key": "app/welcome/title", "source": { "text": "Welcome to our app", "language": "en-US" }, "translations": [ { "language": "zh-CN", "text": "欢迎使用我们的应用", "status": "translated" } ], "status": "new", "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-01T00:00:00Z" } ] } }
2. Content Detail Query Interface
- Description: Get detailed information for a single content
- Method: GET
- URL: /api/v1/repositories/{repositoryId}/contents/
- Response Example:json
{ "code": 200, "message": "Query successful", "data": { "id": "content_uuid", "content_key": "app/welcome/title", "source": { "text": "Welcome to our app", "language": "en-US" }, "translations": [ { "language": "zh-CN", "text": "欢迎使用我们的应用", "status": "translated", "updated_at": "2024-01-01T00:00:00Z", "updated_by": "user_id" } ], "metadata": { "source_type": "local_file", "source_info": { "data_source_id": "uuid", "file_id": "uuid", "sheet_name": "Sheet1", "row_number": 1 } }, "status": "new", "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-01T00:00:00Z", "created_by": "user_id", "updated_by": "user_id" } }
3. Content Update Interface
- Description: Update translation or metadata information for content
- Method: PATCH
- URL: /api/v1/repositories/{repositoryId}/contents/
- Request Example:json
{ "translations": [ { "language": "zh-CN", "text": "欢迎使用我们的应用", "status": "translated" } ], "metadata": { "tags": ["homepage", "welcome"] } } - Response Example:json
{ "code": 200, "message": "Update successful", "data": { "id": "content_uuid", "updated_at": "2024-01-01T00:00:00Z" } }
4. Batch Content Update Interface
- Description: Batch update translations or metadata for multiple contents
- Method: PATCH
- URL: /api/v1/repositories/{repositoryId}/contents/batch
- Request Example:json
{ "items": [ { "id": "content_uuid_1", "translations": [ { "language": "zh-CN", "text": "欢迎", "status": "translated" } ] }, { "id": "content_uuid_2", "translations": [ { "language": "zh-CN", "text": "再见", "status": "translated" } ] } ] } - Response Example:json
{ "code": 200, "message": "Batch update successful", "data": { "success_count": 2, "failed_count": 0, "failed_items": [] } }
5. Content History Query Interface
- Description: Query historical change records for content
- Method: GET
- URL: /api/v1/repositories/{repositoryId}/contents/{contentId}/history
- Request Parameters:json
{ "page": 1, "page_size": 20 } - Response Example:json
{ "code": 200, "message": "Query successful", "data": { "total": 5, "items": [ { "id": "history_uuid", "type": "translation_update", "changes": { "before": { "text": "Old translation", "status": "draft" }, "after": { "text": "New translation", "status": "translated" } }, "action": "user_edit", "created_at": "2024-01-01T00:00:00Z", "created_by": "user_id" } ] } }
6. Content Export Interface
- Description: Export data from the content repository in a specified format
- Method: POST
- URL: /api/v1/repositories/{repositoryId}/contents/export
- Request Example:json
{ "format": "excel", "filters": [ { "field": "status", "operator": "in", "value": ["new", "updated"] } ], "languages": ["en-US", "zh-CN"], "columns": ["content_key", "source", "translations"] } - Response Example:json
{ "code": 200, "message": "Export task created", "data": { "task_id": "task_uuid", "status": "processing" } }
7. Content Export Status Query Interface
- Description: Query the status of a content export task
- Method: GET
- URL: /api/v1/repositories/{repositoryId}/contents/export/
- Response Example:json
{ "code": 200, "message": "Query successful", "data": { "task_id": "task_uuid", "status": "completed", "progress": 100, "file_url": "https://example.com/download/export.xlsx", "created_at": "2024-01-01T00:00:00Z", "completed_at": "2024-01-01T00:01:00Z" } }
8. Content Filter Conditions Query Interface
- Description: Get available filter condition configurations
- Method: GET
- URL: /api/v1/repositories/{repositoryId}/contents/filters
- Response Example:json
{ "code": 200, "message": "Query successful", "data": { "filters": [ { "field": "status", "label": "Status", "type": "enum", "options": [ {"value": "new", "label": "New"}, {"value": "updated", "label": "Updated"}, {"value": "deleted", "label": "Deleted"} ] }, { "field": "created_at", "label": "Creation Time", "type": "datetime" } ] } }
10. Create Query Builder Interface
- Description: Create a new query builder configuration
- Method: POST
- URL: /api/v1/repositories/{repositoryId}/query-builders
- Request Example:json
{ "name": "Pending Localization", "description": "Query all content that needs localization", "conditions": [ { "field": "status", "operator": "in", "value": ["new", "update"] }, { "field": "created_at", "operator": "range", "value": { "start": "2024-01-01T00:00:00Z", "end": "2024-12-31T23:59:59Z" } } ], "is_public": true, // Whether it's public (usable by others) "is_shared": true // Whether it's shared across Repositories } - Response Example:json
{ "code": 200, "message": "Creation successful", "data": { "id": "query_builder_uuid", "created_at": "2024-01-01T00:00:00Z" } }
11. Update Query Builder Interface
- Description: Update an existing query builder configuration
- Method: PUT
- URL: /api/v1/repositories/{repositoryId}/query-builders/
- Request Example:json
{ "name": "Pending Localization", "description": "Query all content that needs localization", "conditions": [ { "field": "status", "operator": "in", "value": ["update"] } ], "is_public": true, "is_shared": true } - Response Example:json
{ "code": 200, "message": "Update successful", "data": { "id": "query_builder_uuid", "updated_at": "2024-01-01T00:00:00Z" } }
12. Delete Query Builder Interface
- Description: Delete a specified query builder configuration
- Method: DELETE
- URL: /api/v1/repositories/{repositoryId}/query-builders/
- Response Example:json
{ "code": 200, "message": "Deletion successful" }
13. Query Builder Detail Interface
- Description: Get detailed configuration for a single query builder
- Method: GET
- URL: /api/v1/repositories/{repositoryId}/query-builders/
- Response Example:json
{ "code": 200, "message": "Query successful", "data": { "id": "query_builder_uuid", "name": "Untranslated Content Query", "description": "Query all untranslated Chinese content", "conditions": [ { "field": "translations.zh-CN.status", "operator": "in", "value": ["untranslated", "draft"] } ], "is_shared": true, "is_public": true, "created_by": "user_id", "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-01T00:00:00Z" } }
16. Content Version List Query Interface
- Description: Get historical versions of one or more contents, supporting batch queries
- Method: POST
- URL: /api/v1/repositories/{repositoryId}/contents/versions/list
- Request Parameters:json
{ "content_ids": ["content_uuid_1", "content_uuid_2"], "page": 1, "page_size": 20 } - Response Example:json
{ "code": 200, "message": "Query successful", "data": { "items": [ { "content_id": "content_uuid_1", "current_version": 3, "versions": [ { "id": "version_uuid", "version": 3, "content": { "source": { "text": "Welcome to our app", "language": "en-US" }, "translations": [ { "language": "zh-CN", "text": "欢迎使用我们的应用", "status": "translated" } ] }, "metadata": { "source_type": "local_file", "source_info": { "data_source_id": "uuid", "file_id": "uuid", "sheet_name": "Sheet1", "row_number": 1 } }, "created_by": "user_id", "created_at": "2024-01-01T00:00:00Z", "comment": "Update Chinese translation" } ] }, { "content_id": "content_uuid_2", "current_version": 2, "versions": [ { "id": "version_uuid_2", "version": 2, "content": { "source": { "text": "Goodbye", "language": "en-US" }, "translations": [ { "language": "zh-CN", "text": "再见", "status": "translated" } ] }, "created_by": "user_id", "created_at": "2024-01-01T00:00:00Z", "comment": "Initial translation" } ] } ] } }
17. Content Version Rollback Interface
- Description: Roll back one or more contents to a specified historical version
- Method: POST
- URL: /api/v1/repositories/{repositoryId}/contents/versions/rollback
- Request Example:json
{ "items": [ { "content_id": "content_uuid_1", "version_id": "version_uuid_1" } ], "comment": "Roll back to pre-modification version" } - Response Example:json
{ "code": 200, "message": "Rollback successful", "data": { "success_count": 1, "failed_count": 0, "failed_items": [], "results": [ { "content_id": "content_uuid_1", "new_version": 4, "status": "success", "updated_at": "2024-01-01T00:00:00Z" } ] } }
18. Tag Rules List Query Interface
- Description: Get a list of available tag rules
- Method: GET
- URL: /api/v1/workspaces/{workspaceId}/content-lockers
- Request Parameters:json
{ "page": 1, "page_size": 20 } - Response Example:json
{ "code": 200, "message": "Query successful", "data": { "total": 10, "items": [ { "id": "locker_uuid", "name": "HTML Tag Locker", "description": "Lock HTML tags to prevent translation from breaking tag structure", "patterns": [ "<[^>]+>", "\\{\\{[^}]+\\}\\}" ], "type": "system", "created_by": "system", "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-01T00:00:00Z" } ] } }
19. Create Tag Rule Interface
- Description: Create a new tag rule
- Method: POST
- URL: /api/v1/workspaces/{workspaceId}/content-lockers
- Request Example:json
{ "name": "Variable Locker", "description": "Lock variable references in code", "patterns": [ "\\$\\{[^}]+\\}", "\\%\\{[^}]+\\}" ] } - Response Example:json
{ "code": 200, "message": "Creation successful", "data": { "id": "locker_uuid", "created_at": "2024-01-01T00:00:00Z" } }
20. Update Tag Rule Interface
- Description: Update an existing tag rule
- Method: PUT
- URL: /api/v1/workspaces/{workspaceId}/content-lockers/
- Request Example:json
{ "name": "Variable Locker-Updated", "description": "Lock variable references in code, supporting more formats", "patterns": [ "\\$\\{[^}]+\\}", "\\%\\{[^}]+\\}", "\\@\\{[^}]+\\}" ] } - Response Example:json
{ "code": 200, "message": "Update successful", "data": { "id": "locker_uuid", "updated_at": "2024-01-01T00:00:00Z" } }
21. Delete Tag Rule Interface
- Description: Delete a specified tag rule (only supports custom lockers)
- Method: DELETE
- URL: /api/v1/workspaces/{workspaceId}/content-lockers/
- Response Example:json
{ "code": 200, "message": "Deletion successful" }
22. Apply Tag Rule Interface
- Description: Apply tag rules to a specified Repository
- Method: POST
- URL: /api/v1/repositories/{repositoryId}/content-lockers
- Request Example:json
{ "locker_ids": ["locker_uuid_1", "locker_uuid_2"] } - Response Example:json
{ "code": 200, "message": "Application successful", "data": { "applied_count": 2 } }
23. Remove Tag Rule Interface
- Description: Remove a specified tag rule from a Repository
- Method: DELETE
- URL: /api/v1/repositories/{repositoryId}/content-lockers/
- Response Example:json
{ "code": 200, "message": "Removal successful" }
Tag Rules Database Design
1. Tag Rules Table (tag_rules)
CREATE TABLE tag_rules (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(100) NOT NULL COMMENT 'Locker name',
description TEXT COMMENT 'Locker description',
workspace_id VARCHAR(36) NOT NULL COMMENT 'Workspace ID it belongs to',
type VARCHAR(20) NOT NULL DEFAULT 'custom' COMMENT 'Type: system-built-in, custom-user defined',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
created_by VARCHAR(36) NOT NULL COMMENT 'Creator ID',
updated_by VARCHAR(36) NOT NULL COMMENT 'Last updater ID',
INDEX idx_workspace_type (workspace_id, type),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Tag rules main table';2. Tag Rule Patterns Table (tag_rule_patterns)
CREATE TABLE tag_rule_patterns (
id VARCHAR(36) PRIMARY KEY,
locker_id VARCHAR(36) NOT NULL COMMENT 'Locker ID it belongs to',
pattern TEXT NOT NULL COMMENT 'Regular expression pattern',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_locker (locker_id),
FOREIGN KEY (locker_id) REFERENCES tag_rules(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Locker patterns table';Content Snapshot Table
CREATE TABLE content_snapshots (
id VARCHAR(36) PRIMARY KEY,
repository_id VARCHAR(36) NOT NULL COMMENT 'Content repository ID',
content_version VARCHAR(36) NOT NULL COMMENT 'Content version ID',
filter_json JSON NOT NULL COMMENT 'Filter conditions JSON',
tag_rules JSON NOT NULL COMMENT 'Tag rules JSON, including rule names, descriptions, and regex patterns',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
created_by VARCHAR(36) NOT NULL COMMENT 'Creator ID',
INDEX idx_repository (repository_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Content snapshot table';