I am looking for a simple tool that would check text for terminology based on a replacement list.

Example of a replacement definition:

  • allowed: application
  • disallowed: app; consider: application
  • disallowed: program; consider: application
  • allowed: bonus program
  • disallowed: bounty program; consider: bonus program

Example text:

Our app supports the bounty program.


error: app
error: bounty program

Suggested text:

Our application supports the bonus program.


error: program

Note how the software has to consider longer terms over short terms, otherwise there would be too many false positives.


  • simple editing of the replacement list with free tools or Microsoft Office
  • machine readable format of the replacement list so that we can write tools that support the workflow
  • run on Windows
  • is free / open source
  • finds errors as explained above
  • color highlighting
    • red: error
    • green: recognized term
    • I'm looking for some sort of report, not a modification of the original file. It may be a temporary report displayed on the screen. No need to be saved.
  • makes suggestions as explained above
  • if multiple suggestions apply, let the user choose which one to take

I have already tried:

  • TermXAct (German), but a) it's commercial and b) does not prefer long terms over short ones and c) is not feaure-complete
  • "Color highlighting" — Are you asking for an output document (a report) that has this highlighting, or for the original document to be modified to use this highlighting? May 29, 2017 at 0:23
  • @Kodiologist: thanks for the question. I'm looking for some sort of report. It may be a temporary report displayed on the screen. No need to be saved. May 29, 2017 at 9:28

1 Answer 1


Here's how to do it in Python 3. This program has all the requested features except for color highlighting, because the Win32 console only supports color as of the Threshold 2 Update for Windows 10. Most of the complexity of the program is for handling the case of multiple suggestions.

 import sys, re, collections

 context_size = 30

 defs_path, doc_path = sys.argv[1:]

 defs = collections.defaultdict(list)
 with open(defs_path, 'rt') as o:
     for l in o:
         bad, _, good = l.strip().partition(' -> ')

 with open(doc_path, 'rt') as o:
     doc = o.read()

 def replacement_f(m):
     print('\nerror:', m.group())
     candidates = defs[m.group()]
     if len(candidates) == 1:
         print('Replacing with:', candidates[0])
         return candidates[0]
     print('There are multiple possible replacements.')
     print('Context:', re.sub(r'\s+', ' ', doc[
         max(m.start() - context_size, 0) :
         min(m.start() + context_size, len(doc))]))
     print('Candidates:', dict(enumerate(candidates)))
     while True:
        n = input('Enter a number: ')
        if n.isdigit() and int(n) < len(candidates):
            return candidates[int(n)]
 doc = re.sub(
     '|'.join(re.escape(bad) for bad in
         sorted(defs.keys(), key = len, reverse = True)),


Now suppose you have a file defs.txt like this:

app -> application
program -> application
bounty program -> bonus program
supports -> can use
supports -> has support for

and a file input.txt like this:

Our app supports the bounty program.

If the Python program is named script.py, you can run it with the command:

python3 script.py defs.txt input.txt

The result looks like this:

error: app
Replacing with: application

error: supports
There are multiple possible replacements.
Context: Our app supports the bounty program. 
Candidates: {0: 'can use', 1: 'has support for'}
Enter a number: 0

error: bounty program
Replacing with: bonus program


Our application can use the bonus program.
  • Wow, I knew it wasn't that hard to implement, but I'm surprised how short it actually can be. I'm in a training for the next 3 days. I will try the solution when I'm back in the office, May 29, 2017 at 19:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.