
# Slack Translate Buddy
* This is a pretty lengthy project but the logic is simple.
* This project requires intermediate level of understanding of UiPath Studio which can all be learnt from here:
* This is a free course for RPA developer offered by UiPath https://academy.uipath.com/learn/public/learning_plan/view/35/RPADeveloper
* However, you can just follow the steps below and build it whoohoo.
**Terms:**
* Source language = the language that you speak.
* Target language = the language that you want to communicate with.
## Overview

## What does it do?
This robot will help you chat in and understand any languages in Slack as long as Google Translate and Microsoft Translate support them. Specifically, here are things it can do:
1. Translate an input text to the target language and type into Slack (CTRL + DOWN).
2. Detect the target language automatically by highlighting a sample text on the screen, in case you don't know it (CTRL + LEFT).
3. Automatically detect the language of any highlighted text on the screen and translate it to the source language (CTRL + UP).
4. Change to different languages in the middle of the process (CTRL + RIGHT).
5. Quit at any time (CTRL + S).**
**EXTRA CHALLENGES:**
6. Automatically detect the language of any highlighted text on the screen, translate to, and read it out loud in the source language (CTRL + D).
7. Translate your speech in the source language into the target language and type into Slack (CTRL + E).
## What do you need?
* `UiPath Studio`. Download community version (free) here:
* https://www.uipath.com/platform-trial
* A basic understanding of UIPath Studio, e.g. how to create workflow, search and drag activities, install packages, create variables, scopes, selectors...
* `Slack` installed and a chat window opened.
* `Languages.xlsx` which contain languages codes that both Microsoft and Google support. This can be found in the project download.
* Microsoft Text Translation API key: `"0d3217ea2b0a4108bb9592377c9b081a"`
* Google API key & Service Account key:
* Google Cognitive, Text-to-Speech/Speech-to-Text API keys: `"AIzaSyBeDPga5A1UIcD0_TGZNjCvIeQAqBzXp2Y"`
* Service Account (JSON): Download here (UiPath account required) https://uipath.atlassian.net/wiki/download/attachments/1092944480/integrations-219615-65219556418f.json?version=1&modificationDate=1539889912461&cacheVersion=1&api=v2
* Save as `"astral-host-247516-05fe48d45647.json"` into your project folder
## Let's do it
### 1. Create Our Skeleton
* Open `UiPath Studio`
* Click on `Process`

* Name it whatever you want, choose the location for your project and put in any description you like.
* Search for `Flowchart` under `Activities` and drag it to the middle.

* Search for `Sequence` in the activities pane, drag 2 to the middle and connect them. Name them as in the picture.

* Right click on each sequence and choose `Extract as Workflow` and click OK. You should have something like this:

* Go to `Manage Packages` and install these 4 packages:




* Go to `Variables` at the bottom of the screen and create these variables as follow:
* You can always choose `Browse for types` in `Variable type` and search for any types you want. In this case it is:


### 2. InitializeLanguages workflow
* Double click on `Invoke InitializeLanguages workflow` in the middle pane.
* Right click on it and choose `Open Workflow`, you will see an empty sequence.
* Go to `Variables` and create:

* Go to `Arguments` and create:

* Search for these activities in `Activities` pane and drag into the sequence in order as in these pictures:
* The red squares are the name of the activities.
* You will have something like this when you finish.




1. This will out put a log message at the beginning of the execution of the sequence. You can see it in the `Output` pane.
2. This will read all non-empty cells in the `Sheet1` of the Excel file `Languages.xlsx`

In the right `Properties` pane, check `AddHeaders` and type `languageDT` in `DataTable` to assign the output of this activity to the variable we created earlier as this activity converts an Excel file to UiPath data table.
3. `out_languageList` = `new List(of string)`
This initialize a new list of String called out_languageList which will later contain the names of all languages.
4. `out_languageCodeGoogleList` = `new List(of string)`
This will contain the language codes defined by Google.
5. `out_languageCodeMicrosoftList` = `new List(of string)`
This will contain the language codes defined by Microsoft.
6. This is a `For Each Row` activity which will loop through every `row` in `LanguageDT` datatable.
7. This will add each cell under column "Language" in the Excel file to a collection of strings for later use.
Set `TypeArgument` to `String` as we adding strings to the collection.

