From 5c44b93fb007bf756445ff06724212903a3ec1e0 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 7 Sep 2019 09:57:52 +0100 Subject: [PATCH] Start of translations --- daemon.py | 110 +++++++++--- translations/en.json | 94 ++++++++++ translations/fr.json | 94 ++++++++++ webinterface.py | 412 +++++++++++++++++++++++-------------------- 4 files changed, 498 insertions(+), 212 deletions(-) create mode 100644 translations/en.json create mode 100644 translations/fr.json diff --git a/daemon.py b/daemon.py index 23ba2a25..537cc644 100644 --- a/daemon.py +++ b/daemon.py @@ -12,6 +12,7 @@ import commentjson import json import time import base64 +import locale # used for mime decoding of message POST import email.parser # for saving images @@ -604,7 +605,8 @@ class PubServer(BaseHTTPRequestHandler): optionsLink=None if len(optionsList)>3: optionsLink=optionsList[3] - msg=htmlPersonOptions(self.server.baseDir, \ + msg=htmlPersonOptions(self.server.translate, \ + self.server.baseDir, \ self.server.domain, \ originPathStr, \ optionsActor, \ @@ -623,7 +625,7 @@ class PubServer(BaseHTTPRequestHandler): if htmlGET and '?rmshare=' in self.path: shareName=self.path.split('?rmshare=')[1] actor=self.server.httpPrefix+'://'+self.server.domainFull+self.path.split('?rmshare=')[0] - msg=htmlRemoveSharedItem(self.server.baseDir,actor,shareName).encode() + msg=htmlRemoveSharedItem(self.server.translate,self.server.baseDir,actor,shareName).encode() if not msg: self._redirect_headers(actor+'/inbox',cookie) self.server.GETbusy=False @@ -919,7 +921,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.GETbusy=False return hashtagStr= \ - htmlHashtagSearch(self.server.baseDir,hashtag,pageNumber, \ + htmlHashtagSearch(self.server.translate, \ + self.server.baseDir,hashtag,pageNumber, \ maxPostsInFeed,self.server.session, \ self.server.cachedWebfingers, \ self.server.personCache, \ @@ -939,7 +942,8 @@ class PubServer(BaseHTTPRequestHandler): if htmlGET and '/users/' in self.path: if self.path.endswith('/search'): # show the search screen - msg=htmlSearch(self.server.baseDir,self.path).encode() + msg=htmlSearch(self.server.translate, \ + self.server.baseDir,self.path).encode() self._set_headers('text/html',len(msg),cookie) self.wfile.write(msg) self.server.GETbusy=False @@ -949,7 +953,9 @@ class PubServer(BaseHTTPRequestHandler): if htmlGET and '/users/' in self.path: if self.path.endswith('/searchemoji'): # show the search screen - msg=htmlSearchEmojiTextEntry(self.server.baseDir,self.path).encode() + msg=htmlSearchEmojiTextEntry(self.server.translate, \ + self.server.baseDir, \ + self.path).encode() self._set_headers('text/html',len(msg),cookie) self.wfile.write(msg) self.server.GETbusy=False @@ -1189,7 +1195,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.useTor) deleteStr= \ - htmlDeletePost(pageNumber, \ + htmlDeletePost(self.server.translate,pageNumber, \ self.server.session,self.server.baseDir, \ deleteUrl,self.server.httpPrefix, \ __version__,self.server.cachedWebfingers, \ @@ -1279,7 +1285,12 @@ class PubServer(BaseHTTPRequestHandler): self.path.endswith('/newdm') or \ self.path.endswith('/newreport') or \ self.path.endswith('/newshare')): - msg=htmlNewPost(self.server.baseDir,self.path,inReplyToUrl,replyToList,shareDescription,replyPageNumber).encode() + msg=htmlNewPost(self.server.translate, \ + self.server.baseDir, \ + self.path,inReplyToUrl, \ + replyToList, \ + shareDescription, \ + replyPageNumber).encode() self._set_headers('text/html',len(msg),cookie) self.wfile.write(msg) self.server.GETbusy=False @@ -1311,7 +1322,8 @@ class PubServer(BaseHTTPRequestHandler): postJsonObject['likes']={'items': []} if self._requestHTTP(): msg= \ - htmlIndividualPost(self.server.session, \ + htmlIndividualPost(self.server.translate, \ + self.server.session, \ self.server.cachedWebfingers,self.server.personCache, \ nickname,self.server.domain,self.server.port, \ authorized,postJsonObject, \ @@ -1361,7 +1373,8 @@ class PubServer(BaseHTTPRequestHandler): print('DEBUG: creating new session') self.server.session= \ createSession(self.server.domain,self.server.port,self.server.useTor) - msg=htmlPostReplies(self.server.baseDir, \ + msg=htmlPostReplies(self.server.translate, \ + self.server.baseDir, \ self.server.session, \ self.server.cachedWebfingers, \ self.server.personCache, \ @@ -1406,7 +1419,8 @@ class PubServer(BaseHTTPRequestHandler): print('DEBUG: creating new session') self.server.session= \ createSession(self.server.domain,self.server.port,self.server.useTor) - msg=htmlPostReplies(self.server.baseDir, \ + msg=htmlPostReplies(self.server.translate, \ + self.server.baseDir, \ self.server.session, \ self.server.cachedWebfingers, \ self.server.personCache, \ @@ -1440,7 +1454,8 @@ class PubServer(BaseHTTPRequestHandler): personLookup(self.server.domain,self.path.replace('/roles',''), \ self.server.baseDir) if getPerson: - msg=htmlProfile(self.server.projectVersion, \ + msg=htmlProfile(self.server.translate, \ + self.server.projectVersion, \ self.server.baseDir, \ self.server.httpPrefix, \ True, \ @@ -1476,7 +1491,8 @@ class PubServer(BaseHTTPRequestHandler): personLookup(self.server.domain,self.path.replace('/skills',''), \ self.server.baseDir) if getPerson: - msg=htmlProfile(self.server.projectVersion, \ + msg=htmlProfile(self.server.translate, \ + self.server.projectVersion, \ self.server.baseDir, \ self.server.httpPrefix, \ True, \ @@ -1533,7 +1549,8 @@ class PubServer(BaseHTTPRequestHandler): if postJsonObject.get('likes'): postJsonObject['likes']={'items': []} if self._requestHTTP(): - msg=htmlIndividualPost(self.server.baseDir, \ + msg=htmlIndividualPost(self.server.translate, \ + self.server.baseDir, \ self.server.session, \ self.server.cachedWebfingers,self.server.personCache, \ nickname,self.server.domain,self.server.port, \ @@ -1823,7 +1840,8 @@ class PubServer(BaseHTTPRequestHandler): print('DEBUG: creating new session') self.server.session= \ createSession(self.server.domain,self.server.port,self.server.useTor) - msg=htmlProfile(self.server.projectVersion, \ + msg=htmlProfile(self.server.translate, \ + self.server.projectVersion, \ self.server.baseDir, \ self.server.httpPrefix, \ authorized, \ @@ -1873,7 +1891,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.session= \ createSession(self.server.domain,self.server.port,self.server.useTor) - msg=htmlProfile(self.server.projectVersion, \ + msg=htmlProfile(self.server.translate, \ + self.server.projectVersion, \ self.server.baseDir, \ self.server.httpPrefix, \ authorized, \ @@ -1921,7 +1940,8 @@ class PubServer(BaseHTTPRequestHandler): print('DEBUG: creating new session') self.server.session= \ createSession(self.server.domain,self.server.port,self.server.useTor) - msg=htmlProfile(self.server.projectVersion, \ + msg=htmlProfile(self.server.translate, \ + self.server.projectVersion, \ self.server.baseDir, \ self.server.httpPrefix, \ authorized, \ @@ -1952,7 +1972,8 @@ class PubServer(BaseHTTPRequestHandler): print('DEBUG: creating new session') self.server.session= \ createSession(self.server.domain,self.server.port,self.server.useTor) - msg=htmlProfile(self.server.projectVersion, \ + msg=htmlProfile(self.server.translate, \ + self.server.projectVersion, \ self.server.baseDir, \ self.server.httpPrefix, \ authorized, \ @@ -2755,7 +2776,8 @@ class PubServer(BaseHTTPRequestHandler): if searchStr.startswith('#'): # hashtag search hashtagStr= \ - htmlHashtagSearch(self.server.baseDir,searchStr[1:],1, \ + htmlHashtagSearch(self.server.translate, \ + self.server.baseDir,searchStr[1:],1, \ maxPostsInFeed,self.server.session, \ self.server.cachedWebfingers, \ self.server.personCache, \ @@ -2789,7 +2811,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.port, \ self.server.useTor) profileStr= \ - htmlProfileAfterSearch(self.server.baseDir, \ + htmlProfileAfterSearch(self.server.translate, \ + self.server.baseDir, \ self.path.replace('/searchhandle',''), \ self.server.httpPrefix, \ nickname, \ @@ -3134,7 +3157,11 @@ class PubServer(BaseHTTPRequestHandler): if '&submitUnblock=' in optionsConfirmParams: if self.server.debug: print('Unblocking '+optionsActor) - msg=htmlUnblockConfirm(self.server.baseDir,originPathStr,optionsActor,optionsAvatarUrl).encode() + msg=htmlUnblockConfirm(self.server.translate, \ + self.server.baseDir, \ + originPathStr, \ + optionsActor, \ + optionsAvatarUrl).encode() self._set_headers('text/html',len(msg),cookie) self.wfile.write(msg) self.server.POSTbusy=False @@ -3142,7 +3169,11 @@ class PubServer(BaseHTTPRequestHandler): if '&submitFollow=' in optionsConfirmParams: if self.server.debug: print('Following '+optionsActor) - msg=htmlFollowConfirm(self.server.baseDir,originPathStr,optionsActor,optionsAvatarUrl).encode() + msg=htmlFollowConfirm(self.server.translate, \ + self.server.baseDir, \ + originPathStr, \ + optionsActor, \ + optionsAvatarUrl).encode() self._set_headers('text/html',len(msg),cookie) self.wfile.write(msg) self.server.POSTbusy=False @@ -3150,7 +3181,11 @@ class PubServer(BaseHTTPRequestHandler): if '&submitUnfollow=' in optionsConfirmParams: if self.server.debug: print('Unfollowing '+optionsActor) - msg=htmlUnfollowConfirm(self.server.baseDir,originPathStr,optionsActor,optionsAvatarUrl).encode() + msg=htmlUnfollowConfirm(self.server.translate, \ + self.server.baseDir, \ + originPathStr, \ + optionsActor, \ + optionsAvatarUrl).encode() self._set_headers('text/html',len(msg),cookie) self.wfile.write(msg) self.server.POSTbusy=False @@ -3159,7 +3194,11 @@ class PubServer(BaseHTTPRequestHandler): if self.server.debug: print('Sending DM to '+optionsActor) reportPath=self.path.replace('/personoptions','')+'/newdm' - msg=htmlNewPost(self.server.baseDir,reportPath,None,[optionsActor],None,pageNumber).encode() + msg=htmlNewPost(self.server.translate, \ + self.server.baseDir, \ + reportPath,None, \ + [optionsActor],None, \ + pageNumber).encode() self._set_headers('text/html',len(msg),cookie) self.wfile.write(msg) self.server.POSTbusy=False @@ -3168,7 +3207,10 @@ class PubServer(BaseHTTPRequestHandler): if self.server.debug: print('Reporting '+optionsActor) reportPath=self.path.replace('/personoptions','')+'/newreport' - msg=htmlNewPost(self.server.baseDir,reportPath,None,[],postUrl,pageNumber).encode() + msg=htmlNewPost(self.server.translate, \ + self.server.baseDir, \ + reportPath,None,[], \ + postUrl,pageNumber).encode() self._set_headers('text/html',len(msg),cookie) self.wfile.write(msg) self.server.POSTbusy=False @@ -3462,6 +3504,26 @@ def runDaemon(projectVersion, \ httpd = ThreadingHTTPServer(serverAddress, PubServerUnitTest) else: httpd = ThreadingHTTPServer(serverAddress, PubServer) + + # load translations dictionary + httpd.translate={} + if not unitTest: + if not os.path.isdir(baseDir+'/translations'): + print('ERROR: translations directory not found') + return + systemLanguage=locale.getdefaultlocale()[0] + if '_' in systemLanguage: + systemLanguage=systemLanguage.split('_')[0] + if '.' in systemLanguage: + systemLanguage=systemLanguage.split('.')[0] + translationsFile=baseDir+'/translations/'+systemLanguage+'.json' + if not os.path.isfile(translationsFile): + systemLanguage='en' + translationsFile=baseDir+'/translations/'+systemLanguage+'.json' + print('System language: '+systemLanguage) + with open(translationsFile, 'r') as fp: + httpd.translate=commentjson.load(fp) + httpd.outboxThread={} httpd.projectVersion=projectVersion # max POST size of 30M diff --git a/translations/en.json b/translations/en.json new file mode 100644 index 00000000..c9e1a759 --- /dev/null +++ b/translations/en.json @@ -0,0 +1,94 @@ +{ + "SHOW MORE": "SHOW MORE", + "Your browser does not support the video tag.": "Your browser does not support the video tag.", + "Your browser does not support the audio tag.": "Your browser does not support the audio tag.", + "Show profile": "Show profile", + "Show options for this person": "Show options for this person", + "Repeat this post": "Repeat this post", + "Undo the repeat": "Undo the repeat", + "Like this post": "Like this post", + "Undo the like": "Undo the like", + "Delete this post": "Delete this post", + "Reply to this post": "Reply to this post", + "Write your post text below.": "Write your post text below.", + "Write your reply to": "Write your reply to", + "this post": "this post", + "Write your report below.": "Write your report below.", + "This message only goes to moderators, even if it mentions other fediverse addresses.": "This message only goes to moderators, even if it mentions other fediverse addresses.", + "Also see": "Also see", + "Terms of Service": "Terms of Service", + "Enter the details for your shared item below.": "Enter the details for your shared item below.", + "Subject or Content Warning (optional)": "Subject or Content Warning (optional)", + "Write something": "Write something", + "Name of the shared item": "Name of the shared item", + "Description of the item being shared": "Description of the item being shared", + "Type of shared item. eg. hat": "Type of shared item. eg. hat", + "Category of shared item. eg. clothing": "Category of shared item. eg. clothing", + "Duration of listing in days": "Duration of listing in days", + "City or location of the shared item": "City or location of the shared item", + "Describe a shared item": "Describe a shared item", + "Public": "Public", + "Visible to anyone": "Visible to anyone", + "Unlisted": "Unlisted", + "Not on public timeline": "Not on public timeline", + "Followers": "Followers", + "Only to followers": "Only to followers", + "DM": "DM", + "Only to mentioned people": "Only to mentioned people", + "Report": "Report", + "Send to moderators": "Send to moderators", + "Search for emoji": "Search for emoji", + "Cancel": "Cancel", + "Submit": "Submit", + "Image description": "Image description", + "Item image": "Item image", + "Type": "Type", + "Category": "Category", + "Location": "Location", + "Login": "Login", + "Edit": "Edit", + "Switch to timeline view": "Switch to timeline view", + "Approve": "Approve", + "Deny": "Deny", + "Posts": "Posts", + "Following": "Following", + "Followers": "Followers", + "Roles": "Roles", + "Skills": "Skills", + "Shares": "Shares", + "Block": "Block", + "Unfollow": "Unfollow", + "Your browser does not support the audio element.": "Your browser does not support the audio element.", + "Your browser does not support the video element.": "Your browser does not support the video element.", + "Create a new post": "Create a new post", + "Create a new DM": "Create a new DM", + "Switch to profile view": "Switch to profile view", + "Inbox": "Inbox", + "Outbox": "Outbox", + "Search and follow": "Search and follow", + "Refresh": "Refresh", + "Nickname or URL. Block using *@domain or nickname@domain": "Nickname or URL. Block using *@domain or nickname@domain", + "Remove the above item": "Remove the above item", + "Remove": "Remove", + "Suspend the above account nickname": "Suspend the above account nickname", + "Suspend": "Suspend", + "Remove a suspension for an account nickname": "Remove a suspension for an account nickname", + "Unsuspend": "Unsuspend", + "Block an account on another instance": "Block an account on another instance", + "Unblock": "Unblock", + "Unblock an account on another instance": "Unblock an account on another instance", + "Information about current blocks/suspensions": "Information about current blocks/suspensions", + "Info": "Info", + "Remove": "Remove", + "Yes": "Yes", + "No": "No", + "Delete this post?": "Delete this post?", + "Follow": "Follow", + "Stop following": "Stop following", + "Options for": "Options for", + "View": "View", + "Stop blocking": "Stop blocking", + "Enter an emoji name to search for": "Enter an emoji name to search for", + "Enter an address, shared item, #hashtag, *skill or :emoji: to search for": "Enter an address, shared item, #hashtag, *skill or :emoji: to search for", + "Go Back": "Go Back" +} diff --git a/translations/fr.json b/translations/fr.json new file mode 100644 index 00000000..afc28d2b --- /dev/null +++ b/translations/fr.json @@ -0,0 +1,94 @@ +{ + "SHOW MORE": "MONTRE PLUS", + "Your browser does not support the video tag.": "Votre navigateur ne supporte pas le tag vidéo.", + "Your browser does not support the audio tag.": "Votre navigateur ne supporte pas la balise audio.", + "Show profile": "Montre le profile", + "Show options for this person": "Afficher les options pour cette personne", + "Repeat this post": "Répétez ce post", + "Undo the repeat": "Annuler la répétition", + "Like this post": "Comme ce poste", + "Undo the like": "Annuler le même", + "Delete this post": "Supprimer ce post", + "Reply to this post": "Répondre à ce post", + "Write your post text below.": "Entrez votre message ci-dessous.", + "Write your reply to": "Écrivez votre réponse à", + "this post": "ce post", + "Write your report below.": "Écrivez votre rapport ci-dessous.", + "This message only goes to moderators, even if it mentions other fediverse addresses.": "Ce message n’adresse que les modérateurs, même s’il mentionne d’autres adresses fedivers.", + "Also see": "Regarde aussi", + "Terms of Service": "Conditions d'utilisation", + "Enter the details for your shared item below.": "Entrez les détails de votre article partagé ci-dessous.", + "Subject or Content Warning (optional)": "Avertissement de sujet ou de contenu (facultatif)", + "Write something": "Écris quelque chose", + "Name of the shared item": "Nom de l'élément partagé", + "Description of the item being shared": "Description de l'élément en cours de partage", + "Type of shared item. eg. hat": "Type d'élément partagé. par exemple. chapeau", + "Category of shared item. eg. clothing": "Catégorie d'élément partagé. par exemple. Vêtements", + "Duration of listing in days": "Durée de la cotation en jours", + "City or location of the shared item": "Ville ou lieu de l'élément partagé", + "Describe a shared item": "Décrire un élément partagé", + "Public": "Publique", + "Visible to anyone": "Visible par n'importe qui", + "Unlisted": "Non répertorié", + "Not on public timeline": "Pas sur la chronologie publique", + "Followers": "Suiveuses", + "Only to followers": "Seulement aux adeptes", + "DM": "MD", + "Only to mentioned people": "Seulement aux personnes mentionnées", + "Report": "Rapport", + "Send to moderators": "Envoyer aux modérateurs", + "Search for emoji": "Recherche emoji", + "Cancel": "Annuler", + "Submit": "Soumettre", + "Image description": "Description de l'image", + "Item image": "Image de l'article", + "Type": "Type", + "Category": "Catégorie", + "Location": "Emplacement", + "Login": "S'identifier", + "Edit": "Modifier", + "Switch to timeline view": "Passer en vue chronologique", + "Approve": "Approuver", + "Deny": "Nier", + "Posts": "Des postes", + "Following": "Suivante", + "Followers": "Suiveuses", + "Roles": "Rôles", + "Skills": "Compétences", + "Shares": "Actions", + "Block": "Bloc", + "Unfollow": "Se désabonner", + "Your browser does not support the audio element.": "Votre navigateur ne supporte pas l'élément audio.", + "Your browser does not support the video element.": "Votre application ne supporte pas le format de l'élément vidéo.", + "Create a new post": "Créer un nouveau post", + "Create a new DM": "Créer un nouveau message direct", + "Switch to profile view": "Passer en vue de profil", + "Inbox": "Réception", + "Outbox": "Envoi", + "Search and follow": "Rechercher et suivre", + "Refresh": "Rafraîchir", + "Nickname or URL. Block using *@domain or nickname@domain": "Surnom ou URL. Bloquer en utilisant *@domain ou pseudo@domain", + "Remove the above item": "Supprimer l'élément ci-dessus", + "Remove": "Retirer", + "Suspend the above account nickname": "Suspendre le pseudo du compte ci-dessus", + "Suspend": "Suspendre", + "Remove a suspension for an account nickname": "Supprimer une suspension pour un pseudo de compte", + "Unsuspend": "Insuffler", + "Block an account on another instance": "Bloquer un compte sur une autre instance", + "Unblock": "Débloquer", + "Unblock an account on another instance": "Débloquer un compte sur une autre instance", + "Information about current blocks/suspensions": "Informations sur les blocs / suspensions en cours", + "Info": "Info", + "Remove": "Retirer", + "Yes": "Oui", + "No": "Non", + "Delete this post?": "Supprimer ce post?", + "Follow": "Suivre", + "Stop following": "Arrête de suivre", + "Options for": "Options pour", + "View": "Vue", + "Stop blocking": "Arrêtez le blocage", + "Enter an emoji name to search for": "Entrez un nom emoji à rechercher", + "Enter an address, shared item, #hashtag, *skill or :emoji: to search for": "Entrez une adresse, un objet partagé, #hashtag, * skill ou: emoji: à rechercher", + "Go Back": "Retourner" +} diff --git a/webinterface.py b/webinterface.py index 332e2e9f..5d98174b 100644 --- a/webinterface.py +++ b/webinterface.py @@ -221,7 +221,8 @@ def htmlModerationInfo(baseDir: str) -> str: infoForm+=htmlFooter() return infoForm -def htmlHashtagSearch(baseDir: str,hashtag: str,pageNumber: int,postsPerPage: int, +def htmlHashtagSearch(translate: {}, \ + baseDir: str,hashtag: str,pageNumber: int,postsPerPage: int, \ session,wfRequest: {},personCache: {}, \ httpPrefix: str,projectVersion: str) -> str: """Show a page containing search results for a hashtag @@ -272,7 +273,8 @@ def htmlHashtagSearch(baseDir: str,hashtag: str,pageNumber: int,postsPerPage: in index-=1 continue hashtagSearchForm+= \ - individualPostAsHtml(None,baseDir,session,wfRequest,personCache, \ + individualPostAsHtml(translate,None, \ + baseDir,session,wfRequest,personCache, \ nickname,domain,port,postJsonObject, \ None,True,False, \ httpPrefix,projectVersion, \ @@ -680,20 +682,23 @@ def htmlSuspended(baseDir: str) -> str: suspendedForm+=htmlFooter() return suspendedForm -def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: str,pageNumber: int) -> str: +def htmlNewPost(translate: {},baseDir: str, \ + path: str,inReplyTo: str, \ + mentions: [], \ + reportUrl: str,pageNumber: int) -> str: """New post screen """ replyStr='' if not path.endswith('/newshare'): if not path.endswith('/newreport'): if not inReplyTo: - newPostText='

