翻訳といえば最近だとGoogle翻訳、Google翻訳な私です。
昔はエキサイト翻訳だったりGoo翻訳だったり・・・だった記憶がありますが
それももはや遠い記憶です。
Googleさんの場合ここらへんのAPIがたくさんあるし、MLやAIで精度を高めたりしてくれているので
こりゃいいや
で早速、PHPのライブラリをば頂きに参ったのです。
が・・・
https://cloud.google.com/translate/docs/quickstart-client-libraries-v3?hl=ja
・・・・・・・・・
・・・・・・・・・
・・・・
・・
え・・・
PHPどこ?
もしかしてベータ版だから今一番HOTな言語でしかライブラリがないのだろうか?
そうだとすると待っておくと言う手もあります。
そもそもベータ版ですから仕様はちょこちょこと変更されてしまうので。
でも使ってみたいですよね
なのでREST APIを叩けるように実装しました。
file_get_contentsを愛してやみません。
ローカルのファイルはもちろんまさか・・・URL越しのデータを取得したり、
POSTやらまでできてしまう万能感を愛してやみません。
もちろん気に食わない方はその部分をcURLにすることもよろしいかと。
ちなみにGoogleCloudPlatformにて
「Cloud Translation API」を有効にして、認証情報で「サービスアカウントキーのJSON」バージョンは先に作っておきましょう。
では早速作ってみましょう。
class HttpClient {
protected $_url;
function __construct($url = null) {
$this->_url = $url;
}
public function get($data = array(), $head = array()) {
if ($data) {
$getd = http_build_query($data, "". "&");
}
if ($head) {
$sendHeader = $head;
}
else {
$sendHeader = array(
'Cache-Control: no-store',
"Content-Type: application/x-www-form-urlencoded",
);
}
$context = array(
"http" => array(
"protocol_version" => "1.1",
"method" => "GET",
"header" => implode("\r\n", $sendHeader),
"ignore_errors" => true
)
);
if ($getd) {
$response = file_get_contents($this->_url . "?{$getd}", false, stream_context_create($context));
}
else {
$response = file_get_contents($this->_url, false, stream_context_create($context));
}
$pos = strpos($http_response_header[0], '200');
if ($pos === false) {
return array(
'status' => 'error',
'error' => $http_response_header[0],
'responce_header' => implode("\n", $http_response_header),
'body' => $response,
);
}
else {
return array(
'status' => 'success',
'body' => $response
);
}
}
public function post($data, $head = array() , $modeJson = false) {
$postd = http_build_query($data, "", "&");
if ($head) {
$sendHeader = $head;
if ($modeJson) {
$postd = $data;
}
else {
$sendHeader[] = "Content-Length: " . strlen($posted);
}
}
else {
$sendHeader = array(
'Cache-Control: no-store',
"Content-Type: application/x-www-form-urlencoded",
"Content-Length: " . strlen($postd),
);
}
$context = array(
"http" => array(
"protocol_version" => "1.1",
"method" => "POST",
"header" => implode("\r\n", $sendHeader),
"content" => $postd,
"ignore_errors" => true
)
);
$response = file_get_contents($this->_url, false, stream_context_create($context));
$pos = strpos($http_response_header[0], '200');
if ($pos === false) {
return array(
'status' => 'error',
'error' => $http_response_header[0],
'responce_header' => implode("\n", $http_response_header),
'body' => $response,
);
}
else {
return array(
'status' => 'success',
'body' => $response
);
}
}
}
と言うことでHTTPでGETとPOSTするのができました。
OAuth2ではJWTと使ってTokenを取得することにします。
ということでネットのソースやら何やらを色々参考にしながら必要最低限、
JWTを作れるものを
class JWT {
public $_support = array(
"HS256" => array("hash_hmac", "sha256"),
"HS512" => array("hash_hmac", "sha512"),
"HS384" => array("hash_hmac", "sha384"),
"RS256" => array("openssl", "sha256"),
"RS384" => array("openssl", "sha384"),
"RS512" => array("openssl", "sha512"),
);
protected $_key;
function __construct($key) {
$this->_key = $key;
}
public function encode($body, $header = array("typ" => "JWT", "alg" => "RS256")) {
$iat = time();
$exp = $iat + 3600;
$head = $this->urlsafeB64Encode(json_encode($header));
$body['iat'] = $iat;
$body['exp'] = $exp;
$payload = $this->urlsafeB64Encode(json_encode($body));
$signing = $this->sign($head . "." . $payload);
return $head . "." . $payload . "." . $this->urlsafeB64Encode($signing);
}
protected function sign($msg, $alg = 'RS256') {
if (empty($this->_support[$alg])) {
throw new Exception("error no JWT algorithm");
}
list($func, $algorithm) = $this->_support[$alg];
if ($func == "hash_hmac") {
return hash_hmac($algorithm, $msg, $this->_key, true);
}
else if ($func == "openssl") {
$s = '';
$success = openssl_sign($msg, $s, $this->_key, $algorithm);
if ($success) {
return $s;
}
else {
throw new Exception("open ssl sign error.");
}
}
}
public function urlsafeB64Decode($input){
$remainder = strlen($input) % 4;
if ($remainder) {
$padlen = 4 - $remainder;
$input .= str_repeat('=', $padlen);
}
return base64_decode(strtr($input, '-_', '+/'));
}
public function urlsafeB64Encode($input) {
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}
}
class GoogleOAuth2 {
protected $_scope;
protected $_json;
protected $_token;
protected $_grantType = "urn:ietf:params:oauth:grant-type:jwt-bearer";
function __construct($scope, $jsonKey) {
$this->_scope = $scope;
$this->_json = json_decode($jsonKey, true);
}
public function token() {
$jwt = new JWT($this->_json['private_key']);
$jwtData = $jwt->encode(array("iss" => $this->_json['client_email'],"aud" => $this->_json['token_uri'],"scope" => $this->_scope));
$client = new HttpClient($this->_json['token_uri']);
$body = $client->post(array('grant_type' => $this->_grantType,'assertion' =>$jwtData));
error_log(var_export($body, true));
if (empty($body['body'])) {
throw Exception("not token");
}
return json_decode($body['body'], true);
}
}
JWT形式のデータを送って、認証を確立し、Tokenをもらいます。
翻訳しようじゃないか
早速翻訳です。
まぁ色々なやり方があるのですが一番シンプルに。
class GoogleTranslate {
const SCOPE = "https://www.googleapis.com/auth/cloud-translation";
const BASEURL = "https://translation.googleapis.com/v3beta1/projects/";
protected $_sourceJson;
protected $_json;
protected $_source;
protected $_target;
function __construct($json, $source = "ja", $target = "en") {
$this->_sourceJson = $json;
$this->_json = json_decode($json, true);
$this->_source = $source;
$this->_target = $target;
}
public function translation($text) {
$google = new GoogleOAuth2(self::SCOPE, $this->_sourceJson);
$token = $google->token();
$url = self::BASEURL . $this->_json['project_id'] . ":translateText";
$xiclient = new HttpClient($url);
$httpHeader[] = "Authorization: Bearer " . $token['access_token'];
$httpHeader[] = "Content-type: application/json; charset=utf-8";
$request = array(
"sourceLanguageCode" => $this->_source,
"targetLanguageCode" => $this->_target,
"contents" => $text
);
$reqjson = json_encode($request);
$translate = $xiclient->post($reqjson, $httpHeader, true);
$translateArr = json_decode($translate['body'], true);
return $translateArr;
}
}
こうしました。
これを一枚のPHPのなかに押し込んでます。
それがいいか悪いかはまぁ・・・別として・・・
使ってみよう。
では使ってみましょう。
まずはGCPから取得しておいたサービアカウントの「JSON」ファイルを読みます。
このときもfile_get_contentsで取得してしまいましょう。
PHPで一番楽だな・・・と思うのはこの関数のおかげです・・・はい。
で使うときはこうです。
$file = "XXXXXXX.json"; ← GCPで取得した「サービスアカウントキー」のJSON
$json = file_get_contents($file);
$googleTranslate = new GoogleTranslate($json);
$text = array(
'こんにちは',
'オッス!オラ悟空!',
'オラ腹減ったぞ!'
);
$d = $googleTranslate->translation($text);
結果は以下になりました。
array(1) {
["translations"]=>
array(3) {
[0]=>
array(1) {
["translatedText"]=>
string(5) "Hello"
}
[1]=>
array(1) {
["translatedText"]=>
string(14) "Oss! Ora Goku!"
}
[2]=>
array(1) {
["translatedText"]=>
string(15) "I'm hungry!"
}
}
}
あくまでサンプルでございますがとりあえず
翻訳はできます。
エラー処理やらなにやらは、是非ご利用頂く方々で実装をよろしくお願いいたします・・・
ライブラリがはやく提供されますように。
Writer:ゆたさん@開発者。
HomePagehome Twitter Facebook