Confluence Cloud + Amazon Translate

Confluence CloudのAppを作ってAmazon Translateをつなげました。 今回は簡単にDemoをする記事を作成してみました。
2020.08.31

Confluence CloudのAppを作ってAmazon Translateにつなげてみました。 それで、簡単にDemoをする記事を作成してみました。

目標

Amazon Translateを利用してConflueceの自動翻訳することです。

screen
大きく

1.ACE(Attlasian Connect Express)を利用してConfluece Appを実装
2.Amazon API Gateway + AWS Lambda + Amazon Translateを利用してAPI Serverを構成

ですが、今回の記事ではACEを主に扱って見ます。

Getting started

ACE(Attlasian Connect Express)とは

Atlassian Connect App構築のためのNode.js Toolkitです。

  • Node.js 12.1.0以上
  • npm

を準備してください。

npm install -g atlas-connect

atlas-connect new [project name]

npm install

次は

  • credentials.json作成
{
    "hosts":{
        "[your confluece domain]":{
            "product":"confluence",
            "username":"[your email]",
            "password":"[your API token]"
        }
    }
}
  • your confluence domain : つなげたいConfluenceのdomainを登録します。
  • username: 自分のemailを登録します。
  • password: API tokenを登録します。
    • 一番簡単な方法はAPI Tokenを通じてTokenをもらう方法です。

登録したconfluece domainに移動 Confluence Cloud Developer Getting startedの Step2を通じてEnable developement modeを選択してください。

最後に

npm start

基本的な開発環境の構成はこれで終わりです。

ACE(attlasian Connect Express)作成

三つのファイルだけ触ってみましょう。

modules

まず、modulesを見る前にatlassian-connect.jsonを簡単にみます。

atlassian-connect.json

{
    "key": "Translate",
    "name": "Confluence Translate",
    "description": "Translate for Confluence",
    "vendor": {
        "name": "Confluence Tutorials",
        "url": "https://www.atlassian.com/"
    },
    "baseUrl": "{{localBaseUrl}}",
    "links": {
        "self": "{{localBaseUrl}}/atlassian-connect.json",
        "homepage": "{{localBaseUrl}}/atlassian-connect.json"
    },
    "authentication": {
        "type": "jwt"
    },
    "lifecycle": {
        "installed": "/installed"
    },
    "scopes": [
        "READ",
        "WRITE"
    ],
    "modules": {
    }
}

Confluence Cloud Developer Getting startedの Step2の通り移動してください。 screen

まず、key,name,description,vendorはappの情報を設定します。

  • baseUrl:App instanceに関する通信に使用するAPPの基本URLです。
  • links:アプリに投稿しようとするリンク集合
  • authentication:つなげたConflueceとの認証形式を正義します。
  • lifecycle: 設置した時呼ぶCallback endPoint、詳細な情報はApp descriptor-Lifecycleを参考してください。
  • scopes:[READ,WRITE]:情報をRead,Writeすることができます。Deleteはできません。と考えばいいです。詳細な情報はScopes for Atlassian Connect appsを参考してください。

では、modulesを作成して見ます。

"modules": {
    "contentBylineItems": [
        {
            "context": "addon",
            "target": {
              "type": "inlinedialog",
              "options": { 
                "height": "100px", 
                "width": "200px"
              } 
            },
            "tooltip": {
              "value": "Page Translate"
            },
            "name": {
              "value": "Page Translate"
            },
            "key": "category",
            "url": "/category?contentId={content.id}&spaceKey={space.key}"
        }
    ],
}

routes

routes -> index.js

app.get('/translate', addon.authenticate(),(req, res) => {
        res.render('translate',{
            spaceKey: req.query['spaceKey'],
            contentId: req.query['contentId']
        });
    });

queryはmodulesのurlを設定したあともらうことができます。

"url": "/translate?contentId={content.id}&spaceKey={space.key}"

views

簡単です。 index.jsのres.renderはviewの中のファイルを選択します。
ではtranslate.hbsファイルを作ってください。

{{!< layout}}
<form>
    <label>sourceLang</label>
    <select id="sourceLang">
        <option value="en">en</option>
        <option value="ja">ja</option>
    </select>

    <label>TranslateLang</label>
    <select id="translateLang">
        <option value="en">en</option>
        <option value="ja">ja</option>
    </select>
    <input id="submit" type="button" value="submit">
