你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于 .NET 的 Azure 认知服务文档翻译客户端库 - 版本 1.0.0
Azure 认知服务文档翻译是一种云服务,用于将文档翻译为 90 种语言和方言,同时保留文档结构和数据格式。 使用用于文档翻译的客户端库可以:
- 将大量大型文件从Azure Blob 存储容器翻译成所选语言的目标容器。
- 检查翻译操作中每个文档的翻译状态和进度。
- 应用自定义翻译模型或术语表,根据特定情况定制翻译。
源代码 | 包 (NuGet) | API 参考文档 | 产品文档 | 样品
入门
安装包
使用 NuGet 安装适用于 .NET 的 Azure 文档翻译客户端库:
dotnet add package Azure.AI.Translation.Document
注意:此版本的客户端库默认为
v1.0
服务版本。
先决条件
- 一个 Azure 订阅。
- 现有的翻译器资源。
创建“翻译”资源
文档翻译仅支持 单服务访问 。 若要访问服务,请创建翻译器资源。
可以使用以下方法创建任一资源:
选项 1:Azure 门户。
选项 2:Azure CLI。
下面是如何使用 CLI 创建翻译器资源的示例:
# Create a new resource group to hold the Translator resource -
# if using an existing resource group, skip this step
az group create --name <your-resource-name> --location <location>
# Create Translator
az cognitiveservices account create \
--name <your-resource-name> \
--custom-domain <your-resource-name> \
--resource-group <your-resource-group-name> \
--kind TextTranslation \
--sku S1 \
--location <location> \
--yes
有关创建资源以及如何获取位置信息的详细信息,请参阅 此处。
验证客户端
若要与文档翻译服务交互,需要创建 DocumentTranslationClient 类的实例。 需要 终结点和API 密钥 或 TokenCredential
实例化客户端对象。 有关使用认知服务进行身份验证的详细信息,请参阅 对 Azure 认知服务的请求进行身份验证。
查找终结点
对于文档翻译,需要使用翻译器资源的名称Custom Domain终结点。
获取 API 密钥
可以从 Azure 门户中的翻译器资源信息获取 API key
。
或者,使用下面的 Azure CLI 代码片段从翻译器资源获取 API 密钥。
az cognitiveservices account keys list --resource-group <your-resource-group-name> --name <your-resource-name>
使用 API 密钥凭据创建 DocumentTranslationClient
获得 API 密钥的值后,请 AzureKeyCredential
创建 。 这样,无需创建新客户端即可更新 API 密钥。
使用 终结点和 AzureKeyCredential
的值,可以创建 DocumentTranslationClient:
string endpoint = "<Document Translator Resource Endpoint>";
string apiKey = "<Document Translator Resource API Key>";
var client = new DocumentTranslationClient(new Uri(endpoint), new AzureKeyCredential(apiKey));
使用 Azure Active Directory 凭据创建 DocumentTranslationClient
本入门指南中的大多数示例中都使用了客户端 API 密钥身份验证,但也可以使用 Azure 标识库通过 Azure Active Directory 进行身份验证。 请注意,区域终结点不支持 AAD 身份验证。
为资源创建自定义子域,以使用此类身份验证。
若要使用如下所示的 DefaultAzureCredential 提供程序或 Azure SDK 提供的其他凭据提供程序,请安装 Azure.Identity 包:
dotnet add package Azure.Identity
还需要注册新的 AAD 应用程序,并通过将角色分配给服务主体来"Cognitive Services User"
授予对翻译器资源的访问权限。
将 AAD 应用程序的 、 和 的值client ID
设置为环境变量:AZURE_CLIENT_ID
、、。 AZURE_CLIENT_SECRET
AZURE_TENANT_ID
client secret
tenant ID
string endpoint = "<Document Translator Resource Endpoint>";
var client = new DocumentTranslationClient(new Uri(endpoint), new DefaultAzureCredential());
关键概念
文档翻译服务要求将文件上传到Azure Blob 存储源容器,并提供可在其中写入已翻译文档的目标容器。 容器的 SAS 令牌 (或文件) 用于访问文档并在目标容器中创建已翻译的文档。 有关此设置的其他信息,请参阅服务文档:
- 使用文档设置Azure Blob 存储容器。
- (可选)应用 术语表 或 自定义模型进行翻译。
- ) 具有适当权限的容器 (或文件生成 SAS 令牌。
DocumentTranslationClient
是 DocumentTranslationClient
使用文档翻译客户端库的开发人员的主要接口。 它提供同步和异步方法来执行以下操作:
- 创建翻译操作来翻译源容器中的文档 () ,并将结果写入目标容器 () 。
- 枚举所有过去和当前翻译操作。
- 确定支持的术语表和文档格式。
翻译输入
若要启动转换操作,需要创建一个 实例或 列表 DocumentTranslationInput
。
文档的单个源 URL 可以翻译为许多不同的语言:
Uri sourceSasUri = new Uri("<source SAS URI>");
Uri frenchTargetSasUri = new Uri("<french target SAS URI>");
var input = new DocumentTranslationInput(sourceSasUri, frenchTargetSasUri, "fr");
或者,可以为每个源提供其自己的目标。
Uri arabicTargetSasUri = new Uri("<arabic target SAS URI>");
Uri spanishTargetSasUri = new Uri("<spanish target SAS URI>");
Uri source1SasUri = new Uri("<source1 SAS URI>");
Uri source2SasUri = new Uri("<source2 SAS URI>");
var inputs = new List<DocumentTranslationInput>
{
new DocumentTranslationInput(source1SasUri, spanishTargetSasUri, "es"),
new DocumentTranslationInput(
source: new TranslationSource(source2SasUri),
targets: new List<TranslationTarget>
{
new TranslationTarget(frenchTargetSasUri, "fr"),
new TranslationTarget(arabicTargetSasUri, "ar")
}),
};
请注意,写入目标容器的文档必须具有唯一的名称。 因此,不能将源容器转换为目标容器两次,也不能将具有相同文档的源转换为同一目标容器。
Long-Running操作
文档翻译作为 长时间运行的操作实现。 长时间运行的操作包括发送到服务以启动操作的初始请求,然后按间隔轮询服务以确定操作是成功完成还是失败。
对于 Azure SDK 中长时间运行的操作,客户端会公开返回 Start<operation-name>
PageableOperation<T>
的方法。 可以使用 扩展方法 WaitForCompletionAsync()
等待操作完成并获取其结果。 下面提供了一个示例代码片段,用于说明如何使用长时间运行的操作。
线程安全
我们保证所有客户端实例方法都是线程安全的,并且彼此独立 (准则) 。 这可确保重用客户端实例的建议始终是安全的,即使在线程之间也是如此。
其他概念
客户端选项 | 访问响应 | 处理失败 | 诊断 | 嘲笑 | 客户端生存期
示例
以下部分提供了使用client
上面创建的 的多个代码片段,并介绍了文档翻译main函数。
注意:我们提供 DocumentTranslationClient
同步和异步方法。
异步示例
同步示例
注意:我们提供 DocumentTranslationClient
同步和异步方法。
开始异步翻译
启动翻译操作以翻译源容器中的文档,并将已翻译的文件写入目标容器。 DocumentTranslationOperation
允许轮询翻译操作的状态并获取各个文档的状态。
Uri sourceUri = new Uri("<source SAS URI>");
Uri targetUri = new Uri("<target SAS URI>");
var input = new DocumentTranslationInput(sourceUri, targetUri, "es");
DocumentTranslationOperation operation = await client.StartTranslationAsync(input);
await operation.WaitForCompletionAsync();
Console.WriteLine($" Status: {operation.Status}");
Console.WriteLine($" Created on: {operation.CreatedOn}");
Console.WriteLine($" Last modified: {operation.LastModified}");
Console.WriteLine($" Total documents: {operation.DocumentsTotal}");
Console.WriteLine($" Succeeded: {operation.DocumentsSucceeded}");
Console.WriteLine($" Failed: {operation.DocumentsFailed}");
Console.WriteLine($" In Progress: {operation.DocumentsInProgress}");
Console.WriteLine($" Not started: {operation.DocumentsNotStarted}");
await foreach (DocumentStatusResult document in operation.Value)
{
Console.WriteLine($"Document with Id: {document.Id}");
Console.WriteLine($" Status:{document.Status}");
if (document.Status == DocumentTranslationStatus.Succeeded)
{
Console.WriteLine($" Translated Document Uri: {document.TranslatedDocumentUri}");
Console.WriteLine($" Translated to language code: {document.TranslatedToLanguageCode}.");
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
}
else
{
Console.WriteLine($" Error Code: {document.Error.Code}");
Console.WriteLine($" Message: {document.Error.Message}");
}
}
异步获取操作历史记录
获取过去 7 天内提交的翻译操作的历史记录。 如果用户想要返回所有提交的操作,则可以忽略 options 参数。
int operationsCount = 0;
int totalDocs = 0;
int docsCanceled = 0;
int docsSucceeded = 0;
int docsFailed = 0;
DateTimeOffset lastWeekTimestamp = DateTimeOffset.Now.AddDays(-7);
var options = new GetTranslationStatusesOptions
{
CreatedAfter = lastWeekTimestamp
};
await foreach (TranslationStatusResult translationStatus in client.GetTranslationStatusesAsync(options))
{
if (translationStatus.Status == DocumentTranslationStatus.NotStarted ||
translationStatus.Status == DocumentTranslationStatus.Running)
{
DocumentTranslationOperation operation = new DocumentTranslationOperation(translationStatus.Id, client);
await operation.WaitForCompletionAsync();
}
operationsCount++;
totalDocs += translationStatus.DocumentsTotal;
docsCanceled += translationStatus.DocumentsCanceled;
docsSucceeded += translationStatus.DocumentsSucceeded;
docsFailed += translationStatus.DocumentsFailed;
}
Console.WriteLine($"# of operations: {operationsCount}");
Console.WriteLine($"Total Documents: {totalDocs}");
Console.WriteLine($"Succeeded Document: {docsSucceeded}");
Console.WriteLine($"Failed Document: {docsFailed}");
Console.WriteLine($"Canceled Documents: {docsCanceled}");
使用多个输入异步开始翻译
启动翻译操作,将多个源容器中的文档翻译成不同语言的多个目标容器。 DocumentTranslationOperation
允许轮询翻译操作的状态并获取各个文档的状态。
Uri source1SasUri = new Uri("<source1 SAS URI>");
Uri source2SasUri = new Uri("<source2 SAS URI>");
Uri frenchTargetSasUri = new Uri("<french target SAS URI>");
Uri arabicTargetSasUri = new Uri("<arabic target SAS URI>");
Uri spanishTargetSasUri = new Uri("<spanish target SAS URI>");
Uri frenchGlossarySasUri = new Uri("<french glossary SAS URI>");
var glossaryFormat = "TSV";
var input1 = new DocumentTranslationInput(source1SasUri, frenchTargetSasUri, "fr", new TranslationGlossary(frenchGlossarySasUri, glossaryFormat));
input1.AddTarget(spanishTargetSasUri, "es");
var input2 = new DocumentTranslationInput(source2SasUri, arabicTargetSasUri, "ar");
input2.AddTarget(frenchTargetSasUri, "fr", new TranslationGlossary(frenchGlossarySasUri, glossaryFormat));
var inputs = new List<DocumentTranslationInput>()
{
input1,
input2
};
DocumentTranslationOperation operation = await client.StartTranslationAsync(inputs);
await operation.WaitForCompletionAsync();
await foreach (DocumentStatusResult document in operation.GetValuesAsync())
{
Console.WriteLine($"Document with Id: {document.Id}");
Console.WriteLine($" Status:{document.Status}");
if (document.Status == DocumentTranslationStatus.Succeeded)
{
Console.WriteLine($" Translated Document Uri: {document.TranslatedDocumentUri}");
Console.WriteLine($" Translated to language code: {document.TranslatedToLanguageCode}.");
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
}
else
{
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
Console.WriteLine($" Error Code: {document.Error.Code}");
Console.WriteLine($" Message: {document.Error.Message}");
}
}
开始翻译
启动翻译操作以翻译源容器中的文档,并将已翻译的文件写入目标容器。 DocumentTranslationOperation
允许轮询翻译操作的状态并获取各个文档的状态。
Uri sourceUri = new Uri("<source SAS URI>");
Uri targetUri = new Uri("<target SAS URI>");
var input = new DocumentTranslationInput(sourceUri, targetUri, "es");
DocumentTranslationOperation operation = client.StartTranslation(input);
TimeSpan pollingInterval = new(1000);
while (true)
{
operation.UpdateStatus();
Console.WriteLine($" Status: {operation.Status}");
Console.WriteLine($" Created on: {operation.CreatedOn}");
Console.WriteLine($" Last modified: {operation.LastModified}");
Console.WriteLine($" Total documents: {operation.DocumentsTotal}");
Console.WriteLine($" Succeeded: {operation.DocumentsSucceeded}");
Console.WriteLine($" Failed: {operation.DocumentsFailed}");
Console.WriteLine($" In Progress: {operation.DocumentsInProgress}");
Console.WriteLine($" Not started: {operation.DocumentsNotStarted}");
if (operation.HasCompleted)
{
break;
}
else
{
if (operation.GetRawResponse().Headers.TryGetValue("Retry-After", out string value))
{
pollingInterval = TimeSpan.FromSeconds(Convert.ToInt32(value));
}
Thread.Sleep(pollingInterval);
}
}
foreach (DocumentStatusResult document in operation.GetValues())
{
Console.WriteLine($"Document with Id: {document.Id}");
Console.WriteLine($" Status:{document.Status}");
if (document.Status == DocumentTranslationStatus.Succeeded)
{
Console.WriteLine($" Translated Document Uri: {document.TranslatedDocumentUri}");
Console.WriteLine($" Translated to language code: {document.TranslatedToLanguageCode}.");
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
}
else
{
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
Console.WriteLine($" Error Code: {document.Error.Code}");
Console.WriteLine($" Message: {document.Error.Message}");
}
}
疑难解答
常规
使用 .NET SDK 与认知服务文档翻译客户端库交互时,服务返回的错误对应于为 REST API 请求返回的相同 HTTP 状态代码。
例如,如果提交包含空目标列表的请求,则会返回一个 400
错误,指示“错误请求”。
var invalidInput = new DocumentTranslationInput(new TranslationSource(new Uri(endpoint)), new List<TranslationTarget>());
try
{
DocumentTranslationOperation operation = client.StartTranslation(invalidInput);
}
catch (RequestFailedException e)
{
Console.WriteLine(e.ToString());
}
你会注意到记录了其他信息,例如操作的客户端请求 ID。
Message:
Azure.RequestFailedException: Service request failed.
Status: 400 (Bad Request)
Content:
{"error":{"code":"InvalidRequest","message":"No translation target found.","target":"TargetInput","innerError":{"code":"NoTranslationTargetFound","message":"No translation target found."}}}
Headers:
Transfer-Encoding: chunked
X-RequestId: REDACTED
Content-Type: application/json; charset=utf-8
Set-Cookie: REDACTED
X-Powered-By: REDACTED
apim-request-id: REDACTED
Strict-Transport-Security: REDACTED
x-content-type-options: REDACTED
Date: Mon, 22 Mar 2021 11:54:58 GMT
设置控制台日志记录
查看日志的最简单方法是启用控制台日志记录。 若要创建将消息输出到控制台的 Azure SDK 日志侦听器,请使用 AzureEventSourceListener.CreateConsoleLogger 方法。
// Setup a listener to monitor logged events.
using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();
若要了解有关其他日志记录机制的详细信息,请参阅 此处。
后续步骤
此 GitHub 存储库中提供了演示如何使用认知服务文档翻译库的示例。
高级示例
供稿
有关构建、测试和参与此库的详细信息,请参阅 CONTRIBUTING.md 。
本项目欢迎贡献和建议。 大多数贡献要求你同意贡献者许可协议 (CLA),并声明你有权(并且确实有权)授予我们使用你的贡献的权利。 有关详细信息,请访问 cla.microsoft.com。
提交拉取请求时,CLA 机器人将自动确定你是否需要提供 CLA,并相应地修饰 PR(例如标签、注释)。 直接按机器人提供的说明操作。 只需使用 CLA 对所有存储库执行一次这样的操作。
此项目采用了 Microsoft 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。