Localizing Google Add-ons - json

We have a published Google Docs Add-on. Where we need 5 different languages. We are reading the Internationalizing Your App documentation. It's mainly describing how it can be done if you are publishing an Chrome Extension (uploading .zip). However an Docs Add-on is written in Google Apps Script.
As per documentation we need to add:
manifest.json
messages.json
"and providing a _locales directory in your app's ZIP file"
Here is where we get trouble. How can we add folders in Google Apps Script & how can we add .json files? The only options are script-files & html-files.

That documentation is NOT for Google Apps Script at all, but for Chrome Apps. So it does not directly apply.
Briefly looking through Google Apps Script docs, i18n is not mentioned. It does not seem like there is any supporting library for it.
Note that according to an earlier question on the topic you can get the user's locale with Session.getActiveUserLocale()) and implement your own i18n.
However, that probably won't enable item i18n in the Web Store itself. There's a bug report describing this situation.
The bug report mentions that you could potentially throw in the locale fields/folders in the generated Chrome app by editing it directly using this procedure. That much is not tested though.

Here is how we did it at Vocal. It's fairly simple and easy to implement (Our example supports english and spanish).
1. Create a dictionary with keys for the different strings in your app:
const LANGUAGE_MAP = {
"RECORD_MESSAGE": {
"en": "Record message",
"es": "Grabar mensaje"
},
"RECORD_MESSAGE_TEXT": {
"en": "1. Click here to record your voice",
"es": "1. Haga clic aquĆ­ para grabar su voz"
}
}
2. Create a function that takes a key as input and returns the string in the proper language based on the user's locale
This is done using Session.getActiveUserLocale()
function translate(key) {
locale = Session.getActiveUserLocale();
if (['en', 'es'].includes(locale)) {
return LANGUAGE_MAP[key][locale]
}
else {
return LANGUAGE_MAP[key]['en']
}
}
Replace all your bare strings with the function created above and the string as key.
CardService.newTextParagraph().setText(translate("RECORD_MESSAGE_TEXT"));

Related

Save Gmail Attachments on Google drive - unknown file type

I looked for previous questions on this subject and found some posts from a few years ago. They don't exactly match my problem and when I try them I get more run errors than the script I am using. In my case, my script creates the files but they show up in my google drive as "unknown file" and can't be opened or previewed in Google drive. However, if I download the file to my pc, it opens and previews correctly and without any problem. How do I correct the "unknown" designation in my Google Drive?
I've tried a lot of possible solutions but either they get run time errors or I end up with an "empty" file.
Does anyone have any ideas on why this is happening or how to correct the unknown files attribute?
//pasted by Cooper as an example
function putyourcodehere() {
//this was posted via a ctrl-K
}
Save Attachment to a folder
function lfunko() {
const query = 'subject:ThisIsATestMessage';
Gmail.Users.Messages.list(gobj.globals.calendarid, { q: query }).messages.forEach(m => {
GmailApp.getMessageById(m.id).getAttachments().forEach(a => {
DriveApp.getFolderById(gobj.globals.testfolderid).createFile(a.copyBlob()).setName(a.getName());
})
})
}
gobj.globals is an object of global variables I use so that I don't have to redact them when used within answers that will be posted on SO. Just treat them as things you will have to replace with your own local variables. I used gobj.globals.calendarid because that's my email address which is what they want for the userid
Of course you will have to enable the Gmail API

Is it possible to initiate Google Drive File Approval via API?

Google Drive Approvals are now out of beta and allow for a user to request one or more other parties to approve/reject a document, then lock it as non-editable. Is there a way to do this via the Google Drive/Google Docs/Google Slides API, or do you have to use the Web GUI?
I have found a workaround to know if a document is approved or not (unfortunately not to start an approval flow):
Open the document you want to start approval;
Click File > Approval > Start new Approval flow, select option "Lock file before sending approval request"
Call API /drive/v3/files/:fileId?fields=contentRestrictions, the response will look like this:
{
"contentRestrictions":[
{
"readOnly":true,
"restrictingUser":{
"kind":"drive#user",
"displayName":"........",
"me":true,
"permissionId":"........",
"emailAddress":".........."
},
"restrictionTime":"2022-04-27T11:03:42.430Z",
"type":"globalContentRestriction"
}
]
}
Back to the document, make the approval, and file will be locked.
Call again API /drive/v3/files/:fileId?fields=contentRestrictions, and now the response response will look like this:
{
"contentRestrictions":[
{
"readOnly":true,
"reason":"Locked for File Approval",
"restrictingUser":{
"kind":"drive#user",
"displayName":"......",
"me":true,
"permissionId":".......",
"emailAddress":"........"
},
"restrictionTime":"2022-04-27T10:54:24.594Z",
"type":"globalContentRestriction"
}
]
}
The difference is in the "reason" field, "Locked for File Approval" means that the file was approved.
P.S.: I don't how trustable this workaround is, I tested several and it seems consistent.
P.S.: I don't know if there is a better way to do it, just could find this one at the moment

