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