class CommonWordsDetector {

  private final static Map<String, List<Language>> word2langs = Collections.synchronizedMap(new HashMap<>());
  private final static Pattern numberPattern = Pattern.compile("[0-9.,%-]+");
  
  private final static Language esLang = Languages.getLanguageForShortCode("es");
  private final static Language caLang = Languages.getLanguageForShortCode("ca");
  private final static Language ptLang = Languages.getLanguageForShortCode("pt");
  // but -cion can be Esperanto; ía(n) can be Galician
  private final static Pattern spanishPattern = Pattern.compile("^[a-zñ]+(ón|cion|aban|ábamos|ábais|íamos|íais|[úí]a[sn]?|úe[ns]?)$");
  private final static Pattern notSpanishPattern = Pattern.compile("^[lmndts]['’].*$|^.*(ns|[áéó].i[oa]s?)$|^.*(ss|[çàèòïâêôãõìù]|l·l).*$");
  private final static Pattern notCatalanPattern = Pattern.compile("^.*([áéó].i[oa]s?|d[oa]s)$|^.*[áâêôãõìùñ].*$");
  private final static Pattern portuguesePattern = Pattern.compile("^.*([áó]ri[oa]|ério)s?$"); // éria can be French
  private static final Pattern PUNCT_PATTERN = Pattern.compile("[(),.:;!?„“\"¡¿\\s\\[\\]{}-«»”]");
  private static final Pattern CHARS_PATTERN = Pattern.compile("\\p{L}+$");
  private static final Pattern SPACE_OR_HYPHEN_PATTERN = Pattern.compile("[ -]");

  public CommonWordsDetector() throws IOException {
    synchronized (word2langs) {
      if (word2langs.isEmpty()) {
        for (Language lang : Languages.get()) {
          if (lang.isVariant() &&
              !lang.getShortCode().equals("no")) {  // ugly hack to quick fix https://github.com/languagetooler-gmbh/languagetool-premium/issues/822 
            continue;
          }
          ResourceDataBroker dataBroker = JLanguageTool.getDataBroker();
          String path = lang.getCommonWordsPath();
          InputStream stream = null;
          try {
            if (path != null) {
              if (dataBroker.resourceExists(path)) {
                stream = dataBroker.getFromResourceDirAsStream(path);
              } else if (new File(path).exists()) {
                stream = new FileInputStream(path);
              } else {
                throw new IOException("Common words file not found for " + lang + ": " + path);
              }
            } else {
              if (!lang.getShortCode().matches("ja|km")) {
                System.out.println("WARN: no common words file defined for " + lang + " - this language might not be correctly auto-detected");
              }
              continue;
            }
            try (Scanner scanner = new Scanner(stream, "utf-8")) {
              while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                if (line.isEmpty() || line.startsWith("#")) {
                  continue;
                }
                String key = line.toLowerCase();
                if (key.length() == 1 && Character.isSpaceChar(key.charAt(0))) {
                  continue;
                }
                List<Language> languages = word2langs.get(key);
                if (languages == null) {
                  // word2langs is static, so this can be accessed from multiple threads concurrently -> prevent exceptions
                  List<Language> l = Collections.synchronizedList(new LinkedList<>());
                  l.add(lang);
                  word2langs.put(key, l);
                } else {
                  if (!languages.contains(lang)) {
                    languages.add(lang);
                  }
                }
              }
            }
          } finally {
            if (stream != null) {
              stream.close();
            }
          }
        }
      }
    }
  }

  public Map<Language, Integer> getKnownWordsPerLanguage(String text) {<FILL_FUNCTION_BODY>}
  
}

    Map<Language,Integer> result = new HashMap<>();
    String auxText = PUNCT_PATTERN.matcher(text).replaceAll(" ");
    if (!auxText.endsWith(" ") && StringUtils.countMatches(auxText, " ") > 0) {
      // last word might not be finished yet, so ignore
      auxText = CHARS_PATTERN.matcher(auxText).replaceFirst("");
    }
    // Proper per-language tokenizing might help, but then the common_words.txt
    // will also need to be tokenized the same way. Also, this is quite fast.
    String[] words = SPACE_OR_HYPHEN_PATTERN.split(auxText);
    for (String word : words) {
      if (numberPattern.matcher(word).matches()) {
        continue;
      }
      String lcWord = word.toLowerCase();
      List<Language> languages = word2langs.get(lcWord);
      if (languages != null) {
        for (Language lang : languages) {
          //System.out.println(lcWord + " -> " + lang);
          result.put(lang, result.getOrDefault(lang, 0) + 1);
        }
      }
      //Portuguese
      if ((languages == null || !languages.contains(ptLang)) && portuguesePattern.matcher(lcWord).matches()) {
        result.put(ptLang, result.getOrDefault(ptLang, 0) + 1);
      }
      //Spanish
      if ((languages == null || !languages.contains(esLang)) && spanishPattern.matcher(lcWord).matches()) {
        result.put(esLang, result.getOrDefault(esLang, 0) + 1);
      }
      if ((languages == null || !languages.contains(esLang)) && notSpanishPattern.matcher(lcWord).matches()) {
        result.put(esLang, result.getOrDefault(esLang, 0) - 1);
      }
      //Catalan
      if ((languages == null || !languages.contains(caLang)) && notCatalanPattern.matcher(lcWord).matches()) {
        result.put(caLang, result.getOrDefault(caLang, 0) - 1);
      }
    }
    //System.out.println("==> " + result);
    return result;
  
<no_super_class>