A media file's translatable details — title, alt text and description — in one language.
Not a table. The text lives on the file row's data column (V199), and
this module is the one read and write path for it:
%{
"en-US" => %{"title" => "Harbour", "alt" => "Boats in a harbour"},
"et" => %{"title" => "Sadam"}
}Every language holds its own text, independently. No language is marked as the primary one in the data, so a site that changes its primary language has nothing to convert: which text stands in for a missing translation is decided when it is read.
This is deliberately not the PhoenixKit.Utils.Multilang structure, which
stores every other language as a diff against an embedded primary. That
pays off for a record with dozens of fields; for three it buys nothing and
ties the stored text to a setting that can change.
Reading
FileDetails.translated_alt(file, "et") # "" when there is none
FileDetails.translated_title(file, "et") # nil when there is none
FileDetails.for_locale(file, "et") # all threeEach field resolves on its own: the language asked for (or a dialect of
it) → the site's current primary language → any other language. The alt
text never falls back to the file name: a file name read aloud helps
nobody, and alt="" correctly marks the image as undescribed.
The site's primary language is read from PhoenixKit.Utils.Multilang; a
caller resolving many files passes it once as primary:.
Files from before V199
They hold a title and description in metadata, in no recorded language.
While a file's data is empty that text is its primary-language text. The
first save moves it into data; from then on data is the truth, and
metadata only receives a copy of the primary-language text for the
readers that still look there (the PDF processor's fill-if-missing title,
the viewer's stored title).
Writing
A save replaces one language's text and nothing else:
Storage.update_file_details(file, %{"title" => "Sadam"}, lang: "et")
Summary
Functions
Changeset for one language's text. attrs holds "title", "alt" and
"description"; a key that is absent keeps its current value.
The content language a page shown in locale edits and reads: the enabled
language that locale names — so a URL's bare "et" and the hook's
"et-EE" store under the one code the site has enabled. A locale that is
no enabled language (the Gettext default on a site that never enabled it)
is the primary language: text must not pile up under a code no page is
ever shown in.
The translatable field names.
The File.details_changeset/2 attrs that store details as file's text
in lang.
All three details of file in locale.
The text file holds in lang itself — no fallback to another language,
so an editor shows what that language really has. "Itself" includes the
same language stored at another precision ("en" for "en-US"), which a
save replaces; it does not include a sibling dialect ("en-GB"), which is
another language — an editor opened on it would save a copy of it.
The display name of content language lang — or nil on a site with a
single language, where there is nothing to tell the editor.
One detail of file in locale: that language's text, else the primary
language's, else any language's, else nil. A nil locale reads the
primary language.
The alt text in locale, ready for an alt attribute: "" when the file
has none. Never the file name.
The description in locale, or nil.
The title in locale, or nil.
Types
Functions
@spec changeset(t(), map()) :: Ecto.Changeset.t()
Changeset for one language's text. attrs holds "title", "alt" and
"description"; a key that is absent keeps its current value.
The content language a page shown in locale edits and reads: the enabled
language that locale names — so a URL's bare "et" and the hook's
"et-EE" store under the one code the site has enabled. A locale that is
no enabled language (the Gettext default on a site that never enabled it)
is the primary language: text must not pile up under a code no page is
ever shown in.
Options: :languages — the enabled language codes, :primary.
@spec fields() :: [String.t()]
The translatable field names.
@spec file_attrs( PhoenixKit.Modules.Storage.File.t(), t(), String.t() | nil, keyword() ) :: %{ metadata: map(), data: map() }
The File.details_changeset/2 attrs that store details as file's text
in lang.
Only that language's entry in data changes (an entry left with no text
is removed). A file from before V199 first gets its metadata text moved
into data under the primary language. When lang is the primary
language, metadata receives a copy — a cleared field as "", not
removed: the PDF processor fills a missing "title" from the document,
and a title the user cleared must stay cleared.
@spec for_locale(PhoenixKit.Modules.Storage.File.t(), String.t() | nil, keyword()) :: %{ title: String.t() | nil, alt: String.t(), description: String.t() | nil }
All three details of file in locale.
@spec from_file(PhoenixKit.Modules.Storage.File.t(), String.t() | nil, keyword()) :: t()
The text file holds in lang itself — no fallback to another language,
so an editor shows what that language really has. "Itself" includes the
same language stored at another precision ("en" for "en-US"), which a
save replaces; it does not include a sibling dialect ("en-GB"), which is
another language — an editor opened on it would save a copy of it.
Options: :primary — the site's primary language (default: the current
one).
The display name of content language lang — or nil on a site with a
single language, where there is nothing to tell the editor.
@spec translated( PhoenixKit.Modules.Storage.File.t(), String.t(), String.t() | nil, keyword() ) :: String.t() | nil
One detail of file in locale: that language's text, else the primary
language's, else any language's, else nil. A nil locale reads the
primary language.
Options: :primary — the site's primary language (default: the current
one).
@spec translated_alt(PhoenixKit.Modules.Storage.File.t(), String.t() | nil, keyword()) :: String.t()
The alt text in locale, ready for an alt attribute: "" when the file
has none. Never the file name.
@spec translated_description( PhoenixKit.Modules.Storage.File.t(), String.t() | nil, keyword() ) :: String.t() | nil
The description in locale, or nil.
@spec translated_title( PhoenixKit.Modules.Storage.File.t(), String.t() | nil, keyword() ) :: String.t() | nil
The title in locale, or nil.