Files
replypier/frontend/src/utils/whatsappLanguages.ts
T

159 lines
6.4 KiB
TypeScript
Raw Normal View History

/*
Copyright 2024-2026 ChatterMate
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* The languages Meta accepts for a WhatsApp message template, transcribed from
* https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates/supported-languages
*
* This list exists only to stop typos reaching Graph — Meta remains the
* authority on what it accepts, and the server passes the code through
* untouched. A language Meta adds after this was written is simply missing from
* the picker until we update it; it is never rejected by us, and a template
* already using one still displays (see languageLabel).
*
* Codes are not uniformly `xx` or `xx_YY`: `fil` and `prs_AF` have three-letter
* languages, `es_CRI` a three-letter region. Do not "tidy" them.
*/
export interface WhatsAppLanguage {
code: string
label: string
}
/** Meta's own names, kept verbatim so they can be cross-referenced against the
* Business Manager UI. Sorted by label here rather than at runtime — a sort on
* import hides the ordering from review and re-runs on every module load. */
export const WHATSAPP_LANGUAGES: readonly WhatsAppLanguage[] = [
{ code: 'af', label: 'Afrikaans' },
{ code: 'sq', label: 'Albanian' },
{ code: 'ar', label: 'Arabic' },
{ code: 'ar_EG', label: 'Arabic (EGY)' },
{ code: 'ar_LB', label: 'Arabic (LBN)' },
{ code: 'ar_MA', label: 'Arabic (MAR)' },
{ code: 'ar_QA', label: 'Arabic (QAT)' },
{ code: 'ar_AE', label: 'Arabic (UAE)' },
{ code: 'az', label: 'Azerbaijani' },
{ code: 'be_BY', label: 'Belarusian' },
{ code: 'bn', label: 'Bengali' },
{ code: 'bn_IN', label: 'Bengali (IND)' },
{ code: 'bg', label: 'Bulgarian' },
{ code: 'ca', label: 'Catalan' },
{ code: 'zh_CN', label: 'Chinese (CHN)' },
{ code: 'zh_HK', label: 'Chinese (HKG)' },
{ code: 'zh_TW', label: 'Chinese (TAI)' },
{ code: 'hr', label: 'Croatian' },
{ code: 'cs', label: 'Czech' },
{ code: 'da', label: 'Danish' },
{ code: 'prs_AF', label: 'Dari' },
{ code: 'nl', label: 'Dutch' },
{ code: 'nl_BE', label: 'Dutch (BEL)' },
{ code: 'en', label: 'English' },
{ code: 'en_AU', label: 'English (AUS)' },
{ code: 'en_CA', label: 'English (CAN)' },
{ code: 'en_GH', label: 'English (GHA)' },
{ code: 'en_IN', label: 'English (IND)' },
{ code: 'en_IE', label: 'English (IRL)' },
{ code: 'en_JM', label: 'English (JAM)' },
{ code: 'en_MY', label: 'English (MYS)' },
{ code: 'en_NZ', label: 'English (NZL)' },
{ code: 'en_QA', label: 'English (QAT)' },
{ code: 'en_SG', label: 'English (SGP)' },
{ code: 'en_AE', label: 'English (UAE)' },
{ code: 'en_UG', label: 'English (UGA)' },
{ code: 'en_GB', label: 'English (UK)' },
{ code: 'en_US', label: 'English (US)' },
{ code: 'en_ZA', label: 'English (ZAF)' },
{ code: 'et', label: 'Estonian' },
{ code: 'fil', label: 'Filipino' },
{ code: 'fi', label: 'Finnish' },
{ code: 'fr', label: 'French' },
{ code: 'fr_BE', label: 'French (BEL)' },
{ code: 'fr_CA', label: 'French (CAN)' },
{ code: 'fr_CH', label: 'French (CHE)' },
{ code: 'fr_CI', label: 'French (CIV)' },
{ code: 'fr_MA', label: 'French (MAR)' },
{ code: 'ka', label: 'Georgian' },
{ code: 'de', label: 'German' },
{ code: 'de_AT', label: 'German (AUT)' },
{ code: 'de_CH', label: 'German (CHE)' },
{ code: 'el', label: 'Greek' },
{ code: 'gu', label: 'Gujarati' },
{ code: 'ha', label: 'Hausa' },
{ code: 'he', label: 'Hebrew' },
{ code: 'hi', label: 'Hindi' },
{ code: 'hu', label: 'Hungarian' },
{ code: 'id', label: 'Indonesian' },
{ code: 'ga', label: 'Irish' },
{ code: 'it', label: 'Italian' },
{ code: 'ja', label: 'Japanese' },
{ code: 'kn', label: 'Kannada' },
{ code: 'kk', label: 'Kazakh' },
{ code: 'rw_RW', label: 'Kinyarwanda' },
{ code: 'ko', label: 'Korean' },
{ code: 'ky_KG', label: 'Kyrgyz (Kyrgyzstan)' },
{ code: 'lo', label: 'Lao' },
{ code: 'lv', label: 'Latvian' },
{ code: 'lt', label: 'Lithuanian' },
{ code: 'mk', label: 'Macedonian' },
{ code: 'ms', label: 'Malay' },
{ code: 'ml', label: 'Malayalam' },
{ code: 'mr', label: 'Marathi' },
{ code: 'nb', label: 'Norwegian' },
{ code: 'ps_AF', label: 'Pashto' },
{ code: 'fa', label: 'Persian' },
{ code: 'pl', label: 'Polish' },
{ code: 'pt_BR', label: 'Portuguese (BR)' },
{ code: 'pt_PT', label: 'Portuguese (POR)' },
{ code: 'pa', label: 'Punjabi' },
{ code: 'ro', label: 'Romanian' },
{ code: 'ru', label: 'Russian' },
{ code: 'sr', label: 'Serbian' },
{ code: 'si_LK', label: 'Sinhala' },
{ code: 'sk', label: 'Slovak' },
{ code: 'sl', label: 'Slovenian' },
{ code: 'es', label: 'Spanish' },
{ code: 'es_AR', label: 'Spanish (ARG)' },
{ code: 'es_CL', label: 'Spanish (CHL)' },
{ code: 'es_CO', label: 'Spanish (COL)' },
{ code: 'es_CRI', label: 'Spanish (CRI)' },
{ code: 'es_DO', label: 'Spanish (DOM)' },
{ code: 'es_EC', label: 'Spanish (ECU)' },
{ code: 'es_HN', label: 'Spanish (HND)' },
{ code: 'es_MX', label: 'Spanish (MEX)' },
{ code: 'es_PA', label: 'Spanish (PAN)' },
{ code: 'es_PE', label: 'Spanish (PER)' },
{ code: 'es_ES', label: 'Spanish (SPA)' },
{ code: 'es_UY', label: 'Spanish (URY)' },
{ code: 'sw', label: 'Swahili' },
{ code: 'sv', label: 'Swedish' },
{ code: 'ta', label: 'Tamil' },
{ code: 'te', label: 'Telugu' },
{ code: 'th', label: 'Thai' },
{ code: 'tr', label: 'Turkish' },
{ code: 'uk', label: 'Ukrainian' },
{ code: 'ur', label: 'Urdu' },
{ code: 'uz', label: 'Uzbek' },
{ code: 'vi', label: 'Vietnamese' },
{ code: 'zu', label: 'Zulu' },
] as const
export const DEFAULT_LANGUAGE = 'en_US'
const BY_CODE = new Map(WHATSAPP_LANGUAGES.map((language) => [language.code, language.label]))
/** The display name for a code, falling back to the code itself — a template
* may use a language Meta added after this list was written, and showing the
* raw code beats showing nothing. */
export const languageLabel = (code: string): string => BY_CODE.get(code) ?? code