1
0
mirror of https://gitcode.com/github-mirrors/react-native-update-cli.git synced 2025-11-01 07:13:11 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee

update i18n

This commit is contained in:
sunnylqm
2025-03-24 23:16:09 +08:00
parent ef7f6a2087
commit 328b1f5447
9 changed files with 119 additions and 63 deletions

View File

@@ -6,19 +6,20 @@ import ProgressBar from 'progress';
import packageJson from '../package.json'; import packageJson from '../package.json';
import tcpp from 'tcp-ping'; import tcpp from 'tcp-ping';
import filesizeParser from 'filesize-parser'; import filesizeParser from 'filesize-parser';
import { pricingPageUrl, credentialFile, IS_CRESC } from './utils/constants'; import {
pricingPageUrl,
credentialFile,
defaultEndpoint,
} from './utils/constants';
import type { Session } from 'types'; import type { Session } from 'types';
import FormData from 'form-data'; import FormData from 'form-data';
import { t } from './utils/i18n';
const tcpPing = util.promisify(tcpp.ping); const tcpPing = util.promisify(tcpp.ping);
let session: Session | undefined; let session: Session | undefined;
let savedSession: Session | undefined; let savedSession: Session | undefined;
const defaultEndpoint = IS_CRESC
? 'https://api.cresc.dev'
: 'https://update.reactnative.cn/api';
const host = const host =
process.env.PUSHY_REGISTRY || process.env.RNU_API || defaultEndpoint; process.env.PUSHY_REGISTRY || process.env.RNU_API || defaultEndpoint;
@@ -73,7 +74,7 @@ async function query(url: string, options: fetch.RequestInit) {
if (resp.status !== 200) { if (resp.status !== 200) {
const message = json?.message || resp.statusText; const message = json?.message || resp.statusText;
if (resp.status === 401) { if (resp.status === 401) {
throw new Error('登录信息已过期,请使用 pushy login 命令重新登录'); throw new Error(t('loginExpired'));
} }
throw new Error(message); throw new Error(message);
} }
@@ -133,10 +134,13 @@ export async function uploadFile(fn: string, key?: string) {
const fileSize = fs.statSync(fn).size; const fileSize = fs.statSync(fn).size;
if (maxSize && fileSize > filesizeParser(maxSize)) { if (maxSize && fileSize > filesizeParser(maxSize)) {
const readableFileSize = `${(fileSize / 1048576).toFixed(1)}m`;
throw new Error( throw new Error(
`此文件大小 ${(fileSize / 1048576).toFixed( t('fileSizeExceeded', {
1, fileSize: readableFileSize,
)}m , 超出当前额度 ${maxSize} 。您可以考虑升级付费业务以提升此额度。详情请访问: ${pricingPageUrl}`, maxSize,
pricingPageUrl,
}),
); );
} }

View File

@@ -14,4 +14,15 @@ Best practices for lock files:
3. Pay attention to changes in the lock file during code review. 3. Pay attention to changes in the lock file during code review.
This can reduce the risk of inconsistent dependencies and supply chain attacks. This can reduce the risk of inconsistent dependencies and supply chain attacks.
`, `,
loginExpired:
'Login information has expired. Please use `cresc login` command to re-login',
fileSizeExceeded:
'This file size is {{fileSize}} , exceeding the current quota {{maxSize}} . You may consider upgrading to a higher plan to increase this quota. Details can be found at: {{pricingPageUrl}}',
bundleNotFound:
'Bundle file not found. Please ensure that this {{packageType}} is a release version and the bundle file name is the default `{{entryFile}}`',
buildTimeNotFound:
'Cannot get the build timestamp of this package. Please update `react-native-update` to the latest version and re-package and upload.',
latestVersionTag: '(latest: {{version}})',
rnuVersionNotFound:
'react-native-update: Cannot get the version number. Please run the command in the project directory',
}; };

View File

@@ -13,4 +13,14 @@ export default {
`, `,
multipleLocksFound: multipleLocksFound:
'检测到多种不同格式的锁文件({lockFiles}),这可能导致依赖关系不一致而使热更异常。', '检测到多种不同格式的锁文件({lockFiles}),这可能导致依赖关系不一致而使热更异常。',
loginExpired: '登录信息已过期,请使用 `pushy login` 命令重新登录',
fileSizeExceeded:
'此文件大小 {{fileSize}} , 超出当前额度 {{maxSize}} 。您可以考虑升级付费业务以提升此额度。详情请访问: {{pricingPageUrl}}',
bundleNotFound:
'找不到 bundle 文件。请确保此 {{packageType}} 为 release 版本,且 bundle 文件名为默认的 `{{entryFile}}`',
buildTimeNotFound:
'无法获取此包的编译时间戳。请更新 `react-native-update` 到最新版本后重新打包上传。',
latestVersionTag: '(最新:{{version}}',
rnuVersionNotFound:
'react-native-update: 无法获取版本号。请在项目目录中运行命令',
}; };

