일부 번역 플랫폼은 번역 키에 사용 가능한 문자 종류나 길이를 제한한다. user.profile.edit.title 같은 계층적인 ID를 그대로 사용할 수 없는 경우가 있다. 빌드 타임에 ID를 해싱하여 단축하면 이러한 제약을 우회할 수 있다.
코드
function toHex(buffer: ArrayBuffer): string { return [...new Uint8Array(buffer)] .map((b) => b.toString(16).padStart(2, '0')) .join('')}
export function createHashStore(alg: string = 'SHA-256') { const contextHash = new Map<string, string>() const msgIdHash = new Map<string, string>()
async function digestContext(context: string): Promise<string> { const data = new TextEncoder().encode(context) const buf = await crypto.subtle.digest(alg, data) return toHex(buf).slice(0, 7) }
async function digestMsgId(msgId: string): Promise<string> { const data = new TextEncoder().encode(msgId) const buf = await crypto.subtle.digest(alg, data) return toHex(buf).slice(0, 10) }
async function saveContext(context: string): Promise<string> { const cached = contextHash.get(context) if (cached) return cached const hash = await digestContext(context) contextHash.set(context, hash) return hash }
async function saveMsgId(msgId: string): Promise<string> { const cached = msgIdHash.get(msgId) if (cached) return cached const hash = await digestMsgId(msgId) msgIdHash.set(msgId, hash) return hash }
return { contextHash, msgIdHash, saveContext, saveMsgId }}Web Crypto API(crypto.subtle.digest)를 사용하므로 브라우저·Node.js·Deno·Bun 어디서든 수정 없이 실행된다. alg에는 'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'를 지정할 수 있다.
동작 방식
saveContext와 saveMsgId는 각각 Map에 캐싱하면서 해시를 반환한다. 동일한 입력에 대해 해시 계산은 최초 1회만 실행된다. 컨텍스트(네임스페이스)는 앞 7자, 메시지 ID는 앞 10자로 잘라낸다. 컨텍스트는 수가 적어 충돌 위험이 낮으므로 더 짧게 설정한다.
응용
빌드 플러그인(Vite 플러그인, 커스텀 코드 변환)에 통합하여 소스 코드의 메시지 ID를 해시 값으로 치환한다. 런타임에서는 원본 문자열이 아닌 해시를 키로 번역 테이블을 참조한다.
해싱 알고리즘을 변경하려면 createHashStore의 인수로 다른 alg를 전달한다. 잘라내는 길이는 slice의 인수로 조정한다.
hsb.horse