Skip to content

Commit e3943b5

Browse files
Copilothotlong
andcommitted
feat(spec): add i18n file organization convention schemas and per-locale example
- Add ObjectTranslationDataSchema for per-object translation file validation - Add FieldTranslationSchema for reusable field translation structure - Add TranslationFileOrganizationSchema enum (bundled, per_locale, per_namespace) - Add TranslationConfigSchema for i18n stack configuration - Add TranslationData type export - Add i18n optional property to ObjectStackDefinitionSchema - Refactor app-todo to per-locale file splitting convention - Add 18 new tests for all new schemas Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 764d8f1 commit e3943b5

8 files changed

Lines changed: 655 additions & 287 deletions

File tree

examples/app-todo/objectstack.config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ export default defineStack({
4848
flows: Object.values(flows) as any,
4949
apps: Object.values(apps),
5050

51+
// I18n Configuration — per-locale file organization
52+
i18n: {
53+
defaultLocale: 'en',
54+
supportedLocales: ['en', 'zh-CN', 'ja-JP'],
55+
fallbackLocale: 'en',
56+
fileOrganization: 'per_locale',
57+
},
58+
5159
// I18n Translation Bundles (en, zh-CN, ja-JP)
5260
translations: Object.values(translations),
5361
});
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import type { TranslationData } from '@objectstack/spec/system';
4+
5+
/**
6+
* English (en) — Todo App Translations
7+
*
8+
* Per-locale file: one file per language, following the `per_locale` convention.
9+
* Each file exports a single `TranslationData` object for its locale.
10+
*/
11+
export const en: TranslationData = {
12+
objects: {
13+
task: {
14+
label: 'Task',
15+
pluralLabel: 'Tasks',
16+
fields: {
17+
subject: { label: 'Subject', help: 'Brief title of the task' },
18+
description: { label: 'Description' },
19+
status: {
20+
label: 'Status',
21+
options: {
22+
not_started: 'Not Started',
23+
in_progress: 'In Progress',
24+
waiting: 'Waiting',
25+
completed: 'Completed',
26+
deferred: 'Deferred',
27+
},
28+
},
29+
priority: {
30+
label: 'Priority',
31+
options: {
32+
low: 'Low',
33+
normal: 'Normal',
34+
high: 'High',
35+
urgent: 'Urgent',
36+
},
37+
},
38+
category: { label: 'Category' },
39+
due_date: { label: 'Due Date' },
40+
reminder_date: { label: 'Reminder Date/Time' },
41+
completed_date: { label: 'Completed Date' },
42+
owner: { label: 'Assigned To' },
43+
tags: {
44+
label: 'Tags',
45+
options: {
46+
important: 'Important',
47+
quick_win: 'Quick Win',
48+
blocked: 'Blocked',
49+
follow_up: 'Follow Up',
50+
review: 'Review',
51+
},
52+
},
53+
is_recurring: { label: 'Recurring Task' },
54+
recurrence_type: { label: 'Recurrence Type' },
55+
recurrence_interval: { label: 'Recurrence Interval' },
56+
is_completed: { label: 'Is Completed' },
57+
is_overdue: { label: 'Is Overdue' },
58+
progress_percent: { label: 'Progress (%)' },
59+
estimated_hours: { label: 'Estimated Hours' },
60+
actual_hours: { label: 'Actual Hours' },
61+
notes: { label: 'Notes' },
62+
category_color: { label: 'Category Color' },
63+
},
64+
},
65+
},
66+
apps: {
67+
todo_app: {
68+
label: 'Todo Manager',
69+
description: 'Personal task management application',
70+
},
71+
},
72+
messages: {
73+
'common.save': 'Save',
74+
'common.cancel': 'Cancel',
75+
'common.delete': 'Delete',
76+
'common.edit': 'Edit',
77+
'common.create': 'Create',
78+
'common.search': 'Search',
79+
'common.filter': 'Filter',
80+
'common.sort': 'Sort',
81+
'common.refresh': 'Refresh',
82+
'common.export': 'Export',
83+
'common.back': 'Back',
84+
'common.confirm': 'Confirm',
85+
'success.saved': 'Successfully saved',
86+
'success.deleted': 'Successfully deleted',
87+
'success.completed': 'Task marked as completed',
88+
'confirm.delete': 'Are you sure you want to delete this task?',
89+
'confirm.complete': 'Mark this task as completed?',
90+
'error.required': 'This field is required',
91+
'error.load_failed': 'Failed to load data',
92+
},
93+
validationMessages: {
94+
completed_date_required: 'Completed date is required when status is Completed',
95+
recurrence_fields_required: 'Recurrence type is required for recurring tasks',
96+
},
97+
};
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import type { TranslationData } from '@objectstack/spec/system';
4+
5+
/**
6+
* 日本語 (ja-JP) — Todo App Translations
7+
*
8+
* Per-locale file: one file per language, following the `per_locale` convention.
9+
*/
10+
export const jaJP: TranslationData = {
11+
objects: {
12+
task: {
13+
label: 'タスク',
14+
pluralLabel: 'タスク',
15+
fields: {
16+
subject: { label: '件名', help: 'タスクの簡単なタイトル' },
17+
description: { label: '説明' },
18+
status: {
19+
label: 'ステータス',
20+
options: {
21+
not_started: '未着手',
22+
in_progress: '進行中',
23+
waiting: '待機中',
24+
completed: '完了',
25+
deferred: '延期',
26+
},
27+
},
28+
priority: {
29+
label: '優先度',
30+
options: {
31+
low: '低',
32+
normal: '通常',
33+
high: '高',
34+
urgent: '緊急',
35+
},
36+
},
37+
category: { label: 'カテゴリ' },
38+
due_date: { label: '期日' },
39+
reminder_date: { label: 'リマインダー日時' },
40+
completed_date: { label: '完了日' },
41+
owner: { label: '担当者' },
42+
tags: {
43+
label: 'タグ',
44+
options: {
45+
important: '重要',
46+
quick_win: 'クイックウィン',
47+
blocked: 'ブロック中',
48+
follow_up: 'フォローアップ',
49+
review: 'レビュー',
50+
},
51+
},
52+
is_recurring: { label: '繰り返しタスク' },
53+
recurrence_type: { label: '繰り返しタイプ' },
54+
recurrence_interval: { label: '繰り返し間隔' },
55+
is_completed: { label: '完了済み' },
56+
is_overdue: { label: '期限超過' },
57+
progress_percent: { label: '進捗率 (%)' },
58+
estimated_hours: { label: '見積時間' },
59+
actual_hours: { label: '実績時間' },
60+
notes: { label: 'メモ' },
61+
category_color: { label: 'カテゴリ色' },
62+
},
63+
},
64+
},
65+
apps: {
66+
todo_app: {
67+
label: 'ToDo マネージャー',
68+
description: '個人タスク管理アプリケーション',
69+
},
70+
},
71+
messages: {
72+
'common.save': '保存',
73+
'common.cancel': 'キャンセル',
74+
'common.delete': '削除',
75+
'common.edit': '編集',
76+
'common.create': '新規作成',
77+
'common.search': '検索',
78+
'common.filter': 'フィルター',
79+
'common.sort': '並べ替え',
80+
'common.refresh': '更新',
81+
'common.export': 'エクスポート',
82+
'common.back': '戻る',
83+
'common.confirm': '確認',
84+
'success.saved': '保存しました',
85+
'success.deleted': '削除しました',
86+
'success.completed': 'タスクを完了にしました',
87+
'confirm.delete': 'このタスクを削除してもよろしいですか?',
88+
'confirm.complete': 'このタスクを完了にしますか?',
89+
'error.required': 'この項目は必須です',
90+
'error.load_failed': 'データの読み込みに失敗しました',
91+
},
92+
validationMessages: {
93+
completed_date_required: 'ステータスが「完了」の場合、完了日は必須です',
94+
recurrence_fields_required: '繰り返しタスクには繰り返しタイプが必要です',
95+
},
96+
};

0 commit comments

Comments
 (0)