8. Same idea for column "Google".

9. Same idea for column "Microsoft".

10. The while loop makes sure the user chooses some source language by keep asking if the answer is empty.
`out_languageList.ToArray` will just convert the list to an Array as `Options` only accepts arrays
Then we set the answer to `out_translateFromString`

11. `Label` = `"If you don't know it, choose a random one and click OK. Then highlight a few words and click CTRL + LEFT, I will detect it for you"`
`Title` = `"What language do you want to communicate with?"`

12. `out_translateFromCodeString` = `out_languageCodeGoogleList(out_languageList.IndexOf(out_translateFromString))`
This will look for the Google language code based on the answer from the user and assign it to an argument to be sent out to the sequence in the next part.
13. `out_translateToCodeString` =
`out_languageCodeGoogleList(out_languageList.IndexOf(out_translateToString))`
14. `"Translating from " + out_translateFromString + " to "+ out_translateToString`
This will just output a message in the `Output` pane for debugging purposes.
**Update**: Put this selector into `Send Hotkey 'UiPath.Studio...'` in the 2 `if`'s after step 10 and 11: `<wnd app='uipath.studio.exe' cls='HwndWrapper*' title='UiPath Studio - Cognitive' />
`
#### Summary:
Up to now we have read the Excel file and store the info of each column into corresponding lists and got the language codes from the user inputs.
### 3. ChooseOptions workflow
* Go back to `Main` and double click on `Invoke ChooseOptions workflow` then right click and choose `Open Workflow`, you will see an empty sequence like in previous step.
* Go to `Arguments` and create:

These are the arguments we will receive from `InitializeLanguages` and `Main`
* This is how it looks like when we finish the step belows:

* To get started do the followings:
* Drag in a `Parallel` activity. This activity will run all the sequences in its body in parallel.
* Drag 7 `Monitor Events` activities into the `Parallel`. This activity will continuously check if any of the triggers inside its body got triggered and execute the according sequence. For each of these:
* Drag a `Hotkey Trigger` into each`Drop trigger activity here`. This activity is used as a trigger when the hot keys are pressed.
* Drag a `Sequence` into `Event Handler`. This is what executes if the hot keys are pressed.
* Now you will have something like this for each of the 7 `Monitor Events`

* In the first `Monitor Events`, choose `CTRL + right` for `Hotkey Trigger` and name the sequence `ChangeLanguages`. Right click on the sequence and choose `Extract as Workflow` and click OK. You will have:

* Keep doing the same thing for the other 5, you have eventually have:


* For this one, notice that we also have an `Input Dialog` which asks user for the input text to translate. In the `Properties` pane of this activity:
* `Label` = `"What do you want to translate?"`
* `Title` = `"Translate from " + in_translateFromString + " to " + in_translateToString`
* Click into the box right next to `Result`, click `CTRL + K` and type `inputTextString` to create a new variable in this scope.





**Update**: Put this selector into `Send Hotkey 'UiPath.Studio...'`: `<wnd app='uipath.studio.exe' cls='HwndWrapper*' title='UiPath Studio - Cognitive' />
`
### 4. Now let's take care of each workflow in each `Event Handler`
#### I. `ChangeLanguages` workflow
* This workflow will let the user change the source and target languages while the process is being run so the process doesn't have to be restarted.
* Right click on it and choose `Open Workflow`
* Go to `Variables` and create:

* Go to `Arguments` and create these arguments:

* This is how it looks like after finishing:


**Update**: For the two `if`'s of step 4-5 and 6-7. Use these expressions:
`not String.IsNullOrEmpty(newTranslateFromString) andalso newTranslateFromString.Equals("Quit")`
`not String.IsNullOrEmpty(newTranslateToString) andalso newTranslateToString.Equals("Quit")`
1. Just another log message.
2. * `Label` = `"Leave empty if you don't want to change"`
* `Title` = `"Current translating from " + in_translateFromString.ToString`

3. * `Label` = `"Leave empty if you don't want to change. If you don't know it, choose a random one and click OK. Then highlight a few words and click CTRL + LEFT, I will detect it for you"`
* `Title` = `"Currently translating to " + in_translateToString.ToString`

4. Assign new language code if user chooses a new one.
* `in_translateFromCodeString` = `in_languageCodeGoogleList(in_languageList.IndexOf(newTranslateFromString))`
5. `in_translateFromString` = `newTranslateFromString`
6. `in_translateToCodeString` = `in_languageCodeGoogleList(in_languageList.IndexOf(newTranslateToString))`
7. `in_translateToString` = `newTranslateToString`
8. `"Translating from " + in_translateFromString + " to "+ in_translateToString`
#### II. `DetectLanguage` workflow
* This workflow will detect the target language automatically from any highlighted text on the screen.
* Go to `Variables` and create:

* Go to `Arguments` and create:

* This is how it looks like after finishing:

1. * Leave `Timeout` at 500 ms to stop checking if any text is highlighted on the screen after 500 milliseconds.
* Put `ContinueOnError` to `True` to let the workflow continue if this is not able to copy any text as we will take care of this case right below.

2. This is the Microsoft's `Detect Language` activity from the left pane which will detect the language from the highlighted text. (Make sure you have installed all the packages at the beginning)
* This will make an API call to Microsoft server and put the detected language back to `Output`

3. * `out_translateToCodeString` = `in_languageCodeGoogleList(in_languageCodeMicrosoftList.IndexOf(detectedLanguageCodeString))`
4. * `out_translateToCodeString + " detected"`
5. Put in `Message`: `in_languageList(in_languageCodeMicrosoftList.IndexOf(detectedLanguageCodeString)) + " detected and set as the target language"`

6. * `out_translateToCodeString` = `in_translateToCodeString`
7. 
#### III. `TranslateInput` workflow
* This workflow will translate the input text to the target language.
* Go to `Variables` and create:

* Go to `Arguments` and create:

* This is how it looks like after finishing:

* The first if check `if` the input text is empty or not. If not, translate it. If yes, leave as is.
* The second `if` checks if the source and target languages are the same or not. If yes, leave as is, if different, translate it.
1. Just another log message
2. * Drag a `Google Text Translate` activity into the `Try` part of the `Try Catch` activity. (Make sure you have installed all the packages at the beginning of the tutorial).
* This activity will make an API call to Google Server and translate the input text from source to target language.

3. * Click on `Exception`, a section will expand. This will output a message if Google is not able to translate the input text.
* Choose `Warn` in the `Log Message` as this is an error.
* In the `Message Box` put `"Cannot translate these languages, please choose another pair"`

4. `translatedTextString` = `in_inputTextString` to leave it as is.
5. This activity will type the translated text into the Slack window.
* Drag a `Type Into` activity and click `Indicate on screen` then choose the whole Slack window.
* Click on the "hamburger" icon and choose `Edit Selector`

* Paste `<wnd app='slack.exe' cls='Chrome_WidgetWin_1' title='*|*' />` into the bottom box.

#### IV. `TranslateText` workflow
* This workflow will translate any highlighted text to the target language.
* Go to `Variables` and create:

* Go to `Arguments` and create:

* This is how it looks like after finishing:


1. Leave `Timeout` at 500 ms to stop checking if any text is highlighted on the screen after 500 milliseconds.
Put `ContinueOnError` to `True` to let the workflow continue if this is not able to copy any text as we will take care of all cases right below.

2. Same as the one in previous workflow.

3. `detectedLanguageCodeString` = `in_languageCodeGoogleList(in_languageCodeMicrosoftList.IndexOf(detectedLanguageCodeString))`
4. `detectedLanguageCodeString + " detected"`
5. `translatedTextString` = `copiedTextString`
6. 
7. 
8. Put `"Cannot translate these languages, please choose another pair"` in the `Message Box`

### 5. Pass around the arguments
In order for all the workflows to work together as a streamline, we need to pass the arguments from one to another. This is how the workflows communicate with each other.
There are just a few more steps we gotta do:
1. Go to back to `Invoke InitializeLanguages workflow`, click on `Import Arguments` and pass into it the arguments from `Main`

2. Do the same thing for `ChooseOptions`

3. Open `ChooseOptions` and pass the arguments to the 4 individual workflows in there:
* 
* 
* 
* 
## Extra Challenges
#### V. `SpeechToText` workflow
* This workflow will translate your speech (in source language) into the target language.
* Go to `Variables` and create:

* Go to `Arguments` and create:

* This is how it looks like after finishing:

1. * Drag the `Speech to text` activity from the left pane.
(Make sure you have installed all the packages at the beginning of the tutorial).

* This activity will make an API call to Google server with a confidence of 0.5 (AI related topic) and put the transcribed text into `speechTextString`
2. 
3. * This is where we reuse the workflow `Translate Input` we created before.
* Click `Project` in the left pane and drag `Translate Input` to the middle pane.

* Then click on `Import Arguments` to pass the arguments it needs into it. As you remember, this will translate the input text into the target language and type into Slack, so we don't need to create the whole process from scratch again.

4. Then import the arguments to the workflows

##### VI. `TextToSpeech` workflow
Almost done, just one more workflow to go.
* This workflow will read out loud any highlighted text on the screen from any languages to source language.
* Go to `Variables` and create:

* Go to `Arguments` and create:

* This workflow has the same activities as the previous ones so I will just clarify what is not shown in the pictures.


**Update**: `Copy Seclect Text` and `Detect Language` settings are the same as in steps 1 and 2 of `DetectLangugage` workflow.
1. `detectedLanguageCodeString` = `in_languageCodeGoogleList(in_languageCodeMicrosoftList.IndexOf(detectedLanguageCodeString))`
2. 
3. `translatedTextString` = `copiedTextString`
4. `detectedLanguageCodeString + " detected and reading in " + in_translateFromCodeString`
5. Drag `Text to speech` activity from the left pane.

6. 
7. In the `Message` of `Attended Robot Status` put `"Nothing highlighted"`
8. Then import the arguments to the workflow

## Extra: Get the keys needed
* Microsoft Text Translation API key.
* Go to https://portal.azure.com
* Register for an account and go to https://portal.azure.com/#create/Microsoft.CognitiveServicesTextTranslation to register for the API.
* Click on 'Keys' and copy any key.

* Google API key & Service Account key.
* Go to https://console.cloud.google.com
* Register an account, search and enable these 3 APIs.

* Go to `API & Services > Credentials`

* Create an API key and a Service Account key.
* Download Google Service Account as JSON file and put it in your project folder under name `"astral-host-247516-05fe48d45647.json"`
## Final words
Phewwww, so we have finally done. You can get it up running and start debugging if there's any.
This is a lengthy project so I may miss some steps or variables here and there. Please feel free to let me know if there's any parts that are obscure or missing so I can fix the instruction accordingly.
Modularizing helps break down the logic and enable debugging smaller module one at a time. However, I know we pass around a lot of arguments and it may seem unnecessary but I decided to break it down to practice modularizing a big workflow but you are free to build the whole project in only one workflow.
I hope you enjoy the workflow and have got something out of it. Happy automation~
**As you run the workflow many times, you will see that some pair of languages don't work well and that's where you need to stabilize the workflow. I will keep this as an extra improvement.**