Skip to content

Storage Interface

The storage interface provides a way to implement a custom storage handler for catalogs. The handler is provided to the adapter config as storage.

An item is a unit (can be a message or a URL) extracted from the source code or the URL patterns you configured, with full translation and reference details.

type FileRefEntry = {
link?: string // for URLs
placeholders: [number, string][]
}
type FileRef = {
file: string
/**
* multiple references in the same file
* null when there is no link or placeholders just that it's referenced
*/
refs: (FileRefEntry | null)[]
}
interface Item {
id: string[]
context?: string
translations: Map<string, string[]>
references: FileRef[]
urlAdapters: string[] // for URLs
// for things that should survive the round trip with the storage
[key: string]: unknown
}

And this is the unit that forms the basis for what exchanged with wuchale.

An additional thing that has to be stored with the translations is the plural rules.

type PluralRule = {
nplurals: number
plural: string
}
type PluralRules = Map<string, PluralRule>

There are just two exchange interactions with wuchale: saving data and loading data. And what the storage has to exchange is this:

type SaveData = {
pluralRules: PluralRules // will always be provided
items: Item[]
}
type LoadData = {
pluralRules?: PluralRules // optional if it's the first time etc, will be filled by the default one
items: Iterable<Item> // not just constrained to being array
}

Putting it all together, what wuchale expects as a storage is a StorageFactory function that accepts StorageFactoryOpts options from wuchale, and returns a CatalogStorage object.

type StorageFactoryOpts = {
locales: string[]
root: string
/** whether the url is configured, can use to load separate url files */
haveUrl: boolean
sourceLocale: string
}
type CatalogStorage = {
/**
* the key to check if two storages share the same location
* e.g. this can be the dir for the pofile storage
* two storages with same keys means they are the same/shared
*/
key: string
load(): Promise<LoadData>
save(items: SaveData): Promise<void>
/** the files controlled by this storage, for e.g. for Vite to watch */
files: string[]
}
type StorageFactory = (opts: StorageFactoryOpts) => CatalogStorage