You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

237 lines
6.9 KiB

  1. // Copyright 2016 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package translate is a client for the Google Translation API.
  15. // See https://cloud.google.com/translation for details.
  16. package translate
  17. import (
  18. "context"
  19. "fmt"
  20. "net/http"
  21. "cloud.google.com/go/internal/version"
  22. raw "cloud.google.com/go/translate/internal/translate/v2"
  23. "golang.org/x/text/language"
  24. "google.golang.org/api/option"
  25. htransport "google.golang.org/api/transport/http"
  26. )
  27. const userAgent = "gcloud-golang-translate/20161115"
  28. // Scope is the OAuth2 scope required by the Google Cloud Vision API.
  29. const Scope = raw.CloudPlatformScope
  30. // Client is a client for the translate API.
  31. type Client struct {
  32. raw *raw.Service
  33. }
  34. const prodAddr = "https://translation.googleapis.com/language/translate/"
  35. // NewClient constructs a new Client that can perform Translation operations.
  36. //
  37. // You can find or create API key for your project from the Credentials page of
  38. // the Developers Console (console.developers.google.com).
  39. func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
  40. o := []option.ClientOption{
  41. option.WithEndpoint(prodAddr),
  42. option.WithScopes(Scope),
  43. option.WithUserAgent(userAgent),
  44. }
  45. o = append(o, opts...)
  46. httpClient, endpoint, err := htransport.NewClient(ctx, o...)
  47. if err != nil {
  48. return nil, fmt.Errorf("dialing: %v", err)
  49. }
  50. rawService, err := raw.New(httpClient)
  51. if err != nil {
  52. return nil, fmt.Errorf("translate client: %v", err)
  53. }
  54. rawService.BasePath = endpoint
  55. return &Client{raw: rawService}, nil
  56. }
  57. // Close closes any resources held by the client.
  58. // Close should be called when the client is no longer needed.
  59. // It need not be called at program exit.
  60. func (c *Client) Close() error { return nil }
  61. // Translate one or more strings of text from a source language to a target
  62. // language. All inputs must be in the same language.
  63. //
  64. // The target parameter supplies the language to translate to. The supported
  65. // languages are listed at
  66. // https://cloud.google.com/translation/v2/translate-reference#supported_languages.
  67. // You can also call the SupportedLanguages method.
  68. //
  69. // The returned Translations appear in the same order as the inputs.
  70. func (c *Client) Translate(ctx context.Context, inputs []string, target language.Tag, opts *Options) ([]Translation, error) {
  71. call := c.raw.Translations.List(inputs, target.String()).Context(ctx)
  72. setClientHeader(call.Header())
  73. if opts != nil {
  74. if s := opts.Source; s != language.Und {
  75. call.Source(s.String())
  76. }
  77. if f := opts.Format; f != "" {
  78. call.Format(string(f))
  79. }
  80. if m := opts.Model; m != "" {
  81. call.Model(m)
  82. }
  83. }
  84. res, err := call.Do()
  85. if err != nil {
  86. return nil, err
  87. }
  88. var ts []Translation
  89. for _, t := range res.Translations {
  90. var source language.Tag
  91. if t.DetectedSourceLanguage != "" {
  92. source, err = language.Parse(t.DetectedSourceLanguage)
  93. if err != nil {
  94. return nil, err
  95. }
  96. }
  97. ts = append(ts, Translation{
  98. Text: t.TranslatedText,
  99. Source: source,
  100. Model: t.Model,
  101. })
  102. }
  103. return ts, nil
  104. }
  105. // Options contains options for Translate.
  106. type Options struct {
  107. // Source is the language of the input strings. If empty, the service will
  108. // attempt to identify the source language automatically and return it within
  109. // the response.
  110. Source language.Tag
  111. // Format describes the format of the input texts. The choices are HTML or
  112. // Text. The default is HTML.
  113. Format Format
  114. // The model to use for translation. The choices are "nmt" or "base". The
  115. // default is "base".
  116. Model string
  117. }
  118. // Format is the format of the input text. Used in Options.Format.
  119. type Format string
  120. // Constants for Options.Format.
  121. const (
  122. HTML Format = "html"
  123. Text Format = "text"
  124. )
  125. // Translation contains the results of translating a piece of text.
  126. type Translation struct {
  127. // Text is the input text translated into the target language.
  128. Text string
  129. // Source is the detected language of the input text, if source was
  130. // not supplied to Client.Translate. If source was supplied, this field
  131. // will be empty.
  132. Source language.Tag
  133. // Model is the model that was used for translation.
  134. // It may not match the model provided as an option to Client.Translate.
  135. Model string
  136. }
  137. // DetectLanguage attempts to determine the language of the inputs. Each input
  138. // string may be in a different language.
  139. //
  140. // Each slice of Detections in the return value corresponds with one input
  141. // string. A slice of Detections holds multiple hypotheses for the language of
  142. // a single input string.
  143. func (c *Client) DetectLanguage(ctx context.Context, inputs []string) ([][]Detection, error) {
  144. call := c.raw.Detections.List(inputs).Context(ctx)
  145. setClientHeader(call.Header())
  146. res, err := call.Do()
  147. if err != nil {
  148. return nil, err
  149. }
  150. var result [][]Detection
  151. for _, raws := range res.Detections {
  152. var ds []Detection
  153. for _, rd := range raws {
  154. tag, err := language.Parse(rd.Language)
  155. if err != nil {
  156. return nil, err
  157. }
  158. ds = append(ds, Detection{
  159. Language: tag,
  160. Confidence: rd.Confidence,
  161. IsReliable: rd.IsReliable,
  162. })
  163. }
  164. result = append(result, ds)
  165. }
  166. return result, nil
  167. }
  168. // Detection represents information about a language detected in an input.
  169. type Detection struct {
  170. // Language is the code of the language detected.
  171. Language language.Tag
  172. // Confidence is a number from 0 to 1, with higher numbers indicating more
  173. // confidence in the detection.
  174. Confidence float64
  175. // IsReliable indicates whether the language detection result is reliable.
  176. IsReliable bool
  177. }
  178. // SupportedLanguages returns a list of supported languages for translation.
  179. // The target parameter is the language to use to return localized, human
  180. // readable names of supported languages.
  181. func (c *Client) SupportedLanguages(ctx context.Context, target language.Tag) ([]Language, error) {
  182. call := c.raw.Languages.List().Context(ctx).Target(target.String())
  183. setClientHeader(call.Header())
  184. res, err := call.Do()
  185. if err != nil {
  186. return nil, err
  187. }
  188. var ls []Language
  189. for _, l := range res.Languages {
  190. tag, err := language.Parse(l.Language)
  191. if err != nil {
  192. return nil, err
  193. }
  194. ls = append(ls, Language{
  195. Name: l.Name,
  196. Tag: tag,
  197. })
  198. }
  199. return ls, nil
  200. }
  201. // A Language describes a language supported for translation.
  202. type Language struct {
  203. // Name is the human-readable name of the language.
  204. Name string
  205. // Tag is a standard code for the language.
  206. Tag language.Tag
  207. }
  208. func setClientHeader(headers http.Header) {
  209. headers.Set("x-goog-api-client", fmt.Sprintf("gl-go/%s gccl/%s", version.Go(), version.Repo))
  210. }