Merge branch 'main' into next

This commit is contained in:
nocobase[bot] 2025-03-18 09:29:50 +00:00
commit feca1396bb
7 changed files with 362 additions and 0 deletions

View File

@ -18,6 +18,7 @@ module.exports = (cli) => {
generateAppDir(); generateAppDir();
require('./global')(cli); require('./global')(cli);
require('./create-nginx-conf')(cli); require('./create-nginx-conf')(cli);
require('./locale')(cli);
require('./build')(cli); require('./build')(cli);
require('./tar')(cli); require('./tar')(cli);
require('./dev')(cli); require('./dev')(cli);

View File

@ -0,0 +1,81 @@
/**
* 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.
*/
const { Command } = require('commander');
const fg = require('fast-glob');
const fs = require('fs-extra');
const path = require('path');
const _ = require('lodash');
const deepmerge = require('deepmerge');
const { getCronstrueLocale } = require('./locale/cronstrue');
const { getReactJsCron } = require('./locale/react-js-cron');
function sortJSON(json) {
if (Array.isArray(json)) {
return json.map(sortJSON);
} else if (typeof json === 'object' && json !== null) {
const sortedKeys = Object.keys(json).sort();
const sortedObject = {};
sortedKeys.forEach((key) => {
sortedObject[key] = sortJSON(json[key]);
});
return sortedObject;
}
return json;
}
/**
*
* @param {Command} cli
*/
module.exports = (cli) => {
const locale = cli.command('locale');
locale.command('generate').action(async (options) => {
const cwd = path.resolve(process.cwd(), 'node_modules', '@nocobase');
const files = await fg('./*/src/locale/*.json', {
cwd,
});
let locales = {};
await fs.mkdirp(path.resolve(process.cwd(), 'storage/locales'));
for (const file of files) {
const locale = path.basename(file, '.json');
const pkg = path.basename(path.dirname(path.dirname(path.dirname(file))));
_.set(locales, [locale.replace(/_/g, '-'), `@nocobase/${pkg}`], await fs.readJSON(path.resolve(cwd, file)));
if (locale.includes('_')) {
await fs.rename(
path.resolve(cwd, file),
path.resolve(cwd, path.dirname(file), `${locale.replace(/_/g, '-')}.json`),
);
}
}
const zhCN = locales['zh-CN'];
const enUS = locales['en-US'];
for (const key1 in zhCN) {
for (const key2 in zhCN[key1]) {
if (!_.get(enUS, [key1, key2])) {
_.set(enUS, [key1, key2], key2);
}
}
}
for (const locale of Object.keys(locales)) {
locales[locale] = deepmerge(enUS, locales[locale]);
locales[locale]['cronstrue'] = getCronstrueLocale(locale);
locales[locale]['react-js-cron'] = getReactJsCron(locale);
}
locales = sortJSON(locales);
for (const locale of Object.keys(locales)) {
await fs.writeFile(
path.resolve(process.cwd(), 'storage/locales', `${locale}.json`),
JSON.stringify(sortJSON(locales[locale]), null, 2),
);
}
});
locale.command('sync').action(async (options) => {});
};

View File

@ -0,0 +1,122 @@
/**
* 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.
*/
const methods = [
'atX0SecondsPastTheMinuteGt20',
'atX0MinutesPastTheHourGt20',
'commaMonthX0ThroughMonthX1',
'commaYearX0ThroughYearX1',
'use24HourTimeFormatByDefault',
'anErrorOccuredWhenGeneratingTheExpressionD',
'everyMinute',
'everyHour',
'atSpace',
'everyMinuteBetweenX0AndX1',
'at',
'spaceAnd',
'everySecond',
'everyX0Seconds',
'secondsX0ThroughX1PastTheMinute',
'atX0SecondsPastTheMinute',
'everyX0Minutes',
'minutesX0ThroughX1PastTheHour',
'atX0MinutesPastTheHour',
'everyX0Hours',
'betweenX0AndX1',
'atX0',
'commaEveryDay',
'commaEveryX0DaysOfTheWeek',
'commaX0ThroughX1',
'commaAndX0ThroughX1',
'first',
'second',
'third',
'fourth',
'fifth',
'commaOnThe',
'spaceX0OfTheMonth',
'lastDay',
'commaOnTheLastX0OfTheMonth',
'commaOnlyOnX0',
'commaAndOnX0',
'commaEveryX0Months',
'commaOnlyInX0',
'commaOnTheLastDayOfTheMonth',
'commaOnTheLastWeekdayOfTheMonth',
'commaDaysBeforeTheLastDayOfTheMonth',
'firstWeekday',
'weekdayNearestDayX0',
'commaOnTheX0OfTheMonth',
'commaEveryX0Days',
'commaBetweenDayX0AndX1OfTheMonth',
'commaOnDayX0OfTheMonth',
'commaEveryHour',
'commaEveryX0Years',
'commaStartingX0',
'daysOfTheWeek',
'monthsOfTheYear',
];
const langs = {
af: 'af',
ar: 'ar',
be: 'be',
ca: 'ca',
cs: 'cs',
da: 'da',
de: 'de',
'en-US': 'en',
es: 'es',
fa: 'fa',
fi: 'fi',
fr: 'fr',
he: 'he',
hu: 'hu',
id: 'id',
it: 'it',
'ja-JP': 'ja',
ko: 'ko',
nb: 'nb',
nl: 'nl',
pl: 'pl',
pt_BR: 'pt_BR',
pt_PT: 'pt_PT',
ro: 'ro',
'ru-RU': 'ru',
sk: 'sk',
sl: 'sl',
sv: 'sv',
sw: 'sw',
'th-TH': 'th',
'tr-TR': 'tr',
uk: 'uk',
'zh-CN': 'zh_CN',
'zh-TW': 'zh_TW',
};
exports.getCronstrueLocale = (lang) => {
const lng = langs[lang] || 'en';
const Locale = require(`cronstrue/locales/${lng}`);
let locale;
if (Locale?.default) {
locale = Locale.default.locales[lng];
} else {
const L = Locale[lng];
locale = new L();
}
const items = {};
for (const method of methods) {
try {
items[method] = locale[method]();
} catch (error) {
// empty
}
}
return items;
};

View File

@ -0,0 +1,75 @@
{
"everyText": "every",
"emptyMonths": "every month",
"emptyMonthDays": "every day of the month",
"emptyMonthDaysShort": "day of the month",
"emptyWeekDays": "every day of the week",
"emptyWeekDaysShort": "day of the week",
"emptyHours": "every hour",
"emptyMinutes": "every minute",
"emptyMinutesForHourPeriod": "every",
"yearOption": "year",
"monthOption": "month",
"weekOption": "week",
"dayOption": "day",
"hourOption": "hour",
"minuteOption": "minute",
"rebootOption": "reboot",
"prefixPeriod": "Every",
"prefixMonths": "in",
"prefixMonthDays": "on",
"prefixWeekDays": "on",
"prefixWeekDaysForMonthAndYearPeriod": "and",
"prefixHours": "at",
"prefixMinutes": ":",
"prefixMinutesForHourPeriod": "at",
"suffixMinutesForHourPeriod": "minute(s)",
"errorInvalidCron": "Invalid cron expression",
"clearButtonText": "Clear",
"weekDays": [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
],
"months": [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
],
"altWeekDays": [
"SUN",
"MON",
"TUE",
"WED",
"THU",
"FRI",
"SAT"
],
"altMonths": [
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
"JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC"
]
}

View File

@ -0,0 +1,17 @@
/**
* 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.
*/
exports.getReactJsCron = (lang) => {
const langs = {
'en-US': require('./en-US.json'),
'zh-CN': require('./zh-CN.json'),
'z-TW': require('./zh-TW.json'),
}
return langs[lang] || langs['en-US'];
}

View File

@ -0,0 +1,33 @@
{
"everyText": "每",
"emptyMonths": "每月",
"emptyMonthDays": "每日(月)",
"emptyMonthDaysShort": "每日",
"emptyWeekDays": "每天(周)",
"emptyWeekDaysShort": "每天(周)",
"emptyHours": "每小时",
"emptyMinutes": "每分钟",
"emptyMinutesForHourPeriod": "每",
"yearOption": "年",
"monthOption": "月",
"weekOption": "周",
"dayOption": "天",
"hourOption": "小时",
"minuteOption": "分钟",
"rebootOption": "重启",
"prefixPeriod": "每",
"prefixMonths": "的",
"prefixMonthDays": "的",
"prefixWeekDays": "的",
"prefixWeekDaysForMonthAndYearPeriod": "或者",
"prefixHours": "的",
"prefixMinutes": ":",
"prefixMinutesForHourPeriod": "的",
"suffixMinutesForHourPeriod": "分钟",
"errorInvalidCron": "不符合 cron 规则的表达式",
"clearButtonText": "清空",
"weekDays": ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
"months": ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
"altWeekDays": ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
"altMonths": ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
}

View File

@ -0,0 +1,33 @@
{
"everyText": "每",
"emptyMonths": "每月",
"emptyMonthDays": "每日(月)",
"emptyMonthDaysShort": "每日",
"emptyWeekDays": "每天(週)",
"emptyWeekDaysShort": "每天(週)",
"emptyHours": "每小時",
"emptyMinutes": "每分鐘",
"emptyMinutesForHourPeriod": "每",
"yearOption": "年",
"monthOption": "月",
"weekOption": "週",
"dayOption": "天",
"hourOption": "小時",
"minuteOption": "分鐘",
"rebootOption": "重啟",
"prefixPeriod": "每",
"prefixMonths": "的",
"prefixMonthDays": "的",
"prefixWeekDays": "的",
"prefixWeekDaysForMonthAndYearPeriod": "或者",
"prefixHours": "的",
"prefixMinutes": ":",
"prefixMinutesForHourPeriod": "的",
"suffixMinutesForHourPeriod": "分鐘",
"errorInvalidCron": "不符合 cron 規則的表示式",
"clearButtonText": "清空",
"weekDays": ["週日", "週一", "週二", "週三", "週四", "週五", "週六"],
"months": ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
"altWeekDays": ["週日", "週一", "週二", "週三", "週四", "週五", "週六"],
"altMonths": ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
}