Skip to content

Commit 478cc18

Browse files
hive-botclaude
andcommitted
feat: add the styleProfile option to text and document translation
Sends style_profile_id with the ID of a style profile string or a StyleProfile object on /v2/translate and /v2/document. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 39273af commit 478cc18

6 files changed

Lines changed: 119 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88
### Added
9+
- Added the `styleProfile` option to `TranslateTextOptions` and
10+
`DocumentTranslateOptions` to translate text and documents with a style
11+
profile, given as its ID or a `StyleProfile` object. It is sent as
12+
`style_profile_id`.
913
- Added style profiles (`/v3/style_profiles`) to `DeepLClient`:
1014
`listStyleProfiles()`, `createStyleProfile()`, `getStyleProfile()`,
1115
`updateStyleProfile()` and `deleteStyleProfile()`. Added the `StyleProfile`,

‎README.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,13 @@ console.log(await deeplClient.translateText('How are you?', null, 'de', { formal
183183
`sourceLang` to be set, and cannot be combined with the singular `glossary` option.
184184
- `styleRule`: specifies a style rule to use with translation, either as a string
185185
containing the style rule ID, or a `StyleRuleInfo` as returned by `getAllStyleRules()`.
186+
- `styleProfile`: specifies a style profile to use with translation, either as a
187+
string containing the style profile ID, or a `StyleProfile` as returned by
188+
`getStyleProfile()`. The profile applies its linked glossaries, style rule lists and
189+
translation memories; a component that does not fit the language pair is left out.
190+
Does not require `sourceLang`. Cannot be combined with `glossary`, `glossaryIds`,
191+
`styleRule`, `translationMemory`, `translationMemoryThreshold` or
192+
`customInstructions`; the API rejects such requests.
186193
- `translationMemory`: specifies a translation memory to use with translation,
187194
either as a string containing the translation memory ID, or a
188195
`TranslationMemoryInfo` as returned by `listTranslationMemories()`.
@@ -286,6 +293,9 @@ directly:
286293
- `glossary`: same as in [Text translation options](#text-translation-options).
287294
- `glossaryIds`: same as in [Text translation options](#text-translation-options).
288295
- `styleRule`: same as in [Text translation options](#text-translation-options).
296+
- `styleProfile`: same as in [Text translation options](#text-translation-options).
297+
A style profile that does not exist fails the translation with a
298+
`DocumentTranslationError` whose message contains `Style profile not found.`.
289299
- `translationMemory`: same as in [Text translation options](#text-translation-options).
290300
- `translationMemoryThreshold`: same as in [Text translation options](#text-translation-options).
291301
- `filename`: if the input file is not provided as file path, this option is
@@ -704,6 +714,18 @@ console.log(updated.description); // undefined
704714
await deeplClient.deleteStyleProfile(styleProfile);
705715
```
706716

717+
To translate with a style profile, pass it as the `styleProfile` option of text or
718+
document translation:
719+
720+
```javascript
721+
const result = await deeplClient.translateText('The artist is here.', null, 'de', {
722+
styleProfile: 'YOUR_STYLE_PROFILE_ID',
723+
});
724+
await deeplClient.translateDocument('input.docx', 'output.docx', null, 'de', {
725+
styleProfile: styleProfile,
726+
});
727+
```
728+
707729
### Translation Memories
708730

709731
Translation memories store and reuse previously created translations, helping to

‎src/types.ts‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ export interface TranslateTextOptions extends BaseRequestOptions {
178178
*/
179179
styleRule?: StyleId | StyleRuleInfo;
180180

181+
/** Specifies the ID of a style profile to use with translation, or a StyleProfile object
182+
* as returned by getStyleProfile(). The style profile applies its linked glossaries, style
183+
* rule lists and translation memories; a component that does not fit the language pair is
184+
* left out. Cannot be combined with the glossary, style rule, translation memory or custom
185+
* instructions options; the API rejects such requests.
186+
*/
187+
styleProfile?: string | StyleProfile;
188+
181189
/** Specifies the ID of a translation memory to use with translation, or
182190
* a TranslationMemoryInfo object as returned by listTranslationMemories().
183191
*/
@@ -252,6 +260,15 @@ export interface DocumentTranslateOptions extends BaseRequestOptions {
252260
*/
253261
styleRule?: StyleId | StyleRuleInfo;
254262

263+
/** Specifies the ID of a style profile to use with translation, or a StyleProfile object
264+
* as returned by getStyleProfile(). The style profile applies its linked glossaries, style
265+
* rule lists and translation memories; a component that does not fit the language pair is
266+
* left out. Cannot be combined with the glossary, style rule or translation memory options;
267+
* the API rejects such requests. A style profile that does not exist fails the document
268+
* translation with a DocumentTranslationError.
269+
*/
270+
styleProfile?: string | StyleProfile;
271+
255272
/** Specifies the ID of a translation memory to use with translation, or
256273
* a TranslationMemoryInfo object as returned by listTranslationMemories().
257274
*/

‎src/utils.ts‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ export function appendTextsAndReturnIsSingular(
267267
}
268268

269269
/**
270-
* Validates and appends style-rule and translation-memory options to HTTP request parameters.
270+
* Validates and appends style-rule, style-profile and translation-memory options to HTTP request parameters.
271271
* These options are shared between text and document translation requests.
272272
* @param data Parameters for HTTP request.
273273
* @param options Options containing style-rule and translation-memory fields.
@@ -277,6 +277,7 @@ export function appendStyleAndTranslationMemoryOptions(
277277
data: URLSearchParams,
278278
options: {
279279
styleRule?: StyleId | StyleRuleInfo;
280+
styleProfile?: string | StyleProfile;
280281
translationMemory?: TranslationMemoryId | TranslationMemoryInfo;
281282
translationMemoryThreshold?: number;
282283
},
@@ -293,6 +294,18 @@ export function appendStyleAndTranslationMemoryOptions(
293294
data.append('style_id', options.styleRule);
294295
}
295296
}
297+
if (options.styleProfile !== undefined) {
298+
if (!isString(options.styleProfile)) {
299+
if (options.styleProfile.styleProfileId === undefined) {
300+
throw new DeepLError(
301+
'styleProfile option should be a string containing the style profile ID or a StyleProfile object.',
302+
);
303+
}
304+
data.append('style_profile_id', options.styleProfile.styleProfileId);
305+
} else {
306+
data.append('style_profile_id', options.styleProfile);
307+
}
308+
}
296309
if (options.translationMemory !== undefined) {
297310
if (!isString(options.translationMemory)) {
298311
if (options.translationMemory.translationMemoryId === undefined) {

‎tests/offline/translateDocument.test.ts‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,35 @@ describe('Translator.uploadDocument', () => {
6767
expect(result).toEqual(handle);
6868
});
6969

70+
it('sends the style profile ID of a string and of a StyleProfile as one part', async () => {
71+
const translator = makeTranslator();
72+
for (const [styleProfile, id] of <Array<[string | deepl.StyleProfile, string]>>[
73+
['sp-1', 'sp-1'],
74+
[<deepl.StyleProfile>{ styleProfileId: 'sp-2' }, 'sp-2'],
75+
]) {
76+
const upload = expectUpload();
77+
78+
await translator.uploadDocument(Buffer.from('x'), null, 'de', {
79+
filename: 'example.txt',
80+
styleProfile,
81+
});
82+
83+
const body = upload.body();
84+
expect(body).toContain(`name="style_profile_id"\r\n\r\n${id}\r\n`);
85+
expect(body.split('name="style_profile_id"').length).toBe(2);
86+
}
87+
});
88+
89+
it('sends no style_profile_id part when styleProfile is unset', async () => {
90+
const upload = expectUpload();
91+
92+
await makeTranslator().uploadDocument(Buffer.from('x'), null, 'de', {
93+
filename: 'example.txt',
94+
});
95+
96+
expect(upload.body()).not.toContain('name="style_profile_id"');
97+
});
98+
7099
it('sends the base name of a file path as the filename', async () => {
71100
const upload = expectUpload();
72101
const [exampleDocument] = createTextDocument();

‎tests/offline/translateText.test.ts‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,39 @@ describe('Translator.translateText', () => {
169169
});
170170
});
171171

172+
it('sends the style profile ID of a string and of a StyleProfile', async () => {
173+
expectTranslateBody({ ...baseBody, style_profile_id: 'sp-1' });
174+
expectTranslateBody({ ...baseBody, style_profile_id: 'sp-2' });
175+
const translator = makeTranslator();
176+
177+
await translator.translateText('abc', null, 'de', { styleProfile: 'sp-1' });
178+
await translator.translateText('abc', null, 'de', {
179+
styleProfile: <deepl.StyleProfile>{ styleProfileId: 'sp-2' },
180+
});
181+
});
182+
183+
it('sends no style_profile_id when styleProfile is unset', async () => {
184+
let sent: Record<string, unknown> = {};
185+
nock(serverUrl)
186+
.post('/v2/translate', (body) => {
187+
sent = body;
188+
return true;
189+
})
190+
.reply(200, translation);
191+
192+
await makeTranslator().translateText('abc', null, 'de', { styleRule: 'style-1' });
193+
194+
expect(sent).toEqual({ ...baseBody, style_id: 'style-1' });
195+
});
196+
197+
it('throws for a styleProfile object without an ID', async () => {
198+
await expect(
199+
makeTranslator().translateText('abc', null, 'de', {
200+
styleProfile: <deepl.StyleProfile>{},
201+
}),
202+
).rejects.toThrow(deepl.DeepLError);
203+
});
204+
172205
it('sends the translation memory ID and threshold', async () => {
173206
expectTranslateBody({
174207
...baseBody,

0 commit comments

Comments
 (0)