Localising a changelog for two languages
A changelog entry declares one language, as a BCP-47 tag, and inherits the app's when it declares none. That is enough to run two languages properly, and it is not an hreflang cluster.

To run a changelog in two languages, publish one entry per language and let each entry declare which language it is written in. A changelog entry in Market4 carries a locale field holding a single BCP-47 tag, such as en or tr-TR. Left empty, the entry inherits whatever language the app publishes in, which is what every entry written before the field existed means. Filling it in is how a Turkish product announces an English release without the page, the feed and the subscriber e-mail all claiming the wrong language.
The locale on a changelog entry states what language that entry is written in, and nothing more. It does not translate the text, it does not pair the entry with its counterpart in another language, and it does not generate alternate-language tags. Declaring a language is a statement about one document; claiming that two documents are translations of each other is a relationship between two documents, and conflating the two would produce hreflang tags nobody authored.
That single-tag shape is the reason the two-entry pattern is the right one. An entry that mixed English and Turkish paragraphs under one locale would be lying about half of itself, and the readers that consume the declaration are exactly the ones that cannot recover from a lie: a screen reader mispronounces text in a language it was told is a different one, and a crawler segments words by rules that belong to the language it was given.
A changelog entry is not only a page. It is also mailed to the subscribers who asked for it, and the mail is assembled from the entry's body plus template wording the product supplies around it. When the declared language disagrees with the body, that mail is where a customer sees it: a Turkish announcement arriving under English template wording, in a message whose html lang attribute says English, is a more obvious defect than the same mismatch sitting quietly on a page.
This is why setting the locale is worth doing at the moment the entry is written rather than as a tidy-up later. The page can be corrected after publication and the correction is invisible to anyone who has not reloaded it. The e-mail cannot be corrected after it has been sent.

A changelog migration is four decisions, not a copy and paste: where the entries live from now on, what address each one answers at, what happens to the links people already shared, and who writes the next entry.

A breaking change is the one entry a reader cannot skim. It has to name what stops working, the date it stops, and the replacement — and no common changelog standard gives it a category of its own, so the title and the body carry it.
Market4 turns one release note into a changelog page, a blog post, a mail-out and a week of social posts — and then tells you which of them brought anyone back.
| Approach | What a subscriber receives | What it costs you |
|---|---|---|
| One entry containing both languages | One mail with both versions stacked, under a single declared language that is wrong for half of it | Nothing to publish, and a document no assistive technology can read correctly |
| One entry per language, each declaring its own locale | One mail per language, each internally consistent | Two entries to write and two publishes per release |
| A separate app or changelog per language | Fully separate feeds, subscriber lists and pages | Two of everything, including two release calendars to keep in step |
The middle row is the one this field was added for. Two entries per release is more writing, and it is the only option of the three where every published artefact — the page, the feed item and the mail — says one language and means it.
A changelog written in one language and read in two is a common shape for a small product with an international user base, and it does not need a translation pipeline to be handled honestly. What it needs is that every entry says which language it is in, and that nothing in the product guesses on the entry's behalf.
The entry inherits the language the app publishes in. That is the meaning of an empty field rather than a missing value, and it is what every entry written before the field existed means. For a product that publishes in one language, leaving it empty on every entry is correct and no decision has to be made per entry.
No. The locale states what language an entry is written in; it does not claim that any other entry is a translation of it. Alternate-language linking is a relationship between two documents and needs to be authored as one. A field that quietly produced hreflang tags from a language declaration would emit claims about translations that nobody made.
It publishes, and it produces a document whose declared language is wrong for half its content. A screen reader will mispronounce the half that does not match, a crawler will segment it by the wrong rules, and the subscriber mail will carry one html lang attribute for a body written in two. Two entries, each declaring its own language, avoids all three.
BCP-47, the same format an html lang attribute takes. A bare language subtag such as en or tr is valid, and a language with a region such as en-GB or tr-TR is valid when the region genuinely matters to the reader. Pick the shortest tag that is true; a region you do not actually distinguish is a claim you cannot keep.

Somebody deciding whether to buy your product reads the changelog for something your marketing pages cannot tell them: whether anyone is still working on it, and what happens to them when something changes.