Skip to content

Commit

Permalink
Generate separate JSON cache file per application
Browse files Browse the repository at this point in the history
  • Loading branch information
Yannick Plassiard committed Mar 18, 2019
1 parent 3915958 commit 5530d3d
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 32 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
Make NVDA translate any spoken text to the desired language.
## Installation

This add-on installs like any other add-un: Press enter on the "translate-x.y.nvda-addon" file, and answer "Yes" to all questions asked.
This add-on installs like any other add-un: Press enter on the "translate-x.y.nvda-addon" file, and answer "Yes" to all asked questions.

## Usage
When installed, the add-on will detect the language your NVDA installation is set to, or will get the Windows active language as a fallback. This language will be used to translate any spoken text, when the feature is activated.
**Note:** Iit is currently not possible to set this manually within a Preferences dialog, this may however be implemented in a future release.
**Note:** It is currently not possible to set this manually within a Preferences dialog, this may however be implemented in a future release.

Then, to enable or disable the translation, press NVDA+Shift+Control+T. This gesture can be modified within NVDA Preferences menu -> Command Gestures dialog.

Expand All @@ -18,6 +18,8 @@ When active, the add-on will intercept any spoken text and connect to the Google

Please, be aware that when the feature is active, any spoken text is sent to the Google Translate service. It means that any spoken information will be sent, whatever this could be (a simple sentence, file names within your Windows Explorer, mail content, contacts, phone numbers, or even credit card numbers). It is therefore important to activate this feature only when you're certain of which text your NVDA will speak. This module has been primarily developed to be used within games, so no privacy concerns are present. You're free to used it with whatever you want, but at your own risks.

Final note: It is not planned to implement a filter function that would prevent the translation of sensitive information, as it is quite hard to guess what may be considered sensitive. It's therefore the responsibility of the user to deactivate the feature when using sensitive data; the add-on author(s) may not be responsible for translating any sensitive, private, or confidential data.

## About Performances
You may notice that when the feature is active, there is a delay between each spoken text. This is due to the translate API: because the add-on do not use the non-free Google Translate API SDK, an HTTP connection is made each and every time a text has to be translated. Therefore, a 8mbps Internet connection is recommended for this feature to work correctly.
Of course, the more bandwidth you have, the faster the translation will happen.
Expand Down
83 changes: 54 additions & 29 deletions addon/globalPlugins/translate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@



import os, sys, time, io
import os, sys, time, io, re
import globalVars
import globalPluginHandler, logHandler
import api, globalVars, controlTypes
Expand Down Expand Up @@ -46,22 +46,29 @@ def translate(text):
"""
global _translationCache, _enableTranslation, _gpObject

try:
appName = globalVars.focusObject.appModule.appName
except:
appName = "__global__"

if _gpObject is None or _enableTranslation is False:
return None
msg = "Cache Dump:\n"
for key in _translationCache:
msg += " %s => %s\n" %(key, _translationCache[key])
logHandler.log.debugWarning(msg)
translated = _translationCache.get(text, None)
return text
appTable = _translationCache.get(appName, None)
if appTable is None:
_translationCache[appName] = {}
translated = _translationCache[appName].get(text, None)
if translated is not None:
return translated
try:
prepared = text.encode('utf8', ':/')
translated = mtranslate.translate(prepared, _gpObject.language)
except Exception as e:
_translationCache[text] = text
_translationCache[appName][text] = text
return text
_translationCache[text] = translated
if translated is None or len(translated) == 0:
translated = text

_translationCache[appName][text] = translated
return translated


Expand Down Expand Up @@ -275,29 +282,47 @@ def terminate(self):
def loadLocalCache(self):
global _translationCache

path = os.path.join(globalVars.appArgs.configPath, "translation-cache.json")
try:
cacheFile = io.FileIO(path, "r")
except:
return
try:
values = json.load(cacheFile)
cacheFile.close()
except Exception as e:
logHandler.log.error("Cannot read or decode data from {path}: {e}".format(path=path, e=e))
return
_translationCache = values
path = os.path.join(globalVars.appArgs.configPath, "translation-cache")
# Checks that the storage path exists or create it.
if os.path.exists(path) is False:
try:
os.mkdir(path)
except Exception as e:
logHandler.log.error("Failed to create storage path: {path} ({error})".format(path=path, error=e))
return

# Scan stored files and load them.

for entry in os.listdir(path):
m = re.match("(.*)\.json$", entry)
if m is not None:
appName = m.group(1)

try:
cacheFile = io.FileIO(os.path.join(path, entry))
except:
return
try:
values = json.load(cacheFile)
cacheFile.close()
except Exception as e:
logHandler.log.error("Cannot read or decode data from {path}: {e}".format(path=path, e=e))
continue
_translationCache[appName] = values
def saveLocalCache(self):
global _translationCache

path = os.path.join(globalVars.appArgs.configPath, "translation-cache.json")
try:
cacheFile = io.FileIO(path, "w")
json.dump(_translationCache, cacheFile)
cacheFile.close()
except Exception as e:
logHandler.log.error("Failed to save translation cache to {file}: {error}".format(file=path, error=e))
return
path = os.path.join(globalVars.appArgs.configPath, "translation-cache")
for appName in _translationCache:
file = os.path.join(path, "%s.json" %(appName))
try:
cacheFile = io.FileIO(file, "w")
json.dump(_translationCache[appName], cacheFile)
cacheFile.close()
except Exception as e:
logHandler.log.error("Failed to save translation cache for {app} to {file}: {error}".format(apap=appName, file=file, error=e))
continue




Expand Down
2 changes: 1 addition & 1 deletion buildVars.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"addon_description" : _("""Uses the Google Translate API to translate each spoken text to the desired language, on the fly.
This add-on requires an internet connection."""),
# version
"addon_version" : "2019.03.1",
"addon_version" : "2019.03.3",
# Author(s)
"addon_author" : u"Yannick PLASSIARD <podcastcecitek@gmail.com>",
# URL for the add-on documentation support
Expand Down

0 comments on commit 5530d3d

Please sign in to comment.