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