View File

@@ -4,17 +4,19 @@ const AppParser = require('./app');
const supportFileTypes = ['ipa', 'apk', 'app']; const supportFileTypes = ['ipa', 'apk', 'app'];
class AppInfoParser { class AppInfoParser {
file: string | File;
parser: any;
/** /**
* parser for parsing .ipa or .apk file * parser for parsing .ipa or .apk file
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser * @param {String | File} file // file's path in Node, instance of File in Browser
*/ */
constructor(file) { constructor(file: string | File) {
if (!file) { if (!file) {
throw new Error( throw new Error(
"Param miss: file(file's path in Node, instance of File or Blob in browser).", "Param miss: file(file's path in Node, instance of File in browser).",
); );
} }
const splits = (file.name || file).split('.'); const splits = (typeof file === 'string' ? file : file.name).split('.');
const fileType = splits[splits.length - 1].toLowerCase(); const fileType = splits[splits.length - 1].toLowerCase();
if (!supportFileTypes.includes(fileType)) { if (!supportFileTypes.includes(fileType)) {
throw new Error( throw new Error(
@@ -40,4 +42,4 @@ class AppInfoParser {
} }
} }
module.exports = AppInfoParser; export default AppInfoParser;

View File

@@ -17,10 +17,10 @@ export async function checkPlugins(): Promise<BundleParams> {
const isEnabled = await plugin.detect(); const isEnabled = await plugin.detect();
if (isEnabled && plugin.bundleParams) { if (isEnabled && plugin.bundleParams) {
Object.assign(params, plugin.bundleParams); Object.assign(params, plugin.bundleParams);
console.log(`检测到 ${plugin.name} 插件,应用相应打包配置`); console.log(`detected ${plugin.name} plugin`);
} }
} catch (err) { } catch (err) {
console.warn(`检测 ${plugin.name} 插件时出错:`, err); console.warn(`error while detecting ${plugin.name} plugin:`, err);
} }
} }

View File

@@ -1,8 +1,6 @@
import path from 'node:path'; import path from 'node:path';
const scriptName: 'cresc' | 'pushy' = path.basename(process.argv[1]) as const scriptName = path.basename(process.argv[1]) as 'cresc' | 'pushy';
| 'cresc'
| 'pushy';
export const IS_CRESC = scriptName === 'cresc'; export const IS_CRESC = scriptName === 'cresc';
export const credentialFile = IS_CRESC ? '.cresc.token' : '.update'; export const credentialFile = IS_CRESC ? '.cresc.token' : '.update';
@@ -11,3 +9,7 @@ export const tempDir = IS_CRESC ? '.cresc.temp' : '.pushy';
export const pricingPageUrl = IS_CRESC export const pricingPageUrl = IS_CRESC
? 'https://cresc.dev/pricing' ? 'https://cresc.dev/pricing'
: 'https://pushy.reactnative.cn/pricing.html'; : 'https://pushy.reactnative.cn/pricing.html';
export const defaultEndpoint = IS_CRESC
? 'https://api.cresc.dev'
: 'https://update.reactnative.cn/api';

View File

@@ -2,12 +2,18 @@ import i18next from 'i18next';
import en from '../locales/en'; import en from '../locales/en';
import zh from '../locales/zh'; import zh from '../locales/zh';
import { IS_CRESC } from './constants'; import { IS_CRESC } from './constants';
i18next.init({ i18next.init({
lng: IS_CRESC ? 'en' : 'zh', lng: IS_CRESC ? 'en' : 'zh',
// debug: process.env.NODE_ENV !== 'production', // debug: process.env.NODE_ENV !== 'production',
// debug: true,
resources: { resources: {
en, en: {
zh, translation: en,
},
zh: {
translation: zh,
},
}, },
}); });

View File

@@ -9,8 +9,9 @@ import latestVersion from '@badisi/latest-version';
import { checkPlugins } from './check-plugin'; import { checkPlugins } from './check-plugin';
import { read } from 'read'; import { read } from 'read';
import { tempDir } from './constants'; import { IS_CRESC, tempDir } from './constants';
import { depVersions } from './dep-versions'; import { depVersions } from './dep-versions';
import { t } from './i18n';
export async function question(query: string, password?: boolean) { export async function question(query: string, password?: boolean) {
if (NO_INTERACTIVE) { if (NO_INTERACTIVE) {
@@ -46,7 +47,10 @@ export async function getApkInfo(fn: string) {
); );
if (!bundleFile) { if (!bundleFile) {
throw new Error( throw new Error(
'找不到bundle文件。请确保此apk为release版本且bundle文件名为默认的index.android.bundle', t('bundleNotFound', {
packageType: 'apk',
entryFile: 'index.android.bundle',
}),
); );
} }
const updateJsonFile = await appInfoParser.parser.getEntry( const updateJsonFile = await appInfoParser.parser.getEntry(
@@ -66,21 +70,22 @@ export async function getApkInfo(fn: string) {
} }
} }
if (buildTime == 0) { if (buildTime == 0) {
throw new Error( throw new Error(t('buildTimeNotFound'));
'无法获取此包的编译时间戳。请更新 react-native-update 到最新版本后重新打包上传。',
);
} }
return { versionName, buildTime, ...appCredential }; return { versionName, buildTime, ...appCredential };
} }
export async function getAppInfo(fn) { export async function getAppInfo(fn: string) {
const appInfoParser = new AppInfoParser(fn); const appInfoParser = new AppInfoParser(fn);
const bundleFile = await appInfoParser.parser.getEntryFromHarmonyApp( const bundleFile = await appInfoParser.parser.getEntryFromHarmonyApp(
/rawfile\/bundle.harmony.js/, /rawfile\/bundle.harmony.js/,
); );
if (!bundleFile) { if (!bundleFile) {
throw new Error( throw new Error(
'找不到bundle文件。请确保此app为release版本且bundle文件名为默认的bundle.harmony.js', t('bundleNotFound', {
packageType: 'app',
entryFile: 'bundle.harmony.js',
}),
); );
} }
const updateJsonFile = await appInfoParser.parser.getEntryFromHarmonyApp( const updateJsonFile = await appInfoParser.parser.getEntryFromHarmonyApp(
@@ -103,9 +108,7 @@ export async function getAppInfo(fn) {
buildTime = pushy_build_time; buildTime = pushy_build_time;
} }
if (buildTime == 0) { if (buildTime == 0) {
throw new Error( throw new Error(t('buildTimeNotFound'));
'无法获取此包的编译时间戳。请更新 react-native-update 到最新版本后重新打包上传。',
);
} }
return { versionName, buildTime, ...appCredential }; return { versionName, buildTime, ...appCredential };
} }
@@ -117,7 +120,10 @@ export async function getIpaInfo(fn: string) {
); );
if (!bundleFile) { if (!bundleFile) {
throw new Error( throw new Error(
'找不到bundle文件。请确保此ipa为release版本且bundle文件名为默认的main.jsbundle', t('bundleNotFound', {
packageType: 'ipa',
entryFile: 'main.jsbundle',
}),
); );
} }
const updateJsonFile = await appInfoParser.parser.getEntry( const updateJsonFile = await appInfoParser.parser.getEntry(
@@ -139,9 +145,7 @@ export async function getIpaInfo(fn: string) {
); );
} }
if (!buildTimeTxtBuffer) { if (!buildTimeTxtBuffer) {
throw new Error( throw new Error(t('buildTimeNotFound'));
'无法获取此包的编译时间戳。请更新 react-native-update 到最新版本后重新打包上传。',
);
} }
const buildTime = buildTimeTxtBuffer.toString().replace('\n', ''); const buildTime = buildTimeTxtBuffer.toString().replace('\n', '');
return { versionName, buildTime, ...appCredential }; return { versionName, buildTime, ...appCredential };
@@ -168,40 +172,51 @@ async function getLatestVersion(pkgNames: string[]) {
} }
export async function printVersionCommand() { export async function printVersionCommand() {
let [latestPushyCliVersion, latestPushyVersion] = await getLatestVersion([ let [latestRnuCliVersion, latestRnuVersion] = await getLatestVersion([
'react-native-update-cli', 'react-native-update-cli',
'react-native-update', 'react-native-update',
]); ]);
latestPushyCliVersion = latestPushyCliVersion latestRnuCliVersion = latestRnuCliVersion
? ` (最新:${chalk.green(latestPushyCliVersion)}` ? ` ${t('latestVersionTag', {
version: chalk.green(latestRnuCliVersion),
})}`
: ''; : '';
console.log( console.log(
`react-native-update-cli: ${pkg.version}${latestPushyCliVersion}`, `react-native-update-cli: ${pkg.version}${latestRnuCliVersion}`,
); );
let pushyVersion = ''; let rnuVersion = '';
pushyVersion = depVersions['react-native-update']; rnuVersion = depVersions['react-native-update'];
latestPushyVersion = latestPushyVersion latestRnuVersion = latestRnuVersion
? ` (最新:${chalk.green(latestPushyVersion)}` ? ` ${t('latestVersionTag', { version: chalk.green(latestRnuVersion) })}`
: ''; : '';
console.log(`react-native-update: ${pushyVersion}${latestPushyVersion}`); console.log(`react-native-update: ${rnuVersion}${latestRnuVersion}`);
if (pushyVersion) { if (rnuVersion) {
if (semverSatisfies(pushyVersion, '<8.5.2')) { if (IS_CRESC) {
console.warn( if (semverSatisfies(rnuVersion, '<10.27.0')) {
`当前版本已不再支持,请至少升级到 v8 的最新小版本后重新打包(代码无需改动): npm i react-native-update@8 . console.error(
如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`, 'Unsupported version, please update to the latest version: npm i react-native-update@latest',
); );
} else if (semverSatisfies(pushyVersion, '9.0.0 - 9.2.1')) { process.exit(1);
console.warn( }
`当前版本已不再支持,请至少升级到 v9 的最新小版本后重新打包(代码无需改动,可直接热更): npm i react-native-update@9 . } else {
如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`, if (semverSatisfies(rnuVersion, '<8.5.2')) {
); console.warn(
} else if (semverSatisfies(pushyVersion, '10.0.0 - 10.17.0')) { `当前版本已不再支持,请至少升级到 v8 的最新小版本后重新打包(代码无需改动): npm i react-native-update@8 .
console.warn( 如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`,
'当前版本已不再支持,请升级到 v10 的最新小版本(代码无需改动,可直接热更): npm i react-native-update@10', );
); } else if (semverSatisfies(rnuVersion, '9.0.0 - 9.2.1')) {
console.warn(
`当前版本已不再支持,请至少升级到 v9 的最新小版本后重新打包(代码无需改动,可直接热更): npm i react-native-update@9 .
如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`,
);
} else if (semverSatisfies(rnuVersion, '10.0.0 - 10.17.0')) {
console.warn(
'当前版本已不再支持,请升级到 v10 的最新小版本(代码无需改动,可直接热更): npm i react-native-update@10',
);
}
} }
} else { } else {
console.log('react-native-update: 无法获取版本号,请在项目目录中运行命令'); console.log(t('rnuVersionNotFound'));
} }
} }

