@jskit-ai/agent-docs 0.1.247 → 0.1.249
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/guide/agent/app-extras/assistant-conversation.md +4 -2
- package/guide/agent/framework/translation.md +227 -0
- package/guide/agent/index.md +1 -0
- package/package.json +1 -1
- package/patterns/feature-package/example/booking-engine/package.json +1 -1
- package/patterns/minimal-foundation/example/package.json +3 -3
- package/patterns/shell-foundation/example/package.json +4 -4
- package/patterns/shell-foundation/example/packages/main/package.json +1 -1
- package/reference/autogen/KERNEL_MAP.md +27 -2
- package/reference/autogen/PATTERN_INDEX.md +37 -37
- package/reference/autogen/packages/assistant-core.md +21 -3
- package/reference/autogen/packages/assistant-runtime.md +15 -0
- package/reference/autogen/packages/assistant-voice.md +13 -5
- package/reference/autogen/packages/auth-core.md +14 -1
- package/reference/autogen/packages/auth-provider-local-core.md +1 -1
- package/reference/autogen/packages/auth-web.md +12 -2
- package/reference/autogen/packages/connector-google-calendar.md +6 -1
- package/reference/autogen/packages/connectors-catalog.md +19 -4
- package/reference/autogen/packages/connectors-core.md +5 -1
- package/reference/autogen/packages/connectors-web.md +5 -0
- package/reference/autogen/packages/http-runtime.md +6 -3
- package/reference/autogen/packages/http-web.md +27 -18
- package/reference/autogen/packages/kernel.md +74 -7
- package/reference/autogen/packages/mobile-capacitor.md +6 -1
- package/reference/autogen/packages/payments-core.md +2 -2
- package/reference/autogen/packages/payments-web.md +8 -0
- package/reference/autogen/packages/realtime.md +5 -0
- package/reference/autogen/packages/rewarded-web.md +5 -0
- package/reference/autogen/packages/shell-web.md +13 -3
- package/reference/autogen/packages/uploads-image-web.md +5 -0
- package/reference/autogen/packages/uploads-runtime.md +1 -1
- package/reference/autogen/packages/users-core.md +1 -0
- package/reference/autogen/packages/users-web.md +22 -0
- package/reference/autogen/packages/workspaces-core.md +10 -3
- package/reference/autogen/packages/workspaces-web.md +4 -0
- package/reference/autogen/tooling/jskit-catalog.md +28 -0
- package/skills/jskit/SKILL.md +3 -3
- package/skills/jskit/references/pattern-index.md +37 -37
- package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +3 -3
- package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +4 -4
- package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
- package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
- package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
- package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
- package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
- package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +10 -0
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
- package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +7 -0
- package/skills/jskit/references/translation.md +227 -0
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
"db:migrate:status": "knex --knexfile ./knexfile.js migrate:list"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@jskit-ai/connectors-core": "0.
|
|
11
|
-
"@jskit-ai/connector-google-calendar": "0.
|
|
12
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
13
|
-
"@jskit-ai/database-runtime-mysql": "0.1.
|
|
10
|
+
"@jskit-ai/connectors-core": "0.2.0",
|
|
11
|
+
"@jskit-ai/connector-google-calendar": "0.2.0",
|
|
12
|
+
"@jskit-ai/database-runtime": "0.1.249",
|
|
13
|
+
"@jskit-ai/database-runtime-mysql": "0.1.247",
|
|
14
14
|
"knex": "^3.1.0"
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"./shared": "./src/shared/index.js"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@jskit-ai/crud-core": "0.
|
|
12
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
11
|
+
"@jskit-ai/crud-core": "0.2.0",
|
|
12
|
+
"@jskit-ai/resource-crud-core": "0.1.191"
|
|
13
13
|
},
|
|
14
14
|
"jskit": {
|
|
15
15
|
"kind": "runtime",
|
|
@@ -28,6 +28,16 @@ section order, and which account operations require reauthentication.
|
|
|
28
28
|
Use account settings elements and composables from `@jskit-ai/users-web`,
|
|
29
29
|
ordinary `useCommand()` mutation behavior, and JSKIT shell placements.
|
|
30
30
|
|
|
31
|
+
The runtime's `preferences.options.locale` lists the app's `config.languages`
|
|
32
|
+
(`[{ code, name }]` in the public app config), or a built-in list when the app
|
|
33
|
+
configures none; theme, date and number format options arrive translated. The
|
|
34
|
+
saved locale is a canonical BCP 47 code. `useAccountLocale()` from
|
|
35
|
+
`@jskit-ai/users-web/client` returns it as a read-only ref (`""` when signed
|
|
36
|
+
out), updated at bootstrap and after preferences save. JSKIT does not switch the
|
|
37
|
+
app's language; the app does, for example
|
|
38
|
+
`watch(useAccountLocale(), (code) => { if (code) i18n.global.locale.value = code; }, { immediate: true })`.
|
|
39
|
+
Section titles may be plain text, a message key or `{ key, fallback }`.
|
|
40
|
+
|
|
31
41
|
## Invariants
|
|
32
42
|
|
|
33
43
|
- Sections use JSKIT account settings APIs rather than direct HTTP helpers.
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"./shared": "./src/shared/index.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@jskit-ai/crud-core": "0.
|
|
13
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
12
|
+
"@jskit-ai/crud-core": "0.2.0",
|
|
13
|
+
"@jskit-ai/resource-crud-core": "0.1.191"
|
|
14
14
|
},
|
|
15
15
|
"jskit": {
|
|
16
16
|
"kind": "runtime",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"./shared": "./src/shared/index.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@jskit-ai/crud-core": "0.
|
|
13
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
14
|
-
"@jskit-ai/workspaces-core": "0.
|
|
12
|
+
"@jskit-ai/crud-core": "0.2.0",
|
|
13
|
+
"@jskit-ai/resource-crud-core": "0.1.191",
|
|
14
|
+
"@jskit-ai/workspaces-core": "0.2.0"
|
|
15
15
|
},
|
|
16
16
|
"jskit": {
|
|
17
17
|
"kind": "runtime",
|
|
@@ -49,6 +49,13 @@ responses expose optional `roleLabel` alongside the unchanged `roleSid`.
|
|
|
49
49
|
Applications with their own invitation renderer may use its optional
|
|
50
50
|
`roleLabel` input; `roleSid` remains the stored role id.
|
|
51
51
|
|
|
52
|
+
Invitation emails use the recipient's language: `locale` is the saved
|
|
53
|
+
`user_settings.locale` of an existing account with the invited email, else `en`.
|
|
54
|
+
Renderers receive `locale` and `t(key, params)`, which renders a
|
|
55
|
+
`jskit.workspaces.inviteEmail.*` message from the app's
|
|
56
|
+
`src/locales/<code>/jskit.json` (exact locale, then language, then English); the
|
|
57
|
+
mailer's `sendWorkspaceInvite` receives `locale` too.
|
|
58
|
+
|
|
52
59
|
Keep existing permissions, inheritance, assignability and
|
|
53
60
|
`workspace.defaultInviteRole` when adding a label. `owner` remains
|
|
54
61
|
nonassignable. Custom roles, including specialised Training roles, are ordinary
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
<!-- Generated from `packages/agent-docs/site/guide/framework/translation.md` by `npm run agent-docs:build`. -->
|
|
2
|
+
|
|
3
|
+
# Translating a JSKIT app
|
|
4
|
+
|
|
5
|
+
JSKIT ships every screen, message and error in English and can show all of them
|
|
6
|
+
in another language. An app supplies translation files only: it never copies or
|
|
7
|
+
overrides JSKIT components to translate them. An app that supplies no
|
|
8
|
+
translations looks and behaves exactly as an English-only app.
|
|
9
|
+
|
|
10
|
+
## How it fits together
|
|
11
|
+
|
|
12
|
+
- Every JSKIT package with user-visible text ships `locales/en.json`, a nested
|
|
13
|
+
catalog under its own namespace: `jskit.auth.*`, `jskit.users.*`,
|
|
14
|
+
`jskit.shell.*`, `jskit.http.*`, and so on.
|
|
15
|
+
- JSKIT components translate through the app's
|
|
16
|
+
[vue-i18n](https://vue-i18n.intlify.dev/) instance when the app supplies one,
|
|
17
|
+
and through the bundled English otherwise. `vue-i18n` is an optional peer
|
|
18
|
+
dependency; install it only when the app is translated.
|
|
19
|
+
- The server never decides the language of an error. Every error response
|
|
20
|
+
carries a stable `code`, its `params` and the English `message`; the client
|
|
21
|
+
renders the code in the user's language.
|
|
22
|
+
- Choosing and switching the language is the app's job. JSKIT components follow
|
|
23
|
+
vue-i18n's active locale.
|
|
24
|
+
|
|
25
|
+
## Pass the app's vue-i18n instance
|
|
26
|
+
|
|
27
|
+
Create the instance in composition mode and give it to the client bootstrap:
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
import { createI18n } from "vue-i18n";
|
|
31
|
+
import { bootstrapClientShellApp } from "@jskit-ai/kernel/client";
|
|
32
|
+
import it from "./locales/it/jskit.json" with { type: "json" };
|
|
33
|
+
|
|
34
|
+
const i18n = createI18n({
|
|
35
|
+
legacy: false,
|
|
36
|
+
locale: "en",
|
|
37
|
+
fallbackLocale: "en",
|
|
38
|
+
messages: { it }
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
await bootstrapClientShellApp({ /* existing options */, i18n });
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The bootstrap installs the instance (unless `appPlugins` already does) and
|
|
45
|
+
merges every installed package's English into its `en` messages. The app's own
|
|
46
|
+
`en` messages win, so an app can reword a JSKIT text by defining the same key.
|
|
47
|
+
JSKIT refuses a legacy-mode instance (`createI18n({ legacy: true })`).
|
|
48
|
+
|
|
49
|
+
## Add a language
|
|
50
|
+
|
|
51
|
+
1. Write the merged English of the app's installed JSKIT packages to a file for
|
|
52
|
+
translators:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx jskit i18n export it
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This creates `src/locales/it/jskit.json`. Running it again after upgrading
|
|
59
|
+
JSKIT adds new keys in English and keeps every existing translation.
|
|
60
|
+
2. Translate the values. Keep every `{placeholder}` exactly; plural messages
|
|
61
|
+
keep the same number of `|`-separated choices as the English.
|
|
62
|
+
3. Check the file against the installed packages:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx jskit i18n check it
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
It reports missing and extra keys, invalid messages, placeholder and plural
|
|
69
|
+
mismatches, and (as warnings) values still identical to the English. It exits
|
|
70
|
+
non-zero when keys are missing, a message is invalid or placeholders differ,
|
|
71
|
+
so it can run in CI.
|
|
72
|
+
4. Load the file into the vue-i18n instance under its locale code, as above.
|
|
73
|
+
|
|
74
|
+
Missing keys fall back to English, so a partly translated language still works.
|
|
75
|
+
|
|
76
|
+
### Message syntax
|
|
77
|
+
|
|
78
|
+
JSKIT catalogs use a subset of vue-i18n's syntax, and translations must too:
|
|
79
|
+
|
|
80
|
+
- named placeholders: `Use at least {min} characters.`
|
|
81
|
+
- literal text in quotes for the characters `{ } @ $ |`: `support{'@'}example.com`
|
|
82
|
+
- plural choices separated by `|`, chosen by `count`:
|
|
83
|
+
`{count} file | {count} files` (one | other) or
|
|
84
|
+
`no files | one file | {count} files` (zero | one | other)
|
|
85
|
+
|
|
86
|
+
Linked messages (`@:key`), list placeholders (`{0}`) and HTML are not used.
|
|
87
|
+
|
|
88
|
+
## Use the user's saved language
|
|
89
|
+
|
|
90
|
+
Account preferences store the user's language in `user_settings.locale` as a
|
|
91
|
+
BCP 47 code (for example `it-IT`). The "Language / locale" select offers the
|
|
92
|
+
app's configured languages:
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
// config/public.js
|
|
96
|
+
config.languages = [
|
|
97
|
+
{ code: "en-US", name: "English (US)" },
|
|
98
|
+
{ code: "it-IT", name: "Italiano" }
|
|
99
|
+
];
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Each `name` may also be a message key. A saved locale that is not among the
|
|
103
|
+
configured languages stays selectable under its language name. Without
|
|
104
|
+
`config.languages` the select keeps JSKIT's built-in list, unchanged.
|
|
105
|
+
|
|
106
|
+
JSKIT never switches the app's language itself. `useAccountLocale()` from
|
|
107
|
+
`@jskit-ai/users-web/client` is a read-only ref holding the signed-in user's
|
|
108
|
+
saved locale (`""` when nobody is signed in); it updates after sign-in and after
|
|
109
|
+
the preferences are saved. Follow it in the app:
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
import { watch } from "vue";
|
|
113
|
+
import { useAccountLocale } from "@jskit-ai/users-web/client";
|
|
114
|
+
|
|
115
|
+
watch(useAccountLocale(), (locale) => {
|
|
116
|
+
if (locale) i18n.global.locale.value = pickSupportedLocale(locale);
|
|
117
|
+
}, { immediate: true });
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`pickSupportedLocale` is the app's own choice, for example `it-IT` → `it` when
|
|
121
|
+
the app ships only `src/locales/it/jskit.json`.
|
|
122
|
+
|
|
123
|
+
## How errors are shown
|
|
124
|
+
|
|
125
|
+
Every error response from a JSKIT HTTP API has a `code` and `params` next to
|
|
126
|
+
the English `message`:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{ "error": "Invalid email or password.", "code": "auth.login.invalidCredentials", "params": {} }
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
- Codes added for translation are dotted (`<namespace>.<area>.<name>`) and
|
|
133
|
+
render from the key `jskit.<code>`.
|
|
134
|
+
- Older codes such as `ACTION_PERMISSION_DENIED` or `not_found` keep their
|
|
135
|
+
values and render from `jskit.errors.<code>`.
|
|
136
|
+
- Validation errors keep `details.fieldErrors` (English) and add
|
|
137
|
+
`details.fieldErrorCodes: { field: { code, params } }`.
|
|
138
|
+
- Where one code covers several different sentences (for example
|
|
139
|
+
`connector_input_invalid`), the response also has `messageCode` and
|
|
140
|
+
`messageParams` for the exact sentence.
|
|
141
|
+
|
|
142
|
+
The client translates a code only when the English the server sent is JSKIT's
|
|
143
|
+
English for that code. An app's own sentence under a shared code (for example
|
|
144
|
+
`throw new NotFoundError("Contact not found.")`) is shown exactly as written, and
|
|
145
|
+
so is any text whose code has no catalog entry.
|
|
146
|
+
|
|
147
|
+
App code that shows errors uses the same helper JSKIT's components use:
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
import { useJskitText } from "@jskit-ai/kernel/client";
|
|
151
|
+
|
|
152
|
+
const { serverMessage, fieldErrorMessages } = useJskitText();
|
|
153
|
+
const message = serverMessage(error); // translated, or the English sent
|
|
154
|
+
const fieldMessages = fieldErrorMessages(error); // { field: text }
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
To give the app's own errors codes, throw them with a code and params and add
|
|
158
|
+
the app's English and translations to its vue-i18n messages under the key the
|
|
159
|
+
code maps to:
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
throw new AppError(409, "That slug is taken.", { code: "app.project.slugTaken" });
|
|
163
|
+
// en: { jskit: { app: { project: { slugTaken: "That slug is taken." } } } }
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Placement labels
|
|
167
|
+
|
|
168
|
+
A placement `label` or `title` may be a message key, `{ key, fallback, params }`
|
|
169
|
+
or plain text. JSKIT's menus, tabs, profile menu and account-settings sections
|
|
170
|
+
translate a key and show any other string as written:
|
|
171
|
+
|
|
172
|
+
```js
|
|
173
|
+
{ label: "jskit.users.accountSettings.menuLabel" }
|
|
174
|
+
{ label: { key: "app.menu.reports", fallback: "Reports" } }
|
|
175
|
+
{ label: "Reports" }
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Dates and numbers
|
|
179
|
+
|
|
180
|
+
JSKIT formats dates, times, numbers and relative times with `Intl` in the
|
|
181
|
+
active vue-i18n locale. Without an instance, each text keeps the format it had
|
|
182
|
+
before translation support (usually the browser's default).
|
|
183
|
+
App code can use the same helpers from `useJskitText()`: `formatDate`,
|
|
184
|
+
`formatTime`, `formatDateTime`, `formatNumber` and `formatRelativeTime`.
|
|
185
|
+
|
|
186
|
+
## Emails
|
|
187
|
+
|
|
188
|
+
The workspace invitation email is rendered in the recipient's saved
|
|
189
|
+
`user_settings.locale` when the recipient already has an account, and in English
|
|
190
|
+
otherwise. The server reads the same `src/locales/<code>/jskit.json` files the
|
|
191
|
+
client uses, so translating `jskit.workspaces.inviteEmail.*` there translates
|
|
192
|
+
the email too. It looks for the exact locale (`it-IT`), then the language
|
|
193
|
+
(`it`), then English. The app's invite mailer also receives the chosen `locale`.
|
|
194
|
+
|
|
195
|
+
Server code that renders JSKIT-style messages itself uses the same lookup:
|
|
196
|
+
|
|
197
|
+
```js
|
|
198
|
+
import { createServerI18n } from "@jskit-ai/kernel/server/i18n";
|
|
199
|
+
|
|
200
|
+
const i18n = createServerI18n({ appRoot, catalogs: [english] });
|
|
201
|
+
i18n.t("it-IT", "jskit.workspaces.inviteEmail.subject", { workspace: "Acme" });
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Password-reset emails are sent by the app's own recovery sender (local
|
|
205
|
+
accounts) or by the identity provider (Supabase, OIDC), so their language is
|
|
206
|
+
the app's or the provider's choice.
|
|
207
|
+
|
|
208
|
+
## What the app translates itself
|
|
209
|
+
|
|
210
|
+
JSKIT's catalogs cover JSKIT's own code. These texts belong to the app:
|
|
211
|
+
|
|
212
|
+
- Vuetify's built-in texts (close buttons, pagination, "No data available").
|
|
213
|
+
Translate them through Vuetify's locale options, or let Vuetify share the
|
|
214
|
+
vue-i18n instance with its `createVueI18nAdapter`.
|
|
215
|
+
- Files the app copied from a JSKIT starter or pattern, such as its
|
|
216
|
+
account-settings sections, placement entries and pages. Once copied they are
|
|
217
|
+
app code: give their texts the app's own keys.
|
|
218
|
+
- The startup HTML in `index.html` (for example "Loading application…"), shown
|
|
219
|
+
before any JavaScript runs.
|
|
220
|
+
|
|
221
|
+
## Checks inside JSKIT
|
|
222
|
+
|
|
223
|
+
Each JSKIT package with a catalog has a test that compiles every message with
|
|
224
|
+
vue-i18n, requires every key and dotted code its source uses to exist, rejects
|
|
225
|
+
unused keys and refuses a key another package already defines. ESLint's
|
|
226
|
+
`@intlify/vue-i18n/no-raw-text` rule rejects untranslated template text in JSKIT
|
|
227
|
+
client code.
|