mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 07:45:18 +00:00
feat(locale): allows to manage locale resources in core package (#2293)
* feat(locale): add app.locales * chore: change directory * chore: change locale directories * fix: test * fix: cached resources changed after sync * chore: change fr-FR locale directory
This commit is contained in:
parent
e27c72e8b0
commit
45bc0b83ba
@ -16,4 +16,4 @@
|
||||
"directory": "packages/actions"
|
||||
},
|
||||
"gitHead": "ce588eefb0bfc50f7d5bbee575e0b5e843bf6644"
|
||||
}
|
||||
}
|
@ -19,4 +19,4 @@
|
||||
"directory": "packages/resourcer"
|
||||
},
|
||||
"gitHead": "ce588eefb0bfc50f7d5bbee575e0b5e843bf6644"
|
||||
}
|
||||
}
|
@ -31,4 +31,4 @@
|
||||
"@types/semver": "^7.3.9"
|
||||
},
|
||||
"gitHead": "ce588eefb0bfc50f7d5bbee575e0b5e843bf6644"
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import { createACL } from './acl';
|
||||
import { AppManager } from './app-manager';
|
||||
import { registerCli } from './commands';
|
||||
import { createI18n, createResourcer, registerMiddlewares } from './helper';
|
||||
import { Locale } from './locale';
|
||||
import { Plugin } from './plugin';
|
||||
import { InstallOptions, PluginManager } from './plugin-manager';
|
||||
|
||||
@ -167,6 +168,8 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
|
||||
|
||||
protected _authManager: AuthManager;
|
||||
|
||||
protected _locales: Locale;
|
||||
|
||||
protected _version: ApplicationVersion;
|
||||
|
||||
protected plugins = new Map<string, Plugin>();
|
||||
@ -230,6 +233,10 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
|
||||
return this._logger;
|
||||
}
|
||||
|
||||
get locales() {
|
||||
return this._locales;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.options.name || 'main';
|
||||
}
|
||||
@ -298,6 +305,8 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
|
||||
this._resourcer.use(this._acl.middleware(), { tag: 'acl', after: ['auth'] });
|
||||
}
|
||||
|
||||
this._locales = new Locale(this);
|
||||
|
||||
registerMiddlewares(this, options);
|
||||
|
||||
if (options.registerActions !== false) {
|
||||
|
1
packages/core/server/src/locale/index.ts
Normal file
1
packages/core/server/src/locale/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './locale';
|
68
packages/core/server/src/locale/locale.ts
Normal file
68
packages/core/server/src/locale/locale.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { Cache, createCache } from '@nocobase/cache';
|
||||
import { lodash } from '@nocobase/utils';
|
||||
import Application from '../application';
|
||||
import { PluginManager } from '../plugin-manager';
|
||||
import { getAntdLocale } from './antd';
|
||||
import { getCronstrueLocale } from './cronstrue';
|
||||
import { getResource } from './resource';
|
||||
|
||||
export class Locale {
|
||||
app: Application;
|
||||
cache: Cache;
|
||||
defaultLang = 'en-US';
|
||||
|
||||
constructor(app: Application) {
|
||||
this.app = app;
|
||||
this.cache = createCache();
|
||||
|
||||
this.app.on('afterLoad', () => this.load());
|
||||
}
|
||||
|
||||
load() {
|
||||
this.getCacheResources(this.defaultLang);
|
||||
}
|
||||
|
||||
async get(lang: string) {
|
||||
return {
|
||||
antd: await this.wrapCache(`locale:antd:${lang}`, () => getAntdLocale(lang)),
|
||||
cronstrue: await this.wrapCache(`locale:cronstrue:${lang}`, () => getCronstrueLocale(lang)),
|
||||
resources: await this.getCacheResources(lang),
|
||||
};
|
||||
}
|
||||
|
||||
async wrapCache(key: string, fn: () => any) {
|
||||
const result = await this.cache.get(key);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
const value = await fn();
|
||||
if (lodash.isEmpty(value)) {
|
||||
return value;
|
||||
}
|
||||
await this.cache.set(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
async getCacheResources(lang: string) {
|
||||
return await this.wrapCache(`locale:resources:${lang}`, () => this.getResources(lang));
|
||||
}
|
||||
|
||||
getResources(lang: string) {
|
||||
const resources = {};
|
||||
const plugins = this.app.pm.getPlugins();
|
||||
for (const name of plugins.keys()) {
|
||||
try {
|
||||
const packageName = PluginManager.getPackageName(name);
|
||||
const res = getResource(packageName, lang);
|
||||
if (res) {
|
||||
resources[name] = { ...res };
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
const res = getResource('@nocobase/client', lang);
|
||||
if (res) {
|
||||
resources['client'] = { ...(resources['client'] || {}), ...res };
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
}
|
27
packages/core/server/src/locale/resource.ts
Normal file
27
packages/core/server/src/locale/resource.ts
Normal file
@ -0,0 +1,27 @@
|
||||
const arr2obj = (items: any[]) => {
|
||||
const obj = {};
|
||||
for (const item of items) {
|
||||
Object.assign(obj, item);
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
export const getResource = (packageName: string, lang: string) => {
|
||||
const resources = [];
|
||||
const prefixes = ['src', 'lib'];
|
||||
for (const prefix of prefixes) {
|
||||
try {
|
||||
const file = `${packageName}/${prefix}/locale/${lang}`;
|
||||
require.resolve(file);
|
||||
const resource = require(file).default;
|
||||
resources.push(resource);
|
||||
} catch (error) {}
|
||||
if (resources.length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (resources.length === 0 && lang.replace('-', '_') !== lang) {
|
||||
return getResource(packageName, lang.replace('-', '_'));
|
||||
}
|
||||
return arr2obj(resources);
|
||||
};
|
@ -16,6 +16,7 @@ const locale = {
|
||||
'7 Days': '7 天',
|
||||
'30 Days': '30 天',
|
||||
'90 Days': '90 天',
|
||||
'Role not found': '角色不存在',
|
||||
};
|
||||
|
||||
export default locale;
|
@ -1,10 +0,0 @@
|
||||
const locale = {
|
||||
'Auth Type': '认证类型',
|
||||
Authenticators: '认证器',
|
||||
Authentication: '用户认证',
|
||||
'Sign in via email': '邮箱登录',
|
||||
'Not allowed to sign up': '禁止注册',
|
||||
'Allow to sign up': '允许注册',
|
||||
};
|
||||
|
||||
export default locale;
|
17
packages/plugins/auth/src/locale/zh-CN.ts
Normal file
17
packages/plugins/auth/src/locale/zh-CN.ts
Normal file
@ -0,0 +1,17 @@
|
||||
const locale = {
|
||||
'Auth Type': '认证类型',
|
||||
Authenticators: '认证器',
|
||||
Authentication: '用户认证',
|
||||
'Sign in via email': '邮箱登录',
|
||||
'Not allowed to sign up': '禁止注册',
|
||||
'Allow to sign up': '允许注册',
|
||||
'The email is incorrect, please re-enter': '邮箱有误,请重新输入',
|
||||
'Please fill in your email address': '请填写邮箱',
|
||||
'The password is incorrect, please re-enter': '密码有误,请重新输入',
|
||||
'Not a valid cellphone number, please re-enter': '不是有效的手机号,请重新输入',
|
||||
'The phone number has been registered, please login directly': '手机号已注册,请直接登录',
|
||||
'The phone number is not registered, please register first': '手机号未注册,请先注册',
|
||||
'Please keep and enable at least one authenticator': '请至少保留并启用一个认证器',
|
||||
};
|
||||
|
||||
export default locale;
|
@ -1,23 +0,0 @@
|
||||
export default {
|
||||
Edit: 'Modifier',
|
||||
Delete: 'Supprimer',
|
||||
Cancel: 'Annuler',
|
||||
Submit: 'Envoyer',
|
||||
Actions: 'Actions',
|
||||
Title: 'Titre',
|
||||
Enable: 'Activer',
|
||||
'SAML manager': 'SAML manager',
|
||||
'SAML Providers': 'SAML Providers',
|
||||
'Redirect url': 'URL de redirection',
|
||||
'SP entity id': 'SP entity id',
|
||||
'Add provider': 'Ajouter',
|
||||
'Edit provider': 'Modifier',
|
||||
'Client id': 'Client id',
|
||||
'Entity id or issuer': 'Entity id or issuer',
|
||||
'Login Url': 'URL de connexion',
|
||||
'Public cert': 'Public cert',
|
||||
'Delete provider': 'Supprimer',
|
||||
'Are you sure you want to delete it?': 'Êtes-vous sûr de vouloir le supprimer ?',
|
||||
'Sign in button name, which will be displayed on the sign in page':
|
||||
'Nom du bouton de connexion, qui sera affiché sur la page de connexion',
|
||||
};
|
@ -1 +1 @@
|
||||
export { default, getResourceLocale } from './server';
|
||||
export { default } from './server';
|
||||
|
@ -1,2 +1 @@
|
||||
export { getResourceLocale } from './resource';
|
||||
export { default } from './server';
|
||||
|
@ -1,141 +0,0 @@
|
||||
const locales = {
|
||||
af: 'af',
|
||||
'ar-dz': 'ar-dz',
|
||||
'ar-kw': 'ar-kw',
|
||||
'ar-ly': 'ar-ly',
|
||||
'ar-ma': 'ar-ma',
|
||||
'ar-sa': 'ar-sa',
|
||||
'ar-tn': 'ar-tn',
|
||||
ar: 'ar',
|
||||
az: 'az',
|
||||
be: 'be',
|
||||
bg: 'bg',
|
||||
bm: 'bm',
|
||||
'bn-bd': 'bn-bd',
|
||||
bn: 'bn',
|
||||
bo: 'bo',
|
||||
br: 'br',
|
||||
bs: 'bs',
|
||||
ca: 'ca',
|
||||
cs: 'cs',
|
||||
cv: 'cv',
|
||||
cy: 'cy',
|
||||
da: 'da',
|
||||
'de-at': 'de-at',
|
||||
'de-ch': 'de-ch',
|
||||
de: 'de',
|
||||
dv: 'dv',
|
||||
el: 'el',
|
||||
'en-au': 'en-au',
|
||||
'en-ca': 'en-ca',
|
||||
'en-gb': 'en-gb',
|
||||
'en-ie': 'en-ie',
|
||||
'en-il': 'en-il',
|
||||
'en-in': 'en-in',
|
||||
'en-nz': 'en-nz',
|
||||
'en-sg': 'en-sg',
|
||||
eo: 'eo',
|
||||
'es-do': 'es-do',
|
||||
'es-mx': 'es-mx',
|
||||
'es-us': 'es-us',
|
||||
es: 'es',
|
||||
et: 'et',
|
||||
eu: 'eu',
|
||||
fa: 'fa',
|
||||
fi: 'fi',
|
||||
fil: 'fil',
|
||||
fo: 'fo',
|
||||
'fr-ca': 'fr-ca',
|
||||
'fr-ch': 'fr-ch',
|
||||
fr: 'fr',
|
||||
fy: 'fy',
|
||||
ga: 'ga',
|
||||
gd: 'gd',
|
||||
gl: 'gl',
|
||||
'gom-deva': 'gom-deva',
|
||||
'gom-latn': 'gom-latn',
|
||||
gu: 'gu',
|
||||
he: 'he',
|
||||
hi: 'hi',
|
||||
hr: 'hr',
|
||||
hu: 'hu',
|
||||
'hy-am': 'hy-am',
|
||||
id: 'id',
|
||||
is: 'is',
|
||||
'it-ch': 'it-ch',
|
||||
it: 'it',
|
||||
'ja-JP': 'ja',
|
||||
jv: 'jv',
|
||||
ka: 'ka',
|
||||
kk: 'kk',
|
||||
km: 'km',
|
||||
kn: 'kn',
|
||||
ko: 'ko',
|
||||
ku: 'ku',
|
||||
ky: 'ky',
|
||||
lb: 'lb',
|
||||
lo: 'lo',
|
||||
lt: 'lt',
|
||||
lv: 'lv',
|
||||
me: 'me',
|
||||
mi: 'mi',
|
||||
mk: 'mk',
|
||||
ml: 'ml',
|
||||
mn: 'mn',
|
||||
mr: 'mr',
|
||||
'ms-my': 'ms-my',
|
||||
ms: 'ms',
|
||||
mt: 'mt',
|
||||
my: 'my',
|
||||
nb: 'nb',
|
||||
ne: 'ne',
|
||||
'nl-be': 'nl-be',
|
||||
nl: 'nl',
|
||||
nn: 'nn',
|
||||
'oc-lnc': 'oc-lnc',
|
||||
'pa-in': 'pa-in',
|
||||
pl: 'pl',
|
||||
'pt-br': 'pt-br',
|
||||
pt: 'pt',
|
||||
ro: 'ro',
|
||||
'ru-RU': 'ru',
|
||||
sd: 'sd',
|
||||
se: 'se',
|
||||
si: 'si',
|
||||
sk: 'sk',
|
||||
sl: 'sl',
|
||||
sq: 'sq',
|
||||
'sr-cyrl': 'sr-cyrl',
|
||||
sr: 'sr',
|
||||
ss: 'ss',
|
||||
sv: 'sv',
|
||||
sw: 'sw',
|
||||
ta: 'ta',
|
||||
te: 'te',
|
||||
tet: 'tet',
|
||||
tg: 'tg',
|
||||
'th-TH': 'th',
|
||||
tk: 'tk',
|
||||
'tl-ph': 'tl-ph',
|
||||
tlh: 'tlh',
|
||||
'tr-TR': 'tr',
|
||||
tzl: 'tzl',
|
||||
'tzm-latn': 'tzm-latn',
|
||||
tzm: 'tzm',
|
||||
'ug-cn': 'ug-cn',
|
||||
uk: 'uk',
|
||||
ur: 'ur',
|
||||
'uz-latn': 'uz-latn',
|
||||
uz: 'uz',
|
||||
vi: 'vi',
|
||||
'x-pseudo': 'x-pseudo',
|
||||
yo: 'yo',
|
||||
'zh-CN': 'zh-cn',
|
||||
'zh-hk': 'zh-hk',
|
||||
'zh-mo': 'zh-mo',
|
||||
'zh-TW': 'zh-tw',
|
||||
};
|
||||
|
||||
export const getMomentLocale = (lang: string) => {
|
||||
return locales[lang] || 'en';
|
||||
};
|
@ -1,69 +0,0 @@
|
||||
import { PluginManager } from '@nocobase/server';
|
||||
|
||||
const arr2obj = (items: any[]) => {
|
||||
const obj = {};
|
||||
for (const item of items) {
|
||||
Object.assign(obj, item);
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
const getResource = (packageName: string, lang: string) => {
|
||||
const resources = [];
|
||||
const prefixes = ['src', 'lib'];
|
||||
const localeKeys = ['locale', 'client/locale', 'server/locale'];
|
||||
for (const prefix of prefixes) {
|
||||
for (const localeKey of localeKeys) {
|
||||
try {
|
||||
const file = `${packageName}/${prefix}/${localeKey}/${lang}`;
|
||||
require.resolve(file);
|
||||
const resource = require(file).default;
|
||||
resources.push(resource);
|
||||
} catch (error) {}
|
||||
}
|
||||
if (resources.length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (resources.length === 0 && lang.replace('-', '_') !== lang) {
|
||||
return getResource(packageName, lang.replace('-', '_'));
|
||||
}
|
||||
return arr2obj(resources);
|
||||
};
|
||||
|
||||
export const getResourceLocale = async (lang: string, db: any) => {
|
||||
const resources = {};
|
||||
const res = getResource('@nocobase/client', lang);
|
||||
const defaults = getResource('@nocobase/client', 'zh-CN');
|
||||
for (const key in defaults) {
|
||||
if (Object.prototype.hasOwnProperty.call(defaults, key)) {
|
||||
defaults[key] = key;
|
||||
}
|
||||
}
|
||||
if (res) {
|
||||
resources['client'] = { ...defaults, ...res };
|
||||
} else {
|
||||
resources['client'] = defaults;
|
||||
}
|
||||
const plugins = await db.getRepository('applicationPlugins').find({
|
||||
filter: {
|
||||
'name.$ne': 'client',
|
||||
},
|
||||
});
|
||||
for (const plugin of plugins) {
|
||||
const packageName = PluginManager.getPackageName(plugin.get('name'));
|
||||
const res = getResource(packageName, lang);
|
||||
const defaults = getResource(packageName, 'zh-CN');
|
||||
for (const key in defaults) {
|
||||
if (Object.prototype.hasOwnProperty.call(defaults, key)) {
|
||||
defaults[key] = key;
|
||||
}
|
||||
}
|
||||
if (res) {
|
||||
resources[plugin.get('name')] = { ...defaults, ...res };
|
||||
} else {
|
||||
resources['client'] = defaults;
|
||||
}
|
||||
}
|
||||
return resources;
|
||||
};
|
@ -1,14 +1,8 @@
|
||||
import { Plugin, PluginManager } from '@nocobase/server';
|
||||
import { lodash } from '@nocobase/utils';
|
||||
import fs from 'fs';
|
||||
import send from 'koa-send';
|
||||
import serve from 'koa-static';
|
||||
import { isAbsolute, resolve } from 'path';
|
||||
import { getAntdLocale } from './antd';
|
||||
import { getCronLocale } from './cron';
|
||||
import { getCronstrueLocale } from './cronstrue';
|
||||
import { getMomentLocale } from './moment-locale';
|
||||
import { getResourceLocale } from './resource';
|
||||
|
||||
async function getReadMe(name: string, locale: string) {
|
||||
const packageName = PluginManager.getPackageName(name);
|
||||
@ -128,7 +122,6 @@ export class ClientPlugin extends Plugin {
|
||||
actions: ['app:reboot', 'app:clearCache'],
|
||||
});
|
||||
const dialect = this.app.db.sequelize.getDialect();
|
||||
const locales = require('./locale').default;
|
||||
const restartMark = resolve(process.cwd(), 'storage', 'restart');
|
||||
this.app.on('beforeStart', async () => {
|
||||
if (fs.existsSync(restartMark)) {
|
||||
@ -159,25 +152,10 @@ export class ClientPlugin extends Plugin {
|
||||
},
|
||||
async getLang(ctx, next) {
|
||||
const lang = await getLang(ctx);
|
||||
if (lodash.isEmpty(locales[lang])) {
|
||||
locales[lang] = {};
|
||||
}
|
||||
if (lodash.isEmpty(locales[lang].resources)) {
|
||||
locales[lang].resources = await getResourceLocale(lang, ctx.db);
|
||||
}
|
||||
if (lodash.isEmpty(locales[lang].antd)) {
|
||||
locales[lang].antd = getAntdLocale(lang);
|
||||
}
|
||||
if (lodash.isEmpty(locales[lang].cronstrue)) {
|
||||
locales[lang].cronstrue = getCronstrueLocale(lang);
|
||||
}
|
||||
if (lodash.isEmpty(locales[lang].cron)) {
|
||||
locales[lang].cron = getCronLocale(lang);
|
||||
}
|
||||
const resources = await ctx.app.locales.get(lang);
|
||||
ctx.body = {
|
||||
lang,
|
||||
moment: getMomentLocale(lang),
|
||||
...locales[lang],
|
||||
...resources,
|
||||
};
|
||||
await next();
|
||||
},
|
||||
|
8
packages/plugins/duplicator/src/locale/zh-CN.ts
Normal file
8
packages/plugins/duplicator/src/locale/zh-CN.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export default {
|
||||
'Select Import data': '请选择导入数据',
|
||||
'Select Import Plugins': '请选择导入插件',
|
||||
'Select User Collections': '请选择用户数据',
|
||||
'Basic Data': '基础数据',
|
||||
'Optional Data': '可选数据',
|
||||
'User Data': '用户数据',
|
||||
};
|
6
packages/plugins/error-handler/src/locale/en_US.ts
Normal file
6
packages/plugins/error-handler/src/locale/en_US.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
'unique violation': '{{field}} must be unique',
|
||||
'notNull violation': 'notNull violation',
|
||||
'Validation error': '{{field}} validation error',
|
||||
'notNull Violation': '{{field}} cannot be null',
|
||||
};
|
6
packages/plugins/error-handler/src/locale/es-ES.ts
Normal file
6
packages/plugins/error-handler/src/locale/es-ES.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
"unique violation": "{{field}} debe ser único",
|
||||
"notNull violation": "notNull violación",
|
||||
"Validation error": "{{field}} error de validación",
|
||||
"notNull Violation": "{{field}} no puede ser null"
|
||||
};
|
6
packages/plugins/error-handler/src/locale/fr_FR.ts
Normal file
6
packages/plugins/error-handler/src/locale/fr_FR.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
'unique violation': '{{field}} doit être unique',
|
||||
'notNull violation': 'Violation de contrainte notNull',
|
||||
'Validation error': 'Erreur de validation de {{field}}',
|
||||
'notNull Violation': '{{field}} ne peut pas être null',
|
||||
};
|
4
packages/plugins/error-handler/src/locale/ja_JP.ts
Normal file
4
packages/plugins/error-handler/src/locale/ja_JP.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export default {
|
||||
'unique violation': '{{field}} は一意でなくてはなりません',
|
||||
'notNull Violation': '{{field}} はNullにできません',
|
||||
};
|
6
packages/plugins/error-handler/src/locale/pt-BR.ts
Normal file
6
packages/plugins/error-handler/src/locale/pt-BR.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
'unique violation': '{{field}} deve ser único',
|
||||
'notNull violation': 'violação de não nulo',
|
||||
'Validation error': 'erro de validação de {{field}}',
|
||||
'notNull Violation': '{{field}} não pode ser nulo',
|
||||
};
|
5
packages/plugins/error-handler/src/locale/zh_CN.ts
Normal file
5
packages/plugins/error-handler/src/locale/zh_CN.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
'unique violation': '{{field}} 字段值是唯一的',
|
||||
'notNull violation': '{{field}} 字段不能为空',
|
||||
'Validation error': '{{field}} 字段规则验证失败',
|
||||
};
|
@ -1,21 +1,21 @@
|
||||
export default {
|
||||
'File manager': 'File manager',
|
||||
'Attachment': 'Attachment',
|
||||
Attachment: 'Attachment',
|
||||
'MIME type': 'MIME type',
|
||||
'Storage display name': 'Storage display name',
|
||||
'Storage name': 'Storage name',
|
||||
'Storage type': 'Storage type',
|
||||
'Default storage': 'Default storage',
|
||||
'Storage base URL': 'Storage base URL',
|
||||
'Destination': 'Destination',
|
||||
Destination: 'Destination',
|
||||
'Use the built-in static file server': 'Use the built-in static file server',
|
||||
'Local storage': 'Local storage',
|
||||
'Aliyun OSS': 'Aliyun OSS',
|
||||
'Tencent COS': 'Tencent COS',
|
||||
'Amazon S3': 'Amazon S3',
|
||||
'Region': 'Region',
|
||||
'Bucket': 'Bucket',
|
||||
'Path': 'Path',
|
||||
'Filename': 'Filename',
|
||||
Region: 'Region',
|
||||
Bucket: 'Bucket',
|
||||
Path: 'Path',
|
||||
Filename: 'Filename',
|
||||
'Will be used for API': 'Will be used for API',
|
||||
};
|
@ -1,21 +1,21 @@
|
||||
export default {
|
||||
'File manager': 'Gestionnaire de fichiers',
|
||||
'Attachment': 'Pièce jointe',
|
||||
Attachment: 'Pièce jointe',
|
||||
'MIME type': 'Type MIME',
|
||||
'Storage display name': 'Nom d\'affichage du stockage',
|
||||
'Storage display name': "Nom d'affichage du stockage",
|
||||
'Storage name': 'Nom du stockage',
|
||||
'Storage type': 'Type de stockage',
|
||||
'Default storage': 'Stockage par défaut',
|
||||
'Storage base URL': 'URL de base du stockage',
|
||||
'Destination': 'Destination',
|
||||
Destination: 'Destination',
|
||||
'Use the built-in static file server': 'Utiliser le serveur de fichiers statique intégré',
|
||||
'Local storage': 'Stockage local',
|
||||
'Aliyun OSS': 'Aliyun OSS',
|
||||
'Tencent COS': 'Tencent COS',
|
||||
'Amazon S3': 'Amazon S3',
|
||||
'Region': 'Region',
|
||||
'Bucket': 'Bucket',
|
||||
'Path': 'Chemin',
|
||||
'Filename': 'Nom de fichier',
|
||||
'Will be used for API': 'Sera utilisé pour l\'API',
|
||||
Region: 'Region',
|
||||
Bucket: 'Bucket',
|
||||
Path: 'Chemin',
|
||||
Filename: 'Nom de fichier',
|
||||
'Will be used for API': "Sera utilisé pour l'API",
|
||||
};
|
@ -1,3 +1,3 @@
|
||||
export { default as enUS } from './en-US';
|
||||
export { default as zhCN } from './zh-CN';
|
||||
export { default as jaJP } from './ja-JP';
|
||||
// export { default as enUS } from './en-US';
|
||||
// export { default as zhCN } from './zh-CN';
|
||||
// export { default as jaJP } from './ja-JP';
|
||||
|
@ -5,11 +5,11 @@ export default {
|
||||
'Collection Search': 'Recherche de collection',
|
||||
'Create Collection': 'Créer une collection',
|
||||
'All Fields': 'Tous les champs',
|
||||
'Association Fields': 'Champs d\'association',
|
||||
'Association Fields': "Champs d'association",
|
||||
'Choices fields': 'Champs de choix',
|
||||
'All relationships': 'Toutes les relations',
|
||||
'Entity relationship only': 'Uniquement les relations d\'entité',
|
||||
'Inheritance relationship only': 'Uniquement les relations d\'héritage',
|
||||
'Entity relationship only': "Uniquement les relations d'entité",
|
||||
'Inheritance relationship only': "Uniquement les relations d'héritage",
|
||||
'Graphical interface': 'Interface graphique',
|
||||
'Selection': 'Sélection',
|
||||
Selection: 'Sélection',
|
||||
};
|
@ -1,2 +1,2 @@
|
||||
export { default as enUS } from './en-US';
|
||||
export { default as zhCN } from './zh-CN';
|
||||
// export { default as enUS } from './en-US';
|
||||
// export { default as zhCN } from './zh-CN';
|
||||
|
@ -20,4 +20,11 @@ export default {
|
||||
Yes: '是',
|
||||
No: '否',
|
||||
'Field {{fieldName}} does not exist': '字段 {{fieldName}} 不存在',
|
||||
'can not find value': '找不到对应值',
|
||||
'password is empty': '密码为空',
|
||||
'Incorrect time format': '时间格式不正确',
|
||||
'Incorrect date format': '日期格式不正确',
|
||||
'Incorrect email format': '邮箱格式不正确',
|
||||
'Illegal percentage format': '百分比格式有误',
|
||||
'Imported template does not match, please download again.': '导入模板不匹配,请检查导入文件标题行或重新下载导入模板',
|
||||
};
|
@ -18,4 +18,4 @@
|
||||
"displayName.zh-CN": "多语言管理",
|
||||
"description": "Allows to manage localization resources of the application.",
|
||||
"description.zh-CN": "支持管理应用程序的多语言资源。"
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import { Context, Next } from '@nocobase/actions';
|
||||
import { Database, Model, Op } from '@nocobase/database';
|
||||
import { getResourceLocale } from '@nocobase/plugin-client';
|
||||
import { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
||||
import LocalizationManagementPlugin from '../plugin';
|
||||
import { getTextsFromDBRecord, getTextsFromUISchema } from '../utils';
|
||||
@ -10,8 +9,8 @@ const getResourcesInstance = async (ctx: Context) => {
|
||||
return plugin.resources;
|
||||
};
|
||||
|
||||
export const getResources = async (locale: string, db: Database) => {
|
||||
const resources = await getResourceLocale(locale, db);
|
||||
export const getResources = async (ctx: Context) => {
|
||||
const resources = await ctx.app.locales.getCacheResources(ctx.get('X-Locale') || 'en-US');
|
||||
const client = resources['client'];
|
||||
// Remove duplicated keys
|
||||
Object.keys(resources).forEach((module) => {
|
||||
@ -24,7 +23,7 @@ export const getResources = async (locale: string, db: Database) => {
|
||||
}
|
||||
});
|
||||
});
|
||||
return resources;
|
||||
return { ...resources };
|
||||
};
|
||||
|
||||
export const getUISchemas = async (db: Database) => {
|
||||
@ -174,7 +173,7 @@ const sync = async (ctx: Context, next: Next) => {
|
||||
|
||||
let resources: { [module: string]: any } = { client: {} };
|
||||
if (type.includes('local')) {
|
||||
resources = await getResources(locale, ctx.db);
|
||||
resources = await getResources(ctx);
|
||||
}
|
||||
if (type.includes('menu')) {
|
||||
const menuTexts = await getTextsFromMenu(ctx.db);
|
||||
|
@ -1,5 +1,3 @@
|
||||
const locale = {
|
||||
|
||||
}
|
||||
const locale = {};
|
||||
|
||||
export default locale;
|
@ -1,5 +1,3 @@
|
||||
const locale = {
|
||||
|
||||
}
|
||||
const locale = {};
|
||||
|
||||
export default locale;
|
@ -1,9 +0,0 @@
|
||||
export default {
|
||||
"Multi-app manager": "Gestor de aplicaciones múltiples",
|
||||
"Applications": "Aplicaciones",
|
||||
"App display name": "Mostrar nombre de aplicación",
|
||||
"App ID": "ID de aplicación",
|
||||
"Pin to menu": " Fijar al menú",
|
||||
"Custom domain": "Dominio personalizado",
|
||||
"Manage applications": "Gestionar aplicaciones"
|
||||
};
|
9
packages/plugins/multi-app-manager/src/locale/es-ES.ts
Normal file
9
packages/plugins/multi-app-manager/src/locale/es-ES.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export default {
|
||||
'Multi-app manager': 'Gestor de aplicaciones múltiples',
|
||||
Applications: 'Aplicaciones',
|
||||
'App display name': 'Mostrar nombre de aplicación',
|
||||
'App ID': 'ID de aplicación',
|
||||
'Pin to menu': ' Fijar al menú',
|
||||
'Custom domain': 'Dominio personalizado',
|
||||
'Manage applications': 'Gestionar aplicaciones',
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
export default {
|
||||
"Share collections": "Tablas compartidas",
|
||||
"Unshared collections": "Tablas no compartidas",
|
||||
"Shared collections": "Tablas compartidas",
|
||||
"All categories": "Todas las categorías",
|
||||
"Enter name or title...": "Introducir nombre o título...",
|
||||
"Are you sure to add the following collections?": "¿Está seguro de que desea añadir las siguientes tablas?",
|
||||
"Are you sure to remove the following collections?": "¿Está seguro de que desea eliminar las siguientes tablas?",
|
||||
"Collection display name": "Mostrar nombre de la tabla",
|
||||
"Collection name": "Nombre de la tabla",
|
||||
"Collection category": "Categoría de tabla"
|
||||
};
|
||||
|
@ -0,0 +1,12 @@
|
||||
export default {
|
||||
'Share collections': 'Tablas compartidas',
|
||||
'Unshared collections': 'Tablas no compartidas',
|
||||
'Shared collections': 'Tablas compartidas',
|
||||
'All categories': 'Todas las categorías',
|
||||
'Enter name or title...': 'Introducir nombre o título...',
|
||||
'Are you sure to add the following collections?': '¿Está seguro de que desea añadir las siguientes tablas?',
|
||||
'Are you sure to remove the following collections?': '¿Está seguro de que desea eliminar las siguientes tablas?',
|
||||
'Collection display name': 'Mostrar nombre de la tabla',
|
||||
'Collection name': 'Nombre de la tabla',
|
||||
'Collection category': 'Categoría de tabla',
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
export default {
|
||||
Edit: 'Modifier',
|
||||
Delete: 'Supprimer',
|
||||
Cancel: 'Annuler',
|
||||
Submit: 'Envoyer',
|
||||
Actions: 'Actions',
|
||||
Title: 'Titre',
|
||||
Enable: 'Activer',
|
||||
'SAML manager': 'SAML manager',
|
||||
'SAML Providers': 'SAML Providers',
|
||||
'Redirect url': 'Url de redirection',
|
||||
'SP entity id': 'SP entity id',
|
||||
'Add provider': 'Ajouter',
|
||||
'Edit provider': 'Modifier',
|
||||
'Client id': 'Client id',
|
||||
'Entity id or issuer': 'Entity id or issuer',
|
||||
'Login Url': 'Url de connexion',
|
||||
'Public cert': 'Public cert',
|
||||
'Delete provider': 'Supprimer',
|
||||
'Are you sure you want to delete it?': 'Êtes-vous sûr de vouloir le supprimer ?',
|
||||
'Sign in button name, which will be displayed on the sign in page':
|
||||
'Nom du bouton de connexion, qui sera affiché sur la page de connexion',
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user