[object Object]

A French-speaking customer lands on your English chat widget, types “Bonjour, j’ai un problème avec ma facture”, and gets routed to an English-speaking agent who replies in stilted Google Translate French. The customer abandons. Language routing in Freshchat looks like a settings problem. It is actually a detection-with-fallback problem, and the failure modes are subtle.

The three signals you have

Three places to learn the visitor’s language, ranked by reliability:

  1. Explicit selection — visitor clicked a language toggle on the widget or your site. Highest confidence. Use first.
  2. Conversation content — what they actually typed. High confidence once you have 5+ words. Requires NLP.
  3. Browser hintsAccept-Language header, geolocation. Low confidence. Visitors travel, share devices, use VPNs.

The routing pipeline uses all three with descending weight.

The pipeline

1. If visitor has explicit lang preference -> route to that pool
2. Else, if first message > 10 chars -> NLP detect, route to detected pool
3. Else, if Accept-Language header -> route to header lang pool
4. Else -> route to English pool (or your largest pool)
5. Always offer an in-chat language switcher

Step 5 is the safety net. Detection is never 100%. The visitor must be one click away from saying “actually, route me to Spanish”.

NLP detection that does not embarrass you

Out-of-the-box language detection libraries struggle with three-to-five word messages, code-switching (“hi can u help me con mi cuenta”), and named entities (a sentence that is mostly an email address and a product name). Freddy on Freshchat handles this reasonably well but is not infallible.

Defensive rules to layer on top:

  • Require minimum 10 characters of natural language before trusting detection. Below that, fall back to the next signal.
  • Score detection confidence. If under 0.8, do not auto-route — present a language confirmation prompt.
  • Code-switch detection: if the message contains tokens from two languages, route to the most-represented one but tag the conversation code_switch_observed for analytics.
async function classifyLanguage(message) {
  const stripped = message
    .replace(/\S+@\S+\.\S+/g, '')
    .replace(/https?:\/\/\S+/g, '')
    .replace(/[0-9]+/g, '')
    .trim();

  if (stripped.length < 10) return { lang: null, confidence: 0, reason: 'too_short' };

  const result = await freddyDetect(stripped);
  if (result.confidence < 0.8) {
    return { lang: result.lang, confidence: result.confidence, reason: 'low_confidence' };
  }
  return { lang: result.lang, confidence: result.confidence, reason: 'ok' };
}

Pre-cleaning matters. A message that is 60% an email address and 40% Spanish should classify on the Spanish part.

Routing pools

In IntelliAssign, build one routing pool per supported language. Agents tagged with their language proficiencies. A pool labelled lang:fr contains every agent with French fluency at a working level. Some agents are in multiple pools (a bilingual agent is in both lang:fr and lang:en).

Workload weighting matters here. If your French pool has 4 agents and English has 40, a small bias in detection toward English starves the French team. Configure IntelliAssign to balance within the language pool, not across. See freshchat-intelliassign-routing for the workload-weighting mechanics.

The off-hours problem

Your French team works 09:00–18:00 Paris time. A French customer chats at 23:00. What happens?

Three options, ranked:

  1. Bot triage with deferred handoff — bot collects context, promises follow-up by 10:00 next day, sends email summary. Works if the visitor has email.
  2. Cross-language coverage with disclaimer — route to the English team with a clear “your usual French team is offline, we can help in English now” message. Honest, often acceptable.
  3. Machine translation bridge — agent types English, system translates to French in transit. Tempting, frequently terrible, and customers usually notice. Avoid unless you have measured quality on real conversations.

Default to option 1 for B2B. Default to option 2 for B2C consumer apps where immediacy matters more than language match.

Override mechanism

The in-chat language switcher is a small dropdown or set of flag icons in the widget header. Click changes the routing pool for the active conversation. Importantly, click does not start the conversation over — it transfers the existing thread, preserving message history.

Wire the switcher as a postback action on a quick reply or as a custom button in the widget header. When triggered:

{
  "action": "transfer_conversation",
  "target_pool": "lang:de",
  "transfer_message": "Transferring to a German-speaking agent. Please wait a moment.",
  "preserve_history": true,
  "audit_event": "manual_lang_switch"
}

The audit event matters. Frequent manual switches from the same detected language to a different one is a signal that your detector or routing has a bug. Surface those switches in a weekly report.

Greeting in the right language

The first message the bot or welcome workflow sends should be in the detected language — even before routing. A visitor on a French IP getting an English “Hi! How can we help?” is already feeling unwelcome. Hold the greeting until after step 1–3 above complete.

If detection is unsure, send a bilingual greeting:

Bonjour ! Comment pouvons-nous vous aider ?
Hi! How can we help?
[Continue in: Français | English]

Three lines, both languages, explicit choice. Choose-your-own works because it converts the ambiguity into the visitor’s preference, which is the highest-quality signal anyway.

Analytics on language distribution

A monthly report on conversation language distribution catches drift:

  • Total conversations by detected language.
  • Manual override rate per language (high = detection problem).
  • Off-hours conversation share per language (informs staffing).
  • Resolution time variance by language (might reveal an undersized pool).

If lang:pt accounts for 6% of conversations but you have one part-time Portuguese-speaking agent, you have a quality risk that wait times are about to expose.

When to add a new language

Three criteria. Add a language when:

  • It accounts for over 3% of detected conversations for two consecutive months.
  • Manual override into that language is over 1% of all conversations.
  • A geographic market expansion has been announced for the next two quarters.

Below 3% you cannot staff it sustainably, the agent’s skills degrade, and quality suffers. Better to gracefully translate or defer than to half-support.

See freshdesk-multilingual-support-setup for the ticket-side equivalent of the same decision framework.

Bottom line

Language routing is detection plus fallback plus override. Trust explicit selection first, NLP next, headers last, and always offer a one-click switcher. Build per-language pools with workload-aware routing, plan for off-hours, and audit manual overrides. The visitor who feels heard in their language stays. The one who gets translated badly leaves and writes a review.

[object Object]
Share