mirror of
https://github.com/modelstudioai/cli.git
synced 2026-09-14 19:49:23 +08:00
refactor(runtime): remove unused i18next dependency
This commit is contained in:
@@ -43,7 +43,6 @@
|
||||
"bailian-cli-core": "workspace:*",
|
||||
"boxen": "catalog:",
|
||||
"chalk": "catalog:",
|
||||
"i18next": "catalog:",
|
||||
"undici": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -124,10 +124,8 @@ export function createCli(commands: Record<string, AnyCommand>, opts: CliOptions
|
||||
|
||||
async function getRegistry(argv: string[]): Promise<CommandRegistry> {
|
||||
const localeSources = buildSources(pickConfigFlag(argv));
|
||||
const [translator, loaded] = await Promise.all([
|
||||
createTranslator(localeSources.file.language ?? DEFAULT_LANGUAGE),
|
||||
getLoadedCommandPacks(),
|
||||
]);
|
||||
const translator = createTranslator(localeSources.file.language ?? DEFAULT_LANGUAGE);
|
||||
const loaded = await getLoadedCommandPacks();
|
||||
return new CommandRegistry(loaded.commands, binName, translator);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,56 +1,16 @@
|
||||
import { createInstance, type ResourceLanguage, type TOptions } from "i18next";
|
||||
import {
|
||||
DEFAULT_LANGUAGE,
|
||||
SUPPORTED_LANGUAGES,
|
||||
type Language,
|
||||
type LocalizedText,
|
||||
} from "bailian-cli-core";
|
||||
import { DEFAULT_LANGUAGE, type Language, type LocalizedText } from "bailian-cli-core";
|
||||
|
||||
export type Translate = (key: string, options?: Record<string, unknown>) => string;
|
||||
|
||||
/** A colocated namespace that a product or feature can register with the CLI runtime. */
|
||||
export interface CliMessageBundle {
|
||||
namespace: string;
|
||||
resources: Partial<Record<Language, ResourceLanguage>>;
|
||||
}
|
||||
|
||||
/** Per-CLI translation surface. The mutable i18next instance stays private to runtime. */
|
||||
/** Per-CLI localized text selector. */
|
||||
export interface Translator {
|
||||
language: Language;
|
||||
translate: Translate;
|
||||
localize(text: LocalizedText): string;
|
||||
}
|
||||
|
||||
export async function createTranslator(
|
||||
language: Language,
|
||||
bundles: readonly CliMessageBundle[] = [],
|
||||
): Promise<Translator> {
|
||||
const instance = createInstance();
|
||||
|
||||
await instance.init({
|
||||
lng: language,
|
||||
fallbackLng: DEFAULT_LANGUAGE,
|
||||
supportedLngs: [...SUPPORTED_LANGUAGES],
|
||||
initAsync: false,
|
||||
interpolation: { escapeValue: false },
|
||||
});
|
||||
|
||||
for (const bundle of bundles) {
|
||||
for (const supportedLanguage of SUPPORTED_LANGUAGES) {
|
||||
const resource = bundle.resources[supportedLanguage];
|
||||
if (resource) {
|
||||
instance.addResourceBundle(supportedLanguage, bundle.namespace, resource, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createTranslator(language: Language): Translator {
|
||||
return {
|
||||
language,
|
||||
localize(text) {
|
||||
return typeof text === "string" ? text : text[language];
|
||||
},
|
||||
translate(key, options = {}) {
|
||||
return String(instance.t(key, options as TOptions));
|
||||
return typeof text === "string" ? text : (text[language] ?? text[DEFAULT_LANGUAGE]);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,27 +1,12 @@
|
||||
import { expect, test } from "vite-plus/test";
|
||||
import { defineCommand } from "bailian-cli-core";
|
||||
import { createTranslator, type CliMessageBundle } from "../src/i18n.ts";
|
||||
import { createTranslator } from "../src/i18n.ts";
|
||||
import { CommandRegistry } from "../src/registry.ts";
|
||||
|
||||
const messages = {
|
||||
namespace: "test",
|
||||
resources: {
|
||||
"en-US": { greeting: "Hello, {{name}}!", englishOnly: "English fallback" },
|
||||
"zh-CN": { greeting: "你好,{{name}}!" },
|
||||
},
|
||||
} satisfies CliMessageBundle;
|
||||
|
||||
test("translator uses the selected language, interpolation and English fallback", async () => {
|
||||
const translator = await createTranslator("zh-CN", [messages]);
|
||||
test("translator resolves colocated text while preserving plain strings", () => {
|
||||
const translator = createTranslator("zh-CN");
|
||||
|
||||
expect(translator.language).toBe("zh-CN");
|
||||
expect(translator.translate("test:greeting", { name: "百炼" })).toBe("你好,百炼!");
|
||||
expect(translator.translate("test:englishOnly")).toBe("English fallback");
|
||||
});
|
||||
|
||||
test("translator resolves colocated text while preserving plain strings", async () => {
|
||||
const translator = await createTranslator("zh-CN");
|
||||
|
||||
expect(translator.localize("Already localized")).toBe("Already localized");
|
||||
expect(
|
||||
translator.localize({
|
||||
@@ -29,10 +14,17 @@ test("translator resolves colocated text while preserving plain strings", async
|
||||
"zh-CN": "显示帮助信息",
|
||||
}),
|
||||
).toBe("显示帮助信息");
|
||||
|
||||
expect(
|
||||
createTranslator("en-US").localize({
|
||||
"en-US": "Show help",
|
||||
"zh-CN": "显示帮助信息",
|
||||
}),
|
||||
).toBe("Show help");
|
||||
});
|
||||
|
||||
test("registry renders runtime help copy with the selected language", async () => {
|
||||
const translator = await createTranslator("zh-CN");
|
||||
const translator = createTranslator("zh-CN");
|
||||
const command = defineCommand({
|
||||
description: {
|
||||
"en-US": "Test command",
|
||||
|
||||
Generated
-18
@@ -24,9 +24,6 @@ catalogs:
|
||||
chalk:
|
||||
specifier: ^5.6.2
|
||||
version: 5.6.2
|
||||
i18next:
|
||||
specifier: ^26.3.6
|
||||
version: 26.3.6
|
||||
smol-toml:
|
||||
specifier: ^1.4.2
|
||||
version: 1.7.0
|
||||
@@ -257,9 +254,6 @@ importers:
|
||||
chalk:
|
||||
specifier: 'catalog:'
|
||||
version: 5.6.2
|
||||
i18next:
|
||||
specifier: 'catalog:'
|
||||
version: 26.3.6(typescript@6.0.3)
|
||||
undici:
|
||||
specifier: 'catalog:'
|
||||
version: 6.27.0
|
||||
@@ -1206,14 +1200,6 @@ packages:
|
||||
resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
i18next@26.3.6:
|
||||
resolution: {integrity: sha512-Bu5Z2nAXgfVyM8xvW3jk9EKRIuX37PudsrBViThNFx7CR7aaYTpP01cxNB/E4c4UUzTDiAZRstEhsRfPOL/8xA==}
|
||||
peerDependencies:
|
||||
typescript: ^5 || ^6 || ^7
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
immediate@3.0.6:
|
||||
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
|
||||
|
||||
@@ -2264,10 +2250,6 @@ snapshots:
|
||||
|
||||
get-east-asian-width@1.6.0: {}
|
||||
|
||||
i18next@26.3.6(typescript@6.0.3):
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
immediate@3.0.6: {}
|
||||
|
||||
inherits@2.0.4: {}
|
||||
|
||||
@@ -9,7 +9,6 @@ catalog:
|
||||
ajv: ^8.20.0
|
||||
boxen: ^8.0.1
|
||||
chalk: ^5.6.2
|
||||
i18next: ^26.3.6
|
||||
tar-stream: ^3.2.0
|
||||
smol-toml: ^1.4.2
|
||||
tsx: ^4.23.0
|
||||
|
||||
Reference in New Issue
Block a user