From 6bc7fc2a5be877ed18ed905fe9d3ea86a7382be0 Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Mon, 8 Sep 2025 15:02:41 +0300 Subject: [PATCH 1/4] Add first draft of default attribute definitions --- spec/attributes/README.md | 232 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 spec/attributes/README.md diff --git a/spec/attributes/README.md b/spec/attributes/README.md new file mode 100644 index 0000000000..03bdd8308b --- /dev/null +++ b/spec/attributes/README.md @@ -0,0 +1,232 @@ +## Expression, Markup, and Message Attributes + +> [!IMPORTANT] +> This part of the specification is under active development, +> and is non-normative. + +The Unicode MessageFormat syntax and data model allow for _attributes_ +to be defined on _expressions_ and _markup_. +These are REQUIRED to have no impact on the formatting of a message, +and are intended to be useful in informing translators and translator tooling +about the specific _expressions_ or _markup_ to which they are attached. + +While the specification does not define how an _attribute_ could be attached +to the _message_ as a whole, +this SHOULD be provided for by a resource container for Unicode MessageFormat messages. + +As all _attributes_ with _reserved identifiers_ are reserved, +definitions are provided here for common _attribute_ use cases. +Custom _attributes_ SHOULD use a _custom identifier_, +preferably one with an appropriate _namespace_. + +### Attribute Values + +_Attributes_ are not required to have a value. +For _attributes_ defined here that explicitly support `yes` as a value, +an _attribute_ with no value is considered synonymous +with the same _attribute_ with the value `yes`. + +### Expression Attributes + +#### @comment + +_Value_: A non-empty string. + +Associates a freeform comment with the _expression_. + +> For example: +> +> ``` +> The {$device @comment=|Possible values: Printer or Stacker|} has been enabled. +> ``` + +#### @example + +_Value_: A non-empty string. + +An example of the value the _expression_ might take. + +> For example: +> +> ``` +> Error: {$details @example=|Failed to fetch RSS feed.|} +> ``` + +#### @term + +_Value_: A non-empty string, or a URI. + +Identifies a well-defined term. +The value may be a short definition of the term, +or a URI pointing to such a definition. + +> For example: +> +> ``` +> He saw his {|doppelgänger| @term=|https://en.wikipedia.org/wiki/Doppelg%C3%A4nger|}. +> ``` + +#### @translate + +_Value:_ `yes` or `no`. + +Indicates whether the _expression_ is translatable or not. + +> For example: +> +> ``` +> He saw his {|doppelgänger| @translate=no}. +> ``` + +### Markup Attributes + +#### @can-copy + +_Value:_ `yes` or `no`. + +Indicates whether or not the _markup_ and its contents can be copied. + +> For example: +> +> ``` +> Have a {#span @can-copy}great and wonderful{/span @can-copy} birthday! +> ``` + +#### @can-delete + +_Value:_ `yes` or `no`. + +Indicates whether or not the _markup_ and its contents can be deleted. + +#### @can-overlap + +_Value:_ `yes` or `no`. + +Indicates whether or not the _markup_ and its contents where this _attribute_ is used +can enclose partial _markup_ +(i.e. a _markup-open_ without its corresponding _markup-end_, +or a _markup-end_ without its corresponding _markup-start_). + +#### #can-reorder + +_Value:_ `yes` or `no`. + +Indicates whether or not the _markup_ and its contents can be re-ordered. + +#### @comment + +_Value_: A non-empty string. + +Associates a freeform comment with the _markup_. + +> For example: +> +> ``` +> Click {#link @comment=|Rendered as a button|}here{/link} to continue. +> ``` + +#### @term + +_Value_: A non-empty string, or a URI. + +Identifies a well-defined term. +The value may be a short definition of the term, +or a URI pointing to such a definition. + +> For example: +> +> ``` +> He saw his {#span @term=|https://en.wikipedia.org/wiki/Doppelg%C3%A4nger|}doppelgänger{/span}. +> ``` + +#### @translate + +_Value:_ `yes` or `no`. + +Indicates whether the _markup_ and its contents are translatable or not. + +> For example: +> +> ``` +> He saw his {#span @translate=no}doppelgänger{/span}. +> ``` + +### Message Attributes + +#### @allow-empty + +_Value:_ `yes` or `no`. + +Explicitly mark a message with an empty _pattern_ as valid. + +Most empty messages are mistakes, +so being able to mark ones that can be empty is useful. + +Should be accompanied by an explanatory `@comment`. + +#### @max-length + +_Value:_ A strictly positive integer, followed by a space, followed by one of the following: +- `chars` +- `bytes` +- `lines` + +Limits the length of a _message_. + +#### @obsolete + +_Value:_ `yes` or `no`. + +Explicitly mark a _message_ as obsolete. + +This might be used in workflows where messages are not immediately removed +when they are no longer referenced by code, +but kept in to support patch releases for previous versions. +During translation, this can be used to de-prioritize such messages. + +> [!NOTE] +> The value could include a way to note some version or timestamp when the removal happened, +> or be paired with a second `@removed-in` or similar tag. + +#### @param + +_Value_: **TBD** + +Documents a _variable_. + +> [!NOTE] +> Having a well-defined structure for this tag is pretty important, +> at least to identify the variable its description is pertaining to. +> In addition to describing the variable in words, it could include: +> - The variable's type -- is it a string, a number, something else? +> - A default example value to use for the variable. + +#### @schema + +_Value:_ A valid URI. + +Identify the _functions_ and _markup_ supported by the _message_ formatter. + +#### @source + +_Value_: A string. + +Provides the _message_ in its source locale. + +#### @translate + +_Value:_ `yes` or `no` + +Indicates whether the _message_ is translatable or not. + +Some _messages_ may be required to have the same value in all locales. + +#### @version + +_Value_: A string. + +Explicitly versions a source string. + +This allows for differentiating typo fixes from actual changes in message contents. +The (message id, version) tuple can be used by tooling instead of just the message id +to uniquely identify a message and its translations. From 39911f260ab2dc30e61ea2a080b476ee4675401a Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Tue, 9 Sep 2025 12:38:43 +0300 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: Addison Phillips --- spec/attributes/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec/attributes/README.md b/spec/attributes/README.md index 03bdd8308b..22ba9f6fbb 100644 --- a/spec/attributes/README.md +++ b/spec/attributes/README.md @@ -6,9 +6,11 @@ The Unicode MessageFormat syntax and data model allow for _attributes_ to be defined on _expressions_ and _markup_. -These are REQUIRED to have no impact on the formatting of a message, -and are intended to be useful in informing translators and translator tooling +These MUST NOT have any impact on the formatting of a message, +and are intended to inform users, such as translators, and tools about the specific _expressions_ or _markup_ to which they are attached. +_Attributes_ MAY be stripped from _expressions_ and _markup_ +with no effect on the message's formatting. While the specification does not define how an _attribute_ could be attached to the _message_ as a whole, @@ -168,7 +170,6 @@ Should be accompanied by an explanatory `@comment`. _Value:_ A strictly positive integer, followed by a space, followed by one of the following: - `chars` -- `bytes` - `lines` Limits the length of a _message_. @@ -195,7 +196,7 @@ _Value_: **TBD** Documents a _variable_. > [!NOTE] -> Having a well-defined structure for this tag is pretty important, +> Having a well-defined structure for this attribute is pretty important, > at least to identify the variable its description is pertaining to. > In addition to describing the variable in words, it could include: > - The variable's type -- is it a string, a number, something else? From cf12529930bf4f9ed8ff58c5d333a50aa92e5cab Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Mon, 22 Sep 2025 11:54:35 +0300 Subject: [PATCH 3/4] Update spec/attributes/README.md --- spec/attributes/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/attributes/README.md b/spec/attributes/README.md index 22ba9f6fbb..5aa052acc7 100644 --- a/spec/attributes/README.md +++ b/spec/attributes/README.md @@ -18,7 +18,7 @@ this SHOULD be provided for by a resource container for Unicode MessageFormat me As all _attributes_ with _reserved identifiers_ are reserved, definitions are provided here for common _attribute_ use cases. -Custom _attributes_ SHOULD use a _custom identifier_, +Use a _custom identifier_ for other (custom) _attributes_, preferably one with an appropriate _namespace_. ### Attribute Values From 50ec0b4b2079c5aa14bdf8c2da40efcfd52d176c Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Mon, 22 Sep 2025 11:56:16 +0300 Subject: [PATCH 4/4] Update spec/attributes/README.md --- spec/attributes/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/attributes/README.md b/spec/attributes/README.md index 5aa052acc7..0caadde958 100644 --- a/spec/attributes/README.md +++ b/spec/attributes/README.md @@ -164,7 +164,7 @@ Explicitly mark a message with an empty _pattern_ as valid. Most empty messages are mistakes, so being able to mark ones that can be empty is useful. -Should be accompanied by an explanatory `@comment`. +Empty _messages_ SHOULD be accompanied by an explanatory `@comment`. #### @max-length