Enter your post text below.

' + newPostText='

'+translate['Write your post text below.']+'

' else: - newPostText='

Enter your reply to this post below.

' + newPostText='

'+translate['Write your reply to']+' '+translate['this post']+'

' replyStr='' else: newPostText= \ - '

Enter your report below.

' + '

'+translate['Write your report below.']+'

' # custom report header with any additional instructions if os.path.isfile(baseDir+'/accounts/report.txt'): @@ -704,9 +709,9 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st customReportText=customReportText.replace('

','

') newPostText+=customReportText - newPostText+='

This message only goes to moderators, even if it mentions other fediverse addresses.

You can also refer to points within the Terms of Service if necessary.

' + newPostText+='

'+translate['This message only goes to moderators, even if it mentions other fediverse addresses.']+'

'+translate['Also see']+' '+translate['Terms of Service']+'

' else: - newPostText='

Enter the details for your shared item below.

' + newPostText='

'+translate['Enter the details for your shared item below.']+'

' if os.path.isfile(baseDir+'/accounts/newpost.txt'): with open(baseDir+'/accounts/newpost.txt', 'r') as file: @@ -721,8 +726,8 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st scopeIcon='scope_public.png' scopeDescription='Public' - placeholderSubject='Subject or Content Warning (optional)...' - placeholderMessage='Write something...' + placeholderSubject=translate['Subject or Content Warning (optional)']+'...' + placeholderMessage=translate['Write something']+'...' extraFields='' endpoint='newpost' if path.endswith('/newunlisted'): @@ -744,23 +749,23 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st if path.endswith('/newshare'): scopeIcon='scope_share.png' scopeDescription='Shared Item' - placeholderSubject='Name of the shared item...' - placeholderMessage='Description of the item being shared...' + placeholderSubject=translate['Name of the shared item']+'...' + placeholderMessage=translate['Description of the item being shared']+'...' endpoint='newshare' extraFields= \ '
' \ - ' ' \ - ' ' \ - ' ' \ + ' ' \ + ' ' \ + ' ' \ '
' \ - '' + '' newPostForm=htmlHeader(newPostCSS) # only show the share option if this is not a reply shareOptionOnDropdown='' if not replyStr: - shareOptionOnDropdown='Share
Describe a shared item
' + shareOptionOnDropdown='Share
'+translate['Describe a shared item']+'
' mentionsStr='' for m in mentions: @@ -803,11 +808,11 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st if not reportUrl: dropDownContent= \ ' ' else: @@ -822,9 +827,9 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st ' '+scopeDescription+''+ \ dropDownContent+ \ ' ' \ - ' ' \ - ' ' \ - ' Search for emoji'+ \ + ' ' \ + ' ' \ + ' '+translate['Search for emoji']+''+ \ ' '+ \ replyStr+ \ ' ' \ @@ -832,7 +837,7 @@ def htmlNewPost(baseDir: str,path: str,inReplyTo: str,mentions: [],reportUrl: st ' ' \ ''+extraFields+ \ '
' \ - ' ' \ + ' ' \ ' ' \ '
' \ @@ -876,7 +881,8 @@ def htmlFooter() -> str: '\n' return htmlStr -def htmlProfilePosts(baseDir: str,httpPrefix: str, \ +def htmlProfilePosts(translate: {}, \ + baseDir: str,httpPrefix: str, \ authorized: bool,ocapAlways: bool, \ nickname: str,domain: str,port: int, \ session,wfRequest: {},personCache: {}, \ @@ -903,7 +909,8 @@ def htmlProfilePosts(baseDir: str,httpPrefix: str, \ break for item in outboxFeed['orderedItems']: if item['type']=='Create': - postStr=individualPostAsHtml(None,baseDir,session,wfRequest,personCache, \ + postStr=individualPostAsHtml(translate,None, \ + baseDir,session,wfRequest,personCache, \ nickname,domain,port,item,None,True,False, \ httpPrefix,projectVersion, \ False,False,False,True) @@ -915,7 +922,7 @@ def htmlProfilePosts(baseDir: str,httpPrefix: str, \ currPage+=1 return profileStr -def htmlProfileFollowing(baseDir: str,httpPrefix: str, \ +def htmlProfileFollowing(translate: {},baseDir: str,httpPrefix: str, \ authorized: bool,ocapAlways: bool, \ nickname: str,domain: str,port: int, \ session,wfRequest: {},personCache: {}, \ @@ -948,7 +955,7 @@ def htmlProfileFollowing(baseDir: str,httpPrefix: str, \ '
Page down
' return profileStr -def htmlProfileRoles(nickname: str,domain: str,rolesJson: {}) -> str: +def htmlProfileRoles(translate: {},nickname: str,domain: str,rolesJson: {}) -> str: """Shows roles on the profile screen """ profileStr='' @@ -963,19 +970,17 @@ def htmlProfileRoles(nickname: str,domain: str,rolesJson: {}) -> str: profileStr='
'+profileStr+'
' return profileStr -def htmlProfileSkills(nickname: str,domain: str,skillsJson: {}) -> str: +def htmlProfileSkills(translate: {},nickname: str,domain: str,skillsJson: {}) -> str: """Shows skills on the profile screen """ profileStr='' for skill,level in skillsJson.items(): profileStr+='
'+skill+'

