fix(whatsapp): admin-pinned template language + Arabic locale support (#647)
Reporter @Rekoo-PS hit three independent gaps trying to deliver an Arabic Meta template. Bundled here because they fan out from the same root cause (no first-class language config on the WhatsApp tab) and the review surfaces are tightly coupled. **1. Test send hardcoded `en_US` (`adminWhatsapp.js:141`).** Smoking gun for "I can't make it work" — Meta returned template_not_found_in_language (132001) on every test send for non-English templates, no matter what else the admin configured. Replaced with `config.template_language || 'en_US'`. **2. No `template_language` field on `whatsapp_configs`.** The only priors were per-message `data.language` (always null from our callers in `adminEvents.js:854,1188`) and `app_settings.general_default_language` (the *system UI* language, not the *template's* language registered with Meta). Migration 137 adds the column; GET + PUT surface it; the processor uses it as the highest-priority default when message_data doesn't override. Resolution order in `whatsappProcessor.processWhatsAppQueue` is now: 1. message_data.language (per-event override — caller path TBD) 2. config.template_language (admin-pinned template language) 3. app_settings.general_default_language (system fallback) 4. en_US (hardcoded last resort) **3. `LANGUAGE_MAP` + `PASSWORD_LABELS` didn't cover Arabic.** Added `ar` (Meta's single-code form per RFC; no region variant). For any language we don't enumerate (e.g. Turkish `tr_TR`, Chinese `zh_CN`, Hebrew `he_IL`), `resolveLanguageCode` now pass-throughs valid-shape codes (lowercase-language + optional underscore + uppercase-region) and forwards them to Meta as-is. If they don't match a registered template Meta returns 132001, which the test route already surfaces back to the admin via `error.message` — fail-loud, no silent fallback. Validation: - Unit smoke on `resolveLanguageCode` across 18 representative inputs (in-map, pass-through, canonicalization, rejection) — all behaviours correct. - Lint clean on all 7 changed files. - Frontend `tsc --noEmit` clean. - Migration `node -c` syntax-checked; additive + `hasColumn`-guarded so re-running is safe. Frontend: free-text input on the WhatsApp tab with EN + DE i18n. Pointing at Meta's supported-languages docs via the hint text — Meta's list grows; a hardcoded dropdown would rot. Closes #647.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Migration 137: WhatsApp template language (#647).
|
||||
*
|
||||
* Adds a `template_language` column to `whatsapp_configs` so admins can
|
||||
* pin their Meta-approved template's language code (e.g. `ar`, `en_US`,
|
||||
* `de_DE`) directly in Settings → WhatsApp. Without this column the only
|
||||
* resolution paths were per-message `data.language` (always null in our
|
||||
* own callers) and `app_settings.general_default_language` — both of
|
||||
* which are tied to the *system* UI language, not the *template's* language
|
||||
* registered with Meta. Reporter @Rekoo-PS hit this with an Arabic
|
||||
* template against the test-send route.
|
||||
*
|
||||
* Additive + hasColumn-guarded. Empty string default means "fall through
|
||||
* to general_default_language" — preserves current behaviour for installs
|
||||
* that don't set it.
|
||||
*/
|
||||
exports.up = async function (knex) {
|
||||
if (!(await knex.schema.hasTable('whatsapp_configs'))) return;
|
||||
if (await knex.schema.hasColumn('whatsapp_configs', 'template_language')) return;
|
||||
await knex.schema.alterTable('whatsapp_configs', (table) => {
|
||||
table.string('template_language', 20).notNullable().defaultTo('');
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = async function (knex) {
|
||||
if (!(await knex.schema.hasTable('whatsapp_configs'))) return;
|
||||
if (!(await knex.schema.hasColumn('whatsapp_configs', 'template_language'))) return;
|
||||
await knex.schema.alterTable('whatsapp_configs', (table) => {
|
||||
table.dropColumn('template_language');
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user