</form>

Confluence Rest API

Confluence CloudのRest APIを利用してConflueceの下ページを作ってみます。
Confluence Cloud REST APIの詳細な内容は Confluence Cloud REST APIを参考してください。

ここではConfluence Cloud JavaScript APIを利用してみます。

{{!< layout}}
<form>
    <label>sourceLang</label>
    <select id="sourceLang">
        <option value="en">en</option>
        <option value="ja">ja</option>
    </select>

    <label>TranslateLang</label>
    <select id="translateLang">
        <option value="en">en</option>
        <option value="ja">ja</option>
    </select>
    <input id="submit" type="button" value="submit">
</form>
<script>
    $(function(){
        $('#submit').on('click',function(){
            let jsonData = {
                "type": "page",
                "space": {
                    "key": "{{spaceKey}}"
                },
                "ancestors":[
                    {
                        "id":"{{contentId}}"
                    }
                ],
                "title": "create page test",
                "body": {
                    "storage": {
                        "value": "creat page test",
                        "representation": "storage"
                    }
                }
            };
            AP.request({
                url:"/rest/api/content",
                type:"POST",
                contentType: "application/json",
                data:JSON.stringify(jsonData),
                success:function(res){
                    AP.navigator.go('contentview',{contentId: JSON.parse(res).id});//作成したしたページに移動
                },
                error:function(err){
                }
            });
        });    
    });
</script>
AP.navigator.go('contentview', {contentId:[contentId]});

の詳細な情報はConfluence JavaScriptAPI-Navigatorを参考してください。

下ページ作成確認

screen

Translate →submitを押してしたページが完成されたら成功です。

Amazon Translateと連動

まず、 Translate + Lambda + API gatewayを 利用して api serverを作ります。今回はこの過程は簡単に紹介だけで飛ばします。

順番

1. LambdaにつなげるIAM RoleにAmazon Translate policyを追加します。
2. Lambdaを作成します。
3. API gatewayをつなげます。

  • Lambda例

Amazon Translate この資料で好きな言語を選んで作成すればいいです。

例ではPythonを使って簡単に作って見ます。

Lambda

import json
import boto3

translate = boto3.client(service_name='translate', region_name='[region]', use_ssl=True)

def lambda_handler(event, context):
  
  result = translate.translate_text(Text="[翻訳するTEXT]", 
            SourceLanguageCode="[翻訳する前の言語]", TargetLanguageCode="[翻訳する言語]")
            
  print('TranslatedText: ' + result.get('TranslatedText'))//翻訳結果
  print('SourceLanguageCode: ' + result.get('SourceLanguageCode'))
  print('TargetLanguageCode: ' + result.get('TargetLanguageCode'))
  
  return {[returnすること]}

このように作成すればいいです。

では、次のAppの方法です。

順番です。

  1. 現在のページのcontentを持ってきます。
  2. API gatewayに送ります。
  3. 翻訳した内容を上の下ページを作るjsonData.body.storage.valueに入れて下ページを作ります。

まず、管理ページを作ってAPI登録、登録したAPIを ajaxを利用してAPI gatewayを送ったあと翻訳した内容をもらいます。

modules(adminPages)

"adminPages": [
    {
        "url": "/myAdimTranslate",
        "name": {
            "value": "Confluence Translate"
        },
        "key": "myAdimTranslate"
    }
]

routes(index.js)

app.get('/myAdimTranslate', addon.authenticate(),(req, res) => {
    res.render('myAdimTranslate');
});

views(myAdimTranslate.hbs)

{{!< layout}}
<div class="field-group">
    <input class="text" type="text" id="api" name="text-input" title="Text input">
    <button id="save">save</button>
</div>

