From 951683f652a4b3b72311c6e1afdb04f928fbdd31 Mon Sep 17 00:00:00 2001 From: Fuqiao Xue Date: Wed, 3 Jun 2026 10:32:55 +0800 Subject: [PATCH 1/5] Add blog post on making JSON strings work for every language Fix #2405. --- ...ng-json-strings-work-for-every-language.md | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 pages/blog/posts/making-json-strings-work-for-every-language.md diff --git a/pages/blog/posts/making-json-strings-work-for-every-language.md b/pages/blog/posts/making-json-strings-work-for-every-language.md new file mode 100644 index 000000000..bc378b11e --- /dev/null +++ b/pages/blog/posts/making-json-strings-work-for-every-language.md @@ -0,0 +1,112 @@ +--- +title: "Making JSON Strings Work for Every Language" +date: "2026-06-08" +type: Engineering +cover: @@ TBD: NOT SURE WHERE TO ADD THE IMAGE @@ +authors: + - name: Fuqiao Xue + photo: @@ TBD: NOT SURE WHERE TO ADD THE IMAGE @@ + twitter: XueFuqiao +excerpt: "How JSON Schema authors preserve language and text direction metadata for the web." +language: en +--- + +JSON is one of the most successful data formats, but its `string` type is too simple. That simplicity becomes a problem when a string contains natural language text. + +Titles, names, error message etc. often needs more than Unicode characters. Consumers may also need to know the language of the text and its direction, especially when displaying right-to-left scripts such as Arabic or Hebrew. Without that metadata, applications fall back to guessing, and guessing fails. + +The W3C Internationalization Working Group is developing [Strings on the Web: Language and Direction Metadata](https://www.w3.org/TR/string-meta/). Its recommendations are directly useful when schemas define fields that contain human-readable text. + +The core recommendation is simple: if a field contains natural language text, it must be possible to determine the language and direction of that specific string. Prefer explicit metadata over heuristics. + +For example, instead of treating every human-readable value as a plain string: + +```json +{ + "title": "HTML و CSS: تصميم و إنشاء مواقع الويب" +} +``` + +a format can define a localizable text object: + +```json +{ + "title": { + "value": "HTML و CSS: تصميم و إنشاء مواقع الويب", + "lang": "ar", + "dir": "rtl" + } +} +``` + +This gives producers and consumers a shared agreement. The producer can preserve the intended language and direction. The consumer can display the string correctly, apply the right `lang` and `dir` attributes in HTML, choose better fonts, select an appropriate text-to-speech voice, improve search and indexing, and avoid bidirectional text spillover. + +A schema can instead make the expected structure explicit: + +```json +{ + "$defs": { + "textDirection": { + "enum": ["ltr", "rtl", "auto"] + }, + "localizableText": { + "type": "object", + "required": ["value"], + "properties": { + "value": { "type": "string" }, + "lang": { "type": "string" }, + "dir": { "$ref": "#/$defs/textDirection" } + }, + "additionalProperties": false + } + }, + "type": "object", + "properties": { + "title": { "$ref": "#/$defs/localizableText" } + } +} +``` + +The `lang` value should be a [BCP 47 language tag](https://www.rfc-editor.org/info/bcp47/). + +The document also explains when not to add language and direction metadata. Not every JSON string is natural language text. Identifiers, protocol keywords, ISBNs, URLs, enum values, and many user-defined tokens are usually syntactic content, not localizable text. Specifications and schemas should distinguish these cases clearly. + +For resources that contain many strings in the same language, a format can define resource-wide defaults, while still allowing string-specific overrides: + +```json +{ + "language": "en-US", + "direction": "ltr", + "name": "Example University", + "description": "A short description.", + "alternateTitle": { + "value": "جامعة المثال", + "lang": "ar", + "dir": "rtl" + } +} +``` + +The document recommends `language` for a resource-wide default language field and `direction` for a resource-wide default direction field. For localizable text objects, the examples use `lang` and `dir`, which align naturally with HTML attributes when the value is eventually displayed. + +For multilingual values, the document recommends language maps, where language tags help consumers find the best localized value: + +```json +{ + "title": { + "en": { "value": "Learning Web Design" }, + "fr": { "value": "Apprendre le design web" }, + "ar": { "value": "تعلم تصميم الويب", "dir": "rtl" } + } +} +``` + +Producers should preserve language and direction metadata when they have it. They should avoid redundant per-string metadata when a resource-wide default already applies, but they should include string-specific metadata when a value uses a different language, a more specific language tag, or a direction opposite to the default. + +Consumers should use the metadata they receive. For example, when inserting a string into HTML, that usually means applying `lang` and `dir` to an element that tightly wraps the inserted text, or using `bdi` when no better element is available. When metadata is absent, the language and direction should be treated as unknown. [First-strong direction](https://www.w3.org/TR/i18n-glossary/#dfn-first-strong-detection) detection can be a fallback, but it should not replace explicit metadata. + +Language metadata also affects font selection, line breaking, hyphenation, spell checking, search, filtering, accessibility, and text-to-speech. + +Unicode lets us exchange the characters, and metadata helps applications process and present those characters correctly. + +We invite JSON Schema users, schema authors, and specification developers to read the recommendations of the W3C Internationalization Working Group and apply its patterns when designing JSON-based formats. Feedback on the document is welcome via the [W3C string-meta GitHub repository](https://github.com/w3c/string-meta/issues). \ No newline at end of file From 551dd7482a421c2411d9bea03035541fe1fc62bc Mon Sep 17 00:00:00 2001 From: Fuqiao Xue Date: Wed, 3 Jun 2026 11:10:51 +0800 Subject: [PATCH 2/5] Add images --- ...ng-json-strings-work-for-every-language.md | 4 +- .../cover.svg | 56 ++++++++++++++++++ .../fuqiaoxue.jpg | Bin 0 -> 28579 bytes 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 public/img/posts/2026/making-json-strings-work-for-every-language/cover.svg create mode 100644 public/img/posts/2026/making-json-strings-work-for-every-language/fuqiaoxue.jpg diff --git a/pages/blog/posts/making-json-strings-work-for-every-language.md b/pages/blog/posts/making-json-strings-work-for-every-language.md index bc378b11e..d0872282d 100644 --- a/pages/blog/posts/making-json-strings-work-for-every-language.md +++ b/pages/blog/posts/making-json-strings-work-for-every-language.md @@ -2,10 +2,10 @@ title: "Making JSON Strings Work for Every Language" date: "2026-06-08" type: Engineering -cover: @@ TBD: NOT SURE WHERE TO ADD THE IMAGE @@ +cover: /img/posts/2026/making-json-strings-work-for-every-language/cover.svg authors: - name: Fuqiao Xue - photo: @@ TBD: NOT SURE WHERE TO ADD THE IMAGE @@ + photo: /img/posts/2026/making-json-strings-work-for-every-language/fuqiaoxue.jpg twitter: XueFuqiao excerpt: "How JSON Schema authors preserve language and text direction metadata for the web." language: en diff --git a/public/img/posts/2026/making-json-strings-work-for-every-language/cover.svg b/public/img/posts/2026/making-json-strings-work-for-every-language/cover.svg new file mode 100644 index 000000000..a5644d6b3 --- /dev/null +++ b/public/img/posts/2026/making-json-strings-work-for-every-language/cover.svg @@ -0,0 +1,56 @@ + + Cover illustration for language and direction metadata in JSON strings + A simple 16 by 9 cover image with standard curly braces and abstract data fields. + + + + + + + + + + + + + + + + + + + + + { + } + + + + + + + + + + + + + + + + + diff --git a/public/img/posts/2026/making-json-strings-work-for-every-language/fuqiaoxue.jpg b/public/img/posts/2026/making-json-strings-work-for-every-language/fuqiaoxue.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a93427c4259d11925b419e9f7123725e5c0842cf GIT binary patch literal 28579 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 Date: Tue, 16 Jun 2026 11:03:24 +0800 Subject: [PATCH 3/5] editorial fix --- pages/blog/posts/making-json-strings-work-for-every-language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/blog/posts/making-json-strings-work-for-every-language.md b/pages/blog/posts/making-json-strings-work-for-every-language.md index d0872282d..f8842afdc 100644 --- a/pages/blog/posts/making-json-strings-work-for-every-language.md +++ b/pages/blog/posts/making-json-strings-work-for-every-language.md @@ -41,7 +41,7 @@ a format can define a localizable text object: This gives producers and consumers a shared agreement. The producer can preserve the intended language and direction. The consumer can display the string correctly, apply the right `lang` and `dir` attributes in HTML, choose better fonts, select an appropriate text-to-speech voice, improve search and indexing, and avoid bidirectional text spillover. -A schema can instead make the expected structure explicit: +A schema can make the expected structure explicit: ```json { From 95abaec5f088525ba5e3ba37593d53684a96acbe Mon Sep 17 00:00:00 2001 From: Fuqiao Xue Date: Tue, 16 Jun 2026 12:12:04 +0800 Subject: [PATCH 4/5] Change examples --- ...aking-json-strings-work-for-every-language.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pages/blog/posts/making-json-strings-work-for-every-language.md b/pages/blog/posts/making-json-strings-work-for-every-language.md index f8842afdc..97f1719f9 100644 --- a/pages/blog/posts/making-json-strings-work-for-every-language.md +++ b/pages/blog/posts/making-json-strings-work-for-every-language.md @@ -13,7 +13,7 @@ language: en JSON is one of the most successful data formats, but its `string` type is too simple. That simplicity becomes a problem when a string contains natural language text. -Titles, names, error message etc. often needs more than Unicode characters. Consumers may also need to know the language of the text and its direction, especially when displaying right-to-left scripts such as Arabic or Hebrew. Without that metadata, applications fall back to guessing, and guessing fails. +Titles, names, error messages, etc. often need more than Unicode characters. Consumers may also need to know the language of the text and its direction, especially when displaying right-to-left scripts such as Arabic or Hebrew. Without that metadata, applications fall back to guessing, and guessing fails. The W3C Internationalization Working Group is developing [Strings on the Web: Language and Direction Metadata](https://www.w3.org/TR/string-meta/). Its recommendations are directly useful when schemas define fields that contain human-readable text. @@ -23,7 +23,7 @@ For example, instead of treating every human-readable value as a plain string: ```json { - "title": "HTML و CSS: تصميم و إنشاء مواقع الويب" + "bookName": "HTML و CSS: تصميم و إنشاء مواقع الويب" } ``` @@ -31,7 +31,7 @@ a format can define a localizable text object: ```json { - "title": { + "bookName": { "value": "HTML و CSS: تصميم و إنشاء مواقع الويب", "lang": "ar", "dir": "rtl" @@ -62,7 +62,7 @@ A schema can make the expected structure explicit: }, "type": "object", "properties": { - "title": { "$ref": "#/$defs/localizableText" } + "bookName": { "$ref": "#/$defs/localizableText" } } } ``` @@ -78,8 +78,8 @@ For resources that contain many strings in the same language, a format can defin "language": "en-US", "direction": "ltr", "name": "Example University", - "description": "A short description.", - "alternateTitle": { + "summary": "A short description.", + "alternateName": { "value": "جامعة المثال", "lang": "ar", "dir": "rtl" @@ -93,7 +93,7 @@ For multilingual values, the document recommends language maps, where language t ```json { - "title": { + "bookName": { "en": { "value": "Learning Web Design" }, "fr": { "value": "Apprendre le design web" }, "ar": { "value": "تعلم تصميم الويب", "dir": "rtl" } @@ -109,4 +109,4 @@ Language metadata also affects font selection, line breaking, hyphenation, spell Unicode lets us exchange the characters, and metadata helps applications process and present those characters correctly. -We invite JSON Schema users, schema authors, and specification developers to read the recommendations of the W3C Internationalization Working Group and apply its patterns when designing JSON-based formats. Feedback on the document is welcome via the [W3C string-meta GitHub repository](https://github.com/w3c/string-meta/issues). \ No newline at end of file +We invite JSON Schema users, schema authors, and specification developers to read the recommendations of the W3C Internationalization Working Group and apply its patterns when designing JSON-based formats. Feedback on the document is welcome via the [W3C string-meta GitHub repository](https://github.com/w3c/string-meta/issues). From 10615ef9c12fcb2787097751865e6aaefa4b57b5 Mon Sep 17 00:00:00 2001 From: Fuqiao Xue Date: Tue, 16 Jun 2026 12:34:25 +0800 Subject: [PATCH 5/5] Enhance examples --- ...ng-json-strings-work-for-every-language.md | 109 +++++++++++++++--- 1 file changed, 92 insertions(+), 17 deletions(-) diff --git a/pages/blog/posts/making-json-strings-work-for-every-language.md b/pages/blog/posts/making-json-strings-work-for-every-language.md index 97f1719f9..40e95a63f 100644 --- a/pages/blog/posts/making-json-strings-work-for-every-language.md +++ b/pages/blog/posts/making-json-strings-work-for-every-language.md @@ -1,6 +1,6 @@ --- title: "Making JSON Strings Work for Every Language" -date: "2026-06-08" +date: "2026-06-16" type: Engineering cover: /img/posts/2026/making-json-strings-work-for-every-language/cover.svg authors: @@ -41,28 +41,37 @@ a format can define a localizable text object: This gives producers and consumers a shared agreement. The producer can preserve the intended language and direction. The consumer can display the string correctly, apply the right `lang` and `dir` attributes in HTML, choose better fonts, select an appropriate text-to-speech voice, improve search and indexing, and avoid bidirectional text spillover. -A schema can make the expected structure explicit: +A schema can make the expected structure explicit. The examples below define the three common patterns as reusable schema resources. The `$id` values use `example.com`; schema authors should replace them with stable identifiers for their own formats. + +For the localizable text object pattern, the reusable schema keeps the string and its metadata together: ```json { - "$defs": { - "textDirection": { - "enum": ["ltr", "rtl", "auto"] - }, - "localizableText": { - "type": "object", - "required": ["value"], - "properties": { - "value": { "type": "string" }, - "lang": { "type": "string" }, - "dir": { "$ref": "#/$defs/textDirection" } - }, - "additionalProperties": false - } + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schemas/localizable-text", + + "type": "object", + "required": ["value"], + "properties": { + "value": { "type": "string" }, + "lang": { "type": "string" }, + "dir": { "enum": ["ltr", "rtl", "auto"] } }, + "additionalProperties": false +} +``` + +A data structure schema can reference it for any field that needs per-string language or direction metadata: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schemas/book", + "type": "object", "properties": { - "bookName": { "$ref": "#/$defs/localizableText" } + "bookName": { "$ref": "https://example.com/schemas/localizable-text" }, + "subtitle": { "$ref": "https://example.com/schemas/localizable-text" } } } ``` @@ -87,6 +96,39 @@ For resources that contain many strings in the same language, a format can defin } ``` +The resource-wide defaults can be described as their own schema: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schemas/global-lang-dir", + + "type": "object", + "properties": { + "language": { "type": "string" }, + "direction": { "enum": ["ltr", "rtl", "auto"] } + } +} +``` + +A data structure schema can then combine those global settings with its own fields: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schemas/university", + + "$ref": "https://example.com/schemas/global-lang-dir", + "type": "object", + "required": ["name", "summary"], + "properties": { + "name": { "type": "string" }, + "summary": { "type": "string" }, + "alternateName": { "$ref": "https://example.com/schemas/localizable-text" } + } +} +``` + The document recommends `language` for a resource-wide default language field and `direction` for a resource-wide default direction field. For localizable text objects, the examples use `lang` and `dir`, which align naturally with HTML attributes when the value is eventually displayed. For multilingual values, the document recommends language maps, where language tags help consumers find the best localized value: @@ -101,6 +143,39 @@ For multilingual values, the document recommends language maps, where language t } ``` +A reusable language map schema can describe this pattern by treating the object property names as language tags and the property values as localizable text objects: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schemas/language-map", + + "type": "object", + "patternProperties": { + "^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$": { + "$ref": "https://example.com/schemas/localizable-text" + } + }, + "additionalProperties": false +} +``` + +A data structure schema can use that language map where a multilingual value is expected: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schemas/book-with-translations", + + "type": "object", + "properties": { + "bookName": { "$ref": "https://example.com/schemas/language-map" } + } +} +``` + +Note that the language tag regular expression above is loose. It applies the value schema to properties whose names look like non-empty, hyphen-separated language tag tokens, but it does not validate the full BCP 47 grammar. Applications that require full BCP 47 validation should use or implement a dedicated validator. + Producers should preserve language and direction metadata when they have it. They should avoid redundant per-string metadata when a resource-wide default already applies, but they should include string-specific metadata when a value uses a different language, a more specific language tag, or a direction opposite to the default. Consumers should use the metadata they receive. For example, when inserting a string into HTML, that usually means applying `lang` and `dir` to an element that tightly wraps the inserted text, or using `bdi` when no better element is available. When metadata is absent, the language and direction should be treated as unknown. [First-strong direction](https://www.w3.org/TR/i18n-glossary/#dfn-first-strong-detection) detection can be a fallback, but it should not replace explicit metadata.