Google ドキュメント、スプレッドシート、スライドのテキストを翻訳する

コーディング レベル: 中級
所要時間: 30 分
プロジェクトの種類: Google Workspace アドオン

目標

  • ソリューションの機能について理解する。
  • ソリューション内での Apps Script サービスの役割を理解する。
  • 環境を設定します。
  • スクリプトを設定します。
  • スクリプトを実行します。

このソリューションについて

このソリューションを使用すると、Google ドキュメント、スプレッドシート、スライド内からテキストを簡単に翻訳できます。

Google Workspace 翻訳アドオンのスクリーンショット

仕組み

ドキュメント、スプレッドシート、スライドでテキストを選択し、アドオンの [選択範囲を取得] をクリックすると、スクリプトがテキストをアドオンにコピーし、翻訳して翻訳されたテキストを表示します。

デフォルトでは、スクリプトはソース言語を検出し、テキストを英語に翻訳します。原文の言語と訳文の言語は編集できます。

Apps Script サービス

このソリューションでは、次のサービスを使用します。

前提条件

このサンプルを使用するには、次の前提条件を満たしている必要があります。

  • Google アカウント(Google Workspace アカウントの場合、管理者の承認が必要となる可能性があります)。
  • インターネットに接続できるウェブブラウザ。

  • Google Cloud プロジェクト

環境の設定

Google Cloud コンソールで Cloud プロジェクトを開く

このサンプルに使用する Cloud プロジェクトをまだ開いていない場合は、開きます。

  1. Google Cloud コンソールで [プロジェクトを選択] ページに移動します。

    Cloud プロジェクトを選択する

  2. 使用する Google Cloud プロジェクトを選択します。または、[プロジェクトを作成] をクリックし、画面の指示に沿って操作します。Google Cloud プロジェクトを作成する場合は、プロジェクトの課金を有効にする必要がある場合があります。

Google Workspace アドオンを使用するには、同意画面を設定する必要があります。アドオンの OAuth 同意画面を構成すると、ユーザーに表示される内容を定義できます。

  1. Google Cloud コンソールで、メニュー > > [ブランディング] に移動します。

    [ブランディング] に移動

  2. をすでに設定している場合は、[ブランディング]、[オーディエンス]、[データアクセス] で次の OAuth 同意画面の設定を構成できます。[ まだ設定されていません] というメッセージが表示された場合は、[使ってみる] をクリックします。
    1. [アプリ情報] の [アプリ名] に、アプリの名前を入力します。
    2. [ユーザー サポートメール] で、ユーザーが同意について問い合わせる際に使用するサポートのメールアドレスを選択します。
    3. [続行] をクリックします。
    4. [視聴者] で [内部] を選択します。
    5. [続行] をクリックします。
    6. [連絡先情報] で、プロジェクトの変更に関する通知を受け取るメールアドレスを入力します。
    7. [続行] をクリックします。
    8. [完了] で Google API サービスのユーザーデータに関するポリシーを確認し、同意する場合は [Google API サービス: ユーザーデータに関するポリシーに同意します] を選択します。
    9. [続行] をクリックします。
    10. [作成] をクリックします。
  3. 現時点では、スコープの追加はスキップできます。 今後、Google Workspace 組織の外部で使用するアプリを作成する場合は、[ユーザータイプ] を [外部] に変更する必要があります。次に、アプリに必要な認可スコープを追加します。詳細については、OAuth 同意画面を構成するガイドをご覧ください。

スクリプトを設定する

Apps Script プロジェクトを作成する

  1. 次のボタンをクリックして、翻訳 Apps Script プロジェクトを開きます。
    プロジェクトを開く

  2. [概要] をクリックします。

  3. 概要ページで、[コピーを作成] コピーを作成するアイコン をクリックします。

Cloud プロジェクト番号をコピーする

  1. Google Cloud コンソールで、メニュー > [IAM と管理] > [設定] に移動します。

    [IAM と管理] の [設定] に移動

  2. [プロジェクト番号] フィールドで値をコピーします。

Apps Script プロジェクトの Cloud プロジェクトを設定する

  1. コピーした Apps Script プロジェクトで、[プロジェクトの設定] プロジェクト設定のアイコン をクリックします。
  2. [Google Cloud Platform(GCP)プロジェクト] で、[プロジェクトを変更] をクリックします。
  3. [GCP プロジェクト番号] に、Google Cloud プロジェクト番号を貼り付けます。
  4. [プロジェクトを設定] をクリックします。

テスト用デプロイメントをインストールする

  1. コピーした Apps Script プロジェクトで、[エディタ] をクリックします。
  2. Code.gs ファイルを開き、[実行] をクリックします。メッセージが表示されたら、スクリプトを承認します。
  3. [Deploy] > [Test deployments] をクリックします。
  4. [インストール] > [完了] をクリックします。

スクリプトを実行する

  1. Google ドキュメントスプレッドシートスライドでファイルを開くか、新しいファイルを作成します。
  2. 右側のサイドバーで、翻訳アドオン を開きます。
  3. メッセージが表示されたら、アドオンを承認します。
  4. ファイル内のテキストを選択します。
  5. アドオンで、[選択範囲を取得] > [翻訳] をクリックします。

コードを確認する

このソリューションの Apps Script コードを確認するには、下の [ソースコードを表示] をクリックします。

ソースコードを表示

コード.gs

const DEFAULT_INPUT_TEXT = ''; const DEFAULT_OUTPUT_TEXT = ''; const DEFAULT_ORIGIN_LAN = ''; // Empty string means detect langauge const DEFAULT_DESTINATION_LAN = 'en' // English  const LANGUAGE_MAP =   [     { text: 'Detect Language', val: '' },     { text: 'Afrikaans', val: 'af' },     { text: 'Albanian', val: 'sq' },     { text: 'Amharic', val: 'am' },     { text: 'Arabic', val: 'ar' },     { text: 'Armenian', val: 'hy' },     { text: 'Azerbaijani', val: 'az' },     { text: 'Basque', val: 'eu' },     { text: 'Belarusian', val: 'be' },     { text: 'Bengali', val: 'bn' },     { text: 'Bosnian', val: 'bs' },     { text: 'Bulgarian', val: 'bg' },     { text: 'Catalan', val: 'ca' },     { text: 'Cebuano', val: 'ceb' },     { text: 'Chinese (Simplified)', val: 'zh-CN' },     { text: 'Chinese (Traditional)', val: 'zh-TW' },     { text: 'Corsican', val: 'co' },     { text: 'Croatian', val: 'hr' },     { text: 'Czech', val: 'cs' },     { text: 'Danish', val: 'da' },     { text: 'Dutch', val: 'nl' },     { text: 'English', val: 'en' },     { text: 'Esperanto', val: 'eo' },     { text: 'Estonian', val: 'et' },     { text: 'Finnish', val: 'fi' },     { text: 'French', val: 'fr' },     { text: 'Frisian', val: 'fy' },     { text: 'Galician', val: 'gl' },     { text: 'Georgian', val: 'ka' },     { text: 'German', val: 'de' },     { text: 'Greek', val: 'el' },     { text: 'Gujarati', val: 'gu' },     { text: 'Haitian Creole', val: 'ht' },     { text: 'Hausa', val: 'ha' },     { text: 'Hawaiian', val: 'haw' },     { text: 'Hebrew', val: 'he' },     { text: 'Hindi', val: 'hi' },     { text: 'Hmong', val: 'hmn' },     { text: 'Hungarian', val: 'hu' },     { text: 'Icelandic', val: 'is' },     { text: 'Igbo', val: 'ig' },     { text: 'Indonesian', val: 'id' },     { text: 'Irish', val: 'ga' },     { text: 'Italian', val: 'it' },     { text: 'Japanese', val: 'ja' },     { text: 'Javanese', val: 'jv' },     { text: 'Kannada', val: 'kn' },     { text: 'Kazakh', val: 'kk' },     { text: 'Khmer', val: 'km' },     { text: 'Korean', val: 'ko' },     { text: 'Kurdish', val: 'ku' },     { text: 'Kyrgyz', val: 'ky' },     { text: 'Lao', val: 'lo' },     { text: 'Latin', val: 'la' },     { text: 'Latvian', val: 'lv' },     { text: 'Lithuanian', val: 'lt' },     { text: 'Luxembourgish', val: 'lb' },     { text: 'Macedonian', val: 'mk' },     { text: 'Malagasy', val: 'mg' },     { text: 'Malay', val: 'ms' },     { text: 'Malayalam', val: 'ml' },     { text: 'Maltese', val: 'mt' },     { text: 'Maori', val: 'mi' },     { text: 'Marathi', val: 'mr' },     { text: 'Mongolian', val: 'mn' },     { text: 'Myanmar (Burmese)', val: 'my' },     { text: 'Nepali', val: 'ne' },     { text: 'Norwegian', val: 'no' },     { text: 'Nyanja (Chichewa)', val: 'ny' },     { text: 'Pashto', val: 'ps' },     { text: 'Persian', val: 'fa' },     { text: 'Polish', val: 'pl' },     { text: 'Portuguese (Portugal, Brazil)', val: 'pt' },     { text: 'Punjabi', val: 'pa' },     { text: 'Romanian', val: 'ro' },     { text: 'Russian', val: 'ru' },     { text: 'Samoan', val: 'sm' },     { text: 'Scots Gaelic', val: 'gd' },     { text: 'Serbian', val: 'sr' },     { text: 'Sesotho', val: 'st' },     { text: 'Shona', val: 'sn' },     { text: 'Sindhi', val: 'sd' },     { text: 'Sinhala (Sinhalese)', val: 'si' },     { text: 'Slovak', val: 'sk' },     { text: 'Slovenian', val: 'sl' },     { text: 'Somali', val: 'so' },     { text: 'Spanish', val: 'es' },     { text: 'Sundanese', val: 'su' },     { text: 'Swahili', val: 'sw' },     { text: 'Swedish', val: 'sv' },     { text: 'Tagalog (Filipino)', val: 'tl' },     { text: 'Tajik', val: 'tg' },     { text: 'Tamil', val: 'ta' },     { text: 'Telugu', val: 'te' },     { text: 'Thai', val: 'th' },     { text: 'Turkish', val: 'tr' },     { text: 'Ukrainian', val: 'uk' },     { text: 'Urdu', val: 'ur' },     { text: 'Uzbek', val: 'uz' },     { text: 'Vietnamese', val: 'vi' },     { text: 'Welsh', val: 'cy' },     { text: 'Xhosa', val: 'xh' },     { text: 'Yiddish', val: 'yi' },     { text: 'Yoruba', val: 'yo' },     { text: 'Zulu', val: 'zu' }   ];   /**  * Callback for rendering the main card.  * @return {CardService.Card} The card to show the user.  */ function onHomepage(e) {   return createSelectionCard(e, DEFAULT_ORIGIN_LAN, DEFAULT_DESTINATION_LAN, DEFAULT_INPUT_TEXT, DEFAULT_OUTPUT_TEXT); }  /**  * Main function to generate the main card.  * @param {String} originLanguage Language of the original text.  * @param {String} destinationLanguage Language of the translation.  * @param {String} inputText The text to be translated.  * @param {String} outputText The text translated.  * @return {CardService.Card} The card to show to the user.  */ function createSelectionCard(e, originLanguage, destinationLanguage, inputText, outputText) {   var hostApp = e['hostApp'];   var builder = CardService.newCardBuilder();    // "From" language selection & text input section   var fromSection = CardService.newCardSection()     .addWidget(generateLanguagesDropdown('origin', 'From: ', originLanguage))     .addWidget(CardService.newTextInput()       .setFieldName('input')       .setValue(inputText)       .setTitle('Enter text...')       .setMultiline(true));    if (hostApp === 'docs') {     fromSection.addWidget(CardService.newButtonSet()       .addButton(CardService.newTextButton()         .setText('Get Selection')         .setOnClickAction(CardService.newAction().setFunctionName('getDocsSelection'))         .setDisabled(false)))   } else if (hostApp === 'sheets') {     fromSection.addWidget(CardService.newButtonSet()       .addButton(CardService.newTextButton()         .setText('Get Selection')         .setOnClickAction(CardService.newAction().setFunctionName('getSheetsSelection'))         .setDisabled(false)))   } else if (hostApp === 'slides') {     fromSection.addWidget(CardService.newButtonSet()       .addButton(CardService.newTextButton()         .setText('Get Selection')         .setOnClickAction(CardService.newAction().setFunctionName('getSlidesSelection'))         .setDisabled(false)))   }     builder.addSection(fromSection);    // "Translation" language selection & text input section   builder.addSection(CardService.newCardSection()     .addWidget(generateLanguagesDropdown('destination', 'To: ', destinationLanguage))     .addWidget(CardService.newTextInput()       .setFieldName('output')       .setValue(outputText)       .setTitle('Translation...')       .setMultiline(true)));    //Buttons section   builder.addSection(CardService.newCardSection()     .addWidget(CardService.newButtonSet()       .addButton(CardService.newTextButton()         .setText('Translate')         .setTextButtonStyle(CardService.TextButtonStyle.FILLED)         .setOnClickAction(CardService.newAction().setFunctionName('translateText'))         .setDisabled(false))       .addButton(CardService.newTextButton()         .setText('Clear')         .setOnClickAction(CardService.newAction().setFunctionName('clearText'))         .setDisabled(false))));    return builder.build();  }  /**  * Helper function to generate the drop down language menu. It checks what language the user had selected.  * @param {String} fieldName  * @param {String} fieldTitle  * @param {String} previousSelected The language the user previously had selected.  * @return {CardService.SelectionInput} The card to show to the user.  */ function generateLanguagesDropdown(fieldName, fieldTitle, previousSelected) {   var selectionInput = CardService.newSelectionInput().setTitle(fieldTitle)     .setFieldName(fieldName)     .setType(CardService.SelectionInputType.DROPDOWN);    LANGUAGE_MAP.forEach((language, index, array) => {     selectionInput.addItem(language.text, language.val, language.val == previousSelected);   })    return selectionInput; }  /**  * Helper function to translate the text. If the originLanguage is an empty string, the API detects the language  * @return {CardService.Card} The card to show to the user.  */ function translateText(e) {   var originLanguage = e.formInput.origin;   var destinationLanguage = e.formInput.destination;   var inputText = e.formInput.input;    if (originLanguage !== destinationLanguage && inputText !== undefined) {     var translation = LanguageApp.translate(e.formInput.input, e.formInput.origin, e.formInput.destination);     return createSelectionCard(e, originLanguage, destinationLanguage, inputText, translation);   } }  /**  * Helper function to clean the text.  * @return {CardService.Card} The card to show to the user.  */ function clearText(e) {   var originLanguage = e.formInput.origin;   var destinationLanguage = e.formInput.destination;   return createSelectionCard(e, originLanguage, destinationLanguage, DEFAULT_INPUT_TEXT, DEFAULT_OUTPUT_TEXT); }  /**  * Helper function to get the text selected.  * @return {CardService.Card} The selected text.  */ function getDocsSelection(e) {   var text = '';   var selection = DocumentApp.getActiveDocument().getSelection();   Logger.log(selection)   if (selection) {     var elements = selection.getRangeElements();     for (var i = 0; i < elements.length; i++) {       Logger.log(elements[i]);       var element = elements[i];       // Only modify elements that can be edited as text; skip images and other non-text elements.       if (element.getElement().asText() && element.getElement().asText().getText() !== '') {         text += element.getElement().asText().getText() + '\n';       }     }   }    if (text !== '') {     var originLanguage = e.formInput.origin;     var destinationLanguage = e.formInput.destination;     var translation = LanguageApp.translate(text, e.formInput.origin, e.formInput.destination);     return createSelectionCard(e, originLanguage, destinationLanguage, text, translation);   } }  /**  * Helper function to get the text of the selected cells.  * @return {CardService.Card} The selected text.  */ function getSheetsSelection(e) {   var text = '';   var ranges = SpreadsheetApp.getActive().getSelection().getActiveRangeList().getRanges();   for (var i = 0; i < ranges.length; i++) {     const range = ranges[i];     const numRows = range.getNumRows();     const numCols = range.getNumColumns();     for (let i = 1; i <= numCols; i++) {       for (let j = 1; j <= numRows; j++) {         const cell = range.getCell(j, i);         if (cell.getValue()) {           text += cell.getValue() + '\n';         }       }     }   }   if (text !== '') {     var originLanguage = e.formInput.origin;     var destinationLanguage = e.formInput.destination;     var translation = LanguageApp.translate(text, e.formInput.origin, e.formInput.destination);     return createSelectionCard(e, originLanguage, destinationLanguage, text, translation);   } }  /**  * Helper function to get the selected text of the active slide.  * @return {CardService.Card} The selected text.  */ function getSlidesSelection(e) {   var text = '';   var selection = SlidesApp.getActivePresentation().getSelection();   var selectionType = selection.getSelectionType();   if (selectionType === SlidesApp.SelectionType.TEXT) {     var textRange = selection.getTextRange();     if (textRange.asString() !== '') {       text += textRange.asString() + '\n';     }   }   if (text !== '') {     var originLanguage = e.formInput.origin;     var destinationLanguage = e.formInput.destination;     var translation = LanguageApp.translate(text, e.formInput.origin, e.formInput.destination);     return createSelectionCard(e, originLanguage, destinationLanguage, text, translation);   } }

appsscript.json

{   "timeZone": "America/New_York",   "dependencies": {},   "exceptionLogging": "STACKDRIVER",   "oauthScopes": [     "https://www.googleapis.com/auth/documents.currentonly",     "https://www.googleapis.com/auth/spreadsheets.currentonly",     "https://www.googleapis.com/auth/presentations.currentonly"   ],   "runtimeVersion": "V8",   "addOns": {     "common": {       "name": "Translate",       "logoUrl": "https://www.gstatic.com/images/branding/product/1x/translate_24dp.png",       "layoutProperties": {         "primaryColor": "#2772ed"       },       "homepageTrigger": {         "runFunction": "onHomepage"       }     },     "docs" : {},     "slides" : {},     "sheets" : {}   } }

寄与者

このサンプルは、Google デベロッパー エキスパートの協力を得て Google によって管理されています。

次のステップ