|
Documentation
Book a DemoPlatform
PlatformMCPCLIAPI
Workflows
GuidesChangelog

Welcome

  • Overview
  • Authentication
  • Errors & status codes
  • Webhook signatures

Localization

  • Overview
  • Create jobs
  • Lock non-translatable keys
  • Track a job group
  • Get a single job
  • List jobs
  • Webhook delivery
  • Live progress (WebSocket)

Pipeline

  • Overview
  • Pre-localization AI edit
  • Human review
  • AI review (post-edit)
  • Rephrase for natural copy
  • Back-translation check
  • Configure the pipeline
  • Observe pipeline runs

Provisioning

  • Overview
  • Create a provisioning job
  • Source types
  • What the AI extracts
  • Webhook delivery
  • Live progress (WebSocket)

Synchronous

  • Localize
  • Recognize

Engine management

  • Engine Suggestions

Recognize

You have a piece of text and no reliable record of what language it is in – a comment a user typed, a string from an uploaded file, the body of an inbound support ticket. Before you can route it, translate it, or even render it correctly, you need its locale: which language, which region, which script, and which way it reads. Recognize closes that gap in one call. You send the text; you get back a structured locale identity, as specific as the text allows.

This page covers the whole endpoint – the request, the response and every field it returns, the language bindings, and what the response does when the text doesn't pin down a region or script. It is a synchronous call: you POST text, the request blocks while it analyzes the text, and the answer comes back in the same round-trip. Authentication is the shared X-API-Key header – see Authentication for how keys work – and any error follows the standard error model.

Request#

text
POST /process/recognize
ParameterTypeDescription
textstringThe text to analyze
labelLocalestring (optional)Locale for the human-readable label (default: en)

Only text is required. labelLocale controls the language of the human-readable label in the response – set it to de and the label for a French input comes back in German instead of English. It does not change what gets detected, only how the result is named back to you.

json
{
  "text": "Bonjour le monde",
  "labelLocale": "en"
}

Response#

json
{
  "locale": "fr",
  "language": "fr",
  "region": null,
  "script": null,
  "label": "French",
  "direction": "ltr"
}
FieldTypeDescription
localestringBCP-47 locale code at the most specific level of confidence
languagestringISO 639 language subtag
regionstring | nullISO 3166 region subtag, or null if indistinguishable
scriptstring | nullISO 15924 script subtag, or null if default for the language
labelstringHuman-readable locale name in the requested labelLocale
direction"ltr" | "rtl"Text direction

Two things in that shape are worth reading closely, because they are what make the result usable rather than just informative.

First, every code is a published standard, not a Lingo.dev invention. The locale is BCP-47; language is an ISO 639 subtag; region is ISO 3166; script is ISO 15924. So whatever you already use to parse locales – your i18n library, an Intl call, a CLDR lookup – consumes this output directly. You are not adapting to a proprietary code system; you are getting the same identifiers the rest of your stack already speaks.

Second, region and script are nullable on purpose. They come back filled only when the text actually demonstrates them – which is the subject of the next two sections, and the property that keeps the endpoint from guessing.

Region and script are returned only when the text shows them#

The obvious worry about any language detector is that it over-reaches: that it will stamp a region or a writing system onto text that never proved one, and you build logic on a guess. Recognize does the opposite. It reports a subtag only when the evidence supports it, and returns null when it does not.

When regional markers are present in the text – Brazilian Portuguese vocabulary, say – the response includes the full tag (pt-BR). When the regional variant is indistinguishable, only the language subtag is returned (pt):

json
{
  "locale": "pt-BR",
  "language": "pt",
  "region": "BR",
  "script": null,
  "label": "Portuguese (Brazil)",
  "direction": "ltr"
}
json
{
  "locale": "pt",
  "language": "pt",
  "region": null,
  "script": null,
  "label": "Portuguese",
  "direction": "ltr"
}

Same language, two honest answers. The first text carried enough to name the region; the second did not, so region is null and the locale collapses to pt. script follows the same rule from the other direction: it is null when the writing system is the default for the language – Latin for French, for instance – and named only when the script is the distinguishing fact.

A null is information, not a gap

region: null does not mean detection failed. It means the text did not contain enough to distinguish a region, so the endpoint declined to invent one – and locale is the language subtag alone. Read it as "as specific as the text allows": branch on locale and let null route you to the language-level default rather than treating it as an error.

This is why locale is the field to build on. It is always the most specific tag the text supports – pt-BR when the evidence is there, pt when it is not – so reading locale gives you the right granularity automatically, without you having to reassemble it from the parts or second-guess a confident-looking region that was really a guess.

direction is there so you can render before you translate#

Language detection is rarely the end goal – usually you detect in order to do something with the text, and the first thing you often do is show it. direction is in the response for exactly that: it tells you whether the text reads left-to-right or right-to-left, so you can set dir="rtl", pick a layout, or choose a font before any translation step. Arabic text comes back "rtl"; the French example above comes back "ltr". You do not have to maintain your own language-to-direction table – the endpoint that identifies the language also hands you the one rendering fact you need first.

Examples#

A single POST with the text and an optional labelLocale. The response is the structured locale object above.

javascript
const response = await fetch(
  "https://api.lingo.dev/process/recognize",
  {
    method: "POST",
    headers: {
      "X-API-Key": "your_api_key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      text: "Bonjour le monde",
      labelLocale: "en",
    }),
  }
);

const result = await response.json();
// { locale: "fr", language: "fr", label: "French", direction: "ltr", ... }

Next steps#

The common reason to detect a language is to act on it – most often, to translate it. Recognize tells you the source locale; the localization endpoints take it from there.

Localize
Feed the detected locale straight into a single-request translation through your configured engine.
Async Localization API
Detected one source locale, need many targets? Fan one request out to up to 100 locales.
API Keys
Generate and manage the organization-scoped key this call authenticates with.

Was this page helpful?

Max PrilutskiyMax Prilutskiy·Updated 3 days ago·6 min read