<script>
    $(function(){
        $('#save').on('click',function(){
            //登録します。
            let jsonData = {
                "string": "[stirng name]",
                "value": $('#api').val()
            };
            AP.request({
                url:"/rest/atlassian-connect/1/addons/[AppKey(atlassian-connect.json의 Key입니다)]/properties/[properties_name]",
                type:"PUT",
                contentType: "application/json",
                data: JSON.stringify(jsonData),
                success:function(res){
                    AP.flag.create({
                        title: 'your Amazon url connection',
                        body: 'This is success',
                        type: 'success'
                    });//成功時に通知を受けるコードです。
                },
                error:function(err){
                    AP.flag.create({
                        title: 'App Err',
                        body: 'This is a Fail',
                        type: 'warning'
                    });//失敗したときに通知を受けるコードです
                }
            });
        }
    });
</script>

AP.flagの内容はConfluence Cloud Reference - Flagを参考してください。

同録確認

screen

Apps→Confluence Translate→SAVEを押して同録してください。

登録が終わりました。
今からは、登録したAPIを利用してAPI Gatewayにページの情報をわたします。

routes(index.js)

app.post('/translateAmazon',addon.authenticate(),(req,res) => {
    //先、登録したAPIを利用して通信します。ここでは、axiosを利用しました。
    axios({
        method:'post',
        url:req.body.url,
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(req.body.value)
    }).then(result => {
        res.send(JSON.stringify(result.data));
    }).catch(res => {
    }); 
});

viewファイルです。重複するコードが多いため同期式に作って順番でコードを説明します。
流れを見ながらもっと効率的なコードを作ればいいです。

views(translate.hbs)

{{!< layout}}

<form>
    <label>sourceLang</label>
    <select id="sourceLang">
        <option value="en">en</option>
        <option value="ja">ja</option>
    </select>

    <label>TranslateLang</label>
    <select id="translateLang">
        <option value="en">en</option>
        <option value="ja">ja</option>
    </select>
    <input id="submit" type="button" value="submit">
</form>

<script>
    $(function(){
        $('#submit').on('click', async function(){
            //現在のページの情報を呼びます。
            let value = await apRequest(
                "/rest/api/content/{{contentId}}?expand=space,body.view,version.container",
                "GET",
                null
            );
            //登録した情報を呼びます。
            let url = await apRequest(
                "/rest/atlassian-connect/1/addons/Trnaslate/properties/Amazon",
                "GET",
                null
            );

            //index.jsの /translateAmazonにrequestします。
            let jsonData1 = {
                "spaceKey":value.space.key,
                "contentId":value.id,
                "sourceLang":$('#sourceLang option:selected').val(),
                "translateLang":$('#translateLang option:selected').val(),
                "value":value.body.view.value,
                "url":url
            };
            let content = await ajaxRequest("/translateAmazon","POST",jsonData1);

            //下ぺージを作ります。
            let jsonData2 = {
                "type": "page",
                "space": {
                    "key": "{{spaceKey}}"
                },
                "ancestors":[
                    {
                        "id":"{{contentId}}"
                    }
                ],
                "title": `${value.title}(${$('#translateLang option:selected').val()})`,
                "body": {
                    "storage": {
                        "value": content,
                        "representation": "storage"
                    }
                }
            };
            await apRequest(
                "/rest/api/content",
                "POST",
                jsonData2
            ).then(res=>{
                AP.navigator.go('contentview', {contentId: res.id});//作成したしたページに移動
            });
        });
    });

    function ajaxRequest(url,type,jsonData){
        return new Promise(function(resolve,reject){
            AP.context.getToken(function(token){//認証が必要です。jwt Tokenをもらいます。
                $.ajax({
                    url:url,
                    type:type,
                    dataType:"json",
                    contentType:"application/json",
                    headers:{
                        "Authorization": `JWT ${token}`//jwt Tokenを登録します。
                    },
                    data:JSON.stringify(jsonData),
                    success:function(res){
                        resolve(JSON.parse(res));
                    },
                    error:function(err){
                        reject(false);
                    }
                });
            });
        });
    }
    function apRequest(url,type,jsonData){
        return new Promise(function(resolve,reject){
            AP.request({
                url:url,
                type:type,
                contentType: "application/json",
                data:JSON.stringify(jsonData),
                success:function(res){
                    resolve(JSON.parse(res));
                },
                error:function(err){
                    reject(false);
                }
            });
        });
    }
</script>

最後に確認

screen

最初の下ページ作成で現在の言語そして翻訳する言語を選んで下ページを作成してください。
ここでは韓国語で翻訳してみました。

終わりです。
もうしUIをもっときれいにしたいならAUI Documentationを参考してください。

以上 Confluece Cloud App + Amazon Translateの Demoをしてみました。
次はAmazon Translateに関する内容を作成して見ます。

参考資料

Confluence Cloud Developer
Confluence Cloud Reference
Confluence Cloud Rest API Reference
AUI Documentation
ATLASSIAN Community