This commit is contained in:
lovebird 2026-02-12 18:20:35 +01:00
parent 633df15f65
commit c5db29352b
8 changed files with 141 additions and 33 deletions

View File

@ -7,3 +7,5 @@ export * from './zod_schema.js';
export * from './zod_types.js';
export * from './constants.js';
export declare const logger: any;
export * from './lib/translate_commons.js';
export * from './lib/translate_text.js';

View File

@ -8,4 +8,6 @@ export * from './zod_schema.js';
export * from './zod_types.js';
export * from './constants.js';
export const logger = createLogger('commons');
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLE9BQU8sQ0FBQTtBQUM5QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBRTVDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBRXBDLGNBQWMsY0FBYyxDQUFBO0FBQzVCLGNBQWMsWUFBWSxDQUFBO0FBQzFCLGNBQWMsaUJBQWlCLENBQUE7QUFDL0IsY0FBYyxnQkFBZ0IsQ0FBQTtBQUM5QixjQUFjLGdCQUFnQixDQUFBO0FBRTlCLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBTyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUEifQ==
export * from './lib/translate_commons.js';
export * from './lib/translate_text.js';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLE9BQU8sQ0FBQTtBQUM5QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBRTVDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBRXBDLGNBQWMsY0FBYyxDQUFBO0FBQzVCLGNBQWMsWUFBWSxDQUFBO0FBQzFCLGNBQWMsaUJBQWlCLENBQUE7QUFDL0IsY0FBYyxnQkFBZ0IsQ0FBQTtBQUM5QixjQUFjLGdCQUFnQixDQUFBO0FBRTlCLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBUSxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUE7QUFFbEQsY0FBYyw0QkFBNEIsQ0FBQTtBQUMxQyxjQUFjLHlCQUF5QixDQUFBIn0=

View File

