Skip to content

Commit f4f878f

Browse files
committed
docs improvements
1 parent a340355 commit f4f878f

File tree

3 files changed

+132
-76
lines changed

3 files changed

+132
-76
lines changed

adminforth/documentation/docs/tutorial/05-Plugins/01-AuditLog.md

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -54,54 +54,59 @@ Also, it excludes itself to avoid infinte logging loop.
5454
Add this code in `auditLogs.ts`:
5555
5656
```ts title='./resources/auditLogs.ts'
57-
export default {
58-
dataSource: 'maindb',
59-
table: 'audit_logs',
60-
columns: [
61-
{ name: 'id', primaryKey: true, required: false, fillOnCreate: ({initialRecord}: any) => uuid(),
62-
showIn: {
63-
list: false,
64-
edit: false,
65-
create: false,
66-
filter: false,
67-
} },
68-
{ name: 'created_at', required: false },
69-
{ name: 'resource_id', required: false },
70-
{ name: 'user_id', required: false,
71-
foreignResource: {
72-
resourceId: 'adminuser',
73-
} },
74-
{ name: 'action', required: false },
75-
{ name: 'diff', required: false, type: AdminForthDataTypes.JSON, showIn: {
76-
list: false,
77-
edit: false,
78-
create: false,
79-
filter: false,
80-
} },
81-
{ name: 'record_id', required: false },
82-
],
83-
options: {
84-
allowedActions: {
57+
58+
import AuditLogPlugin from "@adminforth/audit-log/index.js";
59+
import { AdminForthDataTypes } from "adminforth";
60+
import { randomUUID } from "crypto";
61+
62+
export default {
63+
dataSource: 'maindb',
64+
table: 'audit_logs',
65+
columns: [
66+
{ name: 'id', primaryKey: true, required: false, fillOnCreate: ({initialRecord}: any) => randomUUID(),
67+
showIn: {
68+
list: false,
69+
edit: false,
70+
create: false,
71+
filter: false,
72+
} },
73+
{ name: 'created_at', required: false },
74+
{ name: 'resource_id', required: false },
75+
{ name: 'user_id', required: false,
76+
foreignResource: {
77+
resourceId: 'adminuser',
78+
} },
79+
{ name: 'action', required: false },
80+
{ name: 'diff', required: false, type: AdminForthDataTypes.JSON, showIn: {
81+
list: false,
8582
edit: false,
86-
delete: false,
87-
create: false
83+
create: false,
84+
filter: false,
85+
} },
86+
{ name: 'record_id', required: false },
87+
],
88+
options: {
89+
allowedActions: {
90+
edit: false,
91+
delete: false,
92+
create: false
93+
}
94+
},
95+
plugins: [
96+
new AuditLogPlugin({
97+
// if you want to exclude some resources from logging
98+
//excludeResourceIds: ['adminuser'],
99+
resourceColumns: {
100+
resourceIdColumnName: 'resource_id',
101+
resourceActionColumnName: 'action',
102+
resourceDataColumnName: 'diff',
103+
resourceUserIdColumnName: 'user_id',
104+
resourceRecordIdColumnName: 'record_id',
105+
resourceCreatedColumnName: 'created_at'
88106
}
89-
},
90-
plugins: [
91-
new AuditLogPlugin({
92-
// if you want to exclude some resources from logging
93-
//excludeResourceIds: ['adminuser'],
94-
resourceColumns: {
95-
resourceIdColumnName: 'resource_id',
96-
resourceActionColumnName: 'action',
97-
resourceDataColumnName: 'diff',
98-
resourceUserIdColumnName: 'user_id',
99-
resourceRecordIdColumnName: 'record_id',
100-
resourceCreatedColumnName: 'created_at'
101-
}
102-
}),
103-
],
104-
}
107+
}),
108+
],
109+
}
105110
```
106111
107112
Then you need to import `./resources/auditLogs`:

adminforth/documentation/docs/tutorial/05-Plugins/10-i18n.md

