Skip to content

Instantly share code, notes, and snippets.

@lgaud
Created October 3, 2022 15:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lgaud/1503722b5b332a9a94d1e1b20b9cf052 to your computer and use it in GitHub Desktop.
Save lgaud/1503722b5b332a9a94d1e1b20b9cf052 to your computer and use it in GitHub Desktop.
This example uses Azure Cognitive Services Translator to translate Notion pages into a new Notion page. Code example for www.pynotion.com.
import os
from dotenv import load_dotenv
import requests
"""
This example uses Azure Cognitive Services Translator to translate Notion pages into a new Notion page.
See full explanation at: https://www.pynotion.com/translate-with-azure-translator-part-2
Create a Translator resource in Azure, and set the key and region in your environment or a .env file as
COG_SERVICE_KEY and COG_SERVICE_REGION. The Free tier (F0) should be plenty for demonstration purposes.
This code also works with a multi-service Cognitive Services resource (which does not have a free tier).
More details on creating a Translator Resource
https://learn.microsoft.com/en-us/azure/cognitive-services/translator/quickstart-translator?tabs=python
Create a Notion integration, and set an environment variable or entry in the .env file for NOTION_KEY.
Share a page you'd like to run through the translator with the integration, and take a note of the id
from the URL to use as the page_id argument.
"""
class TranslatorClient():
def __init__(self, cog_service_key, cog_service_region):
self.cog_key = cog_service_key
self.cog_region = cog_service_region
self.translator_endpoint = 'https://api.cognitive.microsofttranslator.com'
self.default_headers = {
'Ocp-Apim-Subscription-Key': self.cog_key,
'Ocp-Apim-Subscription-Region': self.cog_region,
'Content-type': 'application/json'
}
self.session = requests.Session()
self.session.headers.update(self.default_headers)
def translate(self, text, source_language, target_language):
url = self.translator_endpoint + '/translate'
# Specify Query Parameters
params = {
'api-version': '3.0', # Required
'from': source_language, # Optional, will auto-detect in most cases
'to': target_language # Required.
}
body = [{
'text': text
}]
# Send the request and get response
request = self.session.post(url, params=params, json=body)
# Parse the JSON Response
response = request.json()
translation = response[0]["translations"][0]["text"]
# Return the translation
return translation
class NotionClient():
def __init__(self, notion_key):
self.notion_key = notion_key
self.default_headers = {'Authorization': f"Bearer {self.notion_key}",
'Content-Type': 'application/json', 'Notion-Version': '2022-06-28'}
self.session = requests.Session()
self.session.headers.update(self.default_headers)
def get_property(self, page_id, property_id):
url = f"https://api.notion.com/v1/pages/{page_id}/properties/{property_id}"
response = self.session.get(url)
return response.json()
def get_title_text(self, page_id):
title_property = self.get_property(page_id, "title")["results"][0]
return title_property["title"]["plain_text"]
def get_notion_blocks(self, block_id, start_cursor=None, page_size=None):
url = f'https://api.notion.com/v1/blocks/{block_id}/children'
params = {}
if start_cursor is not None:
params["start_cursor"] = start_cursor
if page_size is not None:
params["page_size"] = page_size
response = self.session.get(url, params=params)
return response.json()
def get_text(self, rich_text_object):
# Concatenates a rich text array into plain text
text = ""
for rt in rich_text_object["rich_text"]:
text += rt["plain_text"]
return text
def get_block_text(self, block):
if block["type"] == "paragraph":
return self.get_text(block["paragraph"])
if block["type"] == "heading_1":
return self.get_text(block["heading_1"])
if block["type"] == "heading_2":
return self.get_text(block["heading_2"])
if block["type"] == "heading_3":
return self.get_text(block["heading_3"])
return None
def update_block_text(self, block, new_text):
block[block["type"]]["rich_text"] = [
{"type": "text", "text": {"content": new_text}}]
return block
def create_page(self, parent_page_id, children, title):
create_page_body = {
"parent": {"page_id": parent_page_id},
"properties": {
"title": {
"title": [{"type": "text", "text": {"content": title}}]
}
},
"children": children
}
create_response = self.session.post(
"https://api.notion.com/v1/pages", json=create_page_body)
return create_response
class NotionTranslator():
def __init__(self, notion_client, translate_client, source_language, target_language):
self.notion_client = notion_client
self.translate_client = translate_client
self.source_language = source_language
self.target_language = target_language
def translate_title(self, source_page_id):
title = self.notion_client.get_title_text(source_page_id)
translated_title = self.translate_client.translate(
title, self.source_language, self.target_language)
return translated_title
def translate_all_blocks(self, source_page_id):
blocks_response = self.notion_client.get_notion_blocks(
source_page_id)
translated_blocks = self.translate_blocks(
blocks_response.get("results"))
while blocks_response.get("has_more"):
blocks_response = self.notion_client.get_notion_blocks(
source_page_id, blocks_response.get("next_cursor"))
translated_blocks.extend(self.translate_blocks(
blocks_response.get("results")))
return translated_blocks
def create_translated_page(self, source_page_id, target_page_id=None):
# Create as a child of source page if a parent is not set
if target_page_id is None:
target_page_id = source_page_id
translated_title = self.translate_title(source_page_id)
translated_content = self.translate_all_blocks(source_page_id)
response = self.notion_client.create_page(
target_page_id, translated_content, translated_title)
return response
def translate_blocks(self, blocks):
translated_blocks = []
for block in blocks:
source_text = self.notion_client.get_block_text(block)
if source_text is not None:
translated = self.translate_client.translate(
source_text, self.source_language, self.target_language)
translated_blocks.append(
self.notion_client.update_block_text(block, translated))
elif block["type"] == "child_page":
pass
elif block["type"] != "unsupported":
translated_blocks.append(block)
return translated_blocks
def main(notion_page_id, source_language="en", target_language="fr"):
notion_client = NotionClient(os.getenv('NOTION_KEY'))
translate_client = TranslatorClient(
os.getenv('COG_SERVICE_KEY'), os.getenv('COG_SERVICE_REGION'))
translator = NotionTranslator(
notion_client, translate_client, source_language, target_language)
response = translator.create_translated_page(notion_page_id)
if (response.ok):
print("Page translated successfully!")
print(response.json()["url"])
else:
print("Error translating page")
if __name__ == "__main__":
import argparse
load_dotenv(override=True)
parser = argparse.ArgumentParser(
description="Translate a Notion page's title. Supported language codes are listed at https://learn.microsoft.com/en-us/azure/cognitive-services/translator/language-support")
parser.add_argument('page_id', type=str,
help='A Notion page ID to translate')
parser.add_argument('target',
help='language code to translate the page to')
parser.add_argument('--source', default="en",
help="language code for the original language of the page")
args = parser.parse_args()
main(args.page_id, args.source, args.target)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment