本快速入门创建了一个 Google 幻灯片编辑器插件,可用于翻译演示文稿中的所选文本。

目标

  • 设置脚本。
  • 运行脚本。

前提条件

如需使用此示例,您需要满足以下前提条件:

  • Google 帐号(Google Workspace 帐号可能需要管理员批准)。
  • 一个能够访问互联网的网络浏览器。

设置脚本

/**
 * @OnlyCurrentDoc Limits the script to only accessing the current presentation.
 */

/**
 * Create a open translate menu item.
 * @param {Event} event The open event.
 */
function onOpen(event) {
  SlidesApp.getUi().createAddonMenu()
      .addItem('Open Translate', 'showSidebar')
      .addToUi();
}

/**
 * Open the Add-on upon install.
 * @param {Event} event The install event.
 */
function onInstall(event) {
  onOpen(event);
}

/**
 * Opens a sidebar in the document containing the add-on's user interface.
 */
function showSidebar() {
  const ui = HtmlService
      .createHtmlOutputFromFile('sidebar')
      .setTitle('Translate');
  SlidesApp.getUi().showSidebar(ui);
}

/**
 * Recursively gets child text elements a list of elements.
 * @param {PageElement[]} elements The elements to get text from.
 * @return {Text[]} An array of text elements.
 */
function getElementTexts(elements) {
  let texts = [];
  elements.forEach((element)=> {
    switch (element.getPageElementType()) {
      case SlidesApp.PageElementType.GROUP:
        element.asGroup().getChildren().forEach((child)=> {
          texts = texts.concat(getElementTexts(child));
        });
        break;
      case SlidesApp.PageElementType.TABLE:
        const table = element.asTable();
        for (let y = 0; y < table.getNumColumns(); ++y) {
          for (let x = 0; x < table.getNumRows(); ++x) {
            texts.push(table.getCell(x, y).getText());
          }
        }
        break;
      case SlidesApp.PageElementType.SHAPE:
        texts.push(element.asShape().getText());
        break;
    }
  });
  return texts;
}

/**
 * Translates selected slide elements to the target language using Apps Script's Language service.
 *
 * @param {string} targetLanguage The two-letter short form for the target language. (ISO 639-1)
 * @return {number} The number of elements translated.
 */
function translateSelectedElements(targetLanguage) {
  // Get selected elements.
  const selection = SlidesApp.getActivePresentation().getSelection();
  const selectionType = selection.getSelectionType();
  let texts = [];
  switch (selectionType) {
    case SlidesApp.SelectionType.PAGE:
      selection.getPageRange().getPages().forEach((page)=> {
        texts = texts.concat(getElementTexts(page.getPageElements()));
      });
      break;
    case SlidesApp.SelectionType.PAGE_ELEMENT:
      const pageElements = selection.getPageElementRange().getPageElements();
      texts = texts.concat(getElementTexts(pageElements));
      break;
    case SlidesApp.SelectionType.TABLE_CELL:
      selection.getTableCellRange().getTableCells().forEach((cell)=> {
        texts.push(cell.getText());
      });
      break;
    case SlidesApp.SelectionType.TEXT:
      selection.getPageElementRange().getPageElements().forEach((element) =>{
        texts.push(element.asShape().getText());
      });
      break;
  }

  // Translate all elements in-place.
  texts.forEach((text)=> {
    text.setText(LanguageApp.translate(text.asRenderedString(), '', targetLanguage));
  });

  return texts.length;
}
<html>
<head>
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
  <style>
    .logo { vertical-align: middle; }
    ul { list-style-type: none; padding: 0; }
    h4 { margin: 0; }
  </style>
</head>
<body>
<form class="sidebar branding-below">
  <h4>Translate selected slides into:</h4>
  <ul id="languages"></ul>
  <div class="block" id="button-bar">
    <button class="blue" id="run-translation">Translate</button>
  </div>
  <h5 class="error" id="error"></h5>
</form>
<div class="sidebar bottom">
  <img alt="Add-on logo" class="logo"
       src="https://www.gstatic.com/images/branding/product/1x/translate_48dp.png" width="27" height="27">
  <span class="gray branding-text">Translate sample by Google</span>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
  $(function() {
    // Add an input radio button for every language.
    const languages = {
      ar: 'Arabic',
      zh: 'Chinese',
      en: 'English',
      fr: 'French',
      de: 'German',
      hi: 'Hindi',
      ja: 'Japanese',
      pt: 'Portuguese',
      es: 'Spanish'
    };
    const languageList = Object.keys(languages).map((id)=> {
      return $('<li>').html([
        $('<input>')
                .attr('type', 'radio')
                .attr('name', 'dest')
                .attr('id', 'radio-dest-' + id)
                .attr('value', id),
        $('<label>')
                .attr('for', 'radio-dest-' + id)
                .html(languages[id])
      ]);
    });

    $('#run-translation').click(runTranslation);
    $('#languages').html(languageList);
  });

  /**
   * Runs a server-side function to translate the text on all slides.
   */
  function runTranslation() {
    this.disabled = true;
    $('#error').text('');
    google.script.run
            .withSuccessHandler((numTranslatedElements, element) =>{
              element.disabled = false;
              if (numTranslatedElements === 0) {
                $('#error').empty()
                        .append('Did you select elements to translate?')
                        .append('<br/>')
                        .append('Please select slides or individual elements.');
              }
              return false;
            })
            .withFailureHandler((msg, element)=> {
              element.disabled = false;
              $('#error').text('Something went wrong. Please check the add-on logs.');
              return false;
            })
            .withUserObject(this)
            .translateSelectedElements($('input[name=dest]:checked').val());
  }
</script>
</body>
</html>

运行脚本

  1. 在幻灯片演示文稿中,重新加载页面。
  2. 依次点击扩展程序 > 翻译文档 > 开始。插件菜单项可能需要几秒钟才会显示。
  3. 当系统提示时,请授权该插件。
  4. 再次点击扩展程序 > 翻译文档 > 开始
  5. 为您的演示文稿添加文本并将其选中。
  6. 点击插件中的翻译。如需替换文档中的文本,请点击插入

后续步骤