你当前正在访问 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 服务版本。

先决条件

创建“翻译”资源

文档翻译仅支持 单服务访问 。 若要访问服务,请创建翻译器资源。

可以使用以下方法创建任一资源:

选项 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_SECRETAZURE_TENANT_IDclient secrettenant ID

string endpoint = "<Document Translator Resource Endpoint>";
var client = new DocumentTranslationClient(new Uri(endpoint), new DefaultAzureCredential());

关键概念

文档翻译服务要求将文件上传到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 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。

曝光数