{"id":28419366,"url":"https://github.com/deeplcom/deepl-dotnet","last_synced_at":"2026-04-09T20:22:15.356Z","repository":{"id":38352372,"uuid":"420956375","full_name":"DeepLcom/deepl-dotnet","owner":"DeepLcom","description":"Official .NET library for the DeepL language translation API.","archived":false,"fork":false,"pushed_at":"2025-06-26T14:36:54.000Z","size":398,"stargazers_count":193,"open_issues_count":23,"forks_count":26,"subscribers_count":16,"default_branch":"main","last_synced_at":"2025-06-26T15:33:29.783Z","etag":null,"topics":["api","csharp","deepl","dotnet","i18n","language","official","translation","translator"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DeepLcom.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-10-25T09:19:49.000Z","updated_at":"2025-06-26T14:36:59.000Z","dependencies_parsed_at":"2023-02-14T18:45:49.932Z","dependency_job_id":"2d28a837-2106-4e87-b88b-bbedf00fe3bf","html_url":"https://github.com/DeepLcom/deepl-dotnet","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/DeepLcom/deepl-dotnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeepLcom%2Fdeepl-dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeepLcom%2Fdeepl-dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeepLcom%2Fdeepl-dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeepLcom%2Fdeepl-dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DeepLcom","download_url":"https://codeload.github.com/DeepLcom/deepl-dotnet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeepLcom%2Fdeepl-dotnet/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262172445,"owners_count":23270009,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","csharp","deepl","dotnet","i18n","language","official","translation","translator"],"created_at":"2025-06-04T17:30:41.852Z","updated_at":"2026-04-09T20:22:15.341Z","avatar_url":"https://github.com/DeepLcom.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DeepL .NET Library\n\n[![NuGet](https://img.shields.io/nuget/v/deepl.net.svg)](https://www.nuget.org/packages/DeepL.net/)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blueviolet.svg)](https://github.com/DeepLcom/deepl-dotnet/blob/main/LICENSE)\n[![.NET](https://github.com/DeepLcom/deepl-dotnet/actions/workflows/build_default.yml/badge.svg)](https://github.com/DeepLcom/deepl-dotnet/actions/workflows/build_default.yml)\n\nThe [DeepL API](https://www.deepl.com/docs-api?utm_source=github\u0026utm_medium=github-dotnet-readme) is a language\nAI API that allows other computer programs to send texts and documents to DeepL's servers and receive\nhigh-quality translations and improvements to the text. This opens a whole universe of opportunities\nfor developers: any translation product you can imagine can now be built on top of DeepL's best-in-class\ntranslation technology.\n\nThe DeepL .NET library offers a convenient way for applications written in .NET to interact with the DeepL API. We\nintend to support all API functions with the library, though support for new features may be added to the library after\nthey’re added to the API.\n\n## Getting an authentication key\n\nTo use the DeepL .NET Library, you'll need an API authentication key. To get a key,\n[please create an account here](https://www.deepl.com/pro?utm_source=github\u0026utm_medium=github-dotnet-readme#developer).\nWith a DeepL API Free account you can consume up to 500,000 characters/month for free.\n\n## Installation\n\nUsing the .NET Core command-line interface (CLI) tools:\n\n```\ndotnet add package DeepL.net\n```\n\nUsing the NuGet Command Line Interface (CLI):\n\n```\nnuget install DeepL.net\n```\n\n## Usage\n\nAll entities in the DeepL .NET library are in the `DeepL` namespace:\n\n```c#\nusing DeepL;\n```\n\nCreate a `DeepLClient` object providing your DeepL API authentication key.\n\nBe careful not to expose your key, for example when sharing source code.\n\n```c#\nvar authKey = \"f63c02c5-f056-...\"; // Replace with your key\nvar client = new DeepLClient(authKey);\n```\n\nThis example is for demonstration purposes only. In production code, the authentication key should not be hard-coded,\nbut instead fetched from a configuration file or environment variable.\n\n`DeepLClient` accepts options as the second argument, see [Configuration](#configuration) for more information.\n\n### Translating text\n\nTo translate text, call `TranslateTextAsync()`. The first argument is a string containing the text to translate, or\n`IEnumerable` of strings to translate multiple texts.\n\nThe second and third arguments are case-insensitive language codes for the source and target language respectively,\nfor example `\"DE\"`, `\"FR\"`.\nThe `LanguageCode` static class defines constants for the currently supported languages, for example\n`LanguageCode.German`, `LanguageCode.French`.\nTo auto-detect the input text language, specify `null` as the source language.\n\nAdditional `TextTranslateOptions` can also be provided, see [Text translation options](#text-translation-options) below.\n\n`TranslateTextAsync()` returns a `TextResult` or `TextResult` array corresponding to the input text(s).\nThe `TextResult` contains:\n\n- the translated text,\n- the detected source language code,\n- the number of characters billed for the text, and\n- the translation model type used (only non-null if the ModelType option is specified.)\n\n```c#\n// Translate text into a target language, in this case, French:\nvar translatedText = await client.TranslateTextAsync(\n      \"Hello, world!\",\n      LanguageCode.English,\n      LanguageCode.French);\nConsole.WriteLine(translatedText); // \"Bonjour, le monde !\"\n// Note: printing or converting the result to a string uses the output text.\n\n// Translate multiple texts into British English:\nvar translations = await client.TranslateTextAsync(\n      new[] { \"お元気ですか？\", \"¿Cómo estás?\" }, null, \"EN-GB\");\nConsole.WriteLine(translations[0].Text); // \"How are you?\"\nConsole.WriteLine(translations[0].DetectedSourceLanguageCode); // \"JA\"\nConsole.WriteLine(translations[0].BilledCharacters); // 7 - the number of characters in the source text \"お元気ですか？\"\nConsole.WriteLine(translations[1].Text); // \"How are you?\"\nConsole.WriteLine(translations[1].DetectedSourceLanguageCode); // \"ES\"\nConsole.WriteLine(translations[1].BilledCharacters); // 12 - the number of characters in the source text \"¿Cómo estás?\"\n\n// Translate into German with less and more Formality:\nforeach (var formality in new[] { Formality.Less, Formality.More }) {\n  Console.WriteLine(\n        await client.TranslateTextAsync(\n              \"How are you?\",\n              null,\n              LanguageCode.German,\n              new TextTranslateOptions { Formality = formality }));\n}\n// Will print: \"Wie geht es dir?\" \"Wie geht es Ihnen?\"\n```\n\n#### Text translation options\n\n`TextTranslateOptions` has the following properties that impact text translation:\n\n- `SentenceSplittingMode`: specifies how input text should be split into\n  sentences, default: `'SentenceSplittingMode.All'`.\n  - `SentenceSplittingMode.All`: input text will be split into sentences using\n    both newlines and punctuation.\n  - `SentenceSplittingMode.Off`: input text will not be split into sentences.\n    Use this for applications where each input text contains only one\n    sentence.\n  - `SentenceSplittingMode.NoNewlines`: input text will be split into\n    sentences using punctuation but not newlines.\n- `PreserveFormatting`: controls automatic-formatting-correction. Set to\n  `true` to prevent automatic-correction of formatting, default: `false`.\n- `Formality`: controls whether translations should lean toward informal or\n  formal language. This option is only available for some target languages, see\n  [Listing available languages](#listing-available-languages).\n  - `Formality.Less`: use informal language.\n  - `Formality.More`: use formal, more polite language.\n  - `Formality.Default`: standard level of formality.\n  - `Formality.PreferLess`: less formality, if available for the specified target language, otherwise default.\n  - `Formality.PreferMore`: more formality, if available for the specified target language, otherwise default.\n- `GlossaryId`: specifies a glossary to use with translation, as a string\n  containing the glossary ID.\n- `StyleId`: specifies a style rule to use with translation, as a string\n  containing the ID of the style rule.\n- `TranslationMemoryId`: specifies a translation memory to use with translation,\n  as a string containing the translation memory ID.\n- `TranslationMemoryThreshold`: specifies the minimum matching percentage\n  (0 to 100) for translation memory matches. We recommend a minimum\n  threshold of 75%.\n- `Context`: specifies additional context to influence translations, that is not\n  translated itself. Characters in the `context` parameter are not counted toward billing.\n  See the [API documentation][api-docs-context-param] for more information and\n  example usage.\n- `CustomInstructions`: an array of instructions to customize the translation behavior.\n  Up to 10 custom instructions can be specified, each with a maximum of 300 characters.\n  Important: The target language must be `de`, `en`, `es`, `fr`, `it`, `ja`, `ko`, `zh`\n  or any variants of these languages.\n  Note: Any request with the `CustomInstructions` parameter enabled will use\n  `quality_optimized` models as the default. Requests combining \n  `CustomInstructions` and `ModelType: latency_optimized` will be rejected.\n- `ModelType`: specifies the type of translation model to use, options are:\n  - `'quality_optimized'` (`ModelType.QualityOptimized`): use a translation\n    model that maximizes translation quality, at the cost of response time.\n    This option may be unavailable for some language pairs.\n  - `'prefer_quality_optimized'` (`ModelType.PreferQualityOptimized`): use\n    the highest-quality translation model for the given language pair.\n  - `'latency_optimized'` (`ModelType.LatencyOptimized`): use a translation\n    model that minimizes response time, at the cost of translation quality.\n- `TagHandling`: type of tags to parse before translation, options are\n  `\"html\"` and `\"xml\"`.\n- `TagHandlingVersion`: specifies which version of the tag handling algorithm\n  to use. Options are `\"v1\"` and `\"v2\"`. This parameter is only used if\n  `TagHandling` is set to `\"html\"` or `\"xml\"`.\n\nThe following options are only used if `TagHandling` is set to `'xml'`:\n\n- `OutlineDetection`: set to `false` to disable automatic tag detection,\n  default is `true`.\n- `SplittingTags`: `List` of XML tags that should be used to split text into\n  sentences. Tags may be specified individually (`['tag1', 'tag2']`),\n  or a comma-separated list of strings (`'tag1,tag2'`). The default is an empty\n  list.\n- `NonSplittingTags`: `List` of XML tags that should not be used to split\n  text into sentences. Format and default are the same as for splitting tags.\n- `IgnoreTags`: `List` of XML tags that containing content that should not be\n  translated. Format and default are the same as for splitting tags.\n- `ExtraBodyParameters`: `Dictionary\u003cstring, string\u003e` of extra parameters to pass in the body of the HTTP request. Keys\n  in this dictionary will be added to the request body and can override built-in parameters. Mostly used by DeepL\n  employees to test functionality, or for beta programs.\n\nFor a detailed explanation of the XML handling options, see the [API documentation][api-docs-xml-handling].\n\n### Improving text (Write API)\n\nYou can use the Write API to improve or rephrase text. This is implemented in\nthe `RephraseTextAsync()` method. The first argument is a string containing the text\nyou want to translate, or a list of strings if you want to translate multiple texts.\n\n`targetLanguageCode` optionally specifies the target language, e.g. when you want to change\nthe variant of a text (for example, you can send an english text to the write API and\nuse `targetLanguageCode` to turn it into British or American English). Please note that the\nWrite API itself does NOT translate. If you wish to translate and improve a text, you\nwill need to make multiple calls in a chain.\n\nLanguage codes are the same as for translating text.\n\nExample call:\n\n```c#\nWriteResult result = await client.RephraseTextAsync(\"A rainbouw has seven colours.\", \"EN-US\");\nConsole.WriteLine(result);\n```\n\nAdditionally, you can optionally specify a style OR a tone (not both at once) that the\nimprovement should be in. The following styles are supported (`default` will be used if\nnothing is selected):\n\n- `academic`\n- `business`\n- `casual`\n- `default`\n- `simple`\n\nThe following tones are supported (`default` will be used if nothing is selected):\n\n- `confident`\n- `default`\n- `diplomatic`\n- `enthusiastic`\n- `friendly`\n\nYou can also prefix any non-default style or tone with `prefer_` (`prefer_academic`, etc.),\nin which case the style/tone will only be applied if the language supports it. If you do not\nuse `prefer_`, requests with `targetLanguageCode`s or detected languages that do not support\nstyles and tones will fail. The current list of supported languages can be found in our\n[API documentation][api-docs]. We plan to also expose this information via an API endpoint\nin the future.\n\nYou can pass a style like so:\n\n```c#\nvar options = new TextRephraseOptions { WritingStyle = \"business\" }\nvar result = await client.RephraseTextAsync(\"A rainbouw has seven colours.\", \"EN-US\", options);\nConsole.WriteLine(result);\n```\n\n### Translating documents\n\nTo translate documents, call `TranslateDocumentAsync()` with the input and output files as `FileInfo`\nobjects, and provide the source and target language as above.\n\nAdditional `DocumentTranslateOptions` are also available,\nsee [Document translation options](#document-translation-options) below.\nNote that file paths are not accepted as strings, to avoid mixing up the file and language arguments.\n\n```c#\n// Translate a formal document from English to German\ntry {\n  await client.TranslateDocumentAsync(\n        new FileInfo(\"Instruction Manual.docx\"),\n        new FileInfo(\"Bedienungsanleitung.docx\"),\n        \"EN\",\n        \"DE\",\n        new DocumentTranslateOptions { Formality = Formality.More });\n} catch (DocumentTranslationException exception) {\n  // If the error occurs *after* upload, the DocumentHandle will contain the document ID and key\n  if (exception.DocumentHandle != null) {\n    var handle = exception.DocumentHandle.Value;\n    Console.WriteLine($\"Document ID: {handle.DocumentId}, Document key: {handle.DocumentKey}\");\n  } else {\n    Console.WriteLine($\"Error occurred during document upload: {exception.Message}\");\n  }\n}\n```\n\nAlternatively the input and output files may be provided as `Stream` objects; in\nthat case the input file name (or extension) is required, so the DeepL API can\ndetermine the file type:\n\n```c#\n...\n  await client.TranslateDocumentAsync(\n        new MemoryStream(buffer),\n        \"Input file.docx\", // An extension like \".docx\" is also sufficient\n        File.OpenWrite(outputDocumentPath),\n        \"EN\",\n        \"DE\",\n        new DocumentTranslateOptions { Formality = Formality.More });\n```\n\n`TranslateDocumentAsync()` manages the upload, wait until translation is complete, and download steps. If your\napplication needs to execute these steps individually, you can instead use the following functions directly:\n\n- `TranslateDocumentUploadAsync()`,\n- `TranslateDocumentStatusAsync()` (or `TranslateDocumentWaitUntilDoneAsync()`), and\n- `TranslateDocumentDownloadAsync()`\n\n#### Document translation options\n\n`DocumentTranslateOptions` has the following properties that impact text translation:\n\n- `Formality`:  same as in [Text translation options](#text-translation-options).\n- `GlossaryId`:  same as in [Text translation options](#text-translation-options).\n- `EnableDocumentMinification`: A `bool` value. If set to `true`, the library will try to minify a document\n  before translating it through the API, sending a smaller document if the file contains a lot of media. This is\n  currently only supported for `pptx` and `docx` files. See also [Document minification](#document-minification).\n  Note that this only works in the high-level `TranslateDocumentDownloadAsync` method, not\n  `TranslateDocumentUploadAsync`. However, the behavior can be emulated by creating a new `DocumentMinifier`\n  object and calling the minifier's methods in between.\n- `OutputFormat`: using the parameter during document upload, you can select alternative output formats. See\n  the [API documentation][api-docs-outputformat-param] for more information and example usage.\n- `ExtraBodyParameters`: `Dictionary\u003cstring, string\u003e` of extra parameters to pass in the body of the HTTP request. Keys\n  in this dictionary will be added to the request body and can override built-in parameters. Mostly used by DeepL\n  employees to test functionality, or for beta programs.\n\n#### Document minification\n\nIn some contexts, one can end up with large document files (e.g. PowerPoint presentations\nor Word files with many contributors, especially in a larger organization). However, the\nDeepL API enforces a limit of 30 MB for most of these files (see Usage Limits in the docs).\nIn the case that most of this size comes from media included in the documents (e.g. images,\nvideos, animations), document minification can help.\nIn this case, the library will create a temporary directory to extract the document into,\nreplace the large media with tiny placeholders, create a minified document, translate that\nvia the API, and re-insert the original media into the original file. Please note that this\nrequires a bit of additional (temporary) disk space, we recommend at least 2x the file size\nof the document to be translated.\nTo use document minification, simply pass the option to the `TranslateDocumentAsync` function:\n\n```c#\nawait client.TranslateDocumentAsync(\n    inFile, outFile, \"EN\", \"DE\", new DocumentTranslateOptions { EnableDocumentMinification = true }\n);\n```\n\nIn order to use document minification with the lower-level `TranslateDocumentUploadAsync`,\n`TranslateDocumentWaitUntilDoneAsync` and `TranslateDocumentDownloadAsync` methods as well as other details,\nsee the `DocumentMinifier` class.\nCurrently supported document types for minification:\n\n1. `pptx`\n2. `docx`\n   Currently supported media types for minification:\n1. `png`\n2. `jpg`\n3. `jpeg`\n4. `emf`\n5. `bmp`\n6. `tiff`\n7. `wdp`\n8. `svg`\n9. `gif`\n10. `mp4`\n11. `asf`\n12. `avi`\n13. `m4v`\n14. `mpg`\n15. `mpeg`\n16. `wmv`\n17. `mov`\n18. `aiff`\n19. `au`\n20. `mid`\n21. `midi`\n22. `mp3`\n23. `m4a`\n24. `wav`\n25. `wma`\n\n### Glossaries\n\nGlossaries allow you to customize your translations using defined terms.\nMultiple glossaries can be stored with your account, each with a user-specified name and a uniquely-assigned ID.\n\n### v2 versus v3 glossary APIs\n\nThe newest version of the glossary APIs are the `/v3` endpoints, allowing both\nediting functionality plus support for multilingual glossaries. New methods and\nobjects have been created to support interacting with these new glossaries.\nDue to this new functionality, users are recommended to utilize these\nmultilingual glossary methods. However, to continue using the `v2` glossary API\nendpoints, please continue to use the existing endpoints in the `Translator.cs`\n(e.g. `CreateGlossaryAsync()`, `GetGlossaryAsync()`, etc).\n\nTo migrate to use the new multilingual glossary methods from the current\nmonolingual glossary methods, please refer to\n[this migration guide](upgrading_to_multilingual_glossaries.md).\n\nThe following sections describe how to interact with multilingual glossaries\nusing the new functionality:\n\n#### Creating a glossary\n\nYou can create a glossary with your desired terms and name using\n`CreateMultilingualGlossaryAsync()`. Each glossary applies to a single source-target language\npair. Note: Glossaries are only supported for some language pairs, see\n[Listing available glossary languages](#listing-available-glossary-languages)\nfor more information. The entries should be specified as a `Dictionary`.\n\nIf successful, the glossary is created and stored with your DeepL account, and\na `MultilingualGlossaryInfo` object is returned including the ID, name, languages and entry\ncount.\n\n```c#\n// Create a glossary with an English to German dictionary containing two terms:\nvar entriesDictionary = new Dictionary\u003cstring, string\u003e{{\"artist\", \"Maler\"}, {\"prize\", \"Gewinn\"}};\nvar glossaryDicts = new[] {new MultilingualGlossaryDictionaryEntries(\n  \"EN\", \"DE\", new GlossaryEntries(entriesDictionary))};\nvar glossaryEnToDe = await client.CreateMultilingualGlossaryAsync(\"My glossary\", glossaryDicts);\n\nvar glossaryDictEnToDe = glossaryEnToDe.Dictionaries[0]\nConsole.WriteLine($\"Created {glossaryEnToDe.Name}' ({glossaryEnToDe.GlossaryId}) \" +\n    $\"with {glossaryEnToDe.Dictionaries.Length} dictionary where its language pair is \"\n    $\"{glossaryDictEnToDe.SourceLanguageCode}-\u003e{glossaryDictEnToDe.TargetLanguageCode} \" +\n    $\"containing {glossaryDictEnToDe.EntryCount} entries\"\n);\n// Example: Created 'My glossary' (559192ed-8e23-...) with 1 dictionary where\n// its language pair is EN-\u003eDE containing 2 entries\n\nYou can also upload a glossary downloaded from the DeepL website using\n`CreateMultilingualGlossaryFromCsvAsync()`. Instead of supplying the entries as a dictionary,\nspecify the CSV data as a `Stream` containing file content:\n\n```c#\nvar csvStream =  File.OpenRead(\"myGlossary.csv\");\nvar csvGlossary = await client.CreateMultilingualGlossaryFromCsvAsync(\"My CSV glossary\", \"EN\", \"DE\", csvStream);\n```\n\nThe [API documentation][api-docs-csv-format] explains the expected CSV format in detail.\n\n#### Getting, listing and deleting stored glossaries\n\nFunctions to get, list, and delete stored glossaries are also provided:\n\n- `GetMultilingualGlossaryAsync()` takes a glossary ID and returns a\n  `MultilingualGlossaryInfo` object for a stored glossary, or raises an\n  exception if no such glossary is found.\n- `ListMultilingualGlossariesAsync()` returns a `List` of\n  `MultilingualGlossaryInfo` objects corresponding to all of your stored\n  glossaries.\n- `DeleteMultilingualGlossaryAsync()` takes a glossary ID or\n  `MultilingualGlossaryInfo` object and deletes the stored glossary from the\n  server, or raises an exception if no such glossary is found.\n- `DeleteMultilingualGlossaryDictionaryAsync()` takes a glossary ID or\n  `MultilingualGlossaryInfo` object to identify the glossary. Additionally\n  takes in a source and target language or a\n  `MultilingualGlossaryDictionaryInfo` object and deletes the stored dictionary\n  from the server, or raises an exception if no such glossary dictionary is\n  found.\n\n```c#\n// Retrieve a stored glossary using the ID\nvar myGlossary = await client.GetMultilingualGlossaryAsync(\"559192ed-8e23-...\");\n\n// Delete a glossary dictionary from a stored glossary\nawait client.DeleteMultilingualGlossaryDictionaryAsync(myGlossary, myGlossary.Dictionaries[0]);\n\n// Find and delete glossaries named 'Old glossary'\nvar glossaries = await client.ListMultilingualGlossariesAsync();\nforeach (var glossaryInfo in glossaries) {\n  if (glossaryInfo.Name == \"Old glossary\")\n    await client.DeleteMultilingualGlossaryAsync(glossaryInfo);\n}\n```\n\n#### Listing entries in a stored glossary\n\nThe `MultilingualGlossaryDictionaryInfo` object does not contain the glossary entries, but instead\nonly the number of entries in the `EntryCount` property.\n\nTo list the entries contained within a stored glossary, use\n`GetMultilingualGlossaryDictionaryEntriesAsync()` providing either the `MultilingualGlossaryInfo` object or glossary ID\nand either a `MultilingualGlossaryDictionaryInfo` or source and target language pair:\n\n```c#\nvar glossaryDicts = await client.GetMultilingualGlossaryDictionaryEntriesAsync(myGlossary, \"en\", \"de\");\n\nforeach (KeyValuePair\u003cstring, string\u003e entry in glossaryDicts[0].Entries.ToDictionary()) {\n  Console.WriteLine($\"{entry.Key}: {entry.Value}\");\n}\n// prints:\n//   artist: Maler\n//   prize: Gewinn\n```\n\n#### Editing a glossary\n\nFunctions to edit stored glossaries are also provided:\n\n- `UpdateMultilingualGlossaryDictionaryAsync()` takes a glossary ID or `MultilingualGlossaryInfo`\n  object, plus a source language, target language, and a dictionary of entries.\n  It will then either update the list of entries for that dictionary (either\n  inserting new entires or replacing the target phrase for any existing\n  entries) or will insert a new glossary dictionary if that language pair is\n  not currently in the stored glossary.\n- `ReplaceMultilingualGlossaryDictionaryAsync()` takes a glossary ID or `MultilingualGlossaryInfo`\n  object, plus a source language, target language, and a dictionary of entries.\n  It will then either set the entries to the parameter value, completely\n  replacing any pre-existing entries for that language pair.\n- `UpdateMultilingualGlossaryNameAsync()` takes a glossary ID or `MultilingualGlossaryInfo`\n  object, plus the new name of the glossary.\n\n```c#\n// Update glossary dictionary\nvar entries = new Dictionary\u003cstring, string\u003e{{\"artist\", \"Maler\"}, {\"hello\", \"guten tag\"}};\nvar dictionaries = new[] {new MultilingualGlossaryDictionaryEntries(\"EN\", \"DE\", entries)};\nvar myGlossary = await client.CreateMultilingualGlossaryAsync(\n    \"My glossary\",\n    dictionaries\n);\nvar newEntries = new Dictionary\u003cstring, string\u003e{{\"hello\", \"hallo\"}, {\"prize\", \"Gewinn\"}};\nvar glossaryDict = new MultilingualGlossaryDictionaryEntries(\"EN\", \"DE\", newEntries);\nvar updatedGlossary = await client.UpdateMultilingualGlossaryDictionaryAsync(\n    myGlossary,\n    glossaryDict\n);\n\nvar entriesResponse = await client.GetMultilingualGlossaryEntriesAsync(myGlossary, \"EN\", \"DE\");\n\nforeach (KeyValuePair\u003cstring, string\u003e entry in entriesResponse.Dictionaries[0].Entries.ToDictionary()) {\n  Console.WriteLine($\"{entry.Key}: {entry.Value}\");\n}\n// prints:\n//   artist: Maler\n//   hello: hallo\n//   prize: Gewinn\n\n// Update a glossary dictionary from CSV\nvar csvStream =  File.OpenRead(\"myGlossary.csv\");\nvar csvGlossary = await client.UpdateMultilingualGlossaryDictionaryFromCsvAsync(\"4c81ffb4-2e...\", \"EN\", \"DE\", csvStream);\n\n// Replace glossary dictionary\nvar replacementEntries = new Dictionary\u003cstring, string\u003e{{\"goodbye\", \"Auf Wiedersehen\"}};\nvar glossaryDict = new MultilingualGlossaryDictionaryEntries(\"EN\", \"DE\", new GlossaryEntries(replacementEntries));\nvar updatedGlossary = await client.ReplaceMultilingualGlossaryDictionaryAsync(\n  myGlossary,\n  glossaryDict);\nvar entriesResponse = await client.GetMultilingualGlossaryEntries(myGlossary, \"EN\", \"DE\");\nforeach (KeyValuePair\u003cstring, string\u003e entry in entriesResponse.Dictionaries[0].Entries.ToDictionary()) {\n  Console.WriteLine($\"{entry.Key}: {entry.Value}\");\n}\n// prints:\n//   goodbye: Auf Wiedersehen\n\n// Replace a glossary dictionary from CSV\nvar csvStream =  File.OpenRead(\"myGlossary.csv\");\nvar csvGlossary = await client.ReplaceMultilingualGlossaryDictionaryFromCsvAsync(\"4c81ffb4-2e...\", \"EN\", \"DE\", csvStream);\n\n// Update the glossary name\nvar updatedGlossary = await client.UpdateMultilingualGlossaryNameAsync(\n  myGlossary,\n  \"My new glossary name\"\n);\nConsole.WriteLine(updatedGlossary.Name); // 'My new glossary name'\n```\n\n#### Using a stored glossary\n\nYou can use a stored glossary for text (or document) translation by setting the\n`TextTranslationOptions` (or `DocumentTranslationOptions`) `GlossaryId` property\nto the glossary ID. You must also specify the `source_lang` argument (it is\nrequired when using a glossary):\n\n```c#\nvar resultWithGlossary = await client.TranslateTextAsync(\n    \"The artist was awarded a prize.\",\n    \"EN\",\n    \"DE\",\n    new TextTranslateOptions { GlossaryId = glossaryEnToDe.GlossaryId });\n// resultWithGlossary.Text == \"Der Maler wurde mit einem Gewinn ausgezeichnet.\"\n// Without using a glossary: \"Der Künstler wurde mit einem Preis ausgezeichnet.\"\n```\n\n### Style Rules\n\nStyle rules allow you to customize your translations using a managed, shared list\nof rules for style, formatting, and more. Multiple style rules can be stored with\nyour account, each with a user-specified name and a uniquely-assigned ID.\n\n#### Creating a style rule\n\nUse `CreateStyleRuleAsync()` to create a new style rule with a name and language\ncode. You can optionally provide `configuredRules` and `customInstructions`.\n\n```c#\nvar rule = await client.CreateStyleRuleAsync(\"My Style Rule\", \"en\");\nConsole.WriteLine($\"Created: {rule.Name} ({rule.StyleId})\");\n```\n\n#### Retrieving and listing style rules\n\nUse `GetStyleRuleAsync()` to retrieve a single style rule by ID, or\n`GetAllStyleRulesAsync()` to list all style rules.\n\n`GetAllStyleRulesAsync()` returns an array of `StyleRuleInfo` objects\ncorresponding to all of your stored style rules. The method accepts optional\nparameters: `page` (page number for pagination, 0-indexed), `pageSize` (number\nof items per page), and `detailed`. When `true`, the response includes\n`ConfiguredRules` and `CustomInstructions` for each style rule. When `false`\n(default), these fields are omitted for faster responses.\n\n```c#\n// Get a single style rule by ID\nvar rule = await client.GetStyleRuleAsync(\"YOUR_STYLE_ID\");\nConsole.WriteLine($\"{rule.Name} ({rule.Language})\");\n\n// List all style rules\nvar styleRules = await client.GetAllStyleRulesAsync();\nforeach (var r in styleRules) {\n  Console.WriteLine($\"{r.Name} ({r.StyleId})\");\n}\n\n// List with detailed configuration\nvar styleRulesDetailed = await client.GetAllStyleRulesAsync(detailed: true);\nforeach (var r in styleRulesDetailed) {\n  if (r.ConfiguredRules?.Numbers != null) {\n    Console.WriteLine($\"  Number formatting: {string.Join(\", \", r.ConfiguredRules.Numbers.Keys)}\");\n  }\n}\n```\n\n#### Updating a style rule\n\nUse `UpdateStyleRuleNameAsync()` to rename a style rule, and\n`UpdateStyleRuleConfiguredRulesAsync()` to update its configured rules.\n\n```c#\n// Update the name\nvar updated = await client.UpdateStyleRuleNameAsync(\"YOUR_STYLE_ID\", \"New Name\");\n\n// Update configured rules\nvar configuredRules = new ConfiguredRules(\n    styleAndTone: new Dictionary\u003cstring, string\u003e { [\"formality\"] = \"formal\" });\nvar updatedRules = await client.UpdateStyleRuleConfiguredRulesAsync(\"YOUR_STYLE_ID\", configuredRules);\n```\n\n#### Managing custom instructions\n\nCustom instructions allow you to add free-text prompts to a style rule. Use\n`CreateStyleRuleCustomInstructionAsync()`, `GetStyleRuleCustomInstructionAsync()`,\n`UpdateStyleRuleCustomInstructionAsync()`, and\n`DeleteStyleRuleCustomInstructionAsync()` to manage them.\n\n```c#\n// Create a custom instruction\nvar instruction = await client.CreateStyleRuleCustomInstructionAsync(\n    \"YOUR_STYLE_ID\", \"Formal tone\", \"Always use formal language\");\nConsole.WriteLine($\"Created instruction: {instruction.Id}\");\n\n// Get a custom instruction\nvar retrieved = await client.GetStyleRuleCustomInstructionAsync(\n    \"YOUR_STYLE_ID\", instruction.Id);\n\n// Update a custom instruction\nvar updated = await client.UpdateStyleRuleCustomInstructionAsync(\n    \"YOUR_STYLE_ID\", instruction.Id, \"Updated label\", \"Use very formal language\");\n\n// Delete a custom instruction\nawait client.DeleteStyleRuleCustomInstructionAsync(\n    \"YOUR_STYLE_ID\", instruction.Id);\n```\n\n#### Deleting a style rule\n\nUse `DeleteStyleRuleAsync()` to delete a style rule by ID.\n\n```c#\nawait client.DeleteStyleRuleAsync(\"YOUR_STYLE_ID\");\n```\n\n### Translation Memories\n\nTranslation memories store and reuse previously created translations, helping to\nensure consistency across your translations and reduce the number of characters\nthat need to be translated.\n\n#### Uploading and managing translation memories\n\nCurrently translation memories must be uploaded and managed in the DeepL UI via\nhttps://www.deepl.com/translation-memory. Full CRUD functionality via the APIs will\ncome shortly.\n\n#### Listing translation memories\n\nUse `ListTranslationMemoriesAsync()` to retrieve all translation memories\nassociated with your account:\n\n```c#\nvar translationMemories = await client.ListTranslationMemoriesAsync();\nforeach (var tm in translationMemories) {\n  Console.WriteLine($\"{tm.Name} ({tm.TranslationMemoryId})\");\n}\n```\n\n#### Using a translation memory in translations\n\nYou can use a translation memory for text translation by setting the\n`TranslationMemoryId` property in `TextTranslateOptions`. Optionally, set\n`TranslationMemoryThreshold` to control the minimum similarity score for matches:\n\n```c#\nvar result = await client.TranslateTextAsync(\n    \"Hello, world!\",\n    \"EN\",\n    \"DE\",\n    new TextTranslateOptions {\n      TranslationMemoryId = \"YOUR_TM_ID\",\n      TranslationMemoryThreshold = 80\n    });\nConsole.WriteLine(result.Text);\n```\n\nYou can also construct `TextTranslateOptions` using a `TranslationMemoryInfo`\nobject:\n\n```c#\nvar translationMemories = await client.ListTranslationMemoriesAsync();\nvar tm = translationMemories[0];\n\nvar result = await client.TranslateTextAsync(\n    \"Hello, world!\",\n    \"EN\",\n    \"DE\",\n    new TextTranslateOptions(tm) { TranslationMemoryThreshold = 80 });\nConsole.WriteLine(result.Text);\n```\n\n### Check account usage\n\n```c#\nvar usage = await client.GetUsageAsync();\nif (usage.AnyLimitReached) {\n  Console.WriteLine(\"Translation limit exceeded.\");\n} else if (usage.Character != null) {\n  Console.WriteLine($\"Character usage: {usage.Character}\");\n} else {\n  Console.WriteLine($\"{usage}\");\n}\n```\n\n### Listing available languages\n\nYou can request the list of languages supported by DeepL for text and documents\nusing the `GetSourceLanguagesAsync()` and `GetTargetLanguagesAsync()` functions.\nThey both return a list of `Language` objects.\n\nThe `Name` property gives the name of the language in English, and the `Code`\nproperty gives the language code. The `SupportsFormality` property only appears\nfor target languages, and indicates whether the target language supports the\noptional `Formality` parameter.\n\n```c#\n// Source and target languages\nvar sourceLanguages = await client.GetSourceLanguagesAsync();\nforeach (var lang in sourceLanguages) {\n  Console.WriteLine($\"{lang.Name} ({lang.Code})\"); // Example: \"English (EN)\"\n}\nvar targetLanguages = await client.GetTargetLanguagesAsync();\nforeach (var lang in targetLanguages) {\n  if (lang.SupportsFormality ?? false) {\n    Console.WriteLine($\"{lang.Name} ({lang.Code}) supports formality\");\n     // Example: \"German (DE) supports formality\"\n  }\n}\n```\n\n#### Listing available glossary languages\n\nGlossaries are supported for a subset of language pairs. To retrieve those\nlanguages use the `GetGlossaryLanguagesAsync()` function, which returns an array\nof `GlossaryLanguagePair` objects. Use the `SourceLanguage` and\n`TargetLanguage` properties to check the pair of language codes supported.\n\n```c#\n\n// Glossary languages\nvar glossaryLanguages = await client.GetGlossaryLanguagesAsync();\nforeach (var languagePair in glossaryLanguages) {\n  Console.WriteLine($\"{languagePair.SourceLanguage} to {languagePair.TargetLanguage}\");\n  // Example: \"EN to DE\", \"DE to EN\", etc.\n}\n```\n\nYou can also find the list of supported glossary language pairs in the\n[API documentation][api-docs-glossary-lang-list].\n\nNote that glossaries work for all target regional-variants: a glossary for the\ntarget language English (`\"EN\"`) supports translations to both American English\n(`\"EN-US\"`) and British English (`\"EN-GB\"`).\n\n### Exceptions\n\nAll library functions may raise `DeepLException` or one of its subclasses. If\ninvalid arguments are provided, they may raise the standard exceptions\n`ArgumentException`.\n\n### Writing a Plugin\n\nIf you use this library in an application, please identify the application with\n`DeepLClientOptions.appInfo`, which needs the name and version of the app:\n\n```c#\nvar options = new DeepLClientOptions {\n  appInfo =  new AppInfo { AppName = \"my-dotnet-test-app\", AppVersion = \"1.2.3\"}\n};\nvar client = new DeepLClient(AuthKey, options);\n```\n\nThis information is passed along when the library makes calls to the DeepL API.\nBoth name and version are required. Please note that setting the `User-Agent` header\nvia `DeepLClientOptions.Headers` will override this setting, if you need to use this,\nplease manually identify your Application in the `User-Agent` header.\n\n### Configuration\n\nThe `DeepLClient` constructor accepts `DeepLClientOptions` as a second argument,\nfor example:\n\n```c#\nvar options = new DeepLClientOptions {\n      MaximumNetworkRetries = 5,\n      PerRetryConnectionTimeout = TimeSpan.FromSeconds(10),\n};\nvar client = new DeepLClient(authKey, options);\n```\n\nSee the `DeepLClientOptions` class for details about the available options.\n\n#### Proxy configuration\n\nTo use the library with a proxy, override the `ClientFactory` with a function returning a custom `HttpClient`:\n\n```c#\nvar proxyUrl = \"http://localhost:3001\";\nvar handler = new System.Net.Http.HttpClientHandler {\n      Proxy = new System.Net.WebProxy(proxyUrl), UseProxy = true,\n};\nvar options = new DeepLClientOptions {\n      ClientFactory = () =\u003e new HttpClientAndDisposeFlag {\n            HttpClient = new HttpClient(handler), DisposeClient = true,\n      }\n};\nvar client = new DeepLClient(authKey, options);\n```\n\n#### Anonymous platform information\n\nBy default, we send some basic information about the platform the client library is running\non with each request,\nsee [here for an explanation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent).\nThis data is completely anonymous and only used to improve our product, not track any\nindividual users. If you do not wish to send this data, you can opt-out when creating\nyour `DeepLClient` object by setting the `sendPlatformInfo` flag in the\n`DeepLClientOptions` to `false` like so:\n\n```c#\nvar options = new DeepLClientOptions { sendPlatformInfo = false };\nvar client = new DeepLClient(authKey, options);\n```\n\n## Issues\n\nIf you experience problems using the library, or would like to request a new feature, please open an\n[issue][issues].\n\n## Development\n\nWe welcome Pull Requests, please read the [contributing guidelines](CONTRIBUTING.md).\n\n### Tests\n\nExecute the tests using `dotnet test`. The tests communicate with the DeepL API using the auth key defined by the\n`DEEPL_AUTH_KEY` environment variable.\n\nBe aware that the tests make DeepL API requests that contribute toward your API usage.\n\nThe test suite may instead be configured to communicate with the mock-server provided by\n[deepl-mock](https://www.github.com/DeepLcom/deepl-mock). Although most test cases work for either, some test cases work\nonly with the DeepL API or the mock-server and will be otherwise skipped. The test cases that require the mock-server\ntrigger server errors and test the client error-handling. To execute the tests using deepl-mock, run it in another\nterminal while executing the tests. Execute the tests using `dotnet test` with the `DEEPL_MOCK_SERVER_PORT` and\n`DEEPL_SERVER_URL` environment variables defined referring to the mock-server.\n\n\n[api-docs-context-param]: https://www.deepl.com/docs-api/translating-text/?utm_source=github\u0026utm_medium=github-dotnet-readme\n\n[api-docs-csv-format]: https://www.deepl.com/docs-api/managing-glossaries/supported-glossary-formats/?utm_source=github\u0026utm_medium=github-dotnet-readme\n\n[api-docs-glossary-lang-list]: https://www.deepl.com/docs-api/managing-glossaries/?utm_source=github\u0026utm_medium=github-dotnet-readme\n\n[api-docs-outputformat-param]: https://www.deepl.com/docs-api/documents/format-conversions/?utm_source=github\u0026utm_medium=github-dotnet-readme\n\n[api-docs-xml-handling]: https://www.deepl.com/docs-api/handling-xml/?utm_source=github\u0026utm_medium=github-dotnet-readme\n\n[issues]: https://www.github.com/DeepLcom/deepl-dotnet/issues\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeeplcom%2Fdeepl-dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeeplcom%2Fdeepl-dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeeplcom%2Fdeepl-dotnet/lists"}