View File

@@ -6,6 +6,7 @@ import { choosePackage } from './package';
import { compare } from 'compare-versions'; import { compare } from 'compare-versions';
import { depVersions } from './utils/dep-versions'; import { depVersions } from './utils/dep-versions';
import { getCommitInfo } from './utils/git'; import { getCommitInfo } from './utils/git';
import { Platform } from 'types';
async function showVersion(appId: string, offset: number) { async function showVersion(appId: string, offset: number) {
const { data, count } = await get(`/app/${appId}/version/list`); const { data, count } = await get(`/app/${appId}/version/list`);
@@ -61,7 +62,7 @@ async function chooseVersion(appId: string) {
const cmd = await question( const cmd = await question(
'Enter versionId or page Up/page Down/Begin(U/D/B)', 'Enter versionId or page Up/page Down/Begin(U/D/B)',
); );
switch (cmd.toLowerCase()) { switch (cmd.toUpperCase()) {
case 'U': case 'U':
offset = Math.max(0, offset - 10); offset = Math.max(0, offset - 10);
break; break;
@@ -82,7 +83,12 @@ async function chooseVersion(appId: string) {
} }
export const commands = { export const commands = {
publish: async function ({ args, options }) { publish: async function ({ args, options }: { args: string[]; options: {
name: string;
description?: string;
metaInfo?: string;
platform?: Platform;
} }) {
const fn = args[0]; const fn = args[0];
const { name, description, metaInfo } = options; const { name, description, metaInfo } = options;
@@ -136,7 +142,7 @@ export const commands = {
versionId = null; versionId = null;
} }
let pkgId; let pkgId: string | undefined;
let pkgVersion = options.packageVersion; let pkgVersion = options.packageVersion;
let minPkgVersion = options.minPackageVersion; let minPkgVersion = options.minPackageVersion;
let maxPkgVersion = options.maxPackageVersion; let maxPkgVersion = options.maxPackageVersion;