v135 · graphics
OffscreenCanvas worker locale
The feature that motivated ctx.lang: OffscreenCanvas runs in a Worker with no DOM and therefore no lang attribute. Before Chrome 135, there was no way to set locale for glyph selection in a Worker — CJK characters would render with the wrong regional form. Now ctx.lang solves it.
CanvasRenderingContext2D.lang: checking…
Why this matters for Workers: Image processing, chart rendering, and PDF generation often run in Workers. When the worker renders CJK text, it used to inherit an undefined locale, causing the browser to pick a default (often Chinese) glyph for characters that should be Japanese or Traditional Chinese.
ctx.lang = 'ja' fixes this without requiring DOM access.
Render settings
Text:
Locale:
With ctx.lang (Chrome 135)
Not rendered yet
Without ctx.lang (before)
Not rendered yet
Notable CJK characters with locale-specific glyphs
| Character | Unicode | Meaning | ja variant | zh-Hans variant | zh-Hant variant |
|---|---|---|---|---|---|
| 骨 | U+9AA8 | bone | ja form | sc form | tc form |
| 語 | U+8A9E | language | ja form | sc form | tc form |
| 直 | U+76F4 | straight | ja form | sc form | same |
| 青 | U+9752 | blue/green | ja form | same | same |
| 勉 | U+52C9 | diligent | ja form | sc form | tc form |
// OffscreenCanvas in a Worker — the actual motivating use case
// Worker code (locale-worker.js):
self.onmessage = async ({ data }) => {
const { width, height, text, lang } = data;
const offscreen = new OffscreenCanvas(width, height);
const ctx = offscreen.getContext('2d');
// Chrome 135: set locale for correct glyph selection
// Without this, CJK characters render with browser-default locale (often zh)
if (lang) {
ctx.lang = lang; // NEW in Chrome 135
}
ctx.font = '48px sans-serif';
ctx.fillStyle = '#000';
ctx.fillText(text, 20, 60);
const bitmap = offscreen.transferToImageBitmap();
self.postMessage({ bitmap }, [bitmap]);
};
// Main thread:
const worker = new Worker('locale-worker.js');
worker.postMessage({ width: 400, height: 100, text: '骨語直', lang: 'ja' });
worker.onmessage = ({ data }) => {
const ctx = canvas.getContext('2d');
ctx.drawImage(data.bitmap, 0, 0); // displays Japanese glyph variants
};