public static void translateParagraph(final Translator translator, final OfflineTranslateUtils.Status status, final String text, final Consumer<String> consumer, final Consumer<Exception> errorConsumer) {
        final Document document = Jsoup.parseBodyFragment(text);
        final List<TextNode> elements = document.children().select("*").textNodes();
        final AtomicInteger remaining = new AtomicInteger(elements.size());
        if (remaining.get() == 0) {
            consumer.accept("");
            status.updateProgress();
        } else {
            for (TextNode textNode : elements) {
                translator.translate(textNode.text())
                        .addOnSuccessListener(translation -> {
                            textNode.text(translation);
                            // check if all done
                            if (remaining.decrementAndGet() == 0) {
                                consumer.accept(document.body().html());
                                status.updateProgress();
                            }
                        })
                        .addOnFailureListener(e -> {
                            Log.e("err: " + e.getMessage());
                            status.abortTranslation();
                            errorConsumer.accept(e);
                        });
            }
        }
    }
Utility method to get a Translator object that can be used to perform offline translation
@param activity      the calling activity
@param sourceLng     language to translate from
@param unsupportedLngConsumer    returned if the sourceLng is not supported
@param downloadingModelConsumer  returned if language models need to be downloaded, should be used to show a progress UI to the user
@param translatorConsumer        returns the translator object
main/src/main/java/cgeo/geocaching/utils/OfflineTranslateUtils.java