The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "W_L10N_DETECT - Locale Detection & Template Rendering",
"active": false,
"settings": {
"executionTimeout": 5,
"saveManualExecutions": true
},
"nodes": [
{
"parameters": {},
"id": "l10n-trigger-01",
"name": "IN - From Core",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"language": "javascript",
"jsCode": "const e = $json;\nconst text = (e.message?.text || e.userText || '').toString();\nconst buttonId = (e.message?.buttonId || '').toString().trim();\nconst isButton = (e.message?.type === 'button');\nconst l10nEnabled = !!(e.l10n && e.l10n.enabled);\n\n// Arabic script detection (Unicode blocks)\nconst hasArabic = /[\\u0600-\\u06FF\\u0750-\\u077F\\u08A0-\\u08FF]/.test(text);\nlet responseLocale = hasArabic ? 'ar' : 'fr';\n\n// Darija (Latin-script Moroccan/Algerian Arabic)\nconst darijaPatterns = [\n 'chno kayn','chnou kayen','wach kayn','wesh kayn','ash kayn','fin menu',\n 'nchouf','warini','bghit','wakha','wah','iyeh','mzyan','zwina',\n 'kml','kammel','kmel','ncommandi','sift','salam','slm','labas'\n];\nconst lower = text.toLowerCase();\nconst isDarija = !hasArabic && darijaPatterns.some(p => lower.includes(p));\nif (isDarija && l10nEnabled) responseLocale = 'darija';\n\n// Buttons: preserve last locale\nif (l10nEnabled && isButton) {\n const prev = ((e.state && (e.state.lastResponseLocale || e.state.localePref || e.state.locale)) || '').toString().trim().toLowerCase();\n if (['ar','fr','darija'].includes(prev)) responseLocale = prev;\n}\n\n// Feature disabled: fall back to legacy\nif (!l10nEnabled) {\n responseLocale = ((e.state && (e.state.localePref || e.state.locale)) || 'fr').toString().toLowerCase();\n}\n\n// Normalize\nresponseLocale = ['ar','darija'].includes(responseLocale) ? responseLocale : 'fr';\n\n// LANG command\nconst langMatch = /^\\s*lang\\s+(fr|ar|dz)\\s*$/i.exec(text);\nlet langSwitched = false;\nlet persistLocale = false;\nif (l10nEnabled && langMatch) {\n responseLocale = langMatch[1].toLowerCase() === 'dz' ? 'darija' : langMatch[1].toLowerCase();\n langSwitched = true;\n persistLocale = true;\n}\n\n// Sticky Arabic session\nconst stickyArEnabled = !!(e.l10n && e.l10n.stickyArEnabled);\nconst stickyAr = !!(e.state && e.state.stickyAr);\nif (l10nEnabled && stickyArEnabled && !hasArabic && isDarija && stickyAr) {\n responseLocale = 'ar';\n}\n\nreturn [{ json: {\n ...e,\n _l10n: {\n responseLocale,\n hasArabic,\n isDarija,\n langSwitched,\n persistLocale,\n stickyAr\n }\n}}];"
},
"id": "l10n-detect-02",
"name": "Detect Locale",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
220,
0
]
},
{
"parameters": {
"language": "javascript",
"jsCode": "const e = $json;\nconst locale = (e._l10n?.responseLocale || 'fr');\nconst templates = (e.templates && typeof e.templates === 'object') ? e.templates : {};\nconst templateVars = (e.templateVars && typeof e.templateVars === 'object') ? e.templateVars : {};\n\nfunction renderTemplate(content, vars, allowed) {\n const v = vars && typeof vars === 'object' ? vars : {};\n const allow = Array.isArray(allowed) ? new Set(allowed.map(String)) : null;\n return (content || '').replace(/\\{\\{\\s*([a-zA-Z0-9_]+)\\s*\\}\\}/g, (_, k) => {\n const key = String(k);\n if (allow && !allow.has(key)) return '';\n const val = v[key];\n return (val === undefined || val === null) ? '' : String(val);\n }).replace(/\\{\\{[^}]+\\}\\}/g, '').trim();\n}\n\nfunction T(key, vars = {}, loc = locale, fallback = '') {\n const k = `${key}::${loc}`;\n const kfr = `${key}::fr`;\n const content = templates[k] || templates[kfr] || fallback || '';\n const allowed = templateVars[k] || templateVars[kfr] || null;\n return renderTemplate(content, vars, allowed);\n}\n\nfunction BTN(id, frTitle, arTitle, darijaTitle) {\n const title = locale === 'ar' ? arTitle : (locale === 'darija' ? (darijaTitle || frTitle) : frTitle);\n return { id, title };\n}\n\n// Attach helpers as serializable references\nreturn [{ json: {\n ...e,\n _l10n: {\n ...e._l10n,\n T_fn: 'available',\n BTN_fn: 'available',\n locale\n }\n}}];"
},
"id": "l10n-tmpl-03",
"name": "Build Template Helpers",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
0
]
}
],
"connections": {
"IN - From Core": {
"main": [
[
{
"node": "Detect Locale",
"type": "main",
"index": 0
}
]
]
},
"Detect Locale": {
"main": [
[
{
"node": "Build Template Helpers",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
W_L10N_DETECT - Locale Detection & Template Rendering. Uses executeWorkflowTrigger. Event-driven trigger; 3 nodes.
Source: https://github.com/zerAda/RestaurantAgentAutomation/blob/41a4d42dcd66e57b1e87b4750c0fd5fbf7058f68/workflows/W_L10N_DETECT.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
W4.1 - ROUTER (State + Voice). Uses executeWorkflowTrigger, postgres, redis. Event-driven trigger; 30 nodes.
[2/2] KNN classifier (lands dataset). Uses httpRequest, stickyNote, executeWorkflowTrigger. Event-driven trigger; 18 nodes.
Workflows from the webinar "Build production-ready AI Agents with Qdrant and n8n".
[3/3] Anomaly detection tool (crops dataset). Uses stickyNote, httpRequest, executeWorkflowTrigger. Event-driven trigger; 17 nodes.
Go to Settings → n8n API and create an API key Add it as credential for the Get Execution Data node Review model mappings in Standardize Names node Review pricing in Model Prices node Add Execute Work