Detecting document language
Routing a document often starts with one question: what language is it in? An incoming invoice in German goes to one queue, the same form in Japanese to another — and the OCR step downstream needs the right language before it can read a single word. Language detection answers that question up front, per page, without sending anything to a server.
This sample shows how to detect the language and text direction of a document using Nutrient Java SDK. Detection runs fully offline — no network, no API keys.
Download sampleHow Nutrient helps
Nutrient Java SDK runs the full offline detection pipeline behind a single method call. The SDK handles:
- Rendering each page to a bitmap
- Identifying the writing script(s) present on the page (Latin, Cyrillic, Arabic, Han, and so on)
- Reading the page’s text in the full repertoire of those scripts, preserving diacritics and tone marks
- Identifying the specific language(s) in that text — distinguishing, for example, French from Spanish within the Latin script
- Serializing the per-page result to JSON
The result is a predicted language plus a per-page breakdown, each with its detected language(s) and text direction.
How detection works
For each page, the SDK first determines which writing scripts are present, then reads the page’s text and identifies the language. Languages are reported as ISO 639-2 three-letter codes (eng, fra, rus, vie). Right-to-left scripts (Arabic, Hebrew) report a rltb text direction; everything else reports lrtb.
Detection runs fully offline; resources for non-Latin scripts are fetched once on first use. Language detection requires the OCR feature in your license.
Detecting multiple languages and scripts
By default, detection reports the single dominant script and language of each page — the fastest path and the right choice for single-language documents. Documents that mix scripts (Cyrillic and Han on the same page) or mix languages within one script (English and French) need detection to consider more than one, so the sample raises two OCR settings before detecting:
setMaxScriptsbounds how many distinct writing scripts a page is read in.setMaxLanguagesbounds how many languages are reported.
Both default to 1. With them raised, each page’s detected languages array lists every language found, ordered most-prominent first.
Multi-page documents
Every page is detected independently and reported in its own entry, so a document whose pages are in different languages surfaces each page’s language rather than collapsing to one. The top-level predictedLanguage is the first page’s language, a convenient default for single-language documents.
Complete implementation
Specify a package name and create a new class:
package io.nutrient.Sample;Import the classes used in the sample:
import io.nutrient.sdk.Document;import io.nutrient.sdk.Vision;import io.nutrient.sdk.exceptions.NutrientException;
import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;
public class DetectDocumentLanguage {Detecting a document’s language
Open the document in a try-with-resources block so resources are cleaned up after processing, raise the script and language caps, create a vision instance bound to it with Vision.set(document), then call detectLanguages():
public static void main(String[] args) { try (Document document = Document.open("input_ocr_multiple_languages.png")) { // Read each page in up to two scripts and report up to two languages. document.getSettings().getOcrSettings().setMaxScripts(2); document.getSettings().getOcrSettings().setMaxLanguages(2);
Vision vision = Vision.set(document); String resultJson = vision.detectLanguages();
Files.writeString(Path.of("output.json"), resultJson); } catch (NutrientException | IOException e) { System.err.println("Error: " + e.getMessage()); } }}Understanding the output
detectLanguages() returns JSON with a top-level languageDetection object:
predictedLanguage— The primary detected language as an ISO 639-2 code. For a document, this is the first page’s language.textDirection— The primary text direction (lrtbleft-to-right,rltbright-to-left).pages— One entry per page, each with itspageNumber, detectedlanguages, andtextDirection.
{ "languageDetection": { "predictedLanguage": "fra", "textDirection": "lrtb", "pages": [ { "pageNumber": 1, "languages": ["fra"], "textDirection": "lrtb" } ] }}Detecting the language of text you already have
When you already have the text — an email body, a database field, your own extraction pipeline — and no file to open, skip the document entirely and call the static Vision.detectLanguagesText("…"). Nothing is opened or rendered; the text is scored directly, and the result has the same shape with an empty pages array:
{ "languageDetection": { "predictedLanguage": "rus", "textDirection": "lrtb", "pages": [] }}Error handling
Vision API raises VisionException (a NutrientException) when detection fails. Common failure scenarios include an unreadable document, a missing or unlicensed script model, or neither a document nor text supplied. In production code, catch NutrientException, return a clear error message, and log failure details for debugging.
Conclusion
The workflow for offline language detection is:
- Open the source document using try-with-resources for automatic resource cleanup.
- Raise
setMaxScripts/setMaxLanguageswhen a page mixes scripts or languages. - Create a vision instance with
Vision.set()and calldetectLanguages()to detect every page and export the result as JSON (or call the staticVision.detectLanguagesText()for text you already have). - Write the JSON to a file for routing or downstream processing.
- Handle
NutrientExceptionfor robust error recovery.
For related extraction workflows, refer to the Java SDK guides.
Download this ready-to-use sample package to explore language detection.