GMail Google Apps Script Plugin "The value returned from Apps Script has a type that cannot be used by the add-ons platform"

In the last 24 hours, a previously working GMail plugin I run has started failing.
I stripped it all the way down to only trying to get the example from the docs working:
var action = CardService.newAction().setFunctionName('composeEmailCallback');
CardService.newTextButton()
.setText('Compose Email')
.setComposeAction(action, CardService.ComposedEmailType.REPLY_AS_DRAFT);
// ...
function composeEmailCallback() {
var thread = GmailApp.getThreadById(e.threadId);
var draft = thread.createDraftReply('This is a reply');
return CardService.newComposeActionResponseBuilder()
.setGmailDraft(draft)
.build();
}
On BUILD (not on button press), the previously working GMail Addon displays the error message:
The value returned from Apps Script has a type that cannot be used by the add-ons platform. Also make sure to call build on any builder before returning it. Value: values {
proto_value {
type_url: "type.googleapis.com/caribou.api.proto.addons.templates.publicapi.ContextualAddOnMarkup.Card"
value: "...(omitted)"
}
}
Is this a new, known issue? Does anyone have some troubleshooting steps to share?
For me the error was was caused by open links not being whitelisted. For example, if you have code like this:
CardService.newOpenLink().setUrl(url)
Then the link returned by 'url' has to be whitelisted in the appscript manifest's openLinkUrlPrefixes list, like so:
"openLinkUrlPrefixes": [
"https://*.example.com"
]
This problem is caused by Google's silent upgrading of Apps Script to the V8 Runtime. To downgrade from this runtime to the old runtime (Rhino), perform this set of actions:
Run -> Disable New Apps Script runtime powered by Chrome V8
A related issue can be found here.

How do you programmatically update an email vacation response using Google Apps Script?

I'm using Google Apps Script for the first time and am trying to simply update my vacation response in Gmail programmatically as a first test of Google Apps Script.
I'm following the documentation here: https://developers.google.com/gmail/api/v1/reference/users/settings/updateVacation
And I have written:
function updateAutoResponse(){
Gmail.Users.Settings.updateVacation('me', {
"enableAutoReply": true,
"responseSubject": "I am not here...",
"responseBodyPlainText": "I am not here...",
"responseBodyHtml": "I am not here...",
"restrictToContacts": false,
"restrictToDomain": false
});
}
Unfortunately, I get an error after it appears to compile. Parse Error (line 65, file "Code")
I've enabled the Gmail API in Advanced Google Services as well as in the Google API Console, so I think this is a syntax issue somewhere.
Any thoughts would be super helpful. Thanks!
this is a simple fix:
function updateAutoResponse(){
Gmail.Users.Settings.updateVacation(
{
"enableAutoReply": true,
"responseSubject": "Test",
"responseBodyHtml": "Testing script, not actually gone",
"restrictToContacts": false,
"restrictToDomain": false
},
'me'
);
}
The userId is the second argument, not the first. It's not written in the documentation, however if you allow Apps Script autocomplete to show you the syntax, it states updateVacation(VacationSettings resource, String userId) : VacationSettings.
Also, not sure if this has any impact, but I am pretty sure there is no point in providing both responseBodyHtml and responseBodyPlainText seeing as they fill the exact same spot. If you don't need the HTML, you can just use PlainText, but if you want formatting, you use HTML and PlainText will be used whenever the recipient does not accept HTML (formatting will just get removed)

Alfresco 5.0C advanced search Get slingshot search parameters

When you make an advanced search in Alfresco it returns a json response with results executing the script
http://localhost:8080/share/proxy/alfresco/slingshot/search/?facetFields=..
I have add a button in the aikau advanced search results page and I want to execute the same script. How can I call it and get its parameters ?
The aikau button
var button = {
name: "alfresco/buttons/AlfButton",
config: {
label: "Exec Script",
additionalCssClasses: "call-to-action",
onClick:....... **call facets script**...
}
};
Firstly, if possible I would recommend that you move up to using Alfresco 5.0.d as this will enable you to take advantage of the weekly releases of Aikau as described in this blog post.
As for your specific question... you should not be attempting to define an Aikau button like that (with the "onClick" attribute). Aikau works over a publication/subscription mechanism so buttons would be configured with a publishTopic and a publishPayload. The topic published would need to be subscribed to by another widget or a service.
If you're not familiar with working with Aikau then I suggest that you work through the tutorial on GitHub. You can also find an additional list of educational references here.