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.
🤖🧑💻 AI Agent for Top n8n Creators Leaderboard Reporting. Uses httpRequest, executeWorkflowTrigger, readWriteFile, googleDrive. Event-driven trigger; 49 nodes.
Memorybufferwindow Workflow. Uses emailSend, httpRequest, executeWorkflowTrigger, formTrigger. Event-driven trigger; 45 nodes.
Memorybufferwindow Workflow. Uses telegramTrigger, telegram, executeWorkflowTrigger, httpRequest. Event-driven trigger; 35 nodes.
W4.1 - ROUTER (State + Voice). Uses executeWorkflowTrigger, postgres, redis. Event-driven trigger; 30 nodes.
SHEETS RAG. Uses googleDriveTrigger, postgres, googleSheets, executeWorkflowTrigger. Event-driven trigger; 24 nodes.