mirror of
https://github.com/xxnuo/MTranServer.git
synced 2026-09-03 06:35:20 +08:00
feat: npm package
This commit is contained in:
52
example/README.md
Normal file
52
example/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# MTranServer Usage Examples
|
||||
|
||||
This directory contains examples of how to use `mtranserver` programmatically in your Node.js/Bun applications.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Ensure you have installed the library:
|
||||
|
||||
```bash
|
||||
bun install mtranserver@latest
|
||||
```
|
||||
|
||||
## Running the Example
|
||||
|
||||
You can run the example using `bun`:
|
||||
|
||||
```bash
|
||||
bun example/usage.ts
|
||||
```
|
||||
|
||||
## Code Explanation
|
||||
|
||||
The key component is the `MTran` class:
|
||||
|
||||
```typescript
|
||||
import { MTran } from 'mtranserver';
|
||||
|
||||
// 1. Create instance
|
||||
const mtran = new MTran({
|
||||
modelDir: './models' // Directory to store translation models
|
||||
});
|
||||
|
||||
// 2. Initialize
|
||||
await mtran.init();
|
||||
|
||||
// 3. Translate
|
||||
const result = await mtran.translate('en', 'es', 'Hello world');
|
||||
console.log(result); // "Hola mundo"
|
||||
|
||||
// 4. Cleanup
|
||||
await mtran.close();
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The `MTran` constructor accepts a config object with the following optional properties:
|
||||
|
||||
- `modelDir`: Path to store downloaded models.
|
||||
- `configDir`: Path to store configuration files (like `records.json`).
|
||||
- `logLevel`: Logging verbosity ('debug', 'info', 'warn', 'error').
|
||||
- `workersPerLanguage`: Number of parallel workers for translation.
|
||||
- `enableOfflineMode`: If true, disables auto-downloading of models.
|
||||
52
example/usage.ts
Normal file
52
example/usage.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { MTran } from 'mtranserver';
|
||||
|
||||
async function main() {
|
||||
console.log('--- MTranServer Library Usage Example ---');
|
||||
|
||||
// 1. Initialize MTran instance
|
||||
// You can pass configuration options here.
|
||||
const mtran = new MTran();
|
||||
|
||||
try {
|
||||
// 2. Initialize (loads records, prepares environment)
|
||||
console.log('Initializing MTran...');
|
||||
await mtran.init();
|
||||
|
||||
const fromLang = 'en';
|
||||
const toLang = 'zh';
|
||||
const text = 'Hello world! This is a library test.';
|
||||
|
||||
// 3. (Optional) Ensure the model is downloaded.
|
||||
// .translate() will error if the model is missing in offline mode,
|
||||
// or attempt to download it if online (default).
|
||||
// Calling downloadModel explicitly is good for pre-warming.
|
||||
console.log(`Checking model for ${fromLang} -> ${toLang}...`);
|
||||
await mtran.downloadModel(fromLang, toLang);
|
||||
|
||||
// 4. Perform Translation
|
||||
console.log(`
|
||||
Translating: "${text}"`);
|
||||
const start = performance.now();
|
||||
|
||||
const result = await mtran.translate(fromLang, toLang, text);
|
||||
|
||||
const end = performance.now();
|
||||
console.log(`Translation Result: "${result}"`);
|
||||
console.log(`Time taken: ${(end - start).toFixed(2)}ms`);
|
||||
|
||||
// 5. Language Detection
|
||||
console.log('\nDetecting language for: "Bonjour tout le monde"');
|
||||
const detected = await mtran.detect("Bonjour tout le monde");
|
||||
console.log(`Detected: ${detected}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('An error occurred:', error);
|
||||
} finally {
|
||||
// 6. Cleanup
|
||||
// Important: Stops background worker threads to allow process to exit cleanly
|
||||
console.log('\nCleaning up...');
|
||||
await mtran.close();
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -3,11 +3,13 @@
|
||||
"version": "4.0.13",
|
||||
"type": "module",
|
||||
"description": "Translation server",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"bin": {
|
||||
"mtranserver": "./dist/main.js"
|
||||
},
|
||||
"files": [
|
||||
"mtranserver",
|
||||
"dist",
|
||||
"assets"
|
||||
],
|
||||
"scripts": {
|
||||
@@ -17,6 +19,8 @@
|
||||
"build:docker": "bun scripts/build.ts --docker",
|
||||
"build:node": "bun run gen && rm -rf dist && bun build src/main.ts --outdir dist --target node --format esm --sourcemap --external zstd-wasm-decoder --external express",
|
||||
"build:dev": "bun run gen && rm -rf dist && bun build src/main.ts --outdir dist --target node --format esm --sourcemap --external zstd-wasm-decoder --external express",
|
||||
"build:lib": "bun run gen && rm -rf dist && rm -f ui/dist/assets/*.d.ts && bun build src/index.ts src/main.ts --outdir dist --target node --format esm --sourcemap --external zstd-wasm-decoder --external express && tsc -p tsconfig.lib.json",
|
||||
"prepublishOnly": "bun run build:lib",
|
||||
"start": "node dist/main.js",
|
||||
"test": "bun test",
|
||||
"typecheck": "tsc --noEmit",
|
||||
|
||||
@@ -134,3 +134,8 @@ export function getConfig(): Config {
|
||||
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
export function setConfig(config: Partial<Config>) {
|
||||
const current = getConfig();
|
||||
globalConfig = { ...current, ...config };
|
||||
}
|
||||
|
||||
20
src/globals.d.ts
vendored
20
src/globals.d.ts
vendored
@@ -2,3 +2,23 @@ declare module '*.wasm' {
|
||||
const path: string;
|
||||
export default path;
|
||||
}
|
||||
|
||||
declare module '*.css' {
|
||||
const path: string;
|
||||
export default path;
|
||||
}
|
||||
|
||||
declare module '*.js' {
|
||||
const path: string;
|
||||
export default path;
|
||||
}
|
||||
|
||||
declare module '*.html' {
|
||||
const path: string;
|
||||
export default path;
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const path: string;
|
||||
export default path;
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
export * from '@/config/index.js';
|
||||
export * from '@/logger/index.js';
|
||||
export * from '@/utils/index.js';
|
||||
export * from '@/version/index.js';
|
||||
export * from '@/models/index.js';
|
||||
export * from '@/services/index.js';
|
||||
export * from '@/middleware/index.js';
|
||||
export * from '@/server/index.js';
|
||||
|
||||
68
src/mtran.ts
Normal file
68
src/mtran.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { setConfig, getConfig, Config } from '@/config/index.js';
|
||||
import { initRecords, downloadModel } from '@/models/index.js';
|
||||
import { translateWithPivot, cleanupAllEngines } from '@/services/index.js';
|
||||
import { detectLanguage } from '@/services/detector.js';
|
||||
import { normalizeLanguageCode } from '@/utils/index.js';
|
||||
|
||||
export interface MTranConfig extends Partial<Config> {}
|
||||
|
||||
export class MTran {
|
||||
constructor(config?: MTranConfig) {
|
||||
if (config) {
|
||||
setConfig(config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the translation engine (load records, etc.)
|
||||
*/
|
||||
async init(): Promise<void> {
|
||||
await initRecords();
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate text
|
||||
* @param from Source language code (or 'auto')
|
||||
* @param to Target language code
|
||||
* @param text Text to translate
|
||||
* @param html Whether the text is HTML (default: false)
|
||||
*/
|
||||
async translate(from: string, to: string, text: string, html: boolean = false): Promise<string> {
|
||||
const normalizedFrom = from === 'auto' ? 'auto' : normalizeLanguageCode(from);
|
||||
const normalizedTo = normalizeLanguageCode(to);
|
||||
return translateWithPivot(normalizedFrom, normalizedTo, text, html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect language of the text
|
||||
* @param text Text to analyze
|
||||
*/
|
||||
async detect(text: string): Promise<string | null> {
|
||||
return detectLanguage(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure model is downloaded for a language pair
|
||||
* @param from Source language
|
||||
* @param to Target language
|
||||
*/
|
||||
async downloadModel(from: string, to: string): Promise<void> {
|
||||
const normalizedFrom = normalizeLanguageCode(from);
|
||||
const normalizedTo = normalizeLanguageCode(to);
|
||||
await downloadModel(normalizedTo, normalizedFrom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up all loaded engines and release memory
|
||||
*/
|
||||
async close(): Promise<void> {
|
||||
cleanupAllEngines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current configuration
|
||||
*/
|
||||
getConfig(): Config {
|
||||
return getConfig();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import loadCLD2 from '@/lib/cld2/cld2.js';
|
||||
import wasmPath from '@/lib/cld2/cld2.wasm' with { type: 'file' };
|
||||
import * as logger from '@/logger/index.js';
|
||||
@@ -28,7 +30,10 @@ async function initCLD(): Promise<void> {
|
||||
try {
|
||||
logger.debug('Initializing CLD2 language detector');
|
||||
|
||||
const wasmBuffer = await readFile(wasmPath);
|
||||
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const absoluteWasmPath = path.resolve(currentDir, wasmPath);
|
||||
|
||||
const wasmBuffer = await readFile(absoluteWasmPath);
|
||||
|
||||
const module: any = await loadCLD2({
|
||||
print: (msg: string) => logger.debug(`[CLD2]: ${msg}`),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { TranslationEngine } from '@/core/engine.js';
|
||||
import { createResourceLoader } from '@/core/factory.js';
|
||||
@@ -69,8 +70,11 @@ async function getOrCreateSingleEngine(
|
||||
const engine = new TranslationEngine();
|
||||
const loader = createResourceLoader();
|
||||
|
||||
logger.debug(`Loading WASM from: ${wasmPath}`);
|
||||
const wasmBinary = await readFile(wasmPath);
|
||||
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const absoluteWasmPath = path.resolve(currentDir, wasmPath);
|
||||
|
||||
logger.debug(`Loading WASM from: ${absoluteWasmPath}`);
|
||||
const wasmBinary = await readFile(absoluteWasmPath);
|
||||
logger.debug(`WASM loaded, size: ${wasmBinary.byteLength} bytes`);
|
||||
|
||||
const bergamotModule = await loader.loadBergamotModule(wasmBinary, loadBergamot);
|
||||
|
||||
10
tsconfig.lib.json
Normal file
10
tsconfig.lib.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"emitDeclarationOnly": true,
|
||||
"noEmit": false,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [],
|
||||
"files": ["src/index.ts", "src/globals.d.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user