---
# System prepended metadata

title: AI LINE Bot練功坊-L15 Azure Translator 翻譯機器人
tags: [Python, Line Bot]

---

AI LINE Bot練功坊-L15 Azure Translator 翻譯機器人
===
## 安裝開發環境
https://hackmd.io/@ntuebigdata/setup-linebot-development-environment#建立Python虛擬環境
## 註冊Line官方帳號
https://hackmd.io/@ntuebigdata/create-a-line-official-account#1-建立Line-Developers帳號
## 註冊Azure帳號
https://hackmd.io/@ntuebigdata/azure-basic-introduction#註冊Azure帳號

---

## 建立Azure Translation服務

搜尋列輸入翻譯，並點擊翻譯
![image](https://hackmd.io/_uploads/ryXmdmDBC.png)
點選建立
![image](https://hackmd.io/_uploads/SJt6umvSA.png)
輸入資訊點選`檢閱+建立`，若定價層沒有F0則將區域換一個試試看(一個區域只能有一個免費的)
![image](https://hackmd.io/_uploads/SJcut7DS0.png)
確認好資訊後，點選建立便會開始部屬
![image](https://hackmd.io/_uploads/rkmatXPrR.png)
部屬完成後，點選前往資源
![image](https://hackmd.io/_uploads/BJPQqXwHA.png)
往下滑動，會看到金鑰與端點，將金鑰、區域以及文字翻譯的API複製起來，待會程式會用到
![image](https://hackmd.io/_uploads/HJmo9QDr0.png)

## 撰寫程式

### 程式準備

新增一個專案資料夾，並在專案資料夾內新增`.env`、`requirements.txt`及`app.py`檔案，並貼上以下內容
![image](https://hackmd.io/_uploads/Hkskg4DBR.png)

<font style="background:yellow">requirements.txt</font>
```
line-bot-sdk
flask
azure-ai-translation-text
```

<font style="background:yellow">app.py</font>
```python
from flask import Flask, request, abort
from linebot.v3 import (
    WebhookHandler
)
from linebot.v3.exceptions import (
    InvalidSignatureError
)
from linebot.v3.webhooks import (
    MessageEvent,
    TextMessageContent,
    PostbackEvent
)
from linebot.v3.messaging import (
    Configuration,
    ApiClient,
    MessagingApi,
    ReplyMessageRequest,
    TextMessage,
    QuickReply,
    QuickReplyItem,
    PostbackAction
)
#Azure Translation
from azure.ai.translation.text import TextTranslationClient
from azure.core.credentials import AzureKeyCredential
from azure.core.exceptions import HttpResponseError
import os

app = Flask(__name__)

CHANNEL_ACCESS_TOKEN = os.getenv("CHANNEL_ACCESS_TOKEN")
CHANNEL_SECRET = os.getenv("CHANNEL_SECRET")

handler = WebhookHandler(CHANNEL_SECRET)
configuration = Configuration(access_token=CHANNEL_ACCESS_TOKEN)

@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']
    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # parse webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'

@handler.add(MessageEvent, message=TextMessageContent)
def handle_messsage(event):
    text = event.message.text
    quick_reply_items=[
        QuickReplyItem(
            action=PostbackAction(
                label="英文",
                data=f"lang=en&text={text}",
                display_text="英文"
            )
        ),
        QuickReplyItem(
            action=PostbackAction(
                label="日文",
                data=f"lang=ja&text={text}",
                display_text="日文"
            )
        ),
        QuickReplyItem(
            action=PostbackAction(
                label="繁體中文",
                data=f"lang=zh-Hant&text={text}",
                display_text="繁體中文"
            )
        ),
        QuickReplyItem(
            action=PostbackAction(
                label="文言文",
                data=f"lang=lzh&text={text}",
                display_text="文言文"
            )
        ),
        QuickReplyItem(
            action=PostbackAction(
                label="法文",
                data=f"lang=fr&text={text}",
                display_text="法文"
            )
        ),
        QuickReplyItem(
            action=PostbackAction(
                label="德文",
                data=f"lang=de&text={text}",
                display_text="德文"
            )
        ),
        QuickReplyItem(
            action=PostbackAction(
                label="西班牙文",
                data=f"lang=es&text={text}",
                display_text="西班牙文"
            )
        ),
        QuickReplyItem(
            action=PostbackAction(
                label="韓文",
                data=f"lang=ko&text={text}",
                display_text="韓文"
            )
        ),
    ]
    reply_message(event, [TextMessage(
        text='Please select a language:',
        quick_reply=QuickReply(
            items=quick_reply_items
        )
    )])

@handler.add(PostbackEvent)
def handle_postback(event):
    postback_data = event.postback.data
    params = {}
    for param in postback_data.split("&"):
        key, value = param.split("=")
        params[key] = value
    user_input = params.get("text")
    language = params.get("lang")
    result = azure_translate(user_input, language)
    reply_message(event, [TextMessage(text=result if result else "No translation available")])

def reply_message(event, messages):
    with ApiClient(configuration) as api_client:
        line_bot_api = MessagingApi(api_client)
        line_bot_api.reply_message(
            ReplyMessageRequest(
                reply_token=event.reply_token,
                messages=messages
            )
        )
        
def azure_translate(user_input, to_language):
    if to_language == None:
        return "選擇想要翻譯的語言"
    else:
        apikey = os.getenv("API_KEY")
        endpoint = os.getenv("ENDPOINT")
        region = os.getenv("REGION")
        credential = AzureKeyCredential(apikey)
        text_translator = TextTranslationClient(credential=credential, endpoint=endpoint, region=region)
        
        try:
            response = text_translator.translate(body=[user_input], to_language=[to_language])
            translation = response[0] if response else None

            if translation:
                detected_language = translation.detected_language
                result = ''
                if detected_language:
                    print(
                        f"Detected languages of the input text: {detected_language.language} with score: {detected_language.score}."
                    )
                for translated_text in translation.translations:
                    result = f"翻譯出的語言是:'{translated_text.to}'\n翻譯出的結果: '{translated_text.text}'"
                return result

        except HttpResponseError as exception:
            if exception.error is not None:
                print(f"Error Code: {exception.error.code}")
                print(f"Message: {exception.error.message}")

if __name__ == "__main__":
    app.run()
```

<font style="background:yellow">.env</font>
```python=
CHANNEL_ACCESS_TOKEN = "XXX"
CHANNEL_SECRET = "XXX"
API_KEY = "XXX"
REGION = "XXX"
ENDPOINT = "https://api.cognitive.microsofttranslator.com/"
```
貼上之後記得修改幾個地方：
* Line Developers的Channel Access Token
* Line Developers的Channel Secret
* 剛剛建立Azure資源的金鑰
* 剛剛建立Azure資源的區域

可以根據想要翻譯的語言去做選擇，名稱和參數可以參考以下Reference:
>Reference：https://learn.microsoft.com/en-us/azure/ai-services/translator/language-support

### 安裝套件
將`requirements.txt`的路徑複製起來
![image](https://hackmd.io/_uploads/ByX-QEvrA.png)
開啟cmd並啟動先前創立的虛擬環境，並輸入`pip install -r {requirements.txt的路徑}`，
按下enter就會開始安裝
![image](https://hackmd.io/_uploads/SJykrNDHC.png)

---

## 測試效果
在聊天室輸入想要機器人翻譯的單字或句子，如：你好，機器人將回覆翻譯的語言代號以及翻譯出來的結果
![image](https://hackmd.io/_uploads/ryqacEPSA.png)

>Reference：https://pypi.org/project/azure-ai-translation-text/
>Reference：https://learn.microsoft.com/en-us/azure/ai-services/translator/text-sdk-overview?tabs=python

Youtube 課程影片
---
<iframe width="560" height="315" src="https://www.youtube.com/embed/KuAKL5Z-vR8?si=Uzx061B8Xwy20Ydm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

{%hackmd @ntuebigdata/about %}

## 相關教材連結

<div style="display: flex; justify-content:space-between;">
  <div>
    <a class="btn btn-warning" href="https://hackmd.io/@ntuebigdata/azure-basic-introduction" style="color:white;width:300px;text-overflow:ellipsis;overflow:hidden">◀◀◀ L14 Azure基本介紹 ◀◀◀</a>
  </div>
  <div>
    <a class="btn btn-info" href="https://hackmd.io/@ntuebigdata/azure-AI-language" style="color:white;width:300px;text-overflow:ellipsis;overflow:hidden">▶▶▶ L16 Azure AI Language 交談語言理解機器人
▶▶▶</a>
  </div>
</div>