@angular/localize
Version:
Angular - library for localizing messages
258 lines (252 loc) • 7.15 kB
JavaScript
/**
* @license Angular v21.0.8
* (c) 2010-2025 Google LLC. https://angular.dev/
* License: MIT
*/
const BLOCK_MARKER$1 = ':';
const MEANING_SEPARATOR = '|';
const ID_SEPARATOR = '@@';
const LEGACY_ID_INDICATOR = '\u241F';
let textEncoder;
function fingerprint(str) {
textEncoder ??= new TextEncoder();
const utf8 = textEncoder.encode(str);
const view = new DataView(utf8.buffer, utf8.byteOffset, utf8.byteLength);
let hi = hash32(view, utf8.length, 0);
let lo = hash32(view, utf8.length, 102072);
if (hi == 0 && (lo == 0 || lo == 1)) {
hi = hi ^ 0x130f9bef;
lo = lo ^ -0x6b5f56d8;
}
return BigInt.asUintN(32, BigInt(hi)) << BigInt(32) | BigInt.asUintN(32, BigInt(lo));
}
function computeMsgId(msg, meaning = '') {
let msgFingerprint = fingerprint(msg);
if (meaning) {
msgFingerprint = BigInt.asUintN(64, msgFingerprint << BigInt(1)) | msgFingerprint >> BigInt(63) & BigInt(1);
msgFingerprint += fingerprint(meaning);
}
return BigInt.asUintN(63, msgFingerprint).toString();
}
function hash32(view, length, c) {
let a = 0x9e3779b9,
b = 0x9e3779b9;
let index = 0;
const end = length - 12;
for (; index <= end; index += 12) {
a += view.getUint32(index, true);
b += view.getUint32(index + 4, true);
c += view.getUint32(index + 8, true);
const res = mix(a, b, c);
a = res[0], b = res[1], c = res[2];
}
const remainder = length - index;
c += length;
if (remainder >= 4) {
a += view.getUint32(index, true);
index += 4;
if (remainder >= 8) {
b += view.getUint32(index, true);
index += 4;
if (remainder >= 9) {
c += view.getUint8(index++) << 8;
}
if (remainder >= 10) {
c += view.getUint8(index++) << 16;
}
if (remainder === 11) {
c += view.getUint8(index++) << 24;
}
} else {
if (remainder >= 5) {
b += view.getUint8(index++);
}
if (remainder >= 6) {
b += view.getUint8(index++) << 8;
}
if (remainder === 7) {
b += view.getUint8(index++) << 16;
}
}
} else {
if (remainder >= 1) {
a += view.getUint8(index++);
}
if (remainder >= 2) {
a += view.getUint8(index++) << 8;
}
if (remainder === 3) {
a += view.getUint8(index++) << 16;
}
}
return mix(a, b, c)[2];
}
function mix(a, b, c) {
a -= b;
a -= c;
a ^= c >>> 13;
b -= c;
b -= a;
b ^= a << 8;
c -= a;
c -= b;
c ^= b >>> 13;
a -= b;
a -= c;
a ^= c >>> 12;
b -= c;
b -= a;
b ^= a << 16;
c -= a;
c -= b;
c ^= b >>> 5;
a -= b;
a -= c;
a ^= c >>> 3;
b -= c;
b -= a;
b ^= a << 10;
c -= a;
c -= b;
c ^= b >>> 15;
return [a, b, c];
}
var Endian;
(function (Endian) {
Endian[Endian["Little"] = 0] = "Little";
Endian[Endian["Big"] = 1] = "Big";
})(Endian || (Endian = {}));
function parseMessage(messageParts, expressions, location, messagePartLocations, expressionLocations = []) {
const substitutions = {};
const substitutionLocations = {};
const associatedMessageIds = {};
const metadata = parseMetadata(messageParts[0], messageParts.raw[0]);
const cleanedMessageParts = [metadata.text];
const placeholderNames = [];
let messageString = metadata.text;
for (let i = 1; i < messageParts.length; i++) {
const {
messagePart,
placeholderName = computePlaceholderName(i),
associatedMessageId
} = parsePlaceholder(messageParts[i], messageParts.raw[i]);
messageString += `{$${placeholderName}}${messagePart}`;
if (expressions !== undefined) {
substitutions[placeholderName] = expressions[i - 1];
substitutionLocations[placeholderName] = expressionLocations[i - 1];
}
placeholderNames.push(placeholderName);
if (associatedMessageId !== undefined) {
associatedMessageIds[placeholderName] = associatedMessageId;
}
cleanedMessageParts.push(messagePart);
}
const messageId = metadata.customId || computeMsgId(messageString, metadata.meaning || '');
const legacyIds = metadata.legacyIds ? metadata.legacyIds.filter(id => id !== messageId) : [];
return {
id: messageId,
legacyIds,
substitutions,
substitutionLocations,
text: messageString,
customId: metadata.customId,
meaning: metadata.meaning || '',
description: metadata.description || '',
messageParts: cleanedMessageParts,
messagePartLocations,
placeholderNames,
associatedMessageIds,
location
};
}
function parseMetadata(cooked, raw) {
const {
text: messageString,
block
} = splitBlock(cooked, raw);
if (block === undefined) {
return {
text: messageString
};
} else {
const [meaningDescAndId, ...legacyIds] = block.split(LEGACY_ID_INDICATOR);
const [meaningAndDesc, customId] = meaningDescAndId.split(ID_SEPARATOR, 2);
let [meaning, description] = meaningAndDesc.split(MEANING_SEPARATOR, 2);
if (description === undefined) {
description = meaning;
meaning = undefined;
}
if (description === '') {
description = undefined;
}
return {
text: messageString,
meaning,
description,
customId,
legacyIds
};
}
}
function parsePlaceholder(cooked, raw) {
const {
text: messagePart,
block
} = splitBlock(cooked, raw);
if (block === undefined) {
return {
messagePart
};
} else {
const [placeholderName, associatedMessageId] = block.split(ID_SEPARATOR);
return {
messagePart,
placeholderName,
associatedMessageId
};
}
}
function splitBlock(cooked, raw) {
if (raw.charAt(0) !== BLOCK_MARKER$1) {
return {
text: cooked
};
} else {
const endOfBlock = findEndOfBlock(cooked, raw);
return {
block: cooked.substring(1, endOfBlock),
text: cooked.substring(endOfBlock + 1)
};
}
}
function computePlaceholderName(index) {
return index === 1 ? 'PH' : `PH_${index - 1}`;
}
function findEndOfBlock(cooked, raw) {
for (let cookedIndex = 1, rawIndex = 1; cookedIndex < cooked.length; cookedIndex++, rawIndex++) {
if (raw[rawIndex] === '\\') {
rawIndex++;
} else if (cooked[cookedIndex] === BLOCK_MARKER$1) {
return cookedIndex;
}
}
throw new Error(`Unterminated $localize metadata block in "${raw}".`);
}
const $localize = function (messageParts, ...expressions) {
if ($localize.translate) {
const translation = $localize.translate(messageParts, expressions);
messageParts = translation[0];
expressions = translation[1];
}
let message = stripBlock(messageParts[0], messageParts.raw[0]);
for (let i = 1; i < messageParts.length; i++) {
message += expressions[i - 1] + stripBlock(messageParts[i], messageParts.raw[i]);
}
return message;
};
const BLOCK_MARKER = ':';
function stripBlock(messagePart, rawMessagePart) {
return rawMessagePart.charAt(0) === BLOCK_MARKER ? messagePart.substring(findEndOfBlock(messagePart, rawMessagePart) + 1) : messagePart;
}
export { $localize, BLOCK_MARKER$1 as BLOCK_MARKER, computeMsgId, findEndOfBlock, parseMessage, parseMetadata, splitBlock };
//# sourceMappingURL=_localize-chunk.mjs.map