lib/ex_aws/translate.ex

defmodule ExAws.Translate do
  @moduledoc """
  The ExAws.Translate library provides an Elixir API for accessing the AWS Translate APIs. Please refer to the [AWS Translate API Documentation](https://docs.aws.amazon.com/translate/latest/dg/API_Reference.html) for the list of functionalities and available actions.
  """
  import ExAws.Utils, only: [camelize_keys: 2]

  @x_amz_target "AWSShineFrontendService_20170701"

  @doc """
  A synchronous action that deletes a custom terminology.

  ## Examples

      iex> ExAws.Translate.delete_terminology("terminology") |> ExAws.request()
      {:ok, %{}}

  For more information visit the AWS Translate API Documentation for [DeleteTerminology](https://docs.aws.amazon.com/translate/latest/dg/API_DeleteTerminology.html).
  """
  @spec delete_terminology(name :: String.t()) :: ExAws.Operation.JSON.t()
  def delete_terminology(name) do
    request(:delete_terminology, name: name)
  end

  @doc """
  Gets the properties associated with an asycnhronous batch translation job including name, ID, status, source and target languages, input/output S3 buckets, and so on.

  ## Examples

      iex> iex(2)> ExAws.Translate.describe_text_translation_job("12345") |> ExAws.request()
      {:ok,
        %{
          "TextTranslationJobProperties" => %{
            "DataAccessRoleArn" => "arn:aws:iam::123456789123:role/service-role/AmazonTranslateServiceRole-translate",
            "EndTime" => 1592240282.932,
            "InputDataConfig" => %{
              "ContentType" => "text/plain",
              "S3Uri" => "s3://bucket/input/"
            },
            "JobDetails" => %{
              "DocumentsWithErrorsCount" => 0,
              "InputDocumentsCount" => 1,
              "TranslatedDocumentsCount" => 1
            },
            "JobId" => "12345",
            "JobName" => "testjob",
            "JobStatus" => "COMPLETED",
            "Message" => "Your job has completed successfully.",
            "OutputDataConfig" => %{
              "S3Uri" => "s3://bucket/output/123456789123-TranslateText-12345/"
            },
            "SourceLanguageCode" => "en",
            "SubmittedTime" => 1592239611.151,
            "TargetLanguageCodes" => ["es"]
          }
        }
      }

  For more information visit the AWS Translate API Documentation for [DescribeTextTranslationJob](https://docs.aws.amazon.com/translate/latest/dg/API_DescribeTextTranslationJob.html).
  """
  @spec describe_text_translation_job(job_id :: String.t()) :: ExAws.Operation.JSON.t()
  def describe_text_translation_job(job_id) do
    request(:describe_text_translation_job, job_id: job_id)
  end

  @doc """
  Retrieves a custom terminology.

  ## Examples

      iex> ExAws.Translate.get_terminology("terminology") |> ExAws.request()
      {:ok,
        %{
          "TerminologyDataLocation" => %{
            "Location" => "https://aws-translate-terminology-prod-us-east-1.s3.us-east-1.amazonaws.com/123456789123/TEST/LATEST/3953eeac-986d-41b3-a2d5-9d973ace34f1/CSV/terminology.csv?X-Amz-Security-Token=12345",
            "RepositoryType" => "S3"
          },
          "TerminologyProperties" => %{
            "Arn" => "arn:aws:translate:us-east-1:123456789123:terminology/TEST/LATEST",
            "CreatedAt" => 1591997725.869,
            "LastUpdatedAt" => 1591997725.869,
            "Name" => "TEST",
            "SizeBytes" => 24,
            "SourceLanguageCode" => "en",
            "TargetLanguageCodes" => ["fr"],
            "TermCount" => 1
          }
        }
      }

  For more information visit the AWS Translate API Documentation for [GetTerminology](https://docs.aws.amazon.com/translate/latest/dg/API_GetTerminology.html).
  """
  @spec get_terminology(name :: String.t(), terminology_data_format :: String.t()) ::
          ExAws.Operation.JSON.t()
  def get_terminology(name, terminology_data_format) do
    request(:get_terminology, name: name, terminology_data_format: terminology_data_format)
  end

  @doc """
  Creates or updates a custom terminology, depending on whether or not one already exists for the given terminology name. Importing a terminology with the same name as an existing one will merge the terminologies based on the chosen merge strategy. Currently, the only supported merge strategy is OVERWRITE, and so the imported terminology will overwrite an existing terminology of the same name.

  ## Examples

      iex> ExAws.Translate.import_terminology("terminology", %{file: "base64encodedbinary", format: "CSV"}, "OVERWRITE") |> ExAws.request()
      {:ok,
        %{
          "TerminologyProperties" => %{
            "Arn" => "arn:aws:translate:us-east-1:126427819807:terminology/terminology-test/LATEST",
            "CreatedAt" => 1591997291.244,
            "LastUpdatedAt" => 1591997291.244,
            "Name" => "terminology-test",
            "SizeBytes" => 24,
            "SourceLanguageCode" => "en",
            "TargetLanguageCodes" => ["fr"],
            "TermCount" => 1
          }
        }
      }

  For more information visit the AWS Translate API Documentation for [ImportTerminology](https://docs.aws.amazon.com/translate/latest/dg/API_ImportTerminology.html).
  """
  @type import_terminology_opts :: [
          {:description, String.t()},
          {:encrpytion_key, String.t()}
        ]
  @type terminology_data :: %{
          required(:file) => iodata(),
          required(:format) => String.t()
        }

  @spec import_terminology(
          name :: String.t(),
          terminology_data :: terminology_data(),
          merge_strategy :: String.t()
        ) :: ExAws.Operation.JSON.t()
  @spec import_terminology(
          name :: String.t(),
          terminology_data :: terminology_data(),
          merge_strategy :: String.t(),
          opts :: import_terminology_opts()
        ) :: ExAws.Operation.JSON.t()
  def import_terminology(name, terminology_data, merge_strategy, opts \\ []) do
    data =
      Keyword.merge(
        [
          name: name,
          terminology_data: terminology_data,
          merge_strategy: merge_strategy
        ],
        opts
      )

    request(:import_terminology, data)
  end

  @doc """
  Provides a list of custom terminologies associated with your account.

  ## Examples

      iex> ExAws.Translate.list_terminologies() |> ExAws.request()
      {:ok,
        %{
          "TerminologyPropertiesList" => [
            %{
              "Arn" => "arn:aws:translate:us-east-1:126427819807:terminology/TEST/LATEST",
              "CreatedAt" => 1591997725.869,
              "LastUpdatedAt" => 1591997725.869,
              "Name" => "terminology-test",
              "SizeBytes" => 24,
              "SourceLanguageCode" => "en",
              "TargetLanguageCodes" => ["fr"],
              "TermCount" => 1
            }
          ]
        }
      }

  For more information visit the AWS Translate API Documentation for [ListTerminologies](https://docs.aws.amazon.com/translate/latest/dg/API_ListTerminologies.html).
  """
  @type list_terminologies_opts :: [
          {:max_results, integer()},
          {:next_token, String.t()}
        ]

  @spec list_terminologies() :: ExAws.Operation.JSON.t()
  @spec list_terminologies(opts :: list_terminologies_opts()) :: ExAws.Operation.JSON.t()
  def list_terminologies(opts \\ []) do
    request(:list_terminologies, opts)
  end

  @doc """
  Gets a list of the batch translation jobs that you have submitted.

  ## Examples

      iex> ExAws.Translate.list_text_translation_jobs() |> ExAws.request()
      {:ok,
        %{
          "TextTranslationJobPropertiesList" => [
            %{
              "DataAccessRoleArn" => "arn:aws:iam::123456789123:role/service-role/AmazonTranslateServiceRole-translate",
              "EndTime" => 1592240282.932,
              "InputDataConfig" => %{
                "ContentType" => "text/plain",
                "S3Uri" => "s3://bucket/input/"
              },
              "JobDetails" => %{
                "DocumentsWithErrorsCount" => 0,
                "InputDocumentsCount" => 1,
                "TranslatedDocumentsCount" => 1
              },
              "JobId" => "12345",
              "JobName" => "testjob",
              "JobStatus" => "COMPLETED",
              "Message" => "Your job has completed successfully.",
              "OutputDataConfig" => %{
                "S3Uri" => "s3://bucket/output/123456789123-TranslateText-12345/"
              },
              "SourceLanguageCode" => "en",
              "SubmittedTime" => 1592239611.151,
              "TargetLanguageCodes" => ["es"]
            }
          ]
        }
      }

  For more information visit the AWS Translate API Documentation for [ListTestTranslationJobs](https://docs.aws.amazon.com/translate/latest/dg/API_ListTextTranslationJobs.html).
  """
  @type text_translation_job_filter :: %{
          optional(:job_name) => String.t(),
          optional(:job_status) => String.t(),
          optional(:submitted_after_time) => integer(),
          optional(:submitted_before_time) => integer()
        }
  @type list_text_translation_opts :: [
          {:filter, text_translation_job_filter()},
          {:max_results, integer()},
          {:next_token, String.t()}
        ]

  @spec list_text_translation_jobs() :: ExAws.Operation.JSON.t()
  @spec list_text_translation_jobs(opts :: list_text_translation_opts()) ::
          ExAws.Operation.JSON.t()
  def list_text_translation_jobs(opts \\ []) do
    request(:list_text_translation_jobs, opts)
  end

  @doc """
  Starts an asynchronous batch translation job. Batch translation jobs can be used to translate large volumes of text across multiple documents at once. For more information, see [Asynchronous Batch Processing](https://docs.aws.amazon.com/translate/latest/dg/async.html).

  Batch translation jobs can be described with the [DescribeTextTranslationJob](https://docs.aws.amazon.com/translate/latest/dg/API_DescribeTextTranslationJob.html) operation, listed with the [ListTextTranslationJobs](https://docs.aws.amazon.com/translate/latest/dg/API_ListTextTranslationJobs.html) operation, and stopped with the [StopTextTranslationJob](https://docs.aws.amazon.com/translate/latest/dg/API_StopTextTranslationJob.html) operation.

  ## Examples

      iex> ExAws.Translate.start_text_translation_job(
        "ba3e6b13-b79b-4c1c-97ca-7258d7545ec1",
        "arn:aws:iam::123456789123:role/service-role/AmazonTranslateServiceRole-translate",
        %{content_type: "text/plain", s3_uri: "s3://bucket/input"},
        %{s3_uri: "s3://bucket/output"},
        "en",
        ["es"]
      )
      |> ExAws.request()
      {:ok,
        %{"JobId" => "cc4208305119d3fff9a5e8daa702c637", "JobStatus" => "SUBMITTED"}}

  For more information visit the AWS Translate API Documentation for [StartTextTranslationJob](https://docs.aws.amazon.com/translate/latest/dg/API_StartTextTranslationJob.html).
  """
  @type input_data_config :: %{
          required(:content_type) => String.t(),
          required(:s3_uri) => String.t()
        }
  @type output_data_config :: %{
          required(:s3_uri) => String.t()
        }
  @type start_text_translation_job_opts :: [
          {:job_name, String.t()},
          {:terminology_names, list(String.t())}
        ]

  @spec start_text_translation_job(
          client_token :: String.t(),
          data_access_role_arn :: String.t(),
          input_data_config :: input_data_config(),
          output_data_config :: output_data_config(),
          source_language_code :: String.t(),
          target_language_codes :: list()
        ) :: ExAws.Operation.JSON.t()
  @spec start_text_translation_job(
          client_token :: String.t(),
          data_access_role_arn :: String.t(),
          input_data_config :: input_data_config(),
          output_data_config :: output_data_config(),
          source_language_code :: String.t(),
          target_language_codes :: list(),
          opts :: start_text_translation_job_opts()
        ) :: ExAws.Operation.JSON.t()
  def start_text_translation_job(
        client_token,
        data_access_role_arn,
        input_data_config,
        output_data_config,
        source_language_code,
        target_language_codes,
        opts \\ []
      ) do
    data =
      Keyword.merge(
        [
          client_token: client_token,
          data_access_role_arn: data_access_role_arn,
          input_data_config: input_data_config,
          output_data_config: output_data_config,
          source_language_code: source_language_code,
          target_language_codes: target_language_codes
        ],
        opts
      )

    request(:start_text_translation_job, data)
  end

  @doc """
  Stops an asynchronous batch translation job that is in progress.

  If the job's state is IN_PROGRESS, the job will be marked for termination and put into the STOP_REQUESTED state. If the job completes before it can be stopped, it is put into the COMPLETED state. Otherwise, the job is put into the STOPPED state.

  Asynchronous batch translation jobs are started with the [StartTextTranslationJob](https://docs.aws.amazon.com/translate/latest/dg/API_StartTextTranslationJob.html) operation. You can use the [DescribeTextTranslationJob](https://docs.aws.amazon.com/translate/latest/dg/API_DescribeTextTranslationJob.html) or [ListTextTranslationJobs](https://docs.aws.amazon.com/translate/latest/dg/API_ListTextTranslationJobs.html) operations to get a batch translation job's `JobId`.

  ## Examples

    iex> ExAws.Translate.stop_text_translation_job("12345") |> ExAws.request()
    {:ok,
      %{
        "JobId" => "12345",
        "JobStatus" => "STOP_REQUESTED"
      }
    }

  For more information visit the AWS Translate API Documentation for [StopTextTranslationJob](https://docs.aws.amazon.com/translate/latest/dg/API_StopTextTranslationJob.html).
  """
  @spec stop_text_translation_job(job_id :: String.t()) :: ExAws.Operation.JSON.t()
  def stop_text_translation_job(job_id) do
    request(:stop_text_translation_job, job_id: job_id)
  end

  @doc """
  Translates a phrase from the source language to the target language.

  ## Examples

      iex> ExAws.Translate.translate_text("Hello, World!", "en", "es") |> ExAws.request()
      {:ok,
        %{
          "SourceLanguageCode" => "en",
          "TargetLanguageCode" => "es",
          "TranslatedText" => "¡Hola, Mundo!"
        }
      }

  For more information visit the AWS Translate API Documentation for [TranslateText](https://docs.aws.amazon.com/translate/latest/dg/API_TranslateText.html).
  """
  @type translate_text_opts :: [
          {:terminology_names, String.t()}
        ]

  @spec translate_text(
          text :: String.t(),
          source_language_code :: String.t(),
          target_language_code :: String.t()
        ) :: ExAws.Operation.JSON.t()
  @spec translate_text(
          text :: String.t(),
          source_language_code :: String.t(),
          target_language_code :: String.t(),
          opts :: translate_text_opts()
        ) :: ExAws.Operation.JSON.t()
  def translate_text(text, source_language_code, target_language_code, opts \\ []) do
    data =
      Keyword.merge(
        [
          text: text,
          source_language_code: source_language_code,
          target_language_code: target_language_code
        ],
        opts
      )

    request(:translate_text, data)
  end

  @doc false
  defp request(operation, data) do
    %ExAws.Operation.JSON{
      data: normalize_data(data),
      headers: [
        {"Content-Type", "application/x-amz-json-1.1"},
        {"X-Amz-Target", "#{@x_amz_target}.#{normalize_operation(operation)}"}
      ],
      service: :translate
    }
  end

  @doc false
  defp normalize_data(data),
    do:
      data
      |> Enum.into(%{})
      |> camelize_keys(deep: true)

  @doc false
  defp normalize_operation(operation),
    do:
      operation
      |> Atom.to_string()
      |> Macro.camelize()
end