Bluesky: allow setting `langs` on post creation

Summary

Posts published through Zernio are written to the user’s repo without the langs field on the app.bsky.feed.post record. Support confirmed there is no way to pass it on post creation today, and no per-connection default language setting.

The same thing was already asked for in Bluesky Language Selector (https://zernio.featurebase.app/p/bluesky-language-selector-2), filed 11 months ago. It is still sitting at 3 votes with no status on it. I am opening a new post rather than commenting there because that one has gone nowhere, and because it asks for a UI language selector without making the case for why the field matters. That case is below.

The field

In the AT Protocol lexicon for app.bsky.feed.post:

  • Array, maxLength: 3, items of format language, so up to three BCP-47 codes

  • Described as “Indicates human language of post primary text content”

  • Optional. The record only requires text and createdAt

Current behaviour

POST /v1/posts with a Bluesky platform entry publishes successfully, and the resulting record has no langs key at all. Not an empty array, absent.

Repro against any account posted through Zernio, no auth needed. Call app.bsky.feed.getAuthorFeed on public.api.bsky.app and read .feed[].post.record.langs. Every entry comes back null. On our account that is true of every post it has ever made.

Why it matters

Bluesky’s own docs say the field exists for exactly this:

Setting the post’s language helps custom feeds or other services filter and parse posts.

The same page notes that the Bluesky Social client auto-detects languages and sets them as the default langs value. Posts made from the first-party app therefore almost always carry it, which makes API-created posts that omit it the odd ones out.

I sampled 10 public feed generators through app.bsky.feed.getFeed, 557 posts in total:

  • 4 Portuguese-dominant feeds (90%+ pt), 202 posts: 0 with null langs

  • The other 6 feeds, 355 posts: 91 with null langs

  • One general news feed in the sample was 76% untagged on its own

So untagged posts are not rare on Bluesky. They just do not reach a language-scoped feed.

Worth separating two layers, because only one is the problem:

  • The in-app content-language filter is not it. isPostInLanguage in the official client falls back to a text-based language model (lande) when langs is absent, in src/locale/helpers.ts, so an untagged post can still pass.

  • Feed generators are. They read record.langs off the firehose with no equivalent fallback, and getFeedSkeleton hands them Accept-Language to filter or rank on. An untagged post never matches.

No workaround

langs is set when the record is created, so it cannot be added afterwards, and Bluesky itself has no post edit. The only way around it is to bypass Zernio for Bluesky and write the record directly through com.atproto.repo.createRecord, which means giving up scheduling, threading, media handling and analytics on that platform.

Proposed

  • Accept an optional langs on post creation, something like platformSpecificData.bluesky.langs: [“pt”], validated as up to 3 BCP-47 codes to match the lexicon

  • A default language per Bluesky connection, applied when the request does not specify one, which covers the common case of an account that only ever posts in one language

Auto-detecting it the way the official client does would work too, but an explicit field is easier to reason about for scheduled posts.

This is not only a non-English problem. Any account that relies on a language-scoped feed for reach is affected.

Please authenticate to join the conversation.

Upvoters
Status

Completed

Board
💡

Feature Request

Date

25 days ago

Author

Evandro Neri

Subscribe to post

Get notified by email when there are changes.