Skip to content

Commit da29976

Browse files
Editorial review: Document canvas context lang attribute (mdn#39642)
* Document canvas context lang attribute * Add explanation of off-screen canvas inherit, and update demo to suit * Add explanatory text to make purpose clear * Update files/en-us/web/api/canvasrenderingcontext2d/lang/index.md Co-authored-by: wbamberg <will@bootbonnet.ca> * Update files/en-us/web/api/canvasrenderingcontext2d/lang/index.md Co-authored-by: wbamberg <will@bootbonnet.ca> * Update files/en-us/web/api/canvasrenderingcontext2d/lang/index.md Co-authored-by: wbamberg <will@bootbonnet.ca> * Fixes for wbamberg review comments * Update files/en-us/glossary/bcp_47_language_tag/index.md Co-authored-by: wbamberg <will@bootbonnet.ca> --------- Co-authored-by: wbamberg <will@bootbonnet.ca>
1 parent b38959f commit da29976

File tree

6 files changed

+264
-21
lines changed

6 files changed

+264
-21
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: BCP 47 language tag
3+
slug: Glossary/BCP_47_language_tag
4+
page-type: glossary-definition
5+
---
6+
7+
{{GlossarySidebar}}
8+
9+
A **BCP 47 language tag** is a string of characters that precisely specifies a human language in terms of the basic language, but also optionally the writing system and dialect. For example, `en` specifies English, but `en-GB` and `en-US` more precisely specify British English and American English, respectively.
10+
11+
BCP 47 language tags are used anywhere on the web platform where a feature has been designed to output different results depending on the specified language, enabling {{glossary("internationalization")}} support.
12+
13+
Examples include:
14+
15+
- The HTML [`lang`](/en-US/docs/Web/HTML/Reference/Global_attributes/lang) attribute
16+
- The HTML {{htmlelement("track")}} element
17+
- The {{jsxref("Temporal")}} object
18+
- The {{domxref("CanvasRenderingContext2D.lang")}} property
19+
- The [Translator and Language Detector APIs](/en-US/docs/Web/API/Translator_and_Language_Detector_APIs)
20+
21+
## BCP 47 syntax
22+
23+
The full BCP 47 syntax is specified in {{rfc("5646")}}. It is capable of identifying extremely specific language dialects, but most usage is much simpler.
24+
25+
A language tag is made of hyphen-separated _subtags_, where each subtag indicates a certain property of the language. The three most common subtags are:
26+
27+
- Language subtag
28+
- : A 2-or-3-character code that defines the basic language, typically written in all lowercase. For example, the language code for English is `en`, and the code for Badeshi is `bdz`.
29+
- Script subtag {{optional_inline}}
30+
31+
- : This subtag defines the writing system used for the language, and is always 4 characters long, with the first letter capitalized. For example, French-in-Braille is `fr-Brai` and Japanese written with the Katakana alphabet is `ja-Kana`.
32+
33+
> [!NOTE]
34+
> If the language is written in a highly typical way, like English in the Latin alphabet, there is no need to use this subtag.
35+
36+
- Region subtag {{optional_inline}}
37+
- : This subtag defines a dialect of the base language from a particular location and is either two upper-case letters matching a country code or three numbers matching a non-country area. For example, `es-ES` is for Spanish as spoken in Spain, and `es-013` is Spanish as spoken in Central America. "International Spanish" would just be `es`.
38+
39+
The script subtag precedes the region subtag if both are present — `ru-Cyrl-BY` is Russian, written in the Cyrillic alphabet, as spoken in Belarus.
40+
41+
## See also
42+
43+
- [RFC 5646: Tags for Identifying Languages](https://datatracker.ietf.org/doc/html/rfc5646): where BCP 47 language tags are specified.
44+
- [BCP 47 language subtag lookup](https://r12a.github.io/app-subtags/): look up subtag codes for a language.

files/en-us/web/api/canvasrenderingcontext2d/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ The following properties control how text is laid out.
128128
- : Text rendering. Possible values: `auto` (default), `optimizeSpeed`, `optimizeLegibility`, `geometricPrecision`.
129129
- {{domxref("CanvasRenderingContext2D.wordSpacing")}}
130130
- : Word spacing. Default value: `0px`
131+
- {{domxref("CanvasRenderingContext2D.lang")}}
132+
- : Gets or sets the language of the canvas drawing context.
131133

132134
### Fill and stroke styles
133135

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
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)

files/en-us/web/api/htmltrackelement/srclang/index.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ browser-compat: api.HTMLTrackElement.srclang
1111
The **`srclang`** property of the {{domxref("HTMLTrackElement")}} interface reflects the value of
1212
the {{HTMLElement("track")}} element's [`srclang`](/en-US/docs/Web/HTML/Reference/Elements/track#srclang) attribute or the empty string if not defined.
1313

14-
The `srclang` attribute is a [BCP 47 language tag](/en-US/docs/Web/HTML/Reference/Global_attributes/lang#language_tag_syntax)
15-
indicating the language of the text track's data.
14+
The `srclang` attribute is a {{glossary("BCP 47 language tag")}} indicating the language of the text track's data.
1615

1716
## Value
1817

@@ -38,4 +37,3 @@ trackElement.srclang = "en-US";
3837

3938
- {{domxref("HTMLTrackElement")}}
4039
- {{HTMLElement("track")}}
41-
- [`lang` syntax](/en-US/docs/Web/HTML/Reference/Global_attributes/lang#language_tag_syntax)

files/en-us/web/api/offscreencanvasrenderingcontext2d/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ The following properties control how text is laid out.
128128
- : Text rendering. Possible values: `auto` (default), `optimizeSpeed`, `optimizeLegibility`, `geometricPrecision`.
129129
- {{domxref("CanvasRenderingContext2D.wordSpacing")}}
130130
- : Word spacing. Default value: `0px`
131+
- {{domxref("CanvasRenderingContext2D.lang")}}
132+
- : Gets or sets the language of the canvas drawing context.
131133

132134
### Fill and stroke styles
133135

files/en-us/web/html/reference/global_attributes/lang/index.md

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ browser-compat: html.global_attributes.lang
77

88
{{HTMLSidebar("Global_attributes")}}
99

10-
The **`lang`** [global attribute](/en-US/docs/Web/HTML/Reference/Global_attributes) helps define the language of an element: the language that non-editable elements are written in, or the language that the editable elements should be written in by the user. The attribute contains a single "language tag" in the format defined in {{RFC(5646, "Tags for Identifying Languages (also known as BCP 47)")}}.
10+
The **`lang`** [global attribute](/en-US/docs/Web/HTML/Reference/Global_attributes) helps define the language of an element: the language that non-editable elements are written in, or the language that the editable elements should be written in by the user. The attribute contains a single {{glossary("BCP 47 language tag")}}.
1111

1212
> [!NOTE]
1313
> The default value of `lang` is the empty string, which means that the language is unknown. Therefore, it is recommended to always specify an appropriate value for this attribute.
@@ -42,23 +42,6 @@ Even if the `lang` attribute is set, it may not be taken into account, as the `x
4242

4343
For the CSS pseudo-class {{cssxref(":lang")}}, two invalid language names are different if their names are different. So while `:lang(es)` matches both `lang="es-ES"` and `lang="es-419"`, `:lang(xyzzy)` would _not_ match `lang="xyzzy-Zorp!"`.
4444

45-
## Language tag syntax
46-
47-
The full BCP47 syntax is in-depth enough to mark extremely specific language dialects, but most usage is much simpler.
48-
49-
A language tag is made of hyphen-separated _language subtags_, where each subtag indicates a certain property of the language. The 3 most common subtags are:
50-
51-
- Language subtag
52-
- : Required. A 2-or-3-character code that defines the basic language, typically written in all lowercase. For example, the language code for English is `en`, and the code for Badeshi is `bdz`.
53-
- Script subtag
54-
- : Optional. This subtag defines the writing system used for the language, and is always 4 characters long, with the first letter capitalized. For example, French-in-Braille is `fr-Brai` and `ja-Kana` is Japanese written with the Katakana alphabet. If the language is written in a highly typical way, like English in the Latin alphabet, there is no need to use this subtag.
55-
- Region subtag
56-
- : Optional. This subtag defines a dialect of the base language from a particular location and is either two upper-case letters matching a country code or three numbers matching a non-country area. For example, `es-ES` is for Spanish as spoken in Spain, and `es-013` is Spanish as spoken in Central America. "International Spanish" would just be `es`.
57-
58-
The script subtag precedes the region subtag if both are present — `ru-Cyrl-BY` is Russian, written in the Cyrillic alphabet, as spoken in Belarus.
59-
60-
To find the correct subtag codes for a language, try [the Language Subtag Lookup](https://r12a.github.io/app-subtags/).
61-
6245
## Accessibility concerns
6346

6447
WCAG Success Criterion 3.1.1 **requires** that a page language is specified in a way which may be 'programmatically determined' (i.e., via the **`lang`** attribute).

0 commit comments

Comments
 (0)