@ -24,6 +24,9 @@ export interface IDeepLOptions {
splitting_tags?: string[];
ignore_tags?: string[];
glossary_id?: string;
name?: string;
entries?: string;
entries_format?: string;
}
export interface IDeepLResponse {
translations: {

View File

@ -14,14 +14,8 @@ export const translate_deepl = async (parameters) => {
const sub_domain = parameters.free_api ? 'api-free' : 'api';
try {
let params = stringify(parameters);
// console.log('DEBUG: translate_deepl params:', params);
return axios.post(`https://${sub_domain}.deepl.com/v2/translate`, params, {});
// return (ret as any).data
/*
const ret = await axios.post(
`https://${sub_domain}.deepl.com/v2/translate`,
params, {}) as any
return (ret as any).data
*/
}
catch (error) {
console.error('error : translate_deepl', error.message);
@ -31,14 +25,28 @@ export const translate_deepl = async (parameters) => {
export const create_glossary = async (parameters) => {
const sub_domain = parameters.free_api ? 'api-free' : 'api';
try {
const params = stringify(parameters);
"auth_key=34dbf59f-adeb-1959-d906-502e0ec6afb8&free_api=false&name=pp&target_lang=DE&source_lang=EN&entries=Mould%2CKunststoffform%0D%0AShredder%2CGranulator%0D%0A&entries_format=csv";
const ret = await axios.post(`https://${sub_domain}.deepl.com/v2/glossaries`, params);
// v3 requires structured payload
const p = parameters;
const payload = {
name: p.name || 'Glossary',
dictionaries: [{
source_lang: p.source_lang,
target_lang: p.target_lang,
entries: p.entries,
entries_format: p.entries_format || 'tsv'
}]
};
const ret = await axios.post(`https://${sub_domain}.deepl.com/v3/glossaries`, payload, {
headers: {
'Authorization': `DeepL-Auth-Key ${parameters.auth_key}`,
'Content-Type': 'application/json'
}
});
return ret.data;
}
catch (error) {
//@todo : never called
console.error(error.response.data);
console.error(error.response?.data || error.message);
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2RlZXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDdkMsT0FBTyxFQUFFLE9BQU8sSUFBSSxLQUFLLEVBQUUsTUFBTSxPQUFPLENBQUE7QUF5Q3hDLE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHLEtBQUssRUFDakMsVUFBeUIsRUFDM0IsRUFBRTtJQUNBLElBQUksQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLGtLQUFrSyxDQUFBO1FBQ2pMLE1BQU0sR0FBRyxHQUFJLEtBQUssQ0FDZCxvQ0FBb0MsRUFDcEMsTUFBYSxDQUFRLENBQUE7UUFDekIsT0FBTyxHQUFHLENBQUE7SUFDZCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ2hDLENBQUM7QUFDTCxDQUFDLENBQUE7QUFDRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsS0FBSyxFQUNoQyxVQUF5QixFQUMzQixFQUFFO0lBQ0EsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDNUQsSUFBSSxDQUFDO1FBQ0QsSUFBSSxNQUFNLEdBQUcsU0FBUyxDQUFDLFVBQWlCLENBQUMsQ0FBQTtRQUN6QyxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQ2IsV0FBVyxVQUFVLHlCQUF5QixFQUM5QyxNQUFNLEVBQUUsRUFBRSxDQUFRLENBQUE7UUFDdEIsMkJBQTJCO1FBQ25DOzs7OztrQkFLVTtJQUNOLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDdkQsOEJBQThCO0lBQ2xDLENBQUM7QUFDTCxDQUFDLENBQUE7QUFFRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsS0FBSyxFQUNoQyxVQUF5QixFQUMzQixFQUFFO0lBQ0EsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUE7SUFDM0QsSUFBSSxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLFVBQWlCLENBQUMsQ0FBQTtRQUMzQyx1TEFBdUwsQ0FBQTtRQUN2TCxNQUFNLEdBQUcsR0FBRyxNQUFPLEtBQUssQ0FBQyxJQUFJLENBQ3pCLFdBQVcsVUFBVSwwQkFBMEIsRUFDL0MsTUFBTSxDQUFTLENBQUE7UUFFbkIsT0FBUSxHQUFXLENBQUMsSUFBSSxDQUFBO0lBRTVCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2Isc0JBQXNCO1FBQ3RCLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUN0QyxDQUFDO0FBQ0wsQ0FBQyxDQUFBIn0=
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2RlZXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDdkMsT0FBTyxFQUFFLE9BQU8sSUFBSSxLQUFLLEVBQUUsTUFBTSxPQUFPLENBQUE7QUE2Q3hDLE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHLEtBQUssRUFDakMsVUFBeUIsRUFDM0IsRUFBRTtJQUNBLElBQUksQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLGtLQUFrSyxDQUFBO1FBQ2pMLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FDYixvQ0FBb0MsRUFDcEMsTUFBYSxDQUFRLENBQUE7UUFDekIsT0FBTyxHQUFHLENBQUE7SUFDZCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ2hDLENBQUM7QUFDTCxDQUFDLENBQUE7QUFDRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsS0FBSyxFQUNoQyxVQUF5QixFQUMzQixFQUFFO0lBQ0EsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDNUQsSUFBSSxDQUFDO1FBQ0QsSUFBSSxNQUFNLEdBQUcsU0FBUyxDQUFDLFVBQWlCLENBQUMsQ0FBQTtRQUN6Qyx5REFBeUQ7UUFDekQsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUNiLFdBQVcsVUFBVSx5QkFBeUIsRUFDOUMsTUFBTSxFQUFFLEVBQUUsQ0FBUSxDQUFBO0lBQzFCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDdkQsOEJBQThCO0lBQ2xDLENBQUM7QUFDTCxDQUFDLENBQUE7QUFFRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsS0FBSyxFQUNoQyxVQUF5QixFQUMzQixFQUFFO0lBQ0EsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUE7SUFDM0QsSUFBSSxDQUFDO1FBQ0QsaUNBQWlDO1FBQ2pDLE1BQU0sQ0FBQyxHQUFRLFVBQVUsQ0FBQztRQUMxQixNQUFNLE9BQU8sR0FBRztZQUNaLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxJQUFJLFVBQVU7WUFDMUIsWUFBWSxFQUFFLENBQUM7b0JBQ1gsV0FBVyxFQUFFLENBQUMsQ0FBQyxXQUFXO29CQUMxQixXQUFXLEVBQUUsQ0FBQyxDQUFDLFdBQVc7b0JBQzFCLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTztvQkFDbEIsY0FBYyxFQUFFLENBQUMsQ0FBQyxjQUFjLElBQUksS0FBSztpQkFDNUMsQ0FBQztTQUNMLENBQUM7UUFFRixNQUFNLEdBQUcsR0FBRyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQ3hCLFdBQVcsVUFBVSwwQkFBMEIsRUFDL0MsT0FBTyxFQUNQO1lBQ0ksT0FBTyxFQUFFO2dCQUNMLGVBQWUsRUFBRSxrQkFBa0IsVUFBVSxDQUFDLFFBQVEsRUFBRTtnQkFDeEQsY0FBYyxFQUFFLGtCQUFrQjthQUNyQztTQUNKLENBQ0csQ0FBQTtRQUVSLE9BQVEsR0FBVyxDQUFDLElBQUksQ0FBQTtJQUU1QixDQUFDO0lBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztRQUNsQixzQkFBc0I7UUFDdEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLElBQUksSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDeEQsQ0FBQztBQUNMLENBQUMsQ0FBQSJ9

View File

@ -0,0 +1,75 @@
# Translation Library Overview (`translate.ts`)
## Description
The `translate.ts` module serves as the core orchestration layer for the i18n package. It handles:
1. Parsing and validating configuration options.
2. Determining the translation mode (text vs. file).
3. Resolving file paths and glob patterns.
4. Dispatching files to appropriate translators based on file extension.
5. Managing API interactions via the DeepL integration.
## Key Exports
### `translate(opts: IOptions)`
The main entry point for the translation process.
- **Parameters**: `opts` - Configuration object containing source paths, destination languages, API keys, etc.
- **Logic Flow**:
1. Validates required options (`api_key`, `src`/`text`, `dstLang`).
2. Resolves root paths and environmental variables.
3. Iterates through target languages (`dstLang`).
4. If `opts.text` is present: Calls `translateDeepL` directly for string translation.
5. If `opts.src` is present: Uses `p-map` to process files concurrently.
### `translateFiles(file, targets, options)`
Handles the translation of a specific file for a set of target languages.
- **Parameters**:
- `file`: Source file path.
- `targets`: Array of target file paths/languages.
- `options`: Global configuration options.
- **Logic Flow**:
1. Identifies the correct translator using `getTranslator(file)`.
2. Checks for dry-run mode (`options.dry`).
3. Executes the translation for each target concurrently.
### `getTranslator(file: string)`
Utility function that returns the appropriate translator function based on the file extension.
## Supported File Types
The module uses a `TRANSLATORS` map to route files to specific handlers:
| Extension | Handler | Description |
| :--- | :--- | :--- |
| `.md`, `.html` | `translateMarkup` | Handles Markdown and HTML content preservation. |
| `.json` | `translateJSON` | Translates JSON values while preserving keys. |
| `.toml` | `translateTOML` | Translates TOML configuration files. |
| `.yaml` | `translateYAML` | Translates YAML configuration files. |
| `.xlsx`, `.xls`| `translateXLS` | Handles Excel spreadsheet translation. |
| `.txt` | `translateText` | Simple text file translation. |
## Dependencies
- **`p-map`**: Used to manage concurrency for file processing and language iteration (limited to concurrency: 1 by default in `translateFiles`).
- **`path`**: For filesystem path resolution.
- **`@polymech/commons`**: specifically `globBase` for handling glob patterns in source paths.
## Glossary System
The package supports term consistency through a glossary system integrated with DeepL's glossary feature.
### 1. Storage Structure
Glossaries are stored locally in the configured `storeRoot` (default: `${OSR_ROOT}/i18n-store`):
- **CSV Data**: `<storeRoot>/glossary/<SRC_LANG>/<DST_LANG>/glossary.csv` contains the term pairs.
- **Metadata**: `<storeRoot>/glossary/<SRC_LANG>/<DST_LANG>/glossary.json` tracks the `glossaryId`, creation time, and content hash.
### 2. Synchronization Logic
To ensure the local glossary matches the one used by DeepL, the system checks for consistency before every translation request:
1. **Hash Verification**: It calculates an MD5 hash of the local CSV file and compares it with the hash stored in the metadata file.
2. **Auto-Update**:
- If the hashes differ (indicating local changes) or if the glossary is missing on the remote, it triggers an update.
- **Re-creation**: The old glossary is deleted from DeepL, and a new one is created using the current CSV content.
- **Metadata Update**: The new `glossaryId` and hash are saved locally.
### 3. Usage
When `translateDeepL` is called, it automatically:
- Attempts to resolve/update the glossary for the requested language pair.
- Injects the `glossary_id` into the DeepL API request options if a valid glossary exists.

View File

@ -10,5 +10,9 @@ export * from './zod_schema.js'
export * from './zod_types.js'
export * from './constants.js'
export const logger:any = createLogger('commons')
export const logger: any = createLogger('commons')
export * from './lib/translate_commons.js'
export * from './lib/translate_text.js'

View File

@ -29,6 +29,10 @@ export interface IDeepLOptions {
splitting_tags?: string[];
ignore_tags?: string[];
glossary_id?: string;
// v3 glossary params (optional in interface but used in create_glossary)
name?: string;
entries?: string;
entries_format?: string;
}
@ -45,9 +49,9 @@ export const translate_deeplT = async (
) => {
try {
const params = "preserve_formatting=1&tag_handling=xml&auth_key=4f6441ab-8e09-48d3-9031-3ca5cd463f79&formality=default&free_api=false&text=Variant&target_lang=de&source_lang=en"
const ret = axios (
const ret = axios(
`https://api.deepl.com/v2/translate`,
params as any) as any
params as any) as any
return ret
} catch (error) {
console.error(error.message)
@ -59,16 +63,10 @@ export const translate_deepl = async (
const sub_domain = parameters.free_api ? 'api-free' : 'api';
try {
let params = stringify(parameters as any)
// console.log('DEBUG: translate_deepl params:', params);
return axios.post(
`https://${sub_domain}.deepl.com/v2/translate`,
params, {}) as any
// return (ret as any).data
/*
const ret = await axios.post(
`https://${sub_domain}.deepl.com/v2/translate`,
params, {}) as any
return (ret as any).data
*/
} catch (error) {
console.error('error : translate_deepl', error.message)
//console.error(error.message)
@ -80,17 +78,34 @@ export const create_glossary = async (
) => {
const sub_domain = parameters.free_api ? 'api-free' : 'api'
try {
const params = stringify(parameters as any)
"auth_key=34dbf59f-adeb-1959-d906-502e0ec6afb8&free_api=false&name=pp&target_lang=DE&source_lang=EN&entries=Mould%2CKunststoffform%0D%0AShredder%2CGranulator%0D%0A&entries_format=csv"
const ret = await (axios.post(
`https://${sub_domain}.deepl.com/v2/glossaries`,
params) as any)
// v3 requires structured payload
const p: any = parameters;
const payload = {
name: p.name || 'Glossary',
dictionaries: [{
source_lang: p.source_lang,
target_lang: p.target_lang,
entries: p.entries,
entries_format: p.entries_format || 'tsv'
}]
};
const ret = await axios.post(
`https://${sub_domain}.deepl.com/v3/glossaries`,
payload,
{
headers: {
'Authorization': `DeepL-Auth-Key ${parameters.auth_key}`,
'Content-Type': 'application/json'
}
}
) as any
return (ret as any).data
} catch (error) {
} catch (error: any) {
//@todo : never called
console.error(error.response.data)
console.error(error.response?.data || error.message)
}
}
@ -123,4 +138,3 @@ export type DeepLLanguages =
| 'SL'
| 'SV'
| 'ZH'

View File

@ -1,7 +1,7 @@
Das ist eine Plattenpresse und eine Spritzgießmaschine (Sie brauchen auch einen Granulator), und wenn Sie nett zu uns sind, geben wir Ihnen noch ein paar Spritzgussformen obendrauf, kostenlos und Open Source - weil wir Sie so sehr lieben! Sehen Sie sich mehr unserer Plattenpressen an.
Das ist eine Plattenpresse und eine Spritzgießmaschine (Sie brauchen auch einen Granulator), und wenn Sie nett zu uns sind, legen wir noch ein paar Spritzgussformen obendrauf, kostenlos und Open Source - weil wir Sie so sehr lieben! Sehen Sie sich mehr unserer Plattenpressen an.
Die Abmessungen des Pakets sind ein Meter mal ein Meter.
Nachstehend finden Sie die aktuellen Optionen für Plattenpressen, Extruder und Injektoren. Sie können uns während der Bürozeiten unter [[TELEFON]] oder per E-Mail unter [[EMAIL]] erreichen
Nachstehend finden Sie die aktuellen Optionen für Plattenpressen, Extruder und Spritzgießmaschinen. Sie können uns während der Bürozeiten unter [[TELEFON]] oder per E-Mail unter [[EMAIL]] erreichen
Cassandra 45 cm