|
| 1 | +--- |
| 2 | +title: "CanvasRenderingContext2D: lang property" |
| 3 | +short-title: lang |
| 4 | +slug: Web/API/CanvasRenderingContext2D/lang |
| 5 | +page-type: web-api-instance-property |
| 6 | +browser-compat: api.CanvasRenderingContext2D.lang |
| 7 | +--- |
| 8 | + |
| 9 | +{{APIRef}} |
| 10 | + |
| 11 | +The **`CanvasRenderingContext2D.lang`** property of the Canvas 2D API gets or sets the language of the canvas drawing context. |
| 12 | + |
| 13 | +## Value |
| 14 | + |
| 15 | +The `lang` property can take one of the following string values: |
| 16 | + |
| 17 | +- A {{glossary("BCP 47 language tag")}} representing the language of the canvas context. |
| 18 | +- The string `inherit`, in which case the language is inherited from the [`lang`](/en-US/docs/Web/HTML/Reference/Global_attributes/lang) attribute of the originating {{HTMLElement("canvas")}} element or the nearest available ancestor with an explicit `lang` set. |
| 19 | +- An empty string (`""`), which can be set to specify that the canvas context has no language. |
| 20 | + |
| 21 | +The default value is `inherit`. |
| 22 | + |
| 23 | +## Description |
| 24 | + |
| 25 | +Sometimes, you need to set a language for a canvas rendering context so that it knows how to render language-dependent features: for example, some fonts have certain characters rendered differently in different languages. An on-screen canvas context (`CanvasRenderingContext2D`) is always associated with a particular `<canvas>` element, so whenever you render content using it, it can derive the language from the value of the `<canvas>` element's `lang` attribute. |
| 26 | + |
| 27 | +Sometimes, it is necessary to set a language for a canvas rendering context so that it knows how to render language-dependent features such as some fonts. An on-screen canvas context (`CanvasRenderingContext2D`) is always associated with a particular `<canvas>` element, so whenever you render content using it, it can derive the language from the value of the `<canvas>` element's `lang` attribute. |
| 28 | + |
| 29 | +However, an off-screen canvas context ({{domxref("OffscreenCanvasRenderingContext2D")}}) renders its content before it is associated with a `<canvas>` element, so it can't derive a rendering language from the `lang` attribute of the `<canvas>` element. The `lang` property addresses this issue, allowing you to set a language directly on a canvas rendering context, whether you are using an on-screen or off-screen canvas. |
| 30 | + |
| 31 | +### The `inherit` value |
| 32 | + |
| 33 | +When the `inherit` value is used, the language of the canvas context is inherited from the [`lang`](/en-US/docs/Web/HTML/Reference/Global_attributes/lang) attribute of the nearest-available HTML source: |
| 34 | + |
| 35 | +- In the case of an on-screen context, or an off-screen context that was transferred from an on-screen context, this will be the originating {{HTMLElement("canvas")}} element, provided it has a valid `lang` attribute set. |
| 36 | +- If a `lang` attribute is not available on an associated `<canvas>` element, which could be the case for an on- or off-screen context, this will be the nearest available ancestor with an explicit `lang` set, which is commonly the document root. |
| 37 | + |
| 38 | +Due to technical limitations, the `inherit` value behaves differently for on-screen and off-screen canvases: |
| 39 | + |
| 40 | +- For on-screen canvases, the `lang` value is inherited when the associated `CanvasRenderingContext2D` object is first created; the inherited `lang` value then changes dynamically if the `lang` attribute value is updated. |
| 41 | +- For off-screen canvases, the `lang` value is inherited when the associated `OffscreenCanvasRenderingContext2D` object is first created, and then fixed for the lifetime of the {{domxref("OffscreenCanvas")}}. It **does not** change if the `lang` attribute value is updated. Because of this, the language of an off-screen canvas can only be changed by setting the `lang` value explicitly. |
| 42 | + |
| 43 | +## Examples |
| 44 | + |
| 45 | +### Basic usage |
| 46 | + |
| 47 | +```js |
| 48 | +const canvasElem = document.querySelector("canvas"); |
| 49 | +const ctx = canvasElem.getContext("2d"); |
| 50 | + |
| 51 | +// Get context language; returns "inherit" by default |
| 52 | +console.log(ctx.lang); |
| 53 | + |
| 54 | +// Set context language |
| 55 | +ctx.lang = "en"; |
| 56 | +// Logs "en" |
| 57 | +console.log(ctx.lang); |
| 58 | +``` |
| 59 | + |
| 60 | +### Demonstrating canvas context localization support |
| 61 | + |
| 62 | +In this example, we render a text string to a 2D canvas context in a particular font that has language-dependent ligatures. We allow the canvas context's language to be adjusted so you can see the difference in rendering. |
| 63 | + |
| 64 | +#### HTML |
| 65 | + |
| 66 | +The HTML features a {{htmlelement("select")}} element that allows you to choose a language — `en` (English) or `tr` (Turkish) — and a {{htmlelement("canvas")}} element to render to. |
| 67 | + |
| 68 | +```html live-example___canvas-l10n |
| 69 | +<p> |
| 70 | + <label for="lang">Choose language:</label> |
| 71 | + <select id="lang" name="lang"> |
| 72 | + <option>en</option> |
| 73 | + <option>tr</option> |
| 74 | + </select> |
| 75 | +</p> |
| 76 | +<canvas></canvas> |
| 77 | +``` |
| 78 | + |
| 79 | +#### JavaScript |
| 80 | + |
| 81 | +In the JavaScript, we first grab references to the `<canvas>` element, its `CanvasRenderingContext2D`, and the `<select>` element, then load the language-dependant font using the [CSS Font Loading API](/en-US/docs/Web/API/CSS_Font_Loading_API). Once the font is loaded, we run an `init()` function. This function defines another function — `drawText()`, which draws some text to the canvas context that uses the loaded font, adds a [`change`](/en-US/docs/Web/API/HTMLElement/change_event) [event listener](/en-US/docs/Web/API/EventTarget/addEventListener) to the `<select>` element, then calls `drawText()` so that the text is immediately drawn to the canvas when the page first loads. |
| 82 | + |
| 83 | +```js live-example___canvas-l10n |
| 84 | +const canvasElem = document.querySelector("canvas"); |
| 85 | +const ctx = canvasElem.getContext("2d"); |
| 86 | + |
| 87 | +const selectElem = document.querySelector("select"); |
| 88 | + |
| 89 | +const latoMediumFontFace = new FontFace( |
| 90 | + // Lato-Medium is a font with language specific ligatures |
| 91 | + "Lato-Medium", |
| 92 | + "url(https://mdn.github.io/shared-assets/fonts/Lato-Medium.ttf)", |
| 93 | +); |
| 94 | + |
| 95 | +latoMediumFontFace.load().then((font) => { |
| 96 | + document.fonts.add(font); |
| 97 | + init(); |
| 98 | +}); |
| 99 | + |
| 100 | +function init() { |
| 101 | + function drawText() { |
| 102 | + ctx.clearRect(0, 0, canvasElem.width, canvasElem.height); |
| 103 | + ctx.font = "30px Lato-Medium"; |
| 104 | + ctx.color = "black"; |
| 105 | + ctx.fillText("finish crafting", 50, 100); |
| 106 | + } |
| 107 | + |
| 108 | + selectElem.addEventListener("change", () => { |
| 109 | + document.documentElement.lang = selectElem.value; |
| 110 | + drawText(); |
| 111 | + }); |
| 112 | + |
| 113 | + drawText(); |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +When the `<select>` value is changed, the `change` event handler function fires, which: |
| 118 | + |
| 119 | +- Sets the value of the `<html>` element's [`lang`](/en-US/docs/Web/HTML/Reference/Global_attributes/lang) attribute to the `<select>` element value, effectively changing the language of the document. |
| 120 | +- Runs the `drawText()` function. The `CanvasRenderingContext2D.lang` property is set to `inherit` by default, therefore the canvas context inherits the language of the document. |
| 121 | + |
| 122 | +#### Result |
| 123 | + |
| 124 | +The example is rendered as follows: |
| 125 | + |
| 126 | +{{ EmbedLiveSample('canvas-l10n', "100%", 220) }} |
| 127 | + |
| 128 | +Try changing the document language using the `<select>` element. When the language is set to English, the font will be rendered with the "fi" ligature. However, when it is set to Turkish, the font will be rendered without the "fi" ligature, because that locale doesn't include it. |
| 129 | + |
| 130 | +### Language support for offscreen canvases |
| 131 | + |
| 132 | +This example is the similar to the previous example, except that the font is rendered to a {{domxref("OffscreenCanvasRenderingContext2D")}} then the resulting bitmap is transferred to the on-screen `<canvas>` to display. |
| 133 | + |
| 134 | +In addition, because an inherited off-screen canvas language is only set once, and not dynamically updated if the inherited `lang` attribute value is changed, we explicitly set the `lang` property on the `OffscreenCanvasRenderingContext2D` instead. |
| 135 | + |
| 136 | +#### HTML |
| 137 | + |
| 138 | +```html live-example___offscreen-l10n |
| 139 | +<p> |
| 140 | + <label for="lang">Choose language:</label> |
| 141 | + <select id="lang" name="lang"> |
| 142 | + <option>en</option> |
| 143 | + <option>tr</option> |
| 144 | + </select> |
| 145 | +</p> |
| 146 | +<canvas></canvas> |
| 147 | +``` |
| 148 | + |
| 149 | +#### JavaScript |
| 150 | + |
| 151 | +The JavaScript works in the same way as the previous example, except that: |
| 152 | + |
| 153 | +- The on-screen canvas context is defined as an {{domxref("ImageBitmapRenderingContext")}}. |
| 154 | +- We define a new `OffscreenCanvasRenderingContext2D` to draw the text onto, transfer the result to a bitmap using {{domxref("OffscreenCanvas.transferToImageBitmap", "transferToImageBitmap()")}}, then render it on the `<canvas>` using {{domxref("ImageBitmapRenderingContext.transferFromImageBitmap", "transferFromImageBitmap()")}}. |
| 155 | +- When the `<select>` value is changed, we update the `lang` property directly on the `OffscreenCanvasRenderingContext2D` instead of changing the `<html>` `lang` attribute value. |
| 156 | + |
| 157 | +```js live-example___offscreen-l10n |
| 158 | +const canvasElem = document.querySelector("canvas"); |
| 159 | +const ctx = canvasElem.getContext("bitmaprenderer"); |
| 160 | + |
| 161 | +const offscreen = new OffscreenCanvas(canvasElem.width, canvasElem.height); |
| 162 | +const offscreen_ctx = offscreen.getContext("2d"); |
| 163 | + |
| 164 | +const selectElem = document.querySelector("select"); |
| 165 | + |
| 166 | +const latoMediumFontFace = new FontFace( |
| 167 | + // Lato-Medium is a font with language specific ligatures. |
| 168 | + "Lato-Medium", |
| 169 | + "url(https://mdn.github.io/shared-assets/fonts/Lato-Medium.ttf)", |
| 170 | +); |
| 171 | + |
| 172 | +latoMediumFontFace.load().then((font) => { |
| 173 | + document.fonts.add(font); |
| 174 | + init(); |
| 175 | +}); |
| 176 | + |
| 177 | +function init() { |
| 178 | + function drawText() { |
| 179 | + offscreen_ctx.clearRect(0, 0, canvasElem.width, canvasElem.height); |
| 180 | + offscreen_ctx.lang = selectElem.value; |
| 181 | + offscreen_ctx.font = "30px Lato-Medium"; |
| 182 | + offscreen_ctx.color = "black"; |
| 183 | + offscreen_ctx.fillText("finish crafting", 50, 100); |
| 184 | + |
| 185 | + const bitmap = offscreen.transferToImageBitmap(); |
| 186 | + ctx.transferFromImageBitmap(bitmap); |
| 187 | + } |
| 188 | + |
| 189 | + selectElem.addEventListener("change", () => { |
| 190 | + drawText(); |
| 191 | + }); |
| 192 | + |
| 193 | + drawText(); |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +#### Result |
| 198 | + |
| 199 | +The example is rendered as follows: |
| 200 | + |
| 201 | +{{ EmbedLiveSample('offscreen-l10n', "100%", 220) }} |
| 202 | + |
| 203 | +## Specifications |
| 204 | + |
| 205 | +{{Specifications}} |
| 206 | + |
| 207 | +## Browser compatibility |
| 208 | + |
| 209 | +{{Compat}} |
| 210 | + |
| 211 | +## See also |
| 212 | + |
| 213 | +- {{domxref("CanvasRenderingContext2D")}} |
| 214 | +- [Canvas Localization Support](https://blogs.igalia.com/schenney/canvas-localization-support/) from Igalia (2025) |
0 commit comments