UNPKG

react-i18next

Version:

Internationalization for react done right. Using the i18next i18n ecosystem.

265 lines (250 loc) 5.25 kB
/** * Common HTML entities map for fast lookup */ const commonEntities = { // Basic entities '&nbsp;': '\u00A0', // Non-breaking space '&amp;': '&', '&lt;': '<', '&gt;': '>', '&quot;': '"', '&apos;': "'", // Copyright, trademark, and registration '&copy;': '©', '&reg;': '®', '&trade;': '™', // Punctuation '&hellip;': '…', '&ndash;': '–', '&mdash;': '—', '&lsquo;': '\u2018', '&rsquo;': '\u2019', '&sbquo;': '\u201A', '&ldquo;': '\u201C', '&rdquo;': '\u201D', '&bdquo;': '\u201E', '&dagger;': '†', '&Dagger;': '‡', '&bull;': '•', '&prime;': '′', '&Prime;': '″', '&lsaquo;': '‹', '&rsaquo;': '›', '&sect;': '§', '&para;': '¶', '&middot;': '·', // Spaces '&ensp;': '\u2002', '&emsp;': '\u2003', '&thinsp;': '\u2009', // Currency '&euro;': '€', '&pound;': '£', '&yen;': '¥', '&cent;': '¢', '&curren;': '¤', // Math symbols '&times;': '×', '&divide;': '÷', '&minus;': '−', '&plusmn;': '±', '&ne;': '≠', '&le;': '≤', '&ge;': '≥', '&asymp;': '≈', '&equiv;': '≡', '&infin;': '∞', '&int;': '∫', '&sum;': '∑', '&prod;': '∏', '&radic;': '√', '&part;': '∂', '&permil;': '‰', '&deg;': '°', '&micro;': 'µ', // Arrows '&larr;': '←', '&uarr;': '↑', '&rarr;': '→', '&darr;': '↓', '&harr;': '↔', '&crarr;': '↵', '&lArr;': '⇐', '&uArr;': '⇑', '&rArr;': '⇒', '&dArr;': '⇓', '&hArr;': '⇔', // Greek letters (lowercase) '&alpha;': 'α', '&beta;': 'β', '&gamma;': 'γ', '&delta;': 'δ', '&epsilon;': 'ε', '&zeta;': 'ζ', '&eta;': 'η', '&theta;': 'θ', '&iota;': 'ι', '&kappa;': 'κ', '&lambda;': 'λ', '&mu;': 'μ', '&nu;': 'ν', '&xi;': 'ξ', '&omicron;': 'ο', '&pi;': 'π', '&rho;': 'ρ', '&sigma;': 'σ', '&tau;': 'τ', '&upsilon;': 'υ', '&phi;': 'φ', '&chi;': 'χ', '&psi;': 'ψ', '&omega;': 'ω', // Greek letters (uppercase) '&Alpha;': 'Α', '&Beta;': 'Β', '&Gamma;': 'Γ', '&Delta;': 'Δ', '&Epsilon;': 'Ε', '&Zeta;': 'Ζ', '&Eta;': 'Η', '&Theta;': 'Θ', '&Iota;': 'Ι', '&Kappa;': 'Κ', '&Lambda;': 'Λ', '&Mu;': 'Μ', '&Nu;': 'Ν', '&Xi;': 'Ξ', '&Omicron;': 'Ο', '&Pi;': 'Π', '&Rho;': 'Ρ', '&Sigma;': 'Σ', '&Tau;': 'Τ', '&Upsilon;': 'Υ', '&Phi;': 'Φ', '&Chi;': 'Χ', '&Psi;': 'Ψ', '&Omega;': 'Ω', // Latin extended '&Agrave;': 'À', '&Aacute;': 'Á', '&Acirc;': 'Â', '&Atilde;': 'Ã', '&Auml;': 'Ä', '&Aring;': 'Å', '&AElig;': 'Æ', '&Ccedil;': 'Ç', '&Egrave;': 'È', '&Eacute;': 'É', '&Ecirc;': 'Ê', '&Euml;': 'Ë', '&Igrave;': 'Ì', '&Iacute;': 'Í', '&Icirc;': 'Î', '&Iuml;': 'Ï', '&ETH;': 'Ð', '&Ntilde;': 'Ñ', '&Ograve;': 'Ò', '&Oacute;': 'Ó', '&Ocirc;': 'Ô', '&Otilde;': 'Õ', '&Ouml;': 'Ö', '&Oslash;': 'Ø', '&Ugrave;': 'Ù', '&Uacute;': 'Ú', '&Ucirc;': 'Û', '&Uuml;': 'Ü', '&Yacute;': 'Ý', '&THORN;': 'Þ', '&szlig;': 'ß', '&agrave;': 'à', '&aacute;': 'á', '&acirc;': 'â', '&atilde;': 'ã', '&auml;': 'ä', '&aring;': 'å', '&aelig;': 'æ', '&ccedil;': 'ç', '&egrave;': 'è', '&eacute;': 'é', '&ecirc;': 'ê', '&euml;': 'ë', '&igrave;': 'ì', '&iacute;': 'í', '&icirc;': 'î', '&iuml;': 'ï', '&eth;': 'ð', '&ntilde;': 'ñ', '&ograve;': 'ò', '&oacute;': 'ó', '&ocirc;': 'ô', '&otilde;': 'õ', '&ouml;': 'ö', '&oslash;': 'ø', '&ugrave;': 'ù', '&uacute;': 'ú', '&ucirc;': 'û', '&uuml;': 'ü', '&yacute;': 'ý', '&thorn;': 'þ', '&yuml;': 'ÿ', // Special characters '&iexcl;': '¡', '&iquest;': '¿', '&fnof;': 'ƒ', '&circ;': 'ˆ', '&tilde;': '˜', '&OElig;': 'Œ', '&oelig;': 'œ', '&Scaron;': 'Š', '&scaron;': 'š', '&Yuml;': 'Ÿ', '&ordf;': 'ª', '&ordm;': 'º', '&macr;': '¯', '&acute;': '´', '&cedil;': '¸', '&sup1;': '¹', '&sup2;': '²', '&sup3;': '³', '&frac14;': '¼', '&frac12;': '½', '&frac34;': '¾', // Card suits '&spades;': '♠', '&clubs;': '♣', '&hearts;': '♥', '&diams;': '♦', // Miscellaneous '&loz;': '◊', '&oline;': '‾', '&frasl;': '⁄', '&weierp;': '℘', '&image;': 'ℑ', '&real;': 'ℜ', '&alefsym;': 'ℵ', }; // Create regex pattern for all entities const entityPattern = new RegExp( Object.keys(commonEntities) .map((entity) => entity.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) .join('|'), 'g', ); /** * Decode HTML entities in text * * Uses a hybrid approach: * 1. First pass: decode common named entities using a map * 2. Second pass: decode numeric entities (decimal and hexadecimal) * * @param {string} text - Text with HTML entities * @returns {string} Decoded text */ export const decodeHtmlEntities = (text) => text // First pass: common named entities .replace(entityPattern, (match) => commonEntities[match]) // Second pass: numeric entities (decimal) .replace(/&#(\d+);/g, (_, num) => String.fromCharCode(parseInt(num, 10))) // Third pass: numeric entities (hexadecimal) .replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));