mirror of
https://github.com/nocobase/nocobase.git
synced 2026-08-28 17:43:07 +08:00
feat(client): support filtered application language resources (#10175)
This commit is contained in:
@@ -13,7 +13,22 @@ export default {
|
||||
tags: ['app'],
|
||||
summary: 'Get the current application language',
|
||||
description: 'Return the current locale used by the server.',
|
||||
parameters: [],
|
||||
parameters: [
|
||||
{
|
||||
name: 'locale',
|
||||
in: 'query',
|
||||
required: false,
|
||||
schema: { type: 'string' },
|
||||
description: 'Requested application locale. The server validates it against enabled languages.',
|
||||
},
|
||||
{
|
||||
name: 'ns',
|
||||
in: 'query',
|
||||
required: false,
|
||||
schema: { type: 'string' },
|
||||
description: 'Comma-separated resource namespaces to return. Omit it to preserve the full legacy payload.',
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
200: {
|
||||
description: 'OK',
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { filterLocaleResources, parseLocaleResourceNamespaces } from '../localeResources';
|
||||
|
||||
describe('locale resource filtering', () => {
|
||||
it('accepts comma-separated and repeated namespace query values', () => {
|
||||
expect(parseLocaleResourceNamespaces(['lm-collections,plugin-a', ' plugin-a , plugin-b '])).toEqual([
|
||||
'lm-collections',
|
||||
'plugin-a',
|
||||
'plugin-b',
|
||||
]);
|
||||
});
|
||||
|
||||
it('preserves the legacy full payload when ns is omitted', () => {
|
||||
const payload = {
|
||||
resources: {
|
||||
client: { Save: 'Save' },
|
||||
'lm-collections': { Users: 'Users' },
|
||||
},
|
||||
antd: { locale: 'en' },
|
||||
};
|
||||
|
||||
expect(filterLocaleResources(payload, undefined)).toBe(payload);
|
||||
});
|
||||
|
||||
it('filters only the resources map and preserves other locale payloads', () => {
|
||||
const payload = {
|
||||
resources: {
|
||||
client: { Save: 'Save' },
|
||||
'lm-collections': { Users: 'Users' },
|
||||
'plugin-a': { Title: 'Title' },
|
||||
},
|
||||
antd: { locale: 'en' },
|
||||
cron: { every: 'every' },
|
||||
};
|
||||
|
||||
expect(filterLocaleResources(payload, 'lm-collections,plugin-a,missing')).toEqual({
|
||||
resources: {
|
||||
'lm-collections': { Users: 'Users' },
|
||||
'plugin-a': { Title: 'Title' },
|
||||
},
|
||||
antd: { locale: 'en' },
|
||||
cron: { every: 'every' },
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
export function parseLocaleResourceNamespaces(value: unknown): string[] {
|
||||
const values = Array.isArray(value) ? value : [value];
|
||||
return [
|
||||
...new Set(
|
||||
values
|
||||
.flatMap((item) => (typeof item === 'string' ? item.split(',') : []))
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
export function filterLocaleResources<T extends { resources?: Record<string, unknown> }>(
|
||||
payload: T,
|
||||
namespaceQuery: unknown,
|
||||
): T {
|
||||
const namespaces = parseLocaleResourceNamespaces(namespaceQuery);
|
||||
if (!namespaces.length) return payload;
|
||||
|
||||
const resources = payload.resources || {};
|
||||
return {
|
||||
...payload,
|
||||
resources: Object.fromEntries(
|
||||
namespaces
|
||||
.filter((namespace) => Object.prototype.hasOwnProperty.call(resources, namespace))
|
||||
.map((namespace) => [namespace, resources[namespace]]),
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import { listAppPortals } from './appPortals';
|
||||
import { getAntdLocale } from './antd';
|
||||
import { getCronLocale } from './cron';
|
||||
import { getCronstrueLocale } from './cronstrue';
|
||||
import { filterLocaleResources } from './localeResources';
|
||||
|
||||
async function getLang(ctx) {
|
||||
const SystemSetting = ctx.db.getRepository('systemSettings');
|
||||
@@ -115,7 +116,7 @@ export class PluginClientServer extends Plugin {
|
||||
},
|
||||
async getLang(ctx, next) {
|
||||
const lang = await getLang(ctx);
|
||||
const resources = await ctx.app.localeManager.get(lang);
|
||||
const resources = filterLocaleResources(await ctx.app.localeManager.get(lang), ctx.request.query.ns);
|
||||
ctx.body = {
|
||||
lang,
|
||||
...resources,
|
||||
|
||||
Reference in New Issue
Block a user