' - if len(profileStr)==0: - profileStr+='

@'+nickname+'@'+domain+' has no skills assigned

' - else: + if len(profileStr)>0: profileStr='
'+profileStr+'
' return profileStr -def htmlProfileShares(nickname: str,domain: str,sharesJson: {}) -> str: +def htmlProfileShares(translate: {},nickname: str,domain: str,sharesJson: {}) -> str: """Shows shares on the profile screen """ profileStr='' @@ -984,19 +989,17 @@ def htmlProfileShares(nickname: str,domain: str,sharesJson: {}) -> str: profileStr+='

'+item['displayName']+'

' if item.get('imageUrl'): profileStr+='' - profileStr+='Item image' + profileStr+=''+translate['Item image']+'' profileStr+='

'+item['summary']+'

' - profileStr+='

Type: '+item['itemType']+' ' - profileStr+='Category: '+item['category']+' ' - profileStr+='Location: '+item['location']+'

' + profileStr+='

'+translate['Type']+': '+item['itemType']+' ' + profileStr+=''+translate['Category']+': '+item['category']+' ' + profileStr+=''+translate['Location']+': '+item['location']+'

' profileStr+='' - if len(profileStr)==0: - profileStr+='

@'+nickname+'@'+domain+' is not sharing any items

' - else: + if len(profileStr)>0: profileStr='
'+profileStr+'
' return profileStr -def htmlProfile(projectVersion: str, \ +def htmlProfile(translate: {},projectVersion: str, \ baseDir: str,httpPrefix: str,authorized: bool, \ ocapAlways: bool,profileJson: {},selected: str, \ session,wfRequest: {},personCache: {}, \ @@ -1043,10 +1046,10 @@ def htmlProfile(projectVersion: str, \ actor=profileJson['id'] if not authorized: - loginButton='
' + loginButton='
' else: - editProfileStr='' - linkToTimelineStart='' + editProfileStr='' + linkToTimelineStart='' linkToTimelineEnd='' # are there any follow requests? followRequestsFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/followrequests.txt' @@ -1073,9 +1076,9 @@ def htmlProfile(projectVersion: str, \ followApprovalsSection+='' followApprovalsSection+=''+followerHandle+'' followApprovalsSection+='' - followApprovalsSection+='' + followApprovalsSection+='' followApprovalsSection+='' - followApprovalsSection+='' + followApprovalsSection+='' followApprovalsSection+='' profileStr= \ @@ -1092,12 +1095,12 @@ def htmlProfile(projectVersion: str, \ linkToTimelineEnd+ \ '
\n' \ '
' \ - ' ' \ - ' ' \ - ' ' \ - ' ' \ - ' ' \ - ' '+ \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' '+ \ editProfileStr+ \ '
' \ '
' @@ -1109,13 +1112,14 @@ def htmlProfile(projectVersion: str, \ if selected=='posts': profileStr+= \ - htmlProfilePosts(baseDir,httpPrefix,authorized, \ + htmlProfilePosts(translate, \ + baseDir,httpPrefix,authorized, \ ocapAlways,nickname,domain,port, \ session,wfRequest,personCache, \ projectVersion) if selected=='following': profileStr+= \ - htmlProfileFollowing(baseDir,httpPrefix, \ + htmlProfileFollowing(translate,baseDir,httpPrefix, \ authorized,ocapAlways,nickname, \ domain,port,session, \ wfRequest,personCache,extraJson, \ @@ -1125,7 +1129,7 @@ def htmlProfile(projectVersion: str, \ pageNumber,maxItemsPerPage) if selected=='followers': profileStr+= \ - htmlProfileFollowing(baseDir,httpPrefix, \ + htmlProfileFollowing(translate,baseDir,httpPrefix, \ authorized,ocapAlways,nickname, \ domain,port,session, \ wfRequest,personCache,extraJson, \ @@ -1135,13 +1139,13 @@ def htmlProfile(projectVersion: str, \ pageNumber,maxItemsPerPage) if selected=='roles': profileStr+= \ - htmlProfileRoles(nickname,domainFull,extraJson) + htmlProfileRoles(translate,nickname,domainFull,extraJson) if selected=='skills': profileStr+= \ - htmlProfileSkills(nickname,domainFull,extraJson) + htmlProfileSkills(translate,nickname,domainFull,extraJson) if selected=='shares': profileStr+= \ - htmlProfileShares(nickname,domainFull,extraJson) + htmlProfileShares(translate,nickname,domainFull,extraJson) profileStr=htmlHeader(profileStyle)+profileStr+htmlFooter() return profileStr @@ -1172,9 +1176,9 @@ def individualFollowAsHtml(baseDir: str,session,wfRequest: {}, \ if authorized: for b in buttons: if b=='block': - buttonsStr+='' + buttonsStr+='' if b=='unfollow': - buttonsStr+='' + buttonsStr+='' return \ '
\n' \ @@ -1238,7 +1242,7 @@ def htmlRemplaceEmojiFromTags(content: str,tag: {}) -> str: content=content.replace(tagItem['name'],emojiHtml) return content -def addEmbeddedAudio(content: str) -> str: +def addEmbeddedAudio(translate: {},content: str) -> str: """Adds embedded audio for mp3/ogg """ if not ('.mp3' in content or '.ogg' in content): @@ -1272,11 +1276,11 @@ def addEmbeddedAudio(content: str) -> str: url=w content+='
' return content -def addEmbeddedVideo(content: str,width=400,height=300) -> str: +def addEmbeddedVideo(translate: {},content: str,width=400,height=300) -> str: """Adds embedded video for mp4/webm/ogv """ if not ('.mp4' in content or '.webm' in content or '.ogv' in content): @@ -1311,11 +1315,11 @@ def addEmbeddedVideo(content: str,width=400,height=300) -> str: url=w content+='
' return content -def addEmbeddedVideoFromSites(content: str,width=400,height=300) -> str: +def addEmbeddedVideoFromSites(translate: {},content: str,width=400,height=300) -> str: """Adds embedded videos """ if '>vimeo.com/' in content: @@ -1355,12 +1359,12 @@ def addEmbeddedVideoFromSites(content: str,width=400,height=300) -> str: return content return content -def addEmbeddedElements(content: str) -> str: +def addEmbeddedElements(translate: {},content: str) -> str: """Adds embedded elements for various media types """ - content=addEmbeddedVideoFromSites(content) - content=addEmbeddedAudio(content) - return addEmbeddedVideo(content) + content=addEmbeddedVideoFromSites(translate,content) + content=addEmbeddedAudio(translate,content) + return addEmbeddedVideo(translate,content) def followerApprovalActive(baseDir: str,nickname: str,domain: str) -> bool: """Returns true if the given account requires follower approval @@ -1374,7 +1378,9 @@ def followerApprovalActive(baseDir: str,nickname: str,domain: str) -> bool: manuallyApprovesFollowers=actorJson['manuallyApprovesFollowers'] return manuallyApprovesFollowers -def insertQuestion(nickname: str,content: str,postJsonObject: {},pageNumber: int) -> str: +def insertQuestion(translate: {}, \ + nickname: str,content: str, \ + postJsonObject: {},pageNumber: int) -> str: """ Inserts question selection into a post """ if not isQuestion(postJsonObject): @@ -1393,11 +1399,12 @@ def insertQuestion(nickname: str,content: str,postJsonObject: {},pageNumber: int if not choice.get('name'): continue content+=' '+choice['name']+'
' - content+='' + content+='' content+='
' return content -def individualPostAsHtml(pageNumber: int,baseDir: str, \ +def individualPostAsHtml(translate: {}, \ + pageNumber: int,baseDir: str, \ session,wfRequest: {},personCache: {}, \ nickname: str,domain: str,port: int, \ postJsonObject: {}, \ @@ -1584,8 +1591,8 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ attachmentStr+='
' attachmentStr+= \ '
' attachmentCtr+=1 elif mediaType=='audio/mpeg' or \ @@ -1598,8 +1605,8 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ attachmentStr+='
' attachmentStr+= \ '
' attachmentCtr+=1 attachmentStr+='' @@ -1627,7 +1634,7 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ avatarImageInPost= \ '
' \ ' ' \ - ' Avatar' \ + ' Avatar' \ '
' messageIdStr='' @@ -1638,7 +1645,7 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ avatarImageInPost= \ '
' \ ' ' \ - ' ' \ + ' ' \ '
' publishedStr=postJsonObject['object']['published'] @@ -1662,11 +1669,11 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ # don't allow announce/repeat of your own posts announceIcon='repeat_inactive.png' announceLink='repeat' - announceTitle='Repeat this post' + announceTitle=translate['Repeat this post'] if announcedByPerson(postJsonObject,nickname,fullDomain): announceIcon='repeat.png' announceLink='unrepeat' - announceTitle='Undo the repeat this post' + announceTitle=translate['Undo the repeat'] announceStr= \ '' \ '' @@ -1675,11 +1682,11 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ if not isModerationPost: likeIcon='like_inactive.png' likeLink='like' - likeTitle='Like this post' + likeTitle=translate['Like this post'] if noOfLikes(postJsonObject)>0: likeIcon='like.png' likeLink='unlike' - likeTitle='Undo the like of this post' + likeTitle=translate['Undo the like'] likeStr= \ '' \ '' @@ -1690,7 +1697,7 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ postJsonObject['object']['id'].startswith(postJsonObject['actor'])): if '/users/'+nickname+'/' in postJsonObject['object']['id']: deleteStr= \ - '' \ + '' \ '' # change the background color for DMs in inbox timeline @@ -1715,11 +1722,11 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ footerStr='
' if not isModerationPost and showRepeatIcon: if not manuallyApprovesFollowers: - footerStr+='' + footerStr+='' else: - footerStr+='' + footerStr+='' else: - footerStr+='' + footerStr+='' footerStr+='' footerStr+=announceStr+likeStr+deleteStr footerStr+=''+publishedStr+'' @@ -1727,8 +1734,8 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ if not postJsonObject['object']['sensitive']: contentStr=postJsonObject['object']['content']+attachmentStr - contentStr=addEmbeddedElements(contentStr) - contentStr=insertQuestion(nickname,contentStr,postJsonObject,pageNumber) + contentStr=addEmbeddedElements(translate,contentStr) + contentStr=insertQuestion(translate,nickname,contentStr,postJsonObject,pageNumber) else: postID='post'+str(createPassword(8)) contentStr='' @@ -1738,11 +1745,11 @@ def individualPostAsHtml(pageNumber: int,baseDir: str, \ containerClass='container report' else: contentStr+='Sensitive ' - contentStr+='' + contentStr+='' contentStr+='
' contentStr+=postJsonObject['object']['content']+attachmentStr - contentStr=addEmbeddedElements(contentStr) - contentStr=insertQuestion(nickname,contentStr,postJsonObject,pageNumber) + contentStr=addEmbeddedElements(translate,contentStr) + contentStr=insertQuestion(translate,nickname,contentStr,postJsonObject,pageNumber) contentStr+='
' if postJsonObject['object'].get('tag'): @@ -1769,7 +1776,8 @@ def isQuestion(postObjectJson: {}) -> bool: return True return False -def htmlTimeline(pageNumber: int,itemsPerPage: int,session,baseDir: str, \ +def htmlTimeline(translate: {},pageNumber: int, \ + itemsPerPage: int,session,baseDir: str, \ wfRequest: {},personCache: {}, \ nickname: str,domain: str,port: int,timelineJson: {}, \ boxName: str,allowDeletion: bool, \ @@ -1823,24 +1831,24 @@ def htmlTimeline(pageNumber: int,itemsPerPage: int,session,baseDir: str, \ if boxName!='dm': if not manuallyApproveFollowers: - newPostButtonStr='Create a new post' + newPostButtonStr=''+translate['Create a new post']+'' else: - newPostButtonStr='Create a new post' + newPostButtonStr=''+translate['Create a new post']+'' else: - newPostButtonStr='Create a new DM' + newPostButtonStr=''+translate['Create a new DM']+'' # banner and row of buttons tlStr+= \ - '' \ + '' \ '
' \ '
' \ '
\n'+ \ - ' ' \ - ' ' \ - ' '+ \ + ' ' \ + ' ' \ + ' '+ \ moderationButtonStr+newPostButtonStr+ \ - ' Search and follow'+ \ - ' Refresh'+ \ + ' '+translate['Search and follow']+''+ \ + ' '+translate['Refresh']+''+ \ followApprovals+ \ '
' @@ -1849,13 +1857,13 @@ def htmlTimeline(pageNumber: int,itemsPerPage: int,session,baseDir: str, \ tlStr+= \ '
' \ '
\n'+ \ - ' ' \ - ' ' \ - ' ' \ - ' ' \ - ' ' \ - ' ' \ - ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ '
' # add the javascript for content warnings @@ -1872,7 +1880,7 @@ def htmlTimeline(pageNumber: int,itemsPerPage: int,session,baseDir: str, \ itemCtr+=1 avatarUrl=getPersonAvatarUrl(baseDir,item['actor'],personCache) tlStr+= \ - individualPostAsHtml(pageNumber, \ + individualPostAsHtml(translate,pageNumber, \ baseDir,session,wfRequest,personCache, \ nickname,domain,port,item,avatarUrl,True, \ allowDeletion, \ @@ -1936,14 +1944,15 @@ def htmlOutbox(pageNumber: int,itemsPerPage: int, \ nickname,domain,port,outboxJson,'outbox',allowDeletion, \ httpPrefix,projectVersion,manuallyApproveFollowers) -def htmlIndividualPost(baseDir: str,session,wfRequest: {},personCache: {}, \ +def htmlIndividualPost(translate: {}, \ + baseDir: str,session,wfRequest: {},personCache: {}, \ nickname: str,domain: str,port: int,authorized: bool, \ postJsonObject: {},httpPrefix: str,projectVersion: str) -> str: """Show an individual post as html """ postStr='' postStr+= \ - individualPostAsHtml(None,baseDir,session,wfRequest,personCache, \ + individualPostAsHtml(translate,None,baseDir,session,wfRequest,personCache, \ nickname,domain,port,postJsonObject,None,True,False, \ httpPrefix,projectVersion,False,authorized,False,False) messageId=postJsonObject['id'].replace('/activity','') @@ -1956,7 +1965,7 @@ def htmlIndividualPost(baseDir: str,session,wfRequest: {},personCache: {}, \ with open(postFilename, 'r') as fp: postJsonObject=commentjson.load(fp) postStr= \ - individualPostAsHtml(None, \ + individualPostAsHtml(translate,None, \ baseDir,session,wfRequest,personCache, \ nickname,domain,port,postJsonObject, \ None,True,False, \ @@ -1975,14 +1984,15 @@ def htmlIndividualPost(baseDir: str,session,wfRequest: {},personCache: {}, \ # add items to the html output for item in repliesJson['orderedItems']: postStr+= \ - individualPostAsHtml(None, \ + individualPostAsHtml(translate,None, \ baseDir,session,wfRequest,personCache, \ nickname,domain,port,item,None,True,False, \ httpPrefix,projectVersion, \ False,authorized,False,False) return htmlHeader()+postStr+htmlFooter() -def htmlPostReplies(baseDir: str,session,wfRequest: {},personCache: {}, \ +def htmlPostReplies(translate: {},baseDir: str, \ + session,wfRequest: {},personCache: {}, \ nickname: str,domain: str,port: int,repliesJson: {}, \ httpPrefix: str,projectVersion: str) -> str: """Show the replies to an individual post as html @@ -1990,13 +2000,16 @@ def htmlPostReplies(baseDir: str,session,wfRequest: {},personCache: {}, \ repliesStr='' if repliesJson.get('orderedItems'): for item in repliesJson['orderedItems']: - repliesStr+=individualPostAsHtml(None,baseDir,session,wfRequest,personCache, \ - nickname,domain,port,item,None,True,False, \ - httpPrefix,projectVersion,False,False,False,False) + repliesStr+= \ + individualPostAsHtml(translate,None, \ + baseDir,session,wfRequest,personCache, \ + nickname,domain,port,item,None,True,False, \ + httpPrefix,projectVersion, \ + False,False,False,False) return htmlHeader()+repliesStr+htmlFooter() -def htmlRemoveSharedItem(baseDir: str,actor: str,shareName: str) -> str: +def htmlRemoveSharedItem(translate: {},baseDir: str,actor: str,shareName: str) -> str: """Shows a screen asking to confirm the removal of a shared item """ nickname=getNicknameFromActor(actor) @@ -2028,13 +2041,13 @@ def htmlRemoveSharedItem(baseDir: str,actor: str,shareName: str) -> str: sharesStr+='
' if sharedItemImageUrl: sharesStr+=' ' - sharesStr+='

Remove '+sharedItemDisplayName+' ?

' + sharesStr+='

'+translate['Remove']+' '+sharedItemDisplayName+' ?

' sharesStr+= \ '
' \ ' ' \ ' ' \ - ' ' \ - ' ' \ + ' ' \ + ' ' \ '
' sharesStr+='
' sharesStr+='
' @@ -2042,7 +2055,7 @@ def htmlRemoveSharedItem(baseDir: str,actor: str,shareName: str) -> str: sharesStr+=htmlFooter() return sharesStr -def htmlDeletePost(pageNumber: int, \ +def htmlDeletePost(translate,pageNumber: int, \ session,baseDir: str,messageId: str, \ httpPrefix: str,projectVersion: str, \ wfRequest: {},personCache: {}) -> str: @@ -2072,23 +2085,29 @@ def htmlDeletePost(pageNumber: int, \ deletePostStr=htmlHeader(profileStyle) deletePostStr+='' deletePostStr+= \ - individualPostAsHtml(pageNumber,baseDir,session,wfRequest,personCache, \ - nickname,domain,port,postJsonObject,None,True,False, \ - httpPrefix,projectVersion,False,False,False,False) + individualPostAsHtml(translate,pageNumber, \ + baseDir,session,wfRequest,personCache, \ + nickname,domain,port,postJsonObject, \ + None,True,False, \ + httpPrefix,projectVersion, \ + False,False,False,False) deletePostStr+='
' - deletePostStr+='

Delete this post?

' + deletePostStr+='

'+translate['Delete this post?']+'

' deletePostStr+= \ '
' \ ' ' \ ' ' \ - ' ' \ - ' ' \ + ' ' \ + ' ' \ '
' deletePostStr+='
' deletePostStr+=htmlFooter() return deletePostStr -def htmlFollowConfirm(baseDir: str,originPathStr: str,followActor: str,followProfileUrl: str) -> str: +def htmlFollowConfirm(translate: {},baseDir: str, \ + originPathStr: str, \ + followActor: str, \ + followProfileUrl: str) -> str: """Asks to confirm a follow """ followDomain,port=getDomainFromActor(followActor) @@ -2105,12 +2124,12 @@ def htmlFollowConfirm(baseDir: str,originPathStr: str,followActor: str,followPro followStr+='
' followStr+=' ' followStr+=' ' - followStr+='

Follow '+getNicknameFromActor(followActor)+'@'+followDomain+' ?

' + followStr+='

'+translate['Follow']+' '+getNicknameFromActor(followActor)+'@'+followDomain+' ?

' followStr+= \ '
' \ ' ' \ - ' ' \ - ' ' \ + ' ' \ + ' ' \ '
' followStr+='
' followStr+='' @@ -2118,7 +2137,10 @@ def htmlFollowConfirm(baseDir: str,originPathStr: str,followActor: str,followPro followStr+=htmlFooter() return followStr -def htmlUnfollowConfirm(baseDir: str,originPathStr: str,followActor: str,followProfileUrl: str) -> str: +def htmlUnfollowConfirm(translate: {},baseDir: str, \ + originPathStr: str, \ + followActor: str, \ + followProfileUrl: str) -> str: """Asks to confirm unfollowing an actor """ followDomain,port=getDomainFromActor(followActor) @@ -2135,12 +2157,12 @@ def htmlUnfollowConfirm(baseDir: str,originPathStr: str,followActor: str,followP followStr+='
' followStr+=' ' followStr+=' ' - followStr+='

Stop following '+getNicknameFromActor(followActor)+'@'+followDomain+' ?

' + followStr+='

'+translate['Stop following']+' '+getNicknameFromActor(followActor)+'@'+followDomain+' ?

' followStr+= \ '
' \ ' ' \ - ' ' \ - ' ' \ + ' ' \ + ' ' \ '
' followStr+='
' followStr+='' @@ -2148,7 +2170,12 @@ def htmlUnfollowConfirm(baseDir: str,originPathStr: str,followActor: str,followP followStr+=htmlFooter() return followStr -def htmlPersonOptions(baseDir: str,domain: str,originPathStr: str,optionsActor: str,optionsProfileUrl: str,optionsLink: str,pageNumber: int) -> str: +def htmlPersonOptions(translate: {},baseDir: str, \ + domain: str,originPathStr: str, \ + optionsActor: str, \ + optionsProfileUrl: str, \ + optionsLink: str, \ + pageNumber: int) -> str: """Show options for a person: view/follow/block/report """ optionsDomain,optionsPort=getDomainFromActor(optionsActor) @@ -2188,18 +2215,18 @@ def htmlPersonOptions(baseDir: str,domain: str,originPathStr: str,optionsActor: optionsStr+='
' optionsStr+=' ' optionsStr+=' ' - optionsStr+='

Options for @'+getNicknameFromActor(optionsActor)+'@'+optionsDomain+'

' + optionsStr+='

'+translate['Options for']+' @'+getNicknameFromActor(optionsActor)+'@'+optionsDomain+'

' optionsStr+= \ '
' \ ' ' \ ' ' \ ' '+ \ optionsLinkStr+ \ - ' ' \ - ' ' \ - ' ' \ - ' ' \ - ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ '
' optionsStr+='
' optionsStr+='' @@ -2207,37 +2234,43 @@ def htmlPersonOptions(baseDir: str,domain: str,originPathStr: str,optionsActor: optionsStr+=htmlFooter() return optionsStr -def htmlBlockConfirm(baseDir: str,originPathStr: str,blockActor: str,blockProfileUrl: str) -> str: - """Asks to confirm a block - """ - blockDomain,port=getDomainFromActor(blockActor) - - if os.path.isfile(baseDir+'/img/block-background.png'): - if not os.path.isfile(baseDir+'/accounts/block-background.png'): - copyfile(baseDir+'/img/block-background.png',baseDir+'/accounts/block-background.png') +#def htmlBlockConfirm(translate: {},baseDir: str, \ +# originPathStr: str, \ +# blockActor: str, \ +# blockProfileUrl: str) -> str: +# """Asks to confirm a block +# """ +# blockDomain,port=getDomainFromActor(blockActor) +# +# if os.path.isfile(baseDir+'/img/block-background.png'): +# if not os.path.isfile(baseDir+'/accounts/block-background.png'): +# copyfile(baseDir+'/img/block-background.png',baseDir+'/accounts/block-background.png') +# +# with open(baseDir+'/epicyon-follow.css', 'r') as cssFile: +# profileStyle = cssFile.read() +# blockStr=htmlHeader(profileStyle) +# blockStr+='
' +# blockStr+='
' +# blockStr+='
' +# blockStr+=' ' +# blockStr+=' ' +# blockStr+='

'+translate['Block']+' '+getNicknameFromActor(blockActor)+'@'+blockDomain+' ?

' +# blockStr+= \ +# '
' \ +# ' ' \ +# ' ' \ +# ' ' \ +# '
' +# blockStr+='
' +# blockStr+='
' +# blockStr+='
' +# blockStr+=htmlFooter() +# return blockStr - with open(baseDir+'/epicyon-follow.css', 'r') as cssFile: - profileStyle = cssFile.read() - blockStr=htmlHeader(profileStyle) - blockStr+='
' - blockStr+='
' - blockStr+='
' - blockStr+=' ' - blockStr+=' ' - blockStr+='

Block '+getNicknameFromActor(blockActor)+'@'+blockDomain+' ?

' - blockStr+= \ - '
' \ - ' ' \ - ' ' \ - ' ' \ - '
' - blockStr+='
' - blockStr+='
' - blockStr+='
' - blockStr+=htmlFooter() - return blockStr - -def htmlUnblockConfirm(baseDir: str,originPathStr: str,blockActor: str,blockProfileUrl: str) -> str: +def htmlUnblockConfirm(translate: {},baseDir: str, \ + originPathStr: str, \ + blockActor: str, \ + blockProfileUrl: str) -> str: """Asks to confirm unblocking an actor """ blockDomain,port=getDomainFromActor(blockActor) @@ -2254,12 +2287,12 @@ def htmlUnblockConfirm(baseDir: str,originPathStr: str,blockActor: str,blockProf blockStr+='
' blockStr+=' ' blockStr+=' ' - blockStr+='

Stop blocking '+getNicknameFromActor(blockActor)+'@'+blockDomain+' ?

' + blockStr+='

'+translate['Stop blocking']+' '+getNicknameFromActor(blockActor)+'@'+blockDomain+' ?

' blockStr+= \ '
' \ ' ' \ - ' ' \ - ' ' \ + ' ' \ + ' ' \ '
' blockStr+='
' blockStr+='' @@ -2267,7 +2300,8 @@ def htmlUnblockConfirm(baseDir: str,originPathStr: str,blockActor: str,blockProf blockStr+=htmlFooter() return blockStr -def htmlSearchEmojiTextEntry(baseDir: str,path: str) -> str: +def htmlSearchEmojiTextEntry(translate: {}, \ + baseDir: str,path: str) -> str: """Search for an emoji by name """ if not os.path.isfile(baseDir+'/emoji/emoji.json'): @@ -2287,12 +2321,12 @@ def htmlSearchEmojiTextEntry(baseDir: str,path: str) -> str: emojiStr+='
' emojiStr+='
' emojiStr+='
' - emojiStr+='

Enter an emoji name to search for

' + emojiStr+='

'+translate['Enter an emoji name to search for']+'

' emojiStr+= \ '
' \ ' ' \ '
' \ - ' ' \ + ' ' \ '
' emojiStr+='
' emojiStr+='
' @@ -2300,7 +2334,8 @@ def htmlSearchEmojiTextEntry(baseDir: str,path: str) -> str: emojiStr+=htmlFooter() return emojiStr -def htmlSearch(baseDir: str,path: str) -> str: +def htmlSearch(translate: {}, \ + baseDir: str,path: str) -> str: """Search called from the timeline icon """ actor=path.replace('/search','') @@ -2317,12 +2352,12 @@ def htmlSearch(baseDir: str,path: str) -> str: followStr+='' @@ -2453,7 +2489,7 @@ def htmlProfileAfterSearch(baseDir: str,path: str,httpPrefix: str, \ if not item.get('object'): continue profileStr+= \ - individualPostAsHtml(None,baseDir, \ + individualPostAsHtml(translate,None,baseDir, \ session,wfRequest,personCache, \ nickname,domain,port, \ item,avatarUrl,False,False, \