Lines changed: 80 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ model translations {
4040
// we need both indexes on en_string+category and separately on category
4141
@@index([en_string, category])
4242
@@index([category])
43+
@@index([completedLangs])
4344
}
4445
```
4546
@@ -454,7 +455,7 @@ import { admin } from '../index';
454455
455456
You can use this module not only to translate admin area of your application but also to translate other parts like SEO-facing or user-facing services.
456457
This will allow you to reuse the same functionality and AI completion adapters for all your translations and manage them in one place.
457-
For example in this app we will consider translating a Nuxt.js SEO-centric frontend which we want to translate with [vue-i18n](https://vue-i18n.intlify.dev/).
458+
For example in this app we will consider translating a Nuxt.js SEO-centric frontend which we want to translate with [nuxt i18n](https://i18n.nuxtjs.org/).
458459
459460
To do it you need to use 2 exposed methods from the plugin: `feedCategoryTranslations` and `getCategoryTranslations`.
460461
@@ -478,7 +479,7 @@ First of all, at some step, e.g. CI pipeline you should get all translation stri
478479

479480
admin.getPluginByClassName<I18nPlugin>('I18nPlugin').feedCategoryTranslations(
480481
messagesForFeed,
481-
'nextApp'
482+
'seoApp'
482483
)
483484

484485
res.json({
@@ -489,60 +490,99 @@ First of all, at some step, e.g. CI pipeline you should get all translation stri
489490

490491
```
491492
492-
For extracting 18n messages we use [vue-i18n-extract](https://github.com/Spittal/vue-i18n-extract) package.
493+
For extracting i18n messages we use [vue-i18n-extract](https://github.com/Spittal/vue-i18n-extract) package.
493494
You can add extract command to `package.json`:
494495
495496
```json
496497
{
497498
"scripts": {
498-
"i18n:extract": "echo '{}' > i18n-empty.json && vue-i18n-extract report --vueFiles './src/**/*.?(js|vue)' --output ./i18n-messages.json --languageFiles 'i18n-empty.json' --add",
499-
"i18n:feed-to-backoffice": "npm run i18n:extract && curl -X POST -H 'Content-Type: application/json' -d @i18n-messages.json http://adminforth:3000/feed-nuxt-strings"
499+
"i18n:extract": "echo '{}' > i18n-empty.json && vue-i18n-extract report --vueFiles './?(pages|components)/**/*.?(js|vue)' --output ./i18n-messages.json --languageFiles 'i18n-empty.json' --add",
500+
"i18n:feed-to-local-backoffice": "npm run i18n:extract && curl -X POST -H 'Content-Type: application/json' -d @i18n-messages.json http://localhost:3000/feed-nuxt-strings"
500501
}
501502
}
502503
```
503504
504-
Make sure to replace `adminforth:3000` with AdminForth API URL. We are assuming it is docker container name in internal docker network.
505+
> For plain non-nuxt apps `--vueFiles './?(pages|components)/**/*.?(js|vue)'` should be replaced with `--vueFiles './src/**/*.?(js|vue)'`
505506
506-
So in the pipeline you should run `npm run i18n:feed-to-backoffice` to extract messages from your Nuxt.js app and feed them to AdminForth.
507+
Make sure to replace `localhost:3000` with AdminForth API URL.
507508
508-
> 👆 The example method is just a stub, please make sure you not expose endpoint to public or add some simple authorization on it,
509-
> otherwise someone might flood you with dump translations requests.
510-
511-
Then in your Nuxt.js app you should call this API and store the strings in the same.
509+
So locally you can run `npm run i18n:feed-to-local-backoffice` to extract messages from your Nuxt.js app and feed them to AdminForth.
512510
513511
Next part. When we will need translations on the nuxt instance, we should use [vue-i18n's lazy loading feature](https://vue-i18n.intlify.dev/guide/advanced/lazy):
514512
515513
```typescript title="./your-nuxt-app-source-file.ts"
516-
import { callAdminForthApi } from '@/utils';
517-
518-
export async function loadLocaleMessages(i18n, locale) {
519-
// load locale messages with dynamic import
520-
const messages = await callAdminForthApi({
521-
path: `/api/translations/?lang=${locale}`,
514+
const { locale, setLocaleMessage, } = useI18n();
515+
const { data: messages } = await useFetch(
516+
useRuntimeConfig().public.adminUrl + `api/translations/?lang=${locale.value}`,
517+
{
522518
method: 'GET',
523-
});
524-
525-
// set locale and locale message
526-
i18n.global.setLocaleMessage(locale, messages.default)
527-
528-
return nextTick()
519+
}
520+
);
521+
if (messages.value) {
522+
setLocaleMessage(locale.value, messages.value);
523+
} else {
524+
console.error('Translations or language data are missing.');
529525
}
530526
```
531527
532-
See [vue-i18n's lazy loading feature](https://vue-i18n.intlify.dev/guide/advanced/lazy) to understand where better to call `loadLocaleMessages` function.
533-
534528
Here is how API for messages will look:
535529
536530
```ts title="./index.ts"
537531
app.get(`${ADMIN_BASE_URL}/api/translations/`,
538532
async (req, res) => {
539-
const lang = req.query.lang;
540-
const messages = await admin.getPluginByClassName<I18nPlugin>('I18nPlugin').getCategoryTranslations('nextApp', lang);
533+
const lang = req.query.lang as string;
534+
const messages = await admin.getPluginByClassName<I18nPlugin>('I18nPlugin').getCategoryTranslations('seoApp', lang);
541535
res.json(messages);
542536
}
543537
);
544538
```
545539
540+
Also in `nuxt.config.ts` you can set `prefix_except_default` strategy and put it in `i18n` config as this:
541+
542+
```
543+
...
544+
i18n: {
545+
locales: ['en', 'uk', 'ja', 'fr'],
546+
defaultLocale: 'en',
547+
strategy: 'prefix_except_default',
548+
detectBrowserLanguage: false,
549+
},
550+
...
551+
```
552+
553+
554+
#### Feeding messages during build time
555+
556+
For Dockerized pipelines you can feed messages when building the image in Docker build time:
557+
558+
```dockerfile
559+
FROM node:22-alpine
560+
WORKDIR /app
561+
ADD package.json /app
562+
ADD package-lock.json /app
563+
RUN true | npm ci
564+
ADD . /app
565+
RUN --mount=type=cache,target=/app/node_modules/.cache true | npm run build
566+
567+
//diff-add
568+
# Run i18n extraction and API call
569+
//diff-add
570+
RUN npm run i18n:extract && \
571+
//diff-add
572+
curl -X POST -H 'Content-Type: application/json' -d @i18n-messages.json http://adminforth:3000/bo/api/feed-nuxt-strings
573+
574+
CMD ["node", ".output/server/index.mjs"]
575+
EXPOSE 3000
576+
```
577+
578+
This assumes that `http://adminforth:3000/` is the name of the Docker service running AdminForth.
579+
580+
This will work if you are building the image in the same Docker network as AdminForth. Otherwise you might need use absolute URL of the AdminForth instance.
581+
582+
> 👆 The example method is just a stub, please make sure you not expose endpoint to public or add some simple authorization on it,
583+
> otherwise someone might flood you with dump translations requests.
584+
585+
546586
### Get language names
547587

548588
Also you can use handy method to get language names in native and English form with emoji flags:
@@ -575,3 +615,16 @@ Response will look like this:
575615
"emojiFlag": "🇦🇷"
576616
},
577617
```
618+
619+
### Disable translation for admin (external app only)
620+
621+
If you want to use this plugin only for external app, and not backoffice, which is probably the case, you can disable translation for admin by setting `externalAppOnly` to `true`:
622+
623+
```ts title="./resources/translations.ts"
624+
new I18nPlugin({
625+
//diff-add
626+
externalAppOnly: true,
627+
supportedLanguages: ['en', 'uk', 'ja', 'fr'],
628+
...
629+
}),
630+
```

live-demo/app/resources/translations.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ export default {
3232
},
3333
plugins: [
3434
new I18nPlugin({
35-
supportedLanguages: ['en', 'uk', 'ja', 'fr', 'de'],
36-
37-
// names of the fields in the resource which will store translations
35+
supportedLanguages: ['en', 'uk', 'ja', 'fr', 'de'], // names of the fields in the resource which will store translations
3836
translationFieldNames: {
3937
en: 'en_string',
4038
uk: 'uk_string',

0 commit comments

Comments
 (0)