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