مستوى الترميز: متوسط
المدة: 30 دقيقة
نوع المشروع: إضافة Google Workspace
الأهداف
- افهم ما يفعله الحل.
- تعرّف على ما تفعله خدمات "برمجة تطبيقات Google" ضمن الحل.
- إعداد البيئة.
- إعداد النص البرمجي.
- شغّل النص البرمجي.
لمحة عن هذا الحل
باستخدام هذا الحل، يمكنك بسهولة ترجمة النص من داخل المستندات وجداول البيانات والعروض التقديمية من Google.
آلية العمل
عند اختيار نص في "مستندات Google" أو "جداول بيانات Google" أو "العروض التقديمية من Google" والنقر على الحصول على اختيار في الإضافة، ينسخ النص البرمجي النص في الإضافة، ويترجمه ويعرض النص المترجم.
يرصد النص البرمجي تلقائيًا اللغة المصدر ويترجم النص إلى اللغة الإنجليزية. يمكنك تعديل اللغات المصدر واللغة المستهدفة.
خدمات برمجة التطبيقات
يستخدم هذا الحل الخدمات التالية:
- خدمة البطاقة–تنشئ واجهة المستخدم للإضافة.
- خدمة اللغة–تترجم النص باستخدام ترجمة Google.
المتطلبات الأساسية
لاستخدام هذا النموذج، تحتاج إلى المتطلبات الأساسية التالية:
- حساب Google (قد تحتاج حسابات Google Workspace إلى موافقة المشرف)
متصفح ويب يتمتع بإمكانية الدخول إلى الإنترنت.
إعداد البيئة
فتح مشروعك على السحابة الإلكترونية في Google Cloud Console
إذا لم يكن مفتوحًا بالفعل، فافتح مشروع السحاب الذي تنوي استخدامه لهذا النموذج:
- في وحدة تحكُّم Google Cloud، انتقِل إلى صفحة اختيار مشروع.
- اختَر مشروع Google Cloud الذي تريد استخدامه. أو انقر على إنشاء مشروع واتبع التعليمات التي تظهر على الشاشة. في حال إنشاء مشروع على Google Cloud، قد تحتاج إلى تفعيل الفوترة للمشروع.
ضبط شاشة موافقة OAuth
تتطلب إضافات Google Workspace ضبط شاشة الموافقة. عند ضبط شاشة إضافة OAuth OAuth، يتم تحديد ما تعرضه Google للمستخدمين.
- في Google Cloud Console، انتقِل إلى القائمة > واجهات برمجة التطبيقات والخدمات > شاشة موافقة OAuth.
- حدد نوع المستخدم لتطبيقك، ثم انقر على إنشاء.
- أكمل نموذج تسجيل التطبيق، ثم انقر على حفظ ومتابعة.
في الوقت الحالي، يمكنك تخطي إضافة نطاقات والنقر على حفظ ومتابعة. في المستقبل، عند إنشاء تطبيق للاستخدام خارج مؤسسة Google Workspace، عليك إضافة نطاقات التفويض التي يتطلبها تطبيقك والتحقّق منها.
- في حال اختيار خارجي لنوع المستخدم، أضِف مستخدمين تجريبيين:
- ضمن اختبار المستخدمين، انقر على إضافة مستخدمين.
- أدخِل عنوان البريد الإلكتروني وأيّ مستخدمين آخرين مُعتمَدين للاختبار، ثم انقر على حفظ ومتابعة.
- راجِع ملخّص تسجيل التطبيقات. لإجراء تغييرات، انقر على تعديل. إذا كان تسجيل التطبيق على ما يرام، انقر على الرجوع إلى لوحة البيانات.
إعداد النص البرمجي
إنشاء مشروع برمجة التطبيقات
انقر على الزر التالي لفتح مشروع برمجة التطبيقات "ترجمة".
فتح المشروعانقر على رمز نظرة عامة
.في صفحة النظرة العامة، انقر على "إنشاء نسخة"
.
نسخ رقم المشروع على السحابة الإلكترونية
- انتقِل إلى مشروعك على Google Cloud في Google Cloud Console.
- انقر على الإعدادات والأدوات المساعدة > إعدادات المشروع.
- انسخ رقم المشروع.
إعداد مشروع السحابة الإلكترونية لمشروع برمجة التطبيقات
- في مشروع "برمجة تطبيقات Google" المنسوخ،
انقر على إعدادات المشروع
.
- ضمن مشروع Google Cloud Platform (GCP)، انقر على تغيير المشروع.
- في رقم مشروع Google Cloud Platform، الصق رقم مشروع Google Cloud.
- انقر على تحديد المشروع.
تثبيت عملية نشر تجريبية
- في مشروع "برمجة تطبيقات Google" المنسوخ، انقر على أداة التعديل .
- افتح الملف
Code.gs
وانقر على تشغيل. فوضّح النص البرمجي عندما يُطلب منك ذلك. - انقر على نشر > اختبار عمليات النشر.
- انقر على تثبيت > تم.
تشغيل النص البرمجي
- افتح ملفًا في تطبيق مستندات Google أو جداول بيانات Google أو العروض التقديمية من Google أو أنشئ ملفًا جديدًا.
- في الشريط الجانبي الأيسر، افتح الإضافة "ترجمة" .
- تفويض الإضافة، إذا طُلب منك ذلك.
- اختَر نصًا في ملفك.
- في الإضافة، انقر على الحصول على مجموعة مختارة > ترجمة.
مراجعة الشفرة
لمراجعة شفرة برمجة التطبيقات لهذا الحل، انقر على عرض شفرة المصدر أدناه:
عرض رمز المصدر
Code.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); } }